Light's Blog

The best or nothing.

Export Music From Itunes to Local App's Sandbox on iPhone

| Comments

Introduction

本文主要介绍app如何获取iTunes中音乐列表,并把iTunes中音乐文件导出至app的沙盒目录下。

import

导入所需的头文件。

1
2
#import <AVFoundation/AVAssetExportSession.h>
#import <MediaPlayer/MediaPlayer.h>

注册通知

注册MPMediaLibraryDidChangeNotification通知,当iTunes音乐库文件发生变化时,做出响应。

1
2
3
4
5
[[NSNotificationCenter defaultCenter]
    addObserver:self
    selector:@selector(mediaLibraryDidChange:)
    name:MPMediaLibraryDidChangeNotification
    object:nil];

开启通知

开启MPMediaLibrary通知。

1
[[MPMediaLibrary defaultMediaLibrary] beginGeneratingLibraryChangeNotifications];

关闭通知

关闭MPMediaLibrary通知。

1
[[MPMediaLibrary defaultMediaLibrary] endGeneratingLibraryChangeNotifications];

MPMediaQuery

通过MPMediaQuery获取iTunes中音乐列表,可以自定义列表类型,调用-collection方法,返回对应列表的数组。数组中元素为MPMediaItemCollection类型。

1
2
3
4
5
6
//  create
MPMediaQuery *mediaQuery = [MPMediaQuery playlistQuery];
//  groupType
mediaQuery.groupingType = MPMediaGroupingAlbumArtist;
//  query
NSArray<MPMediaItemCollection *> *mediaCollections = [mediaQuery collections];

MPMediaItem

通过MPMediaItemCollection获取对应的MPMediaItem,对应多媒体文件。通过MPMediaItem获取文件相关信息。导出时需要文件地址assetURL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
NSMutableArray<MPMediaItem *> mediaItems = [NSMutableArray array];
for (MPMediaItemCollection *collection in mediaCollections) {
  //  mediaItem
  MPMediaItem *mediaItem = [collection representativeItem];
  //  歌曲名称
  NSString *title = [mediaItem valueForProperty:MPMediaItemPropertyTitle];
  //  演唱者
  NSString *artist = [mediaItem valueForProperty:MPMediaItemPropertyArtist];
  //  歌曲封面
  MPMediaItemArtwork *artwork = [mediaItem valueForProperty:MPMediaItemPropertyArtwork];
  //  歌曲格式
  NSString *form = self.assetURL.pathExtension;
  //  歌曲地址,本地iTunes中地址,可用于导出歌曲
  NSURL *assetURL = [mediaItem valueForProperty:MPMediaItemPropertyAssetURL];
  //  add
  [mediaItems addObject:mediaItem];
}

Play

获取到MPMediaItemCollection后,可以选择使用iTunes直接播放该文件。

1
2
3
4
5
MPMediaItemCollection *mediaItemCollection = [mediaCollections firstObject];
MPMediaItem *selectedItem = [collection representativeItem];
[[MPMusicPlayerController iPodMusicPlayer] setQueueWithItemCollection:mediaItemCollection];
[[MPMusicPlayerController iPodMusicPlayer] setNowPlayingItem:selectedItem];
[[MPMusicPlayerController iPodMusicPlayer] play];

Export Music to Local Sandbox

导出音乐文件至本地沙盒目录下:

1、获取音乐文件名(title)及input地址(assetURL);

2、获取沙盒目录,并创建output地址(outputURL);

3、获取AVURLAsset

4、使用AVAssetExportSession导出AVURLAsset。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
for (MPMediaItem *musicItem in musicItems) {
    //  获取文件名及地址
    NSString *title = [mediaItem valueForProperty:MPMediaItemPropertyTitle];
    NSURL *assetURL = [mediaItem valueForProperty:MPMediaItemPropertyAssetURL];
    if (assetURL && [self validIpodLibraryURL:assetURL]) {
      //  创建 output URL,存入沙盒目录下,以文件名为标识
      NSString *pathExtension = assetURL.pathExtension;
      NSArray *paths = NSSearchPathForDirectoriesInDomains(
          NSDocumentDirectory, NSUserDomainMask, YES);
      NSString *documentsDirectory = [paths firstObject];
      NSURL *outputURL =
          [[NSURL fileURLWithPath:[documentsDirectory
                                      stringByAppendingPathComponent:title]]
              URLByAppendingPathExtension:pathExtension];
      //  保证无重复路径
      [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
      //  获取Asset
      NSDictionary *options = [[NSDictionary alloc] init];
      AVURLAsset *asset = [AVURLAsset URLAssetWithURL:assetURL options:options];
      if (asset) {
        //  创建export session
        AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
            initWithAsset:asset
               presetName:AVAssetExportPresetPassthrough];
        if (exportSession) {
            //  导出类型
            if ([pathExtension compare:@"m4a"] == NSOrderedSame) {
              exportSession.outputFileType = AVFileTypeAppleM4A;
            } else if ([pathExtension compare:@"wav"] == NSOrderedSame) {
              exportSession.outputFileType = AVFileTypeWAVE;
            } else if ([pathExtension compare:@"aif"] == NSOrderedSame) {
              exportSession.outputFileType = AVFileTypeAIFF;
            } else if ([pathExtension compare:@"m4v"] == NSOrderedSame) {
              exportSession.outputFileType = AVFileTypeAppleM4V;
            }
            //  导出地址
            exportSession.outputURL = outputURL;
            //  导出
            [exportSession exportAsynchronouslyWithCompletionHandler:^{
              //  状态回调
              if (completion) {
                switch (exportSession.status) {
                case AVAssetExportSessionStatusFailed:
                  NSLog(@"Failed");
                  break;
                case AVAssetExportSessionStatusCancelled:
                  NSLog(@"Cancelled");
                  break;
                case AVAssetExportSessionStatusCompleted:
                  NSLog(@"Completed");
                  break;
                default:
                  break;
                }
              }
            }];
        }
      }
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (BOOL)validIpodLibraryURL:(NSURL *)url {
  NSString *IPOD_SCHEME = @"ipod-library";
  if (nil == url)
    return NO;
  if (nil == url.scheme)
    return NO;
  if ([url.scheme compare:IPOD_SCHEME] != NSOrderedSame)
    return NO;
  if ([url.pathExtension compare:@"aif"] != NSOrderedSame &&
      [url.pathExtension compare:@"m4a"] != NSOrderedSame &&
      [url.pathExtension compare:@"wav"] != NSOrderedSame &&
      [url.pathExtension compare:@"m4v"] != NSOrderedSame) {
    return NO;
  }
  return YES;
}

Comments