Commit c7f449cf authored by yuzheng.tz's avatar yuzheng.tz

优化相机调用前的权限检查,防止第一次请求权限用户拒绝时的相机黑屏

parent a68f8488
......@@ -40,6 +40,7 @@
/// Return YES if Authorized 返回YES如果得到了授权
- (BOOL)authorizationStatusAuthorized;
+ (NSInteger)authorizationStatus;
- (void)requestAuthorizationWithCompletion:(void (^)())completion;
/// Get Album 获得相册/相册数组
- (void)getCameraRollAlbum:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAlbumModel *model))completion;
......
......@@ -32,7 +32,7 @@ static CGFloat TZScreenScale;
// manager.cachingImageManager = [[PHCachingImageManager alloc] init];
// manager.cachingImageManager.allowsCachingHighQualityImages = YES;
}
TZScreenWidth = [UIScreen mainScreen].bounds.size.width;
// 测试发现,如果scale在plus真机上取到3.0,内存会增大特别多。故这里写死成2.0
TZScreenScale = 2.0;
......@@ -62,7 +62,7 @@ static CGFloat TZScreenScale;
/**
* 当某些情况下AuthorizationStatus == AuthorizationStatusNotDetermined时,无法弹出系统首次使用的授权alertView,系统应用设置里亦没有相册的设置,此时将无法使用,故作以下操作,弹出系统首次使用的授权alertView
*/
[self requestAuthorizationWhenNotDetermined];
[self requestAuthorizationWithCompletion:nil];
}
return status == 3;
......@@ -77,18 +77,27 @@ static CGFloat TZScreenScale;
return NO;
}
//AuthorizationStatus == AuthorizationStatusNotDetermined 时询问授权弹出系统授权alertView
- (void)requestAuthorizationWhenNotDetermined {
- (void)requestAuthorizationWithCompletion:(void (^)())completion {
void (^callCompletionBlock)() = ^(){
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion();
}
});
};
if (iOS8Later) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
});
callCompletionBlock();
}];
});
} else {
[self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
} failureBlock:nil];
callCompletionBlock();
} failureBlock:^(NSError *error) {
callCompletionBlock();
}];
}
}
......@@ -667,21 +676,21 @@ static CGFloat TZScreenScale;
// Begin to export video to the output path asynchronously.
[session exportAsynchronouslyWithCompletionHandler:^(void) {
switch (session.status) {
case AVAssetExportSessionStatusUnknown:
case AVAssetExportSessionStatusUnknown:
NSLog(@"AVAssetExportSessionStatusUnknown"); break;
case AVAssetExportSessionStatusWaiting:
case AVAssetExportSessionStatusWaiting:
NSLog(@"AVAssetExportSessionStatusWaiting"); break;
case AVAssetExportSessionStatusExporting:
case AVAssetExportSessionStatusExporting:
NSLog(@"AVAssetExportSessionStatusExporting"); break;
case AVAssetExportSessionStatusCompleted: {
NSLog(@"AVAssetExportSessionStatusCompleted");
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion(outputPath);
}
});
} break;
case AVAssetExportSessionStatusFailed:
case AVAssetExportSessionStatusCompleted: {
NSLog(@"AVAssetExportSessionStatusCompleted");
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion(outputPath);
}
});
} break;
case AVAssetExportSessionStatusFailed:
NSLog(@"AVAssetExportSessionStatusFailed"); break;
default: break;
}
......@@ -854,27 +863,27 @@ static CGFloat TZScreenScale;
// No-op if the orientation is already correct
if (aImage.imageOrientation == UIImageOrientationUp)
return aImage;
return aImage;
// We need to calculate the proper transformation to make the image upright.
// We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
CGAffineTransform transform = CGAffineTransformIdentity;
switch (aImage.imageOrientation) {
case UIImageOrientationDown:
case UIImageOrientationDownMirrored:
case UIImageOrientationDown:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
transform = CGAffineTransformRotate(transform, M_PI_2);
break;
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
......@@ -883,14 +892,14 @@ static CGFloat TZScreenScale;
}
switch (aImage.imageOrientation) {
case UIImageOrientationUpMirrored:
case UIImageOrientationDownMirrored:
case UIImageOrientationUpMirrored:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
case UIImageOrientationLeftMirrored:
case UIImageOrientationRightMirrored:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
......@@ -906,10 +915,10 @@ static CGFloat TZScreenScale;
CGImageGetBitmapInfo(aImage.CGImage));
CGContextConcatCTM(ctx, transform);
switch (aImage.imageOrientation) {
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
// Grr...
CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
break;
......
......@@ -112,7 +112,7 @@ static CGSize AssetGridThumbnailSize;
- (void)configCollectionView {
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
CGFloat margin = 5;
CGFloat itemWH = (self.view.tz_width - (self.columnNumber + 1) * margin) / self.columnNumber;
......@@ -131,7 +131,7 @@ static CGSize AssetGridThumbnailSize;
if (iOS7Later) navigationHeight += 20;
collectionViewHeight = tzImagePickerVc.showSelectBtn ? self.view.tz_height - 50 - navigationHeight : self.view.tz_height - navigationHeight;
}
_collectionView = [[TZCollectionView alloc] initWithFrame:CGRectMake(0, top, self.view.tz_width, collectionViewHeight) collectionViewLayout:layout];
_collectionView.backgroundColor = [UIColor whiteColor];
_collectionView.dataSource = self;
......@@ -252,7 +252,7 @@ static CGSize AssetGridThumbnailSize;
CGFloat rgb2 = 222 / 255.0;
divide.backgroundColor = [UIColor colorWithRed:rgb2 green:rgb2 blue:rgb2 alpha:1.0];
divide.frame = CGRectMake(0, 0, self.view.tz_width, 1);
[bottomToolBar addSubview:divide];
[bottomToolBar addSubview:_previewButton];
[bottomToolBar addSubview:_doneButton];
......@@ -304,7 +304,7 @@ static CGSize AssetGridThumbnailSize;
}
if (info) [infoArr replaceObjectAtIndex:i withObject:info];
[assets replaceObjectAtIndex:i withObject:model.asset];
for (id item in photos) { if ([item isKindOfClass:[NSNumber class]]) return; }
if (havenotShowAlert) {
......@@ -473,6 +473,7 @@ static CGSize AssetGridThumbnailSize;
#pragma mark - Private Method
/// 拍照按钮点击事件
- (void)takePhoto {
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if ((authStatus == AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied) && iOS7Later) {
......@@ -482,17 +483,35 @@ static CGSize AssetGridThumbnailSize;
NSString *message = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\""],appName];
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:[NSBundle tz_localizedStringForKey:@"Can not use camera"] message:message delegate:self cancelButtonTitle:[NSBundle tz_localizedStringForKey:@"Cancel"] otherButtonTitles:[NSBundle tz_localizedStringForKey:@"Setting"], nil];
[alert show];
} else { // 调用相机
UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
self.imagePickerVc.sourceType = sourceType;
if(iOS8Later) {
_imagePickerVc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
[self presentViewController:_imagePickerVc animated:YES completion:nil];
} else if (authStatus == AVAuthorizationStatusNotDetermined) {
// fix issue 466, 防止用户首次拍照拒绝授权时相机页黑屏
if (iOS7Later) {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (granted) {
dispatch_sync(dispatch_get_main_queue(), ^{
[self pushImagePickerController];
});
}
}];
} else {
NSLog(@"模拟器中无法打开照相机,请在真机中使用");
[self pushImagePickerController];
}
} else {
[self pushImagePickerController];
}
}
// 调用相机
- (void)pushImagePickerController {
UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
self.imagePickerVc.sourceType = sourceType;
if(iOS8Later) {
_imagePickerVc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
[self presentViewController:_imagePickerVc animated:YES completion:nil];
} else {
NSLog(@"模拟器中无法打开照相机,请在真机中使用");
}
}
......@@ -709,13 +728,13 @@ static CGSize AssetGridThumbnailSize;
// Update the assets the PHCachingImageManager is caching.
[[TZImageManager manager].cachingImageManager startCachingImagesForAssets:assetsToStartCaching
targetSize:AssetGridThumbnailSize
contentMode:PHImageContentModeAspectFill
options:nil];
targetSize:AssetGridThumbnailSize
contentMode:PHImageContentModeAspectFill
options:nil];
[[TZImageManager manager].cachingImageManager stopCachingImagesForAssets:assetsToStopCaching
targetSize:AssetGridThumbnailSize
contentMode:PHImageContentModeAspectFill
options:nil];
targetSize:AssetGridThumbnailSize
contentMode:PHImageContentModeAspectFill
options:nil];
// Store the preheat rect to compare against in the future.
self.previousPreheatRect = preheatRect;
......
......@@ -22,7 +22,7 @@
NSMutableArray *_selectedPhotos;
NSMutableArray *_selectedAssets;
BOOL _isSelectOriginalPhoto;
CGFloat _itemWH;
CGFloat _margin;
}
......@@ -132,7 +132,7 @@
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"拍照",@"去相册选择", nil];
[sheet showInView:self.view];
} else {
[self pushImagePickerController];
[self pushTZImagePickerController];
}
} else { // preview photos or video / 预览照片或者视频
id asset = _selectedAssets[indexPath.row];
......@@ -196,16 +196,16 @@
#pragma mark - TZImagePickerController
- (void)pushImagePickerController {
- (void)pushTZImagePickerController {
if (self.maxCountTF.text.integerValue <= 0) {
return;
}
TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:self.maxCountTF.text.integerValue columnNumber:self.columnNumberTF.text.integerValue delegate:self pushPhotoPickerVc:YES];
#pragma mark - 四类个性化设置,这些参数都可以不传,此时会走默认设置
imagePickerVc.isSelectOriginalPhoto = _isSelectOriginalPhoto;
if (self.maxCountTF.text.integerValue > 1) {
// 1.设置目前已经选中的图片数组
imagePickerVc.selectedAssets = _selectedAssets; // 目前已经选中的图片数组
......@@ -242,11 +242,11 @@
imagePickerVc.needCircleCrop = self.needCircleCropSwitch.isOn;
imagePickerVc.circleCropRadius = 100;
/*
[imagePickerVc setCropViewSettingBlock:^(UIView *cropView) {
cropView.layer.borderColor = [UIColor redColor].CGColor;
cropView.layer.borderWidth = 2.0;
}];*/
[imagePickerVc setCropViewSettingBlock:^(UIView *cropView) {
cropView.layer.borderColor = [UIColor redColor].CGColor;
cropView.layer.borderWidth = 2.0;
}];*/
//imagePickerVc.allowPreview = NO;
#pragma mark - 到这里为止
......@@ -267,26 +267,44 @@
// 无相机权限 做一个友好的提示
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法使用相机" message:@"请在iPhone的""设置-隐私-相机""中允许访问相机" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
[alert show];
} else if (authStatus == AVAuthorizationStatusNotDetermined) {
// fix issue 466, 防止用户首次拍照拒绝授权时相机页黑屏
if (iOS7Later) {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (granted) {
dispatch_sync(dispatch_get_main_queue(), ^{
[self takePhoto];
});
}
}];
} else {
[self takePhoto];
}
// 拍照之前还需要检查相册权限
} else if ([TZImageManager authorizationStatus] == 2) { // 已被拒绝,没有相册权限,将无法保存拍的照片
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法访问相册" message:@"请在iPhone的""设置-隐私-相册""中允许访问相册" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
alert.tag = 1;
[alert show];
} else if ([TZImageManager authorizationStatus] == 0) { // 正在弹框询问用户是否允许访问相册,监听权限状态
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
return [self takePhoto];
});
} else { // 调用相机
UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
self.imagePickerVc.sourceType = sourceType;
if(iOS8Later) {
_imagePickerVc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
[self presentViewController:_imagePickerVc animated:YES completion:nil];
} else {
NSLog(@"模拟器中无法打开照相机,请在真机中使用");
} else if ([TZImageManager authorizationStatus] == 0) { // 未请求过相册权限
[[TZImageManager manager] requestAuthorizationWithCompletion:^{
[self takePhoto];
}];
} else {
[self pushImagePickerController];
}
}
// 调用相机
- (void)pushImagePickerController {
UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
self.imagePickerVc.sourceType = sourceType;
if(iOS8Later) {
_imagePickerVc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
[self presentViewController:_imagePickerVc animated:YES completion:nil];
} else {
NSLog(@"模拟器中无法打开照相机,请在真机中使用");
}
}
......@@ -346,7 +364,7 @@
if (buttonIndex == 0) { // take photo / 去拍照
[self takePhoto];
} else if (buttonIndex == 1) {
[self pushImagePickerController];
[self pushTZImagePickerController];
}
}
......@@ -379,7 +397,7 @@
/// 用户点击了取消
- (void)tz_imagePickerControllerDidCancel:(TZImagePickerController *)picker {
// NSLog(@"cancel");
}
}
// The picker should dismiss itself; when it dismissed these handle will be called.
// If isOriginalPhoto is YES, user picked the original photo.
......@@ -409,13 +427,13 @@
_selectedAssets = [NSMutableArray arrayWithArray:@[asset]];
// open this code to send video / 打开这段代码发送视频
// [[TZImageManager manager] getVideoOutputPathWithAsset:asset completion:^(NSString *outputPath) {
// NSLog(@"视频导出到本地完成,沙盒路径为:%@",outputPath);
// Export completed, send video here, send by outputPath or NSData
// 导出完成,在这里写上传代码,通过路径或者通过NSData上传
// NSLog(@"视频导出到本地完成,沙盒路径为:%@",outputPath);
// Export completed, send video here, send by outputPath or NSData
// 导出完成,在这里写上传代码,通过路径或者通过NSData上传
// }];
[_collectionView reloadData];
// _collectionView.contentSize = CGSizeMake(0, ((_selectedPhotos.count + 2) / 3 ) * (_margin + _itemWH));
// _collectionView.contentSize = CGSizeMake(0, ((_selectedPhotos.count + 2) / 3 ) * (_margin + _itemWH));
}
// If user picking a gif image, this callback will be called.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment