標籤:media ext auth for distance ret rpe determine services
前言上篇文章iOS開發中的這些許可權,你搞懂了嗎?介紹了一些常用許可權的擷取和要求方法,知道這些方法的使用基本上可以搞定大部分應用的許可權訪問的需求。但是,這些方法並不全面,不能涵蓋住所有許可權訪問的方法。So,筆者在介紹一下剩下的幾種許可權的存取方法和一些使用上的注意事項,希望能給大家的開發過程帶來一絲便利。最後,筆者將經常使用的許可權要求方法封裝開源庫JLAuthorizationManager送給大家,歡迎大家pull request 和 star~~許可權語音辨識;媒體資料庫/Apple Music;Siri;健康資料共用;藍芽;住宅許可權(HomeKit);社交帳號體系許可權;活動與體能訓練記錄;廣告標識;語音辨識引入標頭檔: @import Speech;首先判斷當前應用所處的許可權狀態,若目前狀態為NotDetermined(未確定),此時,需要調用系統提供的請求許可權方法,同時也是觸發系統彈窗的所在點;該許可權涉及到的類為 SFSpeechRecognizer,具體代碼如下: - (void)p_requestSpeechRecognizerAccessWithAuthorizedHandler:(void(^)())authorizedHandler unAuthorizedHandler:(void(^)())unAuthorizedHandler{ SFSpeechRecognizerAuthorizationStatus authStatus = [SFSpeechRecognizer authorizationStatus]; if (authStatus == SFSpeechRecognizerAuthorizationStatusNotDetermined) { //調用系統提供的許可權訪問的方法 [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) { if (status == SFSpeechRecognizerAuthorizationStatusAuthorized) { dispatch_async(dispatch_get_main_queue(), ^{ //授權成功後 authorizedHandler ? authorizedHandler() : nil; }); }else{ dispatch_async(dispatch_get_main_queue(), ^{ //授權失敗後 unAuthorizedHandler ? unAuthorizedHandler() : nil; }); } }]; }else if (authStatus == SFSpeechRecognizerAuthorizationStatusAuthorized){ authorizedHandler ? authorizedHandler() : nil; }else{ unAuthorizedHandler ? unAuthorizedHandler() : nil; }}需要注意的是,調用requestAuthorization方法的block回調是在任意的子線程中進行的,如果你需要在授權成功後重新整理UI的話,需要將對應的方法置於主線程中進行,筆者將上述方法預設在主線程中進行。後續許可權要求方法與此類似,不再贅述。在info.plist添加指定的配置資訊,如下所示:Speech Recognizer媒體資料庫/Apple Music匯入標頭檔@import MediaPlayer;使用類MPMediaLibrary進行許可權訪問,代碼如下; - (void)p_requestAppleMusicAccessWithAuthorizedHandler:(void(^)())authorizedHandler unAuthorizedHandler:(void(^)())unAuthorizedHandler{ MPMediaLibraryAuthorizationStatus authStatus = [MPMediaLibrary authorizationStatus]; if (authStatus == MPMediaLibraryAuthorizationStatusNotDetermined) { [MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus status) { if (status == MPMediaLibraryAuthorizationStatusAuthorized) { dispatch_async(dispatch_get_main_queue(), ^{ authorizedHandler ? authorizedHandler() : nil; }); }else{ dispatch_async(dispatch_get_main_queue(), ^{ unAuthorizedHandler ? unAuthorizedHandler() : nil; }); } }]; }else if (authStatus == MPMediaLibraryAuthorizationStatusAuthorized){ authorizedHandler ? authorizedHandler() : nil; }else{ unAuthorizedHandler ? unAuthorizedHandler() : nil; }}在info.plist添加指定的配置資訊,如下所示:MediaSiri匯入標頭檔@import Intents;;與其他許可權不同的時,使用Siri需要在Xcode中Capabilities開啟Siri開關,Xcode會自動產生一個xx.entitlements檔案,若沒有開啟該開關,項目運行時會報錯。實現代碼如下: - (void)p_requestSiriAccessWithAuthorizedHandler:(void(^)())authorizedHandler unAuthorizedHandler:(void(^)())unAuthorizedHandler{ INSiriAuthorizationStatus authStatus = [INPreferences siriAuthorizationStatus]; if (authStatus == INSiriAuthorizationStatusNotDetermined) { [INPreferences requestSiriAuthorization:^(INSiriAuthorizationStatus status) { if (status == INSiriAuthorizationStatusAuthorized) { dispatch_async(dispatch_get_main_queue(), ^{ authorizedHandler ? authorizedHandler() : nil; }); }else{ dispatch_async(dispatch_get_main_queue(), ^{ unAuthorizedHandler ? unAuthorizedHandler() : nil; }); } }]; }else if (authStatus == INSiriAuthorizationStatusAuthorized){ authorizedHandler ? authorizedHandler() : nil; }else{ unAuthorizedHandler ? unAuthorizedHandler() : nil; }}健康資料共用匯入標頭檔@import HealthKit;健康資料共用許可權相對其他許可權相對複雜一些,分為寫入和讀出許可權.在Xcode 8中的info.plist需要設定以下兩種許可權: 1、Privacy - Health Update Usage Description2、Privacy - Health Share Usage Description具體實現代碼: //設定寫入/共用的健康資料類型- (NSSet *)typesToWrite { HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; return [NSSet setWithObjects:stepType,distanceType, nil];}//設定讀寫以下為設定的權限類別型:- (NSSet *)typesToRead { HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; return [NSSet setWithObjects:stepType,distanceType, nil];}//需要確定裝置支援HealthKitif ([HKHealthStore isHealthDataAvailable]) { return; }HKHealthStore *healthStore = [[HKHealthStore alloc] init]; NSSet * typesToShare = [self typesToWrite]; NSSet * typesToRead = [self typesToRead]; [healthStore requestAuthorizationToShareTypes:typesToShare readTypes:typesToRead completion:^(BOOL success, NSError * _Nullable error) { if (success) { dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"Health has authorized!"); }); }else{ dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"Health has not authorized!"); }); } }];藍芽需要匯入標頭檔@import CoreBluetooth;藍芽的許可權檢測相對其他會複雜一些,需要在代理中檢測藍芽狀態;擷取藍芽許可權: - (void)checkBluetoothAccess { CBCentralManager *cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; CBManagerState state = [cbManager state]; if(state == CBManagerStateUnknown) { NSLog(@"Unknown!"); } else if(state == CBManagerStateUnauthorized) { NSLog(@"Unauthorized!"); } else { NSLog(@"Granted!"); }}- (void)centralManagerDidUpdateState:(CBCentralManager *)central {//這個代理方法會在藍芽許可權狀態發生變化時被調用,並且可以根據不同的狀態進行相應的修改UI或者資料訪問的操作。}請求藍芽許可權 - (void)requestBluetoothAccess { CBCentralManager *cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];//該方法會顯示使用者同意的彈窗 [cbManager scanForPeripheralsWithServices:nil options:nil];}住宅許可權(HomeKit)需匯入標頭檔@import HomeKit;HomeKit請求許可權的方法如下: - (void)requestHomeAccess { self.homeManager = [[HMHomeManager alloc] init];//當設定該代理方法後,會請求使用者權限 self.homeManager.delegate = self;}- (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager { if (manager.homes.count > 0) { // home的數量不為空白,即表示使用者權限已通過 } else { __weak HMHomeManager *weakHomeManager = manager; // Prevent memory leak [manager addHomeWithName:@"Test Home" completionHandler:^(HMHome *home, NSError *error) { if (!error) { //許可權允許 } else { if (error.code == HMErrorCodeHomeAccessNotAuthorized) { //許可權不允許 } else { //處理請求產生的錯誤 } } if (home) { [weakHomeManager removeHome:home completionHandler:^(NSError * _Nullable error) { //移除Home }]; } }]; }}社交帳號體系許可權匯入標頭檔@import Accounts;擷取對應的許可權: - (void)checkSocialAccountAuthorizationStatus:(NSString *)accountTypeIndentifier { ACAccountStore *accountStore = [[ACAccountStore alloc] init]; ACAccountType *socialAccount = [accountStore accountTypeWithAccountTypeIdentifier:accountTypeIndentifier]; if ([socialAccount accessGranted]) { NSLog(@"許可權通過了"); }else{ NSLog(@"許可權未通過!"); }}accountTypeIndentifier 可以是以下類型: ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierTwitter NS_AVAILABLE(NA, 5_0);ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierFacebook NS_AVAILABLE(NA, 6_0);ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierSinaWeibo NS_AVAILABLE(NA, 6_0);ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierTencentWeibo NS_AVAILABLE(NA, 7_0);ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierLinkedIn NS_AVAILABLE(NA, NA);請求對應的許可權: - (void)requestTwitterAccess { ACAccountStore *accountStore = [[ACAccountStore alloc] init]; ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:accountTypeIdentifier]; [accountStore requestAccessToAccountsWithType: accountType options:nil completion:^(BOOL granted, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ if(granted){ NSLog(@"授權通過了"); }else{ NSLog(@"授權未通過"); } }); }];}活動與體能訓練記錄匯入標頭檔@import CoreMotion;具體實現代碼: //訪問活動與體能訓練記錄 CMMotionActivityManager *cmManager = [[CMMotionActivityManager alloc] init]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [cmManager startActivityUpdatesToQueue:queue withHandler:^(CMMotionActivity *activity) { //授權成功後,會進入Block方法內,授權失敗不會進入Block方法內 }];廣告標識匯入標頭檔@import AdSupport;擷取廣告標識的許可權狀態: BOOL isAuthorizedForAd = [[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled];在使用advertisingIdentifier屬性前,必須調用上述方法判斷是否支援,如果上述方法傳回值為NO,則advertising ID訪問將會受限。小結一下通過以上兩篇文章的整理,有關iOS系統許可權問題的處理基本上涵蓋完全了;並不是所有的許可權訪問都有顯式的調用方法,有些是在使用過程中進行訪問的,比如定位許可權、藍芽共用許可權、Homekit許可權、活動與體能訓練許可權,這些許可權在使用時注意回調方法中的許可權處理;HomeKit、HealthKit、Siri需要開啟Capabilities中的開關,即產生projectName.entitlements檔案;開源庫JLAuthorizationManager支援整合大部分常用的許可權訪問,便捷使用 welcome to pull request or star;
再續iOS開發中的這些許可權