iOS 权限设置判断和跳转 - 最全最详细
一、权限设置iOS 10以后,苹果增强了对用户隐私的保护,访问照相机、相册、麦克风、定位、通讯录等,都需要在info.plist 文件中添加权限,而且少一个都不行。根据需要添加,项目中使用了什么,就添加对应的权限。权限字段相册使用权限Privacy - Photo Library Usage Description编辑相册权限Privacy - Photo Library Additions Us
一、权限设置
iOS 10以后,苹果增强了对用户隐私的保护,访问照相机、相册、麦克风、定位、通讯录等,都需要在info.plist 文件中添加权限,而且少一个都不行。根据需要添加,项目中使用了什么,就添加对应的权限。
权限 | 字段 |
---|---|
相册使用权限 | Privacy - Photo Library Usage Description |
编辑相册权限 | Privacy - Photo Library Additions Usage Description |
相机权限 | Privacy - Camera Usage Description |
通讯录权限 | Privacy - Contacts Usage Description |
麦克风权限 | Privacy - Microphone Usage Description |
蓝牙权限 | Privacy - Bluetooth Peripheral Usage Description |
定位权限 | Privacy - Location Always Usage Description |
定位权限 | Privacy - Location Usage Description |
定位权限 | Privacy - Location When In Use Usage Description |
定位权限 | Privacy - Location Always and When In Use Usage Description |
媒体库权限 | Privacy - Media Library Usage Description |
日历权限 | Privacy - Calendars Usage Description |
提醒事项权限 | Privacy - Reminders Usage Description |
FaceID权限 | Privacy - Face ID Usage Description |
健康记录权限 | Privacy - Health Records Usage Description |
健康分享权限 | Privacy - Health Share Usage Description |
健康更新权限 | Privacy - Health Update Usage Description |
运动权限 | Privacy - Motion Usage Description |
音乐权限 | Privacy - Music Usage Description |
NFC权限 | Privacy - NFC Scan Usage Description |
Siri权限 | Privacy - Siri Usage Description |
语音识别权限 | Privacy - Speech Recognition Usage Description |
智能家具权限 | Privacy - HomeKit Usage Description |
电视供应商权限 | Privacy - TV Provider Usage Description |
视频用户账号使用权限 | Privacy - Video Subscriber Account Usage Description |
事例:
Privacy - Camera Usage Description
APP需要选择视频进行编辑,请允许访问您的相机
Privacy - Microphone Usage Description
APP需要选择视频进行编辑,请允许访问您的麦克风
Privacy - Photo Library Additions Usage Description
APP需要导出视频到相册,请允许访问您的相册
二、权限判断
在 APP 的开发中,有很多功能是需要用户授权了之后才能使用,这里将常用的权限判断做一下总结。
2.1 网络权限
@import CoreTelephony; //引入头文件
//应用启动后,检测应用中是否有联网权限
CTCellularData *cellularData = [[CTCellularData alloc]init];
cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state){
//获取联网状态
switch (state) {
case kCTCellularDataRestricted:
NSLog(@"Restricrted");
break;
case kCTCellularDataNotRestricted:
NSLog(@"Not Restricted");
break;
case kCTCellularDataRestrictedStateUnknown:
NSLog(@"Unknown");
break;
default:
break;
};
};
//查询应用是否有联网功能
CTCellularData *cellularData = [[CTCellularData alloc]init];
CTCellularDataRestrictedState state = cellularData.restrictedState;
switch (state) {
case kCTCellularDataRestricted:
NSLog(@"Restricrted");
break;
case kCTCellularDataNotRestricted:
NSLog(@"Not Restricted");
break;
case kCTCellularDataRestrictedStateUnknown:
NSLog(@"Unknown");
break;
default:
break;
}
2.2 相册权限( iOS 8.0以上)
@import Photos; 导入头文件
//检查是否有相册权限
PHAuthorizationStatus photoAuthorStatus = [PHPhotoLibrary authorizationStatus];
switch (photoAuthorStatus) {
case PHAuthorizationStatusAuthorized:
NSLog(@"Authorized");
break;
case PHAuthorizationStatusDenied:
NSLog(@"Denied");
break;
case PHAuthorizationStatusNotDetermined:
NSLog(@"not Determined");
break;
case PHAuthorizationStatusRestricted:
NSLog(@"Restricted");
break;
default:
break;
}
//获取相册权限
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status == PHAuthorizationStatusAuthorized) {
NSLog(@"Authorized");
}else{
NSLog(@"Denied or Restricted");
}
}];
2.3 相机和麦克风权限
@import AVFoundation; //导入头文件
//检查是否有相机或麦克风权限
//相机权限
AVAuthorizationStatus AVstatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
//麦克风权限
AVAuthorizationStatus AVstatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
switch (AVstatus) {
case AVAuthorizationStatusAuthorized:
NSLog(@"Authorized");
break;
case AVAuthorizationStatusDenied:
NSLog(@"Denied");
break;
case AVAuthorizationStatusNotDetermined:
NSLog(@"not Determined");
break;
case AVAuthorizationStatusRestricted:
NSLog(@"Restricted");
break;
default:
break;
}
//获取相机或麦克风权限
//相机权限
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (granted) {
NSLog(@"Authorized");
}else{
NSLog(@"Denied or Restricted");
}
}];
//麦克风权限
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
if (granted) {
NSLog(@"Authorized");
}else{
NSLog(@"Denied or Restricted");
}
}];
2.4 定位权限
@import CoreLocation; //导入头文件
//检查定位功能是否可用
BOOL isLocation = [CLLocationManager locationServicesEnabled];
if (!isLocation) {
NSLog(@"not turn on the location");
}
//检查定位权限
CLAuthorizationStatus CLstatus = [CLLocationManager authorizationStatus];
switch (CLstatus) {
case kCLAuthorizationStatusAuthorizedAlways:
NSLog(@"Always Authorized");
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
NSLog(@"AuthorizedWhenInUse");
break;
case kCLAuthorizationStatusDenied:
NSLog(@"Denied");
break;
case kCLAuthorizationStatusNotDetermined:
NSLog(@"not Determined");
break;
case kCLAuthorizationStatusRestricted:
NSLog(@"Restricted");
break;
default:
break;
}
获取定位权限
CLLocationManager *manager = [[CLLocationManager alloc] init];
//一直获取定位信息
[manager requestAlwaysAuthorization];
//使用的时候获取定位信息
[manager requestWhenInUseAuthorization];
//在代理方法中查看权限是否改变
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
switch (status) {
case kCLAuthorizationStatusAuthorizedAlways:
NSLog(@"Always Authorized");
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
NSLog(@"AuthorizedWhenInUse");
break;
case kCLAuthorizationStatusDenied:
NSLog(@"Denied");
break;
case kCLAuthorizationStatusNotDetermined:
NSLog(@"not Determined");
break;
case kCLAuthorizationStatusRestricted:
NSLog(@"Restricted");
break;
default:
break;
}
}
2.5 推送权限
//检查是否有推送权限
UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings];
switch (settings.types) {
case UIUserNotificationTypeNone:
NSLog(@"None");
break;
case UIUserNotificationTypeAlert:
NSLog(@"Alert Notification");
break;
case UIUserNotificationTypeBadge:
NSLog(@"Badge Notification");
break;
case UIUserNotificationTypeSound:
NSLog(@"sound Notification'");
break;
default:
break;
}
//获取推送权限
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:setting];
2.6 通讯录权限 (iOS9.0及以后)
@import Contacts; //导入头文件
//检查是否有通讯录权限
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
switch (status) {
case CNAuthorizationStatusAuthorized:
{
NSLog(@"Authorized:");
}
break;
case CNAuthorizationStatusDenied:{
NSLog(@"Denied");
}
break;
case CNAuthorizationStatusRestricted:{
NSLog(@"Restricted");
}
break;
case CNAuthorizationStatusNotDetermined:{
NSLog(@"NotDetermined");
}
break;
}
//获取通讯录权限
CNContactStore *contactStore = [[CNContactStore alloc] init];
[contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
NSLog(@"Authorized");
}else{
NSLog(@"Denied or Restricted");
}
}];
2.7 日历、备忘录权限
@import EventKit; //导入头文件
typedef NS_ENUM(NSUInteger, EKEntityType) {
EKEntityTypeEvent, //日历
EKEntityTypeReminder //备忘
};
//检查是否有日历或者备忘录权限
EKAuthorizationStatus EKstatus = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
switch (EKstatus) {
case EKAuthorizationStatusAuthorized:
NSLog(@"Authorized");
break;
case EKAuthorizationStatusDenied:
NSLog(@"Denied'");
break;
case EKAuthorizationStatusNotDetermined:
NSLog(@"not Determined");
break;
case EKAuthorizationStatusRestricted:
NSLog(@"Restricted");
break;
default:
break;
}
//获取日历或备忘录权限
EKEventStore *store = [[EKEventStore alloc]init];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
NSLog(@"Authorized");
}else{
NSLog(@"Denied or Restricted");
}
}];
三、跳转到权限设置页面
在 APP 开发中,经常需要使用到一些权限,比如相机、定位、通知等,这些权限都需要用户授权之后,才能进行使用。一般的,当系统第一次需要用到这些功能时,系统会主动弹出授权提示框,询问用户是否同意 APP 使用该功能。如果用户选择了拒绝授权,那么用户就不能使用改功能。那么在用户拒绝授权之后,如何重新去授权使用该功能呢?通常有两种做法:
- 不做跳转,只弹出提示框,告知用户去 “设置 > 隐私 > 相机” 开启使用相机功能;
- 弹框提示,并跳转到设置的子界面;
方案一是苹果推荐的方法,因为苹果不建议开发者直接跳转到设置的子界面,并且苹果将跳转到设置子界面的一些 API 改成了私有的 API,所以方案二其实上架是有被拒的风险,但是从用户体验来讲,方案二显然更友好,所以开发者自己决定用哪种方案去实现吧,下面直接介绍方案二的实现代码。
// iOS 8.1 ~ iOS 14
- (void)pushSettingController {
NSURL *url1 = [NSURL URLWithString:@"App-Prefs:root=NOTIFICATIONS_ID"];
NSURL *url2 = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if (@available(iOS 11.0, *)) {
if ([[UIApplication sharedApplication] canOpenURL:url2]){
[[UIApplication sharedApplication] openURL:url2 options:@{} completionHandler:nil];
}
} else {
if ([[UIApplication sharedApplication] canOpenURL:url1]){
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:url1 options:@{} completionHandler:nil];
} else {
[[UIApplication sharedApplication] openURL:url1];
}
}
}
}
附:设置页面对应的字符串
页面名称 | 对应字符串 |
---|---|
照片与相机 | App-Prefs:root=Photos |
隐私->麦克风 | App-Prefs:root=Privacy&path=MICROPHONE |
隐私->定位 | App-Prefs:root=Privacy&path=LOCATION |
隐私->相机 | App-Prefs:root=Privacy&path=CAMERA |
个人热点 | App-Prefs:root=INTERNET_TETHERING |
运营商 | App-Prefs:root=Carrier |
无线局域网 | App-Prefs:root=WIFI |
蜂窝移动网络 | App-Prefs:root=MOBILE_DATA_SETTINGS_ID |
蓝牙 | App-Prefs:root=Bluetooth |
通知 | App-Prefs:root=NOTIFICATIONS_ID |
页面名称 | 对应字符串 |
---|---|
通用 | App-Prefs:root=General |
通用-关于本机 | App-Prefs:root=General&path=About |
通用-键盘 | App-Prefs:root=General&path=Keyboard |
通用-辅助功能 | App-Prefs:root=General&path=ACCESSIBILITY |
通用-语言与地区 | App-Prefs:root=General&path=INTERNATIONAL |
通用-还原 | App-Prefs:root=Reset |
墙纸 | App-Prefs:root=Wallpaper |
Siri | App-Prefs:root=SIRI |
隐私 | App-Prefs:root=Privacy |
Safari | App-Prefs:root=SAFARI |
音乐 | App-Prefs:root=MUSIC |
音乐-均衡器 | App-Prefs:root=MUSIC&path=com.apple.Music:EQ |
FaceTime | App-Prefs:root=FACETIME |
四、打开任意APP设置页面
采用逆向开发的手段,通过Hook可以实现跳转到任意APP的设置页面。
#import <Foundation/Foundation.h>
@interface LSApplicationWorkspaceHook : NSObject
+ (instancetype)defaultWorkspace;
- (void)openURL:(NSURL *)url;
- (void)openWeChat;
@end
#import "LSApplicationWorkspaceHook.h"
@implementation LSApplicationWorkspaceHook
-(void)openWeChat {
// 调用 LSApplicationWorkspace 的单例方法
Class aClass = NSClassFromString(@"LSApplicationWorkspace");
LSApplicationWorkspaceHook *hook = [aClass defaultWorkspace];
// 调用 LSApplicationWorkspace 的 `openURL:` 方法
[hook openURL:[NSURL URLWithString:@"app-prefs:com.tencent.xin"]];
}
@end
调用打开微信设置页面:
[[LSApplicationWorkspaceHook alloc] openWeChat];
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)