Browse Source

added support for legacy methods with deprication warnings. updated readme

Yonah Forst 9 years ago
parent
commit
f8821fecd6
2 changed files with 120 additions and 51 deletions
  1. 87 46
      README.md
  2. 33 5
      ReactNativePermissions.ios.js

+ 87 - 46
README.md

@@ -1,69 +1,110 @@
 # React Native Permissions
-Check user permissions (iOS only)
-
-##What
-Some iOS features require the user to grant permission before you can access them.
-
-This library lets you check the current status of those permissions. (Note: it _doesn't_ prompt the user, just silently checks the permission status)
+Request user permissions from React Native (iOS only - android coming soon)
 
 The current supported permissions are:
+- Push Notifications
 - Location
 - Camera
 - Microhone
 - Photos
 - Contacts
-- Event
+- Events
+- Reminders
 - Bluetooth (Peripheral role. Don't use for Central only)
-- RemoteNotifications (Push Notifications)
+- Background Refresh
 
-####Example
-```java
+####General Usage
+```js
 const Permissions = require('react-native-permissions');
 
-//....
+//...
+  //check the status of a single permission
   componentDidMount() {
-    Permissions.locationPermissionStatus()
-    .then(response => {
-      if (response == Permissions.StatusUndetermined) {
-        console.log("Undetermined");
-      } else if (response == Permissions.StatusDenied) {
-        console.log("Denied");
-      } else if (response == Permissions.StatusAuthorized) {
-        console.log("Authorized");
-      } else if (response == Permissions.StatusRestricted) {
-        console.log("Restricted");
-      }
-    });
+    Permissions.getPermissionStatus('photo')
+      .then(response => {
+        //response is one of: 'authorized', 'denied', 'restricted', or 'undetermined'
+        this.setState({ photoPermission: response })
+      });
   }
-//...
-```
-
-
-####API
-
-As shown in the example, methods return a promise with the authorization status as an `int`. You can compare them to the following statuses: `StatusUndetermined`, `StatusDenied`, `StatusAuthorized`, `StatusRestricted`
-
-`locationPermissionStatus()` - checks for access to the user's current location. Note: `AuthorizedAlways` and `AuthorizedWhenInUse` both return `StatusAuthorized`
-
-`cameraPermissionStatus()` - checks for access to the phone's camera
 
-`microphonePermissionStatus()` - checks for access to the phone's microphone
-
-`photoPermissionStatus()` - checks for access to the user's photo album
-
-`contactsPermissionStatus()` - checks for access to the user's address book
-
-`eventPermissionStatus(eventType)` - requires param `eventType`; either `reminder` or `event`. Checks for access to the user's calendar events and reminders
+  //request permission to access photos
+  _requestPermission() {
+    Permissions.requestPermission('photo')
+      .then(response => {
+        //returns once the user has chosen to 'allow' or to 'not allow' access
+        //response is one of: 'authorized', 'denied', 'restricted', or 'undetermined'
+        this.setState({ photoPermission: response })
+      });
+  }
 
-`bluetoothPermissionStatus()` - checks the authorization status of the `CBPeripheralManager` (for sharing data while backgrounded). Note: _Don't_ use this if you're only using `CBCentralManager`
+  //check the status of multiple permissions
+  _checkCameraAndPhotos() {
+    Permissions.checkMultiplePermissions(['camera', 'photo'])
+      .then(response => {
+        //response is an object mapping type to permission
+        this.setState({ 
+          cameraPermission: response.camera,
+          photoPermission: response.photo,
+        })
+      });
+  }
 
-`notificationPermissionStatus()` - checks if the user has authorized remote push notifications. Note: iOS only tells us if the user has ever registered for notification, and which notifications are enabled. Therefore we cannot tell the difference between a user who has never been prompted for notification and a user who denied permission; both will return `StatusUndetermined`. You can determine if `StatusUndetermined` is actually `StatusDenied` by keeping track of whether or not you've already asked the user for permission. This promise *can* return `StatusDenied` if the user switched notifications off from the settings menu. Confusing, I know...
+  // this is a common pattern when asking for permissions.
+  // iOS only gives you once chance to show the permission dialog, 
+  // after which the user needs to manually enable them from settings.
+  // the idea here is to explain why we need access and determine if
+  // the user will say no, so that we don't blow our one chance.
+  // if the user already denied access, we can ask them to enable it from settings.
+  _alertForPhotosPermission() {
+    Alert.alert(
+      'Can we access your photos?',
+      'We need access so you can set your profile pic',
+      [
+        {text: 'No way', onPress: () => console.log('permission denied'), style: 'cancel'},
+        this.state.photoPermission == 'undetermined'? 
+          {text: 'OK', onPress: this._requestPermission.bind(this)}
+          : {text: 'Open Settings', onPress: Permissions.openSettings}
+      ]
+    )
+  }
+//...
+```
 
-`backgroundRefreshStatus()` - checks the authorization status of background refresh
+####API
 
+_Permission statuses_ - `authorized`, `denied`, `restricted`, or `undetermined`
+
+_Permission types_ - `location`, `camera`, `microphone`, `photo`, `contacts`, `event`, `reminder`, `bluetooth`, `notification`, or `backgroundRefresh`
+
+| Method Name | Arguments | Notes
+|---|---|---|
+| `getPermissionStatus` | `type` | - Returns a promise with the permission status. Note: for type `location`, iOS `AuthorizedAlways` and `AuthorizedWhenInUse` both return `authorized` |
+| `requestPermission` | `type` | - Accepts any permission type except `backgroundRefresh`. If the current status is `undetermined`, shows the permission dialog and returns a promise with the resulting status. Otherwise, immediately return a promise with the current status. Note: see below for special cases|
+| `checkMultiplePermissions` | `[types]` | - Accepts an array of permission types and returns a promise with an object mapping permission types to statuses |
+| `getPermissionTypes` | *none* | - Returns an array of valid permission types  |
+| `openSettings` | *none* | - Switches the user to the settings page of your app (iOS 8.0 and later)  |
+| `canOpenSettings` | *none* | - Returns a boolean indicating if the device supports switching to the settings page |
+
+Note: Permission type `bluetooth` represents the status of the `CBPeripheralManager` . Note: Don't use this if you're only using `CBCentralManager`
+
+#####Special cases
+
+`requestPermission` also accepts a second parameter for types `location` and `notification`.
+- `location`: the second parameter is a string, either `always` or `whenInUse`(default).
+- `notification`: the second parameter is an array with the desired alert types. Any combination of `alert`, `badge` and `sound` (default requests all three)
+*_example_*
+```js
+    Permissions.requestPermission('location', 'always')
+      .then(response => {
+        this.setState({ locationPermission: response })
+      })
+
+    Permissions.requestPermission('notification', ['alert', 'badge'])
+      .then(response => {
+        this.setState({ notificationPermission: response })
+      })
+```
 
-You also can open the Settings app.
-`openSettings()` - open the Settings app. Note: this is only supported in ios >= 8. You can use `canOpenSettings()` to determine if it's supported.
 
 ##Setup
 

+ 33 - 5
ReactNativePermissions.ios.js

@@ -3,8 +3,36 @@
 var React = require('react-native');
 var RNPermissions = React.NativeModules.ReactNativePermissions;
 
+const RNPTypes = [
+	'location',
+	'camera',
+	'microphone',
+	'photo',
+	'contacts',
+	'event',
+	'reminder',
+	'bluetooth',
+	'notification',
+	'backgroundRefresh', 
+]
 
 class ReactNativePermissions {
+	constructor() {
+		//legacy support
+		this.StatusUndetermined = 'undetermined'
+		this.StatusDenied = 'denied'
+		this.StatusAuthorized = 'authorized'
+		this.StatusRestricted = 'restricted'
+
+		RNPTypes.forEach(type => {
+			let methodName = `${type}PermissionStatus`
+			this[methodName] = p => {
+				console.warn(`ReactNativePermissions: ${methodName} is depricated. Use getPermissionStatus('${type}') instead.`)
+				return this.getPermissionStatus(p == 'reminder' ? p : type)
+			}
+		})
+	}
+
 	canOpenSettings() {
 		return RNPermissions.canOpenSettings()
 	}
@@ -14,11 +42,11 @@ class ReactNativePermissions {
 	}
 
 	getPermissionTypes() {
-		return RNPermissions.PermissionTypes;
+		return RNPTypes;
 	}
 
 	getPermissionStatus(permission) {
-		if (RNPermissions.PermissionTypes.includes(permission)) {
+		if (RNPTypes.includes(permission)) {
 			return RNPermissions.getPermissionStatus(permission)
 		} else {
 			return Promise.reject(`ReactNativePermissions: ${permission} is not a valid permission type`)
@@ -28,7 +56,7 @@ class ReactNativePermissions {
 	requestPermission(permission, type) {
 		switch (permission) {
 			case "location":
-				return RNPermissions.requestLocation(type)
+				return RNPermissions.requestLocation(type || 'always')
 			case "camera":
 				return RNPermissions.requestCamera();
 			case "microphone":
@@ -44,7 +72,7 @@ class ReactNativePermissions {
 			case "bluetooth":
 				return RNPermissions.requestBluetooth();
 			case "notification":
-				return RNPermissions.requestNotification(type)
+				return RNPermissions.requestNotification(type || ['alert', 'badge', 'sound'])
 			case "backgroundRefresh":
 				return Promise.reject('You cannot request backgroundRefresh')
 			default:
@@ -78,4 +106,4 @@ class ReactNativePermissions {
 	}
 }
 
-export default new ReactNativePermissions();
+export default new ReactNativePermissions()