从iOS库中选择音乐并发送/保存

时间:2012-07-06 15:16:21

标签: objective-c ios mpmediaitem mpmediapickercontroller

我对音乐文件有疑问。

我想从iPhone / iTouch / iPad音乐库中选择一个/多个音乐文件并保存在我的文档文件夹中或发送到服务器。

我粗略地浏览了MPMediaPickerControllerAddMusic(Sample Code)。 但是,我只能获得选择歌曲和播放歌曲的详细信息。

是否可以 保存所选的歌曲 ,我还可以将其用于发送到服务器?

由于

3 个答案:

答案 0 :(得分:11)

是的,有可能。

我认为它会对你有所帮助

// Have to add this framework

//CoreMedia.framework
//AudioToolbox.framework
//CoreAudio.framework
//MediaPlayer.framework
//AVFoundation.framework


//in UploadAudioViewController.h file

#import <UIKit/UIKit.h>
#import <CoreAudio/CoreAudioTypes.h>
#import <AudioToolbox/AudioToolbox.h>
#import <MediaPlayer/MediaPlayer.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreMedia/CoreMedia.h>

@interface UploadAudioViewController : UIViewController<UIActionSheetDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate,MPMediaPickerControllerDelegate,AVAudioRecorderDelegate, AVAudioPlayerDelegate,AVAudioSessionDelegate>{

    MPMediaItem *song;
    NSURL *exportURL;
}

@property (nonatomic, retain) NSData *audioData;



// in UploadAudioViewController.m file

#import "UploadAudioViewController.h"
//#import < AudioToolbox/AudioToolbox.h>

@interface UploadAudioViewController ()

@end

@implementation UploadAudioViewController

@synthesize musicPlayer,audioData;

-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;

}

-(void)viewDidLoad
{

    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    self.title = @"Upload Audio";
    self.musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
    self.audioData=nil;

}

#pragma mark Browse Audio from Device

-(void)PickAudioForIndex_iPhone
{

    if ([[[UIDevice currentDevice] model] isEqualToString:@"iPhone Simulator"]) {
        //device is simulator
        UIAlertView *alert1;
        alert1 = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"There is no Audio file in the Device" delegate:self cancelButtonTitle:nil otherButtonTitles:@"Ok",nil];
        alert1.tag=2;
        [alert1 show];
        //[alert1 release],alert1=nil;
    }else{

        MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic];
        mediaPicker.delegate = self;
        mediaPicker.allowsPickingMultipleItems = NO; // this is the default
        [self presentViewController:mediaPicker animated:YES completion:nil];

    }

}

#pragma mark Media picker delegate methods

-(void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection {

    // We need to dismiss the picker
    [self dismissViewControllerAnimated:YES completion:nil];

    // Assign the selected item(s) to the music player and start playback.
    if ([mediaItemCollection count] < 1) {
        return;
    }
    song = [[mediaItemCollection items] objectAtIndex:0];
    [self handleExportTapped];

}

-(void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker {

    // User did not select anything
    // We need to dismiss the picker

    [self dismissViewControllerAnimated:YES completion:nil ];
}

-(void)handleExportTapped{

    // get the special URL
    if (! song) {
        return;
    }

    //[self startLoaderWithLabel:@"Preparing for upload..."];

    NSURL *assetURL = [song valueForProperty:MPMediaItemPropertyAssetURL];
    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];

    NSLog (@"Core Audio %@ directly open library URL %@",
           coreAudioCanOpenURL (assetURL) ? @"can" : @"cannot",
           assetURL);

    NSLog (@"compatible presets for songAsset: %@",
           [AVAssetExportSession exportPresetsCompatibleWithAsset:songAsset]);


    /* approach 1: export just the song itself
     */
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc]
                                      initWithAsset: songAsset
                                      presetName: AVAssetExportPresetAppleM4A];
    NSLog (@"created exporter. supportedFileTypes: %@", exporter.supportedFileTypes);
    exporter.outputFileType = @"com.apple.m4a-audio";
    NSString *exportFile = [myDocumentsDirectory() stringByAppendingPathComponent: @"exported.m4a"];
    // end of approach 1

    // set up export (hang on to exportURL so convert to PCM can find it)
    myDeleteFile(exportFile);
    //[exportURL release];
    exportURL = [NSURL fileURLWithPath:exportFile];
    exporter.outputURL = exportURL;

    // do the export
    [exporter exportAsynchronouslyWithCompletionHandler:^{
        int exportStatus = exporter.status;
        switch (exportStatus) {
            case AVAssetExportSessionStatusFailed: {
                // log error to text view
                NSError *exportError = exporter.error;
                NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError);
                //errorView.text = exportError ? [exportError description] : @"Unknown failure";
                //errorView.hidden = NO;
                //[self stopLoader];
                //[self showAlertWithMessage:@"There ia an error!"];
                break;
            }
            case AVAssetExportSessionStatusCompleted: {
                NSLog (@"AVAssetExportSessionStatusCompleted");
                //fileNameLabel.text = [exporter.outputURL lastPathComponent];
                // set up AVPlayer
                //[self setUpAVPlayerForURL: exporter.outputURL];
                ///////////////// get audio data from url

                //[self stopLoader];
                //[self showAlertWithMessage:@"There ia an error!"];

                NSURL *audioUrl = exportURL;
                NSLog(@"Audio Url=%@",audioUrl);
                self.audioData = [NSData dataWithContentsOfURL:audioUrl];

                break;
            }
            case AVAssetExportSessionStatusUnknown: {
                NSLog (@"AVAssetExportSessionStatusUnknown");
                //[self stopLoader];
                //[self showAlertWithMessage:@"There ia an error!"];
                break;
            }
            case AVAssetExportSessionStatusExporting: {
                NSLog (@"AVAssetExportSessionStatusExporting");
                //[self stopLoader];
                //[self showAlertWithMessage:@"There ia an error!"];
                break;
            }
            case AVAssetExportSessionStatusCancelled: {
                NSLog (@"AVAssetExportSessionStatusCancelled");
                //[self stopLoader];
                //[self showAlertWithMessage:@"There ia an error!"];
                break;
            }
            case AVAssetExportSessionStatusWaiting: {
                NSLog (@"AVAssetExportSessionStatusWaiting");
                //[self stopLoader];
                //[self showAlertWithMessage:@"There ia an error!"];
                break;
            }
            default: {
                NSLog (@"didn't get export status");
                //[self stopLoader];
                //[self showAlertWithMessage:@"There ia an error!"];
                break;
            }
        }
    }];



}


