iOS开发:iPhone设备图片、音乐、视频获取实践
背景介绍
出于项目需求,需要基于iphone设备内图片及音乐、视频资源完成一些功能。功能包括以几点:1.需要在APP内获得并处理iphone设备内的图片、音频和视频;2.在APP内嵌入拍照入口,可以拍照并展示图片。
开发过程是学习的过程也是解决问题的过程,因此笔者对开发过程中涉及到的iphone设备内图片、音视频获取以及拍照过程中遇到的图片方向问题进行了整理和分析。
开发环境:Xcode10
一、获取本地图片、音乐、视频
iphone设备内相册存储了所有的图片和通过相机拍摄的视频,itunes的资料库存储了所有的音乐和部分视频。
头文件引用:
#import <Photos/Photos.h>
遍历相册,获取相册内的图片和视频
app若想要访问相册,需要获得用户的授权。开发时,要在info.plist文件内添加以下内容,这样在app启动后,系统会提示用户是否授权访问相关资源:
<key>NSPhotoLibraryAddUsageDescription</key><string>需要访问相册,用于保存图片</string><key>NSPhotoLibraryUsageDescription</key><string>如果不允许,您将无法在XXX中使用系统相册</string>
访问相册前,需要判断APP是否具有访问相册权限的权限:
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {//status == PHAuthorizationStatusDenied 用户已经明确否认了权限的访问//status == PHAuthorizationStatusRestricted 此应用程序没有被授权访问的照片数据//status == PHAuthorizationStatusNotDetermined 用户尚未做出选择这个应用程序的问候//status == PHAuthorizationStatusAuthorized 用户已经授权应用访问照片数据}];
获取权限后,便可以访问相册内所有系统相册及用户自定义相册,photos提供的相册种类很多,如下所示:
typedef NS_ENUM(NSInteger, PHAssetCollectionType) {PHAssetCollectionTypeAlbum = 1,PHAssetCollectionTypeSmartAlbum = 2,PHAssetCollectionTypeMoment = 3,
} PHOTOS_ENUM_AVAILABLE_IOS_TVOS(8_0, 10_0);typedef NS_ENUM(NSInteger, PHAssetCollectionSubtype) {// PHAssetCollectionTypeAlbum regular subtypesPHAssetCollectionSubtypeAlbumRegular = 2,PHAssetCollectionSubtypeAlbumSyncedEvent = 3,PHAssetCollectionSubtypeAlbumSyncedFaces = 4,PHAssetCollectionSubtypeAlbumSyncedAlbum = 5,PHAssetCollectionSubtypeAlbumImported = 6,// PHAssetCollectionTypeAlbum shared subtypesPHAssetCollectionSubtypeAlbumMyPhotoStream = 100,PHAssetCollectionSubtypeAlbumCloudShared = 101,// PHAssetCollectionTypeSmartAlbum subtypesPHAssetCollectionSubtypeSmartAlbumGeneric = 200,PHAssetCollectionSubtypeSmartAlbumPanoramas = 201,PHAssetCollectionSubtypeSmartAlbumVideos = 202,PHAssetCollectionSubtypeSmartAlbumFavorites = 203,PHAssetCollectionSubtypeSmartAlbumTimelapses = 204,PHAssetCollectionSubtypeSmartAlbumAllHidden = 205,PHAssetCollectionSubtypeSmartAlbumRecentlyAdded = 206,PHAssetCollectionSubtypeSmartAlbumBursts = 207,PHAssetCollectionSubtypeSmartAlbumSlomoVideos = 208,PHAssetCollectionSubtypeSmartAlbumUserLibrary = 209,PHAssetCollectionSubtypeSmartAlbumSelfPortraits PHOTOS_AVAILABLE_IOS_TVOS(9_0, 10_0) = 210,PHAssetCollectionSubtypeSmartAlbumScreenshots PHOTOS_AVAILABLE_IOS_TVOS(9_0, 10_0) = 211,PHAssetCollectionSubtypeSmartAlbumDepthEffect PHOTOS_AVAILABLE_IOS_TVOS(10_2, 10_1) = 212,PHAssetCollectionSubtypeSmartAlbumLivePhotos PHOTOS_AVAILABLE_IOS_TVOS(10_3, 10_2) = 213,PHAssetCollectionSubtypeSmartAlbumAnimated PHOTOS_AVAILABLE_IOS_TVOS(11_0, 11_0) = 214,PHAssetCollectionSubtypeSmartAlbumLongExposures PHOTOS_AVAILABLE_IOS_TVOS(11_0, 11_0) = 215,// Used for fetching, if you don't care about the exact subtypePHAssetCollectionSubtypeAny = NSIntegerMax
} PHOTOS_ENUM_AVAILABLE_IOS_TVOS(8_0, 10_0);
如果想获取系统创建的相册:
PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
如果想获取用户自定义的相册:
PHFetchResult *albums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
这里PHFetchResult
存储的是相册集合,若要获取每个相册里的每个PHAsset
(图片或视频),则要一一遍历每个相册。以下代码实现了遍历相册里的资源,即图片或视频:
NSMutableArray *picturesInCollection = [NSMutableArray array];NSMutableArray *videosInCollection = [NSMutableArray array];PHFetchOptions *options = [[PHFetchOptions alloc] init];options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];//按日期降序PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:options];[assetsFetchResult enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {if ([obj isKindOfClass:[PHAsset class]]) {PHAsset *asset = (PHAsset *)obj;switch (asset.mediaType) {case PHAssetMediaTypeImage://得到一个图片类型资源break;case PHAssetMediaTypeVideo://得到一个视频类型资源break;default:break;}}}];
遍历iTunes资料库中的视频和音乐
app若想要访问iTunes资料库,同样需要获得用户的授权。开发时,要在info.plist文件内添加以下内容:
<key>NSAppleMusicUsageDescription</key><string>如果不允许,您将无法在XXX中访问媒体资料库</string>
遍历媒体资料库中的音乐,可以获取专辑列表,也可以获取音乐列表,下面获取的是音乐列表,
- (void)browseMPMediaAudio
{NSArray *collections = [[MPMediaQuery songsQuery] collections];NSMutableArray *musics = [NSMutableArray array];for (MPMediaItemCollection *collection in collections){//每个collection是一个专辑,专辑里包含若干个音频for (MPMediaItem *item in [collection items]){//每个item就是一个音频}}
}
媒体资料库也可能存储一些视频,获取方法如下:
- (void)browseMPMediaVideo:(void(^)(NSArray <HLLocalInfo *> *))videoBlock
{MPMediaPropertyPredicate *filterPre = [MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithInt:MPMediaTypeAnyVideo] forProperty:MPMediaItemPropertyMediaType];MPMediaQuery *query = [[MPMediaQuery alloc] init];[query addFilterPredicate:filterPre];NSMutableArray *temp = [NSMutableArray arrayWithCapacity:0];for (MPMediaItem *item in [query items]){//每个item就是一个视频}
}
通过以上的方法,便可以获取到iOS设备内存储的图片、音乐、视频。在获取成功之后,便需要展示这些资源了。
展示图片,播放音频和视频
展示相册里的图片、视频的封面图,需要通过Photos
库提供的方法[PHImageManager defaultManager]
获取,不能根据PHAsset
中的URL直接访问。可以用下面的方法:
PHImageRequestOptions *opt = [[PHImageRequestOptions alloc]init];opt.networkAccessAllowed = YES;opt.resizeMode = PHImageRequestOptionsResizeModeExact;//targetSize可以设置为你想要的大小[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeDefault options:opt resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {//如果没写opt.networkAccessAllowed = YES;,而相册又备份到iCloud上了,这里得到的result可能为nil}];
注意:有些iPhone用户会将相册里的文件备份到iCloud上(可以在“设置”里查看“使用iCloud的应用“,”照片“开关是否打开),这时要想获取图片文件原始数据或播放视频,就需要通过网络从iCloud上拉取,代码里的networkAccessAllowed一定要设置为YES,
若要播放相册里的视频,使用AVPlayer即可,播放之前要先获取视频,networkAccessAllowed
也要设置为YES
PHVideoRequestOptions *option = [[PHVideoRequestOptions alloc] init];option.networkAccessAllowed = YES;option.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {dispatch_async(dispatch_get_main_queue(), ^{if (progressHandler) {progressHandler(progress, error, stop, info);}});};[[PHImageManager defaultManager] requestPlayerItemForVideo:asset options:option resultHandler:^(AVPlayerItem *playerItem, NSDictionary *info) {//获取到的可以用于播放的视频playerItem}];
2.播放媒体库里的视频和音频
播放媒体库的视频和视频,可以通过获取MPMediaItem对象的地址,再用AVPlayer播放
NSString* filePath = [[mediaItem valueForProperty:MPMediaItemPropertyAssetURL] absoluteString];
注意:以上获取资源的过程都应放在子线程操作
二、处理相机拍照所得图片
APP内使用相机,有两种方式,一种时直接调用系统相机视图UIImagePickerController
,优点是使用简单,不用关心图片处理细节,直接在回调方法内取照片即可,缺点是界面单调,图片显示方式单一,通常不能满足项目需求了;第二种是自定义相机,缺点是从界面到获取图片数据都需要自己处理,细节多且复杂,优点是可以最大程度的满足项目的需求,用户体验也比较好。如何实现自定义相机先不说,在这里总结一下遇到的问题:
1.拍照后获取的图片保存后推送到其他设备上被展示时(APP的其中一个功能,可以理解为其他设备用过http请求获取本设备的图片数据并展示),图片被旋转了一定角度;
2.自定义相机拍照,在iOS手机竖向锁定开启和关闭方向下,拍照后在手机上的图片方向显示不一致。
拍照后,可以通过以下方法获取NSData
类型的图片数据(imageData
):
[self.ImageOutPut captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{if (imageDataSampleBuffer == nil) {return;}NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];});}];
如果此时立即将imageData
利用方法imageWithData
转成UIImage
保存到系统相册里,并推送到其他设备上,图片会发生旋转,这时因为:
针对问题1,因在于:相机处于不同方向下,拍摄的图片其方向信息不同,当推送到其他设备时,其他设备按照图片的方向信息,会对图片做出旋转将其方向旋转至0度,这样显示出来的图片就跟拍出来的图片在视觉上不一致。iOS设备拍照后的图片方向(UIImageOrientation)与设备实际方向的关系如下所示,分竖向锁定开启和关闭两种情况。
也就是说,用手机拍照后,我们看到的图片带有一个角度参数,我们要做的是把图片的角度校正至0度,并且校正之后图片在视觉上的方向与拍摄时的看到的图片方向一致。解决了问题1之后,图片的角度被成功的校正至0度了。
但是,这时仍存在一个现象,当竖向锁定开启时,如果当home键在右侧时(即手机屏幕横过来拍),此时拍完照,将home 键旋转至下方的位置,图片没有随着Home键的旋转而旋转,依然保持占满整个屏幕的状态,这不是我们想要的,我们想要看到的是图片随之旋转,手机屏幕上下方留出黑色空白。当竖向锁定关闭时,并没有这个问题。这便是问题2的现象。为了解决这个问题,需要根据拍照时Home键的位置,将图片(此时角度已经是0度)进行旋转。如何判断拍照时Home键的位置。判断出Home键的位置后,图片应旋转的角度请参考上面的表格。
这样拍照图片方向发生旋转的两个问题得以解决了。
以上便是开发过程中的一些总结,可能存在问题,还望批评指正,共同学习~
iOS开发:iPhone设备图片、音乐、视频获取实践相关推荐
- iOS开发------简单实现图片多选功能(Photos.framework篇)
Photos.framework是iOS8后苹果推出的一套替代AssetsLibrary.framework获取相册资源的原生库,至于AL库,欢迎大家给博文iOS开发--简单实现图片多选功能(Asse ...
- 短视频平台开发,将图片、视频保存到本地的相册中
短视频平台开发,将图片.视频保存到本地的相册中实现的相关代码 获取本地相册 - (IBAction)goodsButton1Touch:(id)sender {//拿到获取相册的权限if([UIIma ...
- IOS开发基础之图片轮播器-12
IOS开发基础之图片轮播器-12 核心代码 // // ViewController.m // 12-图片轮播器 // // Created by 鲁军 on 2021/2/2. //#import ...
- iOS开发中,通过URL地址获取网络上的图片
在iOS开发中,我们有时会通过图片的URL地址来获取网上的图片,下面是一个方法实现: /** 通过URL地址从网上获取图片 */ -(UIImage *) getImageFromURL:(NSStr ...
- iOS开发系列-音频、视频以及摄像
--iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制, ...
- IOS 开发 iPhone屏幕尺寸、分辨率及适配
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 1.iPhone尺寸规格 设备 iPhone 宽 Width 高 Height 对角线 Diagonal 逻辑分辨率(point ...
- IOS:批量导入图片和视频到模拟器的相册
批量导入图片和视频到模拟器的相册 IOS开发中我们经常会用到模拟器调试,模拟器有个主要的好处就是程序启动块,最重要的是如果没有证书的话,我们就只能在模拟器上调试了.使用模拟器调试时我们可能碰到需要从系 ...
- iOS开发-------- iPhone X代码适配 (齐刘海处理)
升级了Xcode9,变化很大啊,先说大家一直关心的适配齐刘海吧. 这个东西好像出来之后 我QQ群里面iOS开发的很多人都炸了.确实这个齐刘海对我们开发者很不友好,往上xib的项目适配文章已经有了,但 ...
- iOS开发——仿微信图片浏览交互的实现(向下拖拽图片退出图片浏览器)
点击上方"iOS开发",选择"置顶公众号" 关键时刻,第一时间送达! DEMO的github地址:https://github.com/YYProgrammer ...
最新文章
- “AI”战疫在行动,一文盘点百度大脑增援疫情防控的AI操作
- Ext2.0布局类初探
- Java基础super关键字、final关键字、static关键字、匿名对象整理
- 【转/TCP协议编程】 基于TCP的Socket 编程
- 概述VB.NET正则表达式简化程序代码
- 2020 我的C++学习之路 C++PrimerPlus第十一章课后习题
- ios8 定位问题解决思路
- [2021-09-02 contest]CF1251C,可达性统计(bitset优化dp),Boomerang Tournament(状压dp),小蓝的好友(mrx)(treap平衡树)
- 蓝桥杯基础模块4_3:矩阵按键
- add()方法和Put()方法的差别
- php长链接要配置,PHP链接到配置文件页面。 ?id =
- android设备如何苹果,Android安卓设备如何连接Mac的方法
- 原生js写简单轮播图方式1-从左向右滑动
- SurfaceView 实现 转盘抽奖
- 计算机常见文件后缀名
- flex TLF 文本流编辑器
- Random Walk 随机游走算法
- ArcMap关联图层并发布为服务
- Docker学习三 Docker安装Mysql
- solidworks万向节配合
热门文章
- 电大计算机英语二,2013年考研英语二真题及答案解析.pdf
- 盒子滚动到底部有偏差 js_杭州连廊支座厂家销售,滚动铰支座_衡水安通
- MybatisPlus中queryWrapper的or的使用
- 护网杯2018 easylaravel
- vue css /deep/ 穿透
- (Habitat) A Platform for Embodied AI Research --Facebook开源室内导航仿真平台 的简介和安装
- Unity iOS混合开发
- 英文会议和期刊中引言的研究现状和相关工作中的研究现状有何区别?
- 计算机三级信息安全技术名称的英文缩写(5)
- android launcher folder功能详解