iOS 相冊、相機、通訊錄 錄音權限獲取封裝

在開發中,我們可能會遇到這樣的情況,用戶自己關閉了所有的操作權限,以后要使用我們的App,總是得不到想要的結果。這個時候,對用戶操作權限的獲取,并進行必要的提示就必不可少了。

84B2A9705B046412E1D8F9591830C8FB.png

蘋果對用戶權限邏輯的修改

在iOS10中,如果你的App想要訪問用戶的相機、相冊、麥克風、通訊錄等等權限,都需要進行相關的配置,不然會直接crash(閃退)。
需要在info.plist中添加App需要的一些設備權限。

    <key>NSCalendarsUsageDescription</key>
    <string>訪問日歷</string>
    <key>NSCameraUsageDescription</key>
    <string>訪問相機</string>
    <key>NSContactsUsageDescription</key>
    <string>訪問聯系人</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>我們需要通過您的地理位置信息獲取您周邊的相關數據,提供精準服務</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>我們需要通過您的地理位置信息獲取您周邊的相關數據,提供精準服務</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>訪問麥克風</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>訪問相冊</string>

那么在這種情況下,就需要對用戶權限的獲取狀態和邏輯進行修改。下邊是我對整個App用戶請求權限的封裝。代碼還是很簡單的。

用戶權限狀態的幾種枚舉類型

AuthorizationStatusNotDetermined      // 用戶從未進行過授權等處理,首次訪問相應內容會提示用戶進行授權
 AuthorizationStatusAuthorized = 0,    // 用戶已授權,允許訪問
 AuthorizationStatusDenied,            // 用戶拒絕訪問
 AuthorizationStatusRestricted,        // 應用沒有相關權限,且當前用戶無法改變這個權限,比如:家長控制

常見的幾種可以獲取系統權限的對象


typedef NS_ENUM(NSInteger, KSystemPermissions) {
  
  KAVMediaTypeVideo = 0,  // 相機
  KALAssetsLibrary,       //相冊
  KCLLocationManager,     //地理位置信息
  KAVAudioSession,        //音頻
  KABAddressBook          //手機通訊錄
};

大致的思路就是根據 傳入的需要獲取權限的對象, 彈出響應的提示語,讓用戶根據需要決定是否去設置中開啟相應的權限。
由于代碼比較簡單,這里就大致提一下,具體可以將Demo 下載下來。

我寫的Demo地址: SystemAuthorizationManager。稍后會使用pods的形式,集成到工程中。

//
//  SystemPermissionsManager.h
//  SystemPermissionsManager
//
//  Created by Kenvin on 2016/11/24.
//  Copyright ? 2016年 上海方創金融股份信息服務有限公司. All rights reserved.
//

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, KSystemPermissions) {
    
    KAVMediaTypeVideo = 0,  // 相機
    KALAssetsLibrary,       //相冊
    KCLLocationManager,     //地理位置信息
    KAVAudioSession,        //音頻
    KABAddressBook          //手機通訊錄
};

@interface SystemPermissionsManager : NSObject

+ (instancetype)sharedManager ;

/**
 *  根據場景選擇合適的提示系統權限類型
 *
 *  @param systemPermissions 系統權限類型
 *
 *  @return 是否具有權限
 */
- (BOOL)requestAuthorization:(KSystemPermissions)systemPermissions;
@end

//
//  SystemPermissionsManager.m
//  SystemPermissionsManager
//
//  Created by Kenvin on 2016/11/24.
//  Copyright ? 2016年 上海方創金融股份信息服務有限公司. All rights reserved.
//


#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "SystemPermissionsManager.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <CoreLocation/CoreLocation.h>
#import <Photos/Photos.h>
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#import <ContactsUI/ContactsUI.h>
#import "BlockAlertView.h"

static NSString *const APPNAME = @"";  //填寫自己APP NAME

static SystemPermissionsManager *systemPermissionsManager = nil;

@interface SystemPermissionsManager ()<CLLocationManagerDelegate,UIAlertViewDelegate>

@property(nonatomic,strong) CLLocationManager *locationManager;


@end

