permissions.android.js 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // @flow
  2. import {NativeModules, PermissionsAndroid} from 'react-native';
  3. import AsyncStorage from '@react-native-community/async-storage';
  4. type Status = 'authorized' | 'denied' | 'restricted' | 'undetermined';
  5. type Rationale = {title: string, message: string};
  6. type CheckOptions = string | {type: string};
  7. type RequestOptions = string | {type: string, rationale?: Rationale};
  8. const permissionTypes = {
  9. location: PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
  10. coarseLocation: RNPermissions.PERMISSIONS.ACCESS_COARSE_LOCATION,
  11. camera: PermissionsAndroid.PERMISSIONS.CAMERA,
  12. microphone: PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
  13. contacts: PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
  14. event: PermissionsAndroid.PERMISSIONS.READ_CALENDAR,
  15. storage: PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
  16. photo: PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
  17. callPhone: PermissionsAndroid.PERMISSIONS.CALL_PHONE,
  18. readSms: PermissionsAndroid.PERMISSIONS.READ_SMS,
  19. receiveSms: PermissionsAndroid.PERMISSIONS.RECEIVE_SMS,
  20. };
  21. const RESULTS = {
  22. [PermissionsAndroid.RESULTS.GRANTED]: 'authorized',
  23. [PermissionsAndroid.RESULTS.DENIED]: 'denied',
  24. [PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN]: 'restricted',
  25. };
  26. const STORAGE_KEY = '@RNPermissions:didAskPermission:';
  27. const setDidAskOnce = (permission: string) =>
  28. AsyncStorage.setItem(STORAGE_KEY + permission, 'true');
  29. const getDidAskOnce = (permission: string) =>
  30. AsyncStorage.getItem(STORAGE_KEY + permission).then(item => !!item);
  31. class ReactNativePermissions {
  32. canOpenSettings: () => Promise<boolean> = () => Promise.resolve(false);
  33. openSettings: () => Promise<*> = () =>
  34. Promise.reject(new Error("'openSettings' is deprecated on android"));
  35. getTypes: () => Array<string> = () => Object.keys(permissionTypes);
  36. check = (permission: string, options?: CheckOptions): Promise<Status> => {
  37. if (!permissionTypes[permission]) {
  38. const error = new Error(
  39. `ReactNativePermissions: ${permission} is not a valid permission type on Android`,
  40. );
  41. return Promise.reject(error);
  42. }
  43. return PermissionsAndroid.check(permissionTypes[permission]).then(
  44. isAuthorized => {
  45. if (isAuthorized) {
  46. return 'authorized';
  47. }
  48. return getDidAskOnce(permission).then(didAsk => {
  49. if (didAsk) {
  50. return NativeModules.PermissionsAndroid.shouldShowRequestPermissionRationale(
  51. permissionTypes[permission],
  52. ).then(shouldShow => (shouldShow ? 'denied' : 'restricted'));
  53. }
  54. return 'undetermined';
  55. });
  56. },
  57. );
  58. };
  59. request = (permission: string, options?: RequestOptions): Promise<Status> => {
  60. if (!permissionTypes[permission]) {
  61. const error = new Error(
  62. `ReactNativePermissions: ${permission} is not a valid permission type on Android`,
  63. );
  64. return Promise.reject(error);
  65. }
  66. let rationale;
  67. if (options && options.rationale) {
  68. rationale = options.rationale;
  69. }
  70. return PermissionsAndroid.request(
  71. permissionTypes[permission],
  72. rationale,
  73. ).then(result => {
  74. // PermissionsAndroid.request() to native module resolves to boolean
  75. // rather than string if running on OS version prior to Android M
  76. if (typeof result === 'boolean') {
  77. return result ? 'authorized' : 'denied';
  78. }
  79. return setDidAskOnce(permission).then(() => RESULTS[result]);
  80. });
  81. };
  82. checkMultiple = (permissions: Array<string>): Promise<{[string]: string}> =>
  83. Promise.all(permissions.map(permission => this.check(permission))).then(
  84. result =>
  85. result.reduce((acc, value, index) => {
  86. const name = permissions[index];
  87. acc[name] = value;
  88. return acc;
  89. }, {}),
  90. );
  91. }
  92. export default new ReactNativePermissions();