应项目需求,需要实现本地选取并上传图片、音频和视频文件。
其中选取图片这块有很多开源框架,不再赘述。本文主要是采用iOS自带的类MPMediaPickerController 来实现UIImagePickerController音频、视频文件的选取。
首先需要说明的是,如果需求是需要从语音备忘录里面读取原有录音,那么是较难实现的。我在http://stackoverflow.com/questions/5265215/iphone-access-voice-memos-programmatically上有找到相关回答说目前暂时还不能实现,只能现场马上录制并上传。
So,那么就考虑是从iPod的音乐库中导出音乐。
此处会用到一个类就是`MPMediaPickerController`来访问iPod Library.注意需要导入
简单初始化代码如下:
MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
picker.prompt = @"请选择您需要上传的歌曲";
picker.showsCloudItems = YES; //是否显示下载项
picker.allowsPickingMultipleItems = NO; //是否多选
picker.delegate = self;
[self presentViewController:picker animated:YES completion:nil];
选择界面:
选中和取消代理回调:
#pragma mark MPMediaPickerControllerDelegate
- (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker {
[mediaPicker dismissViewControllerAnimated:YES completion:nil];
}
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection {
[mediaPicker dismissViewControllerAnimated:YES completion:nil];
MPMediaItem *item = mediaItemCollection.items.firstObject;
[self convertToM4A:item];
NSLog(@"%@---%@-----", item.title, item.assetURL);
}
选中回调集合里面放的是`MPMediaItem`对象。每一个此对象都表示了一首歌曲的信息,可以通过MPMediaEntity来访问其属性,具体可以查看.h文件。
值得一提的是其中有一个assetURL属性,格式类似于这样:ipod-library://item/item.wav?id=3524634042900602222
此属性可以直接用于AVPlayer播放该音频,但是如果要通过该URL访问音频数据,则是不能实现的。
要想获取到本地的音频文件,需要用到AVAssetExportSession将其导出。具体操作代码如下
- (void)convertToM4A: (MPMediaItem *)song
{
NSURL *url = [song valueForProperty:MPMediaItemPropertyAssetURL];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [dirs objectAtIndex:0];
NSLog(@"%@", documentsDirectoryPath);
NSLog (@"compatible presets for songAsset: %@",[AVAssetExportSession exportPresetsCompatibleWithAsset:songAsset]);
NSArray *ar = [AVAssetExportSession exportPresetsCompatibleWithAsset: songAsset];
NSLog(@"%@", ar);
AVAssetExportSession *exporter = [[AVAssetExportSession alloc]
initWithAsset: songAsset
presetName: AVAssetExportPresetAppleM4A];
NSLog (@"created exporter. supportedFileTypes: %@", exporter.supportedFileTypes);
exporter.outputFileType = @"com.apple.m4a-audio";
NSString *exportFile = [documentsDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.m4a",[song valueForProperty:MPMediaItemPropertyTitle]]];
NSError *error1;
if([fileManager fileExistsAtPath:exportFile])
{
[fileManager removeItemAtPath:exportFile error:&error1];
}
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager]enumeratorAtPath:documentsDirectoryPath];
for (NSString *fileName in enumerator)
{
NSLog(@"------%@", fileName);
}
NSURL* exportURL = [NSURL fileURLWithPath:exportFile];
exporter.outputURL = exportURL;
// do the export
[exporter exportAsynchronouslyWithCompletionHandler:^
{
NSData *data1 = [NSData dataWithContentsOfFile:exportFile];
double size = (long)data1.length / 1024. / 1024.;
NSString *title = song.title;
if ([[title stringByReplacingOccurrencesOfString:@" " withString:@""] isEqualToString:@""]) {
title = @"无名称音频";
}
title = [title stringByAppendingString:[NSString stringWithFormat:@" %.2fM", size]];
dispatch_async(dispatch_get_main_queue(), ^{
self.audiolb.text = title;
});
// NSLog(@"==================data1:%@",data1);
int exportStatus = exporter.status;
switch (exportStatus) {
case AVAssetExportSessionStatusFailed: {
// log error to text view
NSError *exportError = exporter.error;
NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError);
break;
}
case AVAssetExportSessionStatusCompleted: {
NSLog (@"AVAssetExportSessionStatusCompleted");
break;
}
case AVAssetExportSessionStatusUnknown: {
NSLog (@"AVAssetExportSessionStatusUnknown");
break;
}
case AVAssetExportSessionStatusExporting: {
NSLog (@"AVAssetExportSessionStatusExporting");
break;
}
case AVAssetExportSessionStatusCancelled: {
NSLog (@"AVAssetExportSessionStatusCancelled");
break;
}
case AVAssetExportSessionStatusWaiting: {
NSLog (@"AVAssetExportSessionStatusWaiting");
break;
}
default:
{ NSLog (@"didn't get export status");
break;
}
}
}];
}
需注意在其他线程中操作UI时,应将UI操作用GCD放到主线程中。
视频选择其实用到的就是经常用的图片选择器,iOS中照片和摄像文件同样储存在相册中的,所有跟图片处理器的使用大同小异。
选择好UIImagePickerController的mediaTypes就好
UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.mediaTypes = @[(NSString *)kUTTypeMovie];
picker.delegate = self;
[self presentViewController:picker animated:YES completion:nil];
#pragma mark UIImagePickerControllerDelegate
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissViewControllerAnimated:YES completion:nil];
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if([mediaType isEqualToString:@"public.movie"])
{
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSLog(@"found a video");
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfURL:videoURL options:NSDataReadingUncached error:&error];
if (!error) {
double size = (long)data.length / 1024. / 1024.;
self.vediolb.text = [NSString stringWithFormat:@"%.2fMB", size];
if (size > 30.0) {
//文件过大
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"视频文件不得大于30M" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancle = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:cancle];
[self presentViewController:alert animated:YES completion:nil];
} else {
//保存数据
//获取视频的thumbnail
MPMoviePlayerController *player = [[MPMoviePlayerController alloc]initWithContentURL:videoURL] ;
UIImage *thumbnail = [player thumbnailImageAtTime:0.01 timeOption:MPMovieTimeOptionNearestKeyFrame];
player = nil;
self.vedioimage.image = thumbnail;
}
}
}
}
(欢迎随手给一颗星星哦~)本篇博客Demo地址https://github.com/xmy0010/DemoForCSDN (TyunMediaPickerDemo)
本人邮箱[email protected]欢迎小伙伴一起讨论,学习,进步。