NR - iOS / Android 相机/相册/日历/定位 等权限 检测+申请代码
文章目录
- 两端获取权限的区别
- Android端
- iOS
- iOS 桥接文件
- 使用
RN工程做个权限列表开关
相机
相册
日历
定位
…
两端获取权限的区别
android 调用申请权限,系统会呈现两个还是三个系统弹窗, 直到你同意或拒绝后,选择不在提示,
iOS端,调用申请权限,系统弹窗仅会弹出一次, 该次就决定了你的权限策略, 此后再调用申请权限API 均无系统弹窗了
区别就是:
android,会一直弹出, 直到你同意或不再提示
iOS仅弹出一次,你此次必须决定授权与否, 此次过后不再弹窗,(除非重装)
所以,针对表现形式不同,逻辑也要做不同处理 (如果要做到双端一致的话)
Android端,选择不再提示后, 帮助用户跳转系统设置,交给用户自己处理
iOS端, 申请过一次后, 下次用户再进行设置 ,就应该帮用户直接跳转系统设置
Android端
PermissionsAndroid就足够了
[PermissionsAndroid文档]
(https://reactnative.cn/docs/0.68/permissionsandroid)
Android 权限管理
android端对各种权限的状态获取 / 权限申请, 由于有PermissionsAndroid的关系, 可以直接在RN端处理开发
贴一下RN端处理代码, 仅关注 !isIOS逻辑分支(即Android端)内的即可, else分支内为iOS桥接代码,后面再贴出来.
/*************************** 1 ***************************//*** 检查相册权限状态*/static checkReadWPermission() {return new Promise(async (resolv, reject) => {if (!isIOS) {try {let check_r = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE)let check_w = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE)if (check_r || check_w) {resolv()} else {reject()}} catch (e) {reject()}} else {let res = NativeModules.GeneralModule.checkPhotoAlbumState();if (res === "yes") {resolv()} else {reject()}}})}/*** 申请相册权限(获取读写权限)*/static requestReadWPermission() {return new Promise((resolve, reject) => {if (!isIOS) {PermissionsAndroid.requestMultiple([PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,]).then(granted => {if (granted["android.permission.READ_EXTERNAL_STORAGE"] === PermissionsAndroid.RESULTS.GRANTED ||granted["android.permission.WRITE_EXTERNAL_STORAGE"] === PermissionsAndroid.RESULTS.GRANTED) {rlog('你已获取了相册权限');resolve("yes");}if (granted["android.permission.READ_EXTERNAL_STORAGE"] === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN ||granted["android.permission.WRITE_EXTERNAL_STORAGE"] === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {rlog('不再提示相册权限');resolve("naver");} else {rlog('获取相册权限失败');reject();}}).catch(err => {reject();});}// ioselse {let res = NativeModules.GeneralModule.getPhotoAlbumState();if (res === 'yes') {rlog('你已获取了相册权限');resolve()} else {rlog('获取相册权限失败');reject()}}});}/*** 检查相机权限状态*/static checkCameraPermission() {return new Promise(async (resolv, reject) => {if (!isIOS) {try {let check = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.CAMERA);check ? resolv() : reject()} catch (e) {reject()}} else {let res = NativeModules.GeneralModule.checkCameraState();if (res === "yes") {resolv()} else {reject()}}})}/*** 申请相机权限* @returns {Promise}*/ static requestCameraPermisson() {return new Promise((resolve, reject) => {if (!isIOS) {PermissionsAndroid.requestMultiple([PermissionsAndroid.PERMISSIONS.CAMERA,]).then(granted => {if (granted["android.permission.CAMERA"] === PermissionsAndroid.RESULTS.GRANTED) {rlog('你已获取了相机权限');resolve("yes");}if (granted["android.permission.CAMERA"] === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {rlog("不再提示相机权限")resolve("naver")} else {rlog('获取相机权限失败');reject();}}).catch(err => {reject();});}// ioselse {let res = NativeModules.GeneralModule.getCameraState();if (res === 'yes') {rlog('你已获取了相机权限');resolve()} else {rlog('获取相机权限失败');reject()}}});}/*** 检查日历权限状态*/static checkCalendarPermission() {return new Promise(async (resolv, reject) => {if (!isIOS) {try {let check_r = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.READ_CALENDAR)let check_w = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.WRITE_CALENDAR)if (check_w || check_r) {resolv()} else {reject()}} catch (e) {reject()}} else {let res = NativeModules.GeneralModule.checkCalendarState();if (res === "yes") {resolv()} else {reject()}}})}/*** 申请日历权限*/static requestCalendarPermission() {return new Promise((resolve, reject) => {if (!isIOS) {PermissionsAndroid.requestMultiple([PermissionsAndroid.PERMISSIONS.READ_CALENDAR,PermissionsAndroid.PERMISSIONS.WRITE_CALENDAR,]).then((granted) => {if (granted["android.permission.READ_CALENDAR"] === PermissionsAndroid.RESULTS.GRANTED ||granted["android.permission.WRITE_CALENDAR"] === PermissionsAndroid.RESULTS.GRANTED) {rlog('你已获取了日历权限');resolve("yes")}if (granted["android.permission.READ_CALENDAR"] === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN ||granted["android.permission.WRITE_CALENDAR"] === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {rlog('不再提示日历权限');resolve("naver")} else {rlog('获取日历权限失败');reject()}}).catch(err => {reject()})}// ioselse {let res = NativeModules.GeneralModule.getCalendarState();if (res === 'yes') {rlog('你已获取了日历权限');resolve()} else {rlog('获取日历权限失败');reject()}}});}/*** 检查定位权限状态*/static checkLoacationPermission() {return new Promise(async (resolv, reject) => {if (!isIOS) {try {let check_fine = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION)let check_coarse = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION)if (check_coarse || check_fine) {resolv()} else {reject()}} catch (e) {reject()}} else {let res = NativeModules.GeneralModule.checkLocationState();if (res === "yes") {resolv()} else {reject()}}})}/*** 申请地理位置权限*/static requestloactionPermission() {return new Promise((resolve, reject) => {if (!isIOS) {PermissionsAndroid.requestMultiple([PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,]).then((granted) => {if (granted["android.permission.ACCESS_FINE_LOCATION"] === PermissionsAndroid.RESULTS.GRANTED ||granted["android.permission.ACCESS_COARSE_LOCATION"] === PermissionsAndroid.RESULTS.GRANTED) {rlog('你已获取了定位权限');resolve("yes")}if (granted["android.permission.ACCESS_FINE_LOCATION"] === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN ||granted["android.permission.ACCESS_COARSE_LOCATION"] === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {rlog("不再提示定位权限")resolve("naver")} else {rlog('获取定位权限失败');reject()}}).catch(err => {reject()})}// ioselse {let res = NativeModules.GeneralModule.getLocationState();if (res === 'yes') {rlog('你已获取了定位权限');resolve()} else {rlog('获取定位权限失败');reject()}}});}
iOS
参考: iOS 权限设置判断和跳转 - 最全最详细
头文件:
#import <Photos/Photos.h>
#import <AVFoundation/AVCaptureDevice.h>
#import <AVFoundation/AVMediaFormat.h>
#import <Foundation/Foundation.h>
@import EventKit;
@import CoreLocation;
@import AVFoundation;
iOS原生类 支持的方法列表
+(NSString*)checkPhotoAlbumState;
+(NSString*)getPhotoAlbumState;+(NSString*)checkCameraState;
+(NSString*)getCameraState;+(NSString*)checkCalendarState;
+(NSString*)getCalendarState;+(NSString*)checkLocationState;
+(NSString*)getLocationState;
iOS原生类 支持的方法列表的实现代码
/**检查相册权限*/
+(NSString*)checkPhotoAlbumState{NSString * res = @"";PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];switch(status){case PHAuthorizationStatusAuthorized:res=@"yes";break;case PHAuthorizationStatusDenied:res=@"no";break;case PHAuthorizationStatusNotDetermined:res=@"no";break;case PHAuthorizationStatusRestricted:res=@"yes";break;default:break;}return res;
}/**申请相册*/
+(NSString*)getPhotoAlbumState{__block NSString * res = @"";dispatch_sync(dispatch_get_global_queue(0, 0), ^{dispatch_semaphore_t sema = dispatch_semaphore_create(0);//PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];//----每次都会走进来[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {if (status == PHAuthorizationStatusAuthorized) {res = @"yes";dispatch_semaphore_signal(sema);}else{res = @"no";dispatch_semaphore_signal(sema);}}];dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);});return res;
}/**检查相机权限*/
+(NSString*)checkCameraState{NSString *res=@"";AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];switch (status) {case AVAuthorizationStatusAuthorized:res=@"yes";break;case AVAuthorizationStatusDenied:res=@"no";break;case AVAuthorizationStatusNotDetermined:res=@"no";break;case AVAuthorizationStatusRestricted:res=@"yes";break;default:break;}return res;
}
/**申请相机*/
+(NSString*)getCameraState{__block NSString* res = @"";dispatch_sync(dispatch_get_global_queue(0, 0), ^{dispatch_semaphore_t sema = dispatch_semaphore_create(0);// 触发相册系统弹框[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {if (granted) {res= @"yes";dispatch_semaphore_signal(sema);}else{res= @"no";dispatch_semaphore_signal(sema);}}];dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);});return res;
}/**检查日历权限*/
+(NSString*)checkCalendarState{NSString *res = @"";EKAuthorizationStatus status= [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];switch (status) {case EKAuthorizationStatusAuthorized: //授权res = @"yes";break;case EKAuthorizationStatusDenied: //拒绝res = @"no";break;case EKAuthorizationStatusNotDetermined: // 不确定res = @"no";break;case EKAuthorizationStatusRestricted: //限制res = @"yes";break;default:break;}return res;
}
/**申请日历*/
+(NSString*)getCalendarState{__block NSString* res = @"";dispatch_sync(dispatch_get_global_queue(0, 0), ^{dispatch_semaphore_t sema = dispatch_semaphore_create(0);EKEventStore *store = [[EKEventStore alloc]init];[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {if (granted) {res=@"yes";dispatch_semaphore_signal(sema);}else{res=@"no";dispatch_semaphore_signal(sema);}}];dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);});return res;
}/**检查定位权限*/
+ (NSString *)checkLocationState{NSString *res = @"";//检查定位权限CLAuthorizationStatus CLstatus = [CLLocationManager authorizationStatus];switch (CLstatus) {case kCLAuthorizationStatusAuthorizedAlways:res=@"yes";break;case kCLAuthorizationStatusAuthorizedWhenInUse:res=@"yes";break;case kCLAuthorizationStatusDenied:res=@"no";break;case kCLAuthorizationStatusNotDetermined:res=@"no";break;case kCLAuthorizationStatusRestricted:res=@"yes";break;default:break;}return res;
}
/**申请定位*/
+(NSString*)getLocationState{__block NSString *res = @"";BOOL isLocation = [CLLocationManager locationServicesEnabled];if (isLocation) {CLLocationManager *manager = [[CLLocationManager alloc] init];[manager requestWhenInUseAuthorization];CLAuthorizationStatus status = [CLLocationManager authorizationStatus];if (status == kCLAuthorizationStatusAuthorizedAlways) {res = @"yes";}if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {res = @"yes";}else{res = @"no";}}else{res = @"no";}return res;
}
iOS 桥接文件
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(checkPhotoAlbumState){return [NativeUtils checkPhotoAlbumState];
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getPhotoAlbumState){return [NativeUtils getPhotoAlbumState];
}RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(checkCameraState){return [NativeUtils checkCameraState];
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getCameraState){return [NativeUtils getCameraState];
}RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(checkCalendarState){return [NativeUtils checkCalendarState];
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getCalendarState){return [NativeUtils getCalendarState];
}RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(checkLocationState){return [NativeUtils checkLocationState];
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getLocationState){return [NativeUtils getLocationState];
}
使用
直接调用一开始贴的JS代码即可
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