#pragma mark conveniences

NSString* myDocumentsDirectory(){

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return [paths objectAtIndex:0];;

}

void myDeleteFile (NSString* path){

    if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
        NSError *deleteErr = nil;
        [[NSFileManager defaultManager] removeItemAtPath:path error:&deleteErr];
        if (deleteErr) {
            NSLog (@"Can't delete %@: %@", path, deleteErr);
        }
    }

}

// generic error handler from upcoming "Core Audio" book (thanks, Kevin!)
// if result is nonzero, prints error message and exits program.

static void CheckResult(OSStatus result, const char *operation)
{

    if (result == noErr) return;

    char errorString[20];
    // see if it appears to be a 4-char-code
    *(UInt32 *)(errorString + 1) = CFSwapInt32HostToBig(result);
    if (isprint(errorString[1]) && isprint(errorString[2]) && isprint(errorString[3]) && isprint(errorString[4])) {
        errorString[0] = errorString[5] = '\'';
        errorString[6] = '\0';
    } else
        // no, format it as an integer
        sprintf(errorString, "%d", (int)result);

    fprintf(stderr, "Error: %s (%s)\n", operation, errorString);

    exit(1);

}

#pragma mark core audio test

BOOL coreAudioCanOpenURL (NSURL* url){

    OSStatus openErr = noErr;
    AudioFileID audioFile = NULL;
    openErr = AudioFileOpenURL((__bridge CFURLRef) url,
                               kAudioFileReadPermission ,
                               0,
                               &audioFile);
    if (audioFile) {
        AudioFileClose (audioFile);
    }
    return openErr ? NO : YES;

}

答案 1 :(得分:1)

  

是否可以保存选定的歌曲,我也可以用它们发送到服务器?

不,您只能播放iTunes资料库中的歌曲 原始音频文件无法访问,可能是由于版权保护。

答案 2 :(得分:0)

我已尝试并成功导出ipod库歌曲。请在下面找到我的代码:

extension AudioPostViewController: MPMediaPickerControllerDelegate {

func mediaPicker(mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
    dismissViewControllerAnimated(true, completion: {
        print("You selected \(mediaItemCollection)")

        let item: MPMediaItem = mediaItemCollection.items[0]
        let pathURL: NSURL? = item.valueForProperty(MPMediaItemPropertyAssetURL) as? NSURL
        if pathURL == nil {
            Alert.showPopupWithMessage("Unable to read DRM protected file.")
            return
        }


        let title = item.valueForProperty(MPMediaItemPropertyTitle) as? String ?? "Now Playing..."
        print("\(pathURL), title : \(title) ")

        // get file extension andmime type
        let str = pathURL!.absoluteString
        let str2 = str.stringByReplacingOccurrencesOfString("ipod-library://item/item", withString: "")
        let arr = str2.componentsSeparatedByString("?")
        var mimeType = arr[0]
        mimeType = mimeType.stringByReplacingOccurrencesOfString(".", withString: "")

        // Export the ipod library as .m4a file to local directory for remote upload
        let exportSession = AVAssetExportSession(asset: AVAsset(URL: pathURL!), presetName: AVAssetExportPresetAppleM4A)
        exportSession?.shouldOptimizeForNetworkUse = true
        exportSession?.outputFileType = AVFileTypeAppleM4A
        FilePath.removeAudioFile() // Remove file if it exists
        let fileUrl = FilePath.testFilePathURL()
        exportSession?.outputURL = fileUrl
        exportSession?.exportAsynchronouslyWithCompletionHandler({ () -> Void in

            if exportSession!.status == AVAssetExportSessionStatus.Completed  {
                dispatch_async(dispatch_get_main_queue(), {

                    // Prepare audio to play
                    self.audioTitle = title
                    self.audioPath = fileUrl
                    self.mimeType = "audio/m4a"
                    self.audioFileName = "audio.m4a"


                    UIView.animateWithDuration(0.45, animations: {
                        if Platform.DeviceType.iPhone4 {
                            self.libraryBottomSpacing.constant = 5
                            self.view.layoutIfNeeded()

                        } else {
                            self.libraryBottomSpacing.constant = 25
                            self.view.layoutIfNeeded()

                        }
                        }, completion: {
                            (v: Bool) in
                            self.loadJukeBox(self.audioPath!, title: title)
                    })
                })

            } else {
                dispatch_async(dispatch_get_main_queue(), {
                    Alert.showPopupWithMessage("Unable to read file as its DRM protected.")
                  })

            }

        })

        })


}

func mediaPickerDidCancel(mediaPicker: MPMediaPickerController) {
    dismissViewControllerAnimated(true, completion: nil)
} 
}