文章目录

  • 两端获取权限的区别
  • Android端
  • iOS
  • iOS 桥接文件
  • 使用


RN工程做个权限列表开关
相机
相册
日历
定位

两端获取权限的区别

android 调用申请权限,系统会呈现两个还是三个系统弹窗, 直到你同意或拒绝后,选择不在提示,
iOS端,调用申请权限,系统弹窗仅会弹出一次, 该次就决定了你的权限策略, 此后再调用 申请权限API 均无系统弹窗了
区别就是:
android,会一直弹出, 直到你同意或不再提示
iOS仅弹出一次,你此次必须决定授权与否, 此次过后不再弹窗,(除非重装)

所以,针对表现形式不同,逻辑也要做不同处理 (如果要做到双端一致的话)
Android端,选择不再提示后, 帮助用户跳转系统设置,交给用户自己处理
iOS端, 申请过一次后, 下次用户再进行设置 ,就应该帮用户直接跳转系统设置

Android端

PermissionsAndroid就足够了
[PermissionsAndroid文档]
(https://reactnative.cn/docs/0.68/permissionsandroid)

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();
          });
      }
      // ios
      else {
        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<R>}
   */
  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();
          });
      }
      // ios
      else {
        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()
        })
      }
      // ios
      else {
        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()
        })
      }
      // ios
      else {
        let res = NativeModules.GeneralModule.getLocationState();
        if (res === 'yes') {
          rlog('你已获取了定位权限');
          resolve()
        } else {
          rlog('获取定位权限失败');
          reject()
        }
      }
    });
  }

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代码即可