@implementation SystemPermissionsManager

+ (instancetype)sharedManager {
    static dispatch_once_t onceToken = 0;
    dispatch_once(&onceToken, ^{
        systemPermissionsManager = [[SystemPermissionsManager alloc] init];
    });
    return systemPermissionsManager;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        systemPermissionsManager = [super allocWithZone:zone];
    });
    return systemPermissionsManager;
}

- (id)init {
    self = [super init];
    if (self) {
        //如果不需要定位的話,請刪除與定位相關的代碼即可。
        [self setup];
    }
    return self;
}

- (void)setup {
    //定位
    _locationManager = [[CLLocationManager alloc] init];
    _locationManager.delegate = self;
    _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    _locationManager.distanceFilter = 1.0;
    if([_locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [_locationManager requestAlwaysAuthorization]; // 永久授權
    }
    
    
    if ([CLLocationManager locationServicesEnabled]) {
        if ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 8.0) {
            [_locationManager requestAlwaysAuthorization];
        }
        CLAuthorizationStatus status = CLLocationManager.authorizationStatus;
        if (status == kCLAuthorizationStatusRestricted || status == kCLAuthorizationStatusDenied) {
            
        }else{
            
        }
    }else{
        
    }
    
}


-(id)copyWithZone:(struct _NSZone *)zone{
    return systemPermissionsManager;
}

- (BOOL)requestAuthorization:(KSystemPermissions)systemPermissions{
    switch (systemPermissions) {
        case KAVMediaTypeVideo:{
            if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
                NSString *mediaType = AVMediaTypeVideo;
                AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
                if(authStatus == ALAuthorizationStatusDenied){
                    
                    NSString *tips = [NSString stringWithFormat:@"請在iPhone的”設置-隱私-相機“選項中,允許%@訪問你的手機相機",APPNAME];
                    [self executeAlterTips:tips isSupport:YES];
                    return NO;
                }else if(authStatus == ALAuthorizationStatusRestricted ){
                    [self executeAlterTips:nil isSupport:NO];
                    return NO;
                }else if(authStatus == ALAuthorizationStatusNotDetermined ){
                    [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                        if (granted) {
                            
                        }else{
                            
                        }
                    }];
                }
            }
        }
            break;
        case KALAssetsLibrary:{
            
            if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
                if ([UIDevice currentDevice].systemVersion.floatValue < 8.0) {
                    ALAuthorizationStatus authStatus = [ALAssetsLibrary authorizationStatus];
                    if ( authStatus ==ALAuthorizationStatusDenied){
                        //無權限
                        NSString *tips = [NSString stringWithFormat:@"請在iPhone的”設置-隱私-相冊“選項中,允許%@訪問你的手機相冊",APPNAME];
                        [self executeAlterTips:tips isSupport:YES];
                        return NO;
                    }else if (authStatus == ALAuthorizationStatusRestricted){
                        [self executeAlterTips:nil isSupport:NO];
                        return NO;
                    }
                }else{
                    
                    PHAuthorizationStatus  authorizationStatus = [PHPhotoLibrary   authorizationStatus];
                    if (authorizationStatus == PHAuthorizationStatusRestricted) {
                        [self executeAlterTips:nil isSupport:NO];
                        return NO;
                    }else if(authorizationStatus == PHAuthorizationStatusDenied){
                        
                        NSString *tips = [NSString stringWithFormat:@"請在iPhone的”設置-隱私-相冊“選項中,允許%@訪問你的手機相冊",APPNAME];
                        [self executeAlterTips:tips isSupport:YES];
                        return NO;
                    }else if (authorizationStatus == PHAuthorizationStatusNotDetermined){
                        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                            
                        }];
                    }
                    
                }
                
            }
            
        }
            break;
        case KCLLocationManager:{
            CLAuthorizationStatus authStatus = CLLocationManager.authorizationStatus;
            if ( authStatus == kCLAuthorizationStatusDenied) {
                NSString *tips = [NSString stringWithFormat:@"請在iPhone的”設置-隱私-定位“選項中,允許%@訪問你的定位",APPNAME];
                [self executeAlterTips:tips isSupport:YES];
                return NO;
            }else if(authStatus == kCLAuthorizationStatusRestricted ){
                [self executeAlterTips:nil isSupport:NO];
                return NO;
            }
        }
            break;
        case KAVAudioSession:{
            if (![self canRecord]) {
                NSString *tips = [NSString stringWithFormat:@"請在iPhone的”設置-隱私-麥克風“選項中,允許%@訪問你的麥克風",APPNAME];
                [self executeAlterTips:tips isSupport:YES];
                return NO;
            }
        }
            break;
        case KABAddressBook:{
            ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();
            NSString *tips = [NSString stringWithFormat:@"請在iPhone的”設置-隱私-聯系人“選項中,允許%@訪問你的手機通訊錄",APPNAME];
            
            if ( authStatus ==kABAuthorizationStatusDenied){
                //無權限
                [self executeAlterTips:tips isSupport:YES];
                return NO;
            }else if (authStatus == kABAuthorizationStatusRestricted ){
                [self executeAlterTips:nil isSupport:NO];
                return NO;
            }else if(authStatus == kABAuthorizationStatusNotDetermined){
                __block ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
                
                if (addressBook == NULL) {
                    
                    [self executeAlterTips:nil isSupport:NO];
                    return NO;
                }
                ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
                    
                    if (granted) {
                        
                    }else{
                        
                    }
                    
                    if (addressBook) {
                        CFRelease(addressBook);
                        addressBook = NULL;
                    }
                });
                
            }
        }
            break;
        default:
            break;
    }
    
    return YES;
}


