permissions.android.js 3.7KB

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