2014年4月2日

在iOS應用程式中偵測與請求隱私設定

在開發iOS應用程式中,依據不同的應用程式需求,我們很有可能需要存取使用者的相簿、通訊錄,甚至是要求使用相機、麥克風等設備。然而,iOS系統是非常注重個人隱私的,因此,如何能讓iOS應用程式存取使用者的資料,又能保護使用者的隱私,變成了一個重要的課題。
iOS保護使用者資訊的方式是: 在iOS的設定中,有一項關於隱私的設定。
當任何iOS應用程式第一次執行到需要存取使用者資訊或是使用設備的情況,則iOS系統會自動彈出是否允許的確認視窗,請求使用者允許。

若使用者選擇不允許,則相關程式會回報無法存取的錯誤。而無論使用者選擇允許或不允許,此應用程式皆會出現在設定中。讓使用者再往後得以修改。
存取地理位置
存取地理位置使用CLLocationManager物件,範例如下:

檢查存取地理位置權限

CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if(status == kCLAuthorizationStatusNotDetermined) {
    //UNDETERMINED
}
else if(status == kCLAuthorizationStatusRestricted) {
    //RESTRICTED
}
else if(status == kCLAuthorizationStatusDenied) {
    //DENIED
}
else if(status == kCLAuthorizationStatusAuthorized) {
    //GRANTED
}

請求存取地理位置權限

建立CLLocationManager物件後,當需要存取地理位置時,系統即會彈出對話視窗,請求使用者允許存取地理位置:
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];

[locationManager startUpdatingLocation];
其中CLLocationManager物件需要一個實作CLLocationMangerDelegate的delegate物件,處理地理位置更新時的資訊。此外,使用者在設定中修改了存取地理位置的權限時,CLLocationMangerDelegate的didChangeAuthorizationStatus也會被呼叫:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    if(status == kCLAuthorizationStatusNotDetermined) {
        //UNDETERMINED
    }
    else if(status == kCLAuthorizationStatusRestricted) {
        //RESTRICTED
    }
    else if(status == kCLAuthorizationStatusDenied) {
        //DENIED
    }
    else if(status == kCLAuthorizationStatusAuthorized) {
        //GRANTED
    }
}

存取相簿

這邊要注意的是:若使用者在設定中,更改了某個App存取相簿的權限,則當使用者再次回到該App時,該App會重新啟動。因為相簿存取的API中,並沒有動態偵測使用者改變存取權限的機制。

檢查存取相簿權限

ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];

if(status == ALAuthorizationStatusNotDetermined) {
    //UNDETERMINED
}
else if(status == ALAuthorizationStatusRestricted) {
    //RESTRICTED
}
else if(status == ALAuthorizationStatusDenied) {
    //DENIED
}
else if(status == ALAuthorizationStatusAuthorized) {
    //GRANTED
}

請求存取相簿權限:使用UIImagePickerController

使用UIImagePickerController存取相簿時,系統會在第一次執行時彈出請求允許存取權限的視窗;若先前使用者已曾經按下拒絕,則系統會自動產生一個提示畫面,告知使用者此存取已經被拒絕。
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    [picker setDelegate:self];
    [self presentViewController:picker animated:YES completion:nil];
    picker = nil;

請求存取相簿權限:使用ALAssetsLibrary

若是使用ALAssetsLibrary存取相簿時,系統會在第一次執行時彈出請求允許存取權限的視窗;;若先前使用者已曾經按下拒絕,則failureBlock的區塊將會被執行。
ALAssetsLibrary* assetLibrary = [[ALAssetsLibrary alloc] init];

    [assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll 
        usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
            //SUCCESS
        } failureBlock:^(NSError *error) {
            //FAILED    
    }];

存取麥克風

這邊要注意的也是:當使用者在設定中,更改了某個App存取麥克風的權限時,此App也會重新啟動。
AVAudioSession *session = [[AVAudioSession alloc] init];
[session requestRecordPermission:^(BOOL granted) {
    if(granted) {
        //允許        
        NSError *error;
        [session setCategory:@"AVAudioSessionCategoryPlayAndRecord" error:&error];
    }
    else {
        //不允許
    }
}];

結語

撰寫iOS應用程式時,若能善用使用者資料以及一些周邊裝置,可以使App功能更為豐富、更讓人驚艷;但這同時也是一把雙面刃: 因為這些行為都可能牽涉到使用者的隱私。iOS系統提供許多機制,讓使用者的隱私有了一層基本的保障, 而iOS應用程式開發者也應了解如何處理及請求各種不同的隱私設定。

此外,了解如何使用與使用者隱私處理相關的API固然重要,但這並不代表使用者的隱私已經受到全然的保障,iOS應用程式開發者也更應謹慎思考如何維護使用者的隱私, 讓使用者更能安心的使用你的應用程式。