- (BOOL)canRecord{
    
    __block BOOL bCanRecord = YES;
    if ([[UIDevice currentDevice] systemVersion].floatValue > 7.0){
        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        if ([audioSession respondsToSelector:@selector(requestRecordPermission:)]) {
            [audioSession performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted) {
                if (granted) {
                    bCanRecord = YES;
                } else {
                    bCanRecord = NO;
                }
            }];
        }
    }
    
    return bCanRecord;
}


- (void)executeAlterTips:(NSString *)alterTips isSupport:(BOOL)isSupport{
    
    dispatch_async(dispatch_get_main_queue(), ^{
        NSString *alterContent = @"";
        if (isSupport) {
            alterContent = alterTips;
            [BlockAlertView alertWithTitle:alterContent
                                   message:@""
                     cancelButtonWithTitle:@"取消"
                               cancelBlock:^{
                                   
                               } confirmButtonWithTitle:@"去設置" confrimBlock:^{
                                   [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]
                                                                      options:@{@"url":@""}
                                                            completionHandler:^(BOOL success) {
                                                                
                                                            }];
                               }];
        }else{
            alterContent = @"權限受限";
            [BlockAlertView alertWithTitle:alterContent
                                   message:@""
                     cancelButtonWithTitle:nil
                               cancelBlock:^{
                                   
                               } confirmButtonWithTitle:@"確定"
                              confrimBlock:^{
                                  
                              }];
        }
        
    });
}

@end

#pragma clang diagnostic pop

如何使用,方法如下

    [[SystemPermissionsManager sharedManager] requestAuthorization:KALAssetsLibrary];

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,536評論 25 708
  • 一、為什么要獲取權限 在越來越注重個人隱私的今天,用戶很多情況下希望自己能完全掌握自己手機應用對媒體信息的一些訪問...
    wentianen閱讀 14,949評論 1 23
  • 1.圖層樹 :Core Animation是一個復合引擎,它的職責就是盡可能快地組合屏幕上不同的可視內容,這個內容...
    passionCai閱讀 128評論 0 0
  • 第一天我大概就要入坑了吧。 有喜歡讀書的人喜歡書法的人喜歡音樂的人喜歡古風的人。 不論在哪一方面我都算不上專業但是...
    陌上人如玉l閱讀 143評論 0 0
  • 十、出井入合 六十五難曰∶經言所出為井,所入為合,其法奈何?然所出為井,井者東方春也,萬物之始生,故言所出為井也。...
    妙瑜的記事本閱讀 736評論 0 0