Browse Source

Merge pull request #70 from trestrantham/master

Add support for iOS 10 speech recognition permission requests
Yonah Forst 7 years ago
parent
commit
f401e694e3

+ 1
- 1
Example/ios/Example.xcodeproj/project.pbxproj View File

584
 		83CBB9F71A601CBA00E9B192 /* Project object */ = {
584
 		83CBB9F71A601CBA00E9B192 /* Project object */ = {
585
 			isa = PBXProject;
585
 			isa = PBXProject;
586
 			attributes = {
586
 			attributes = {
587
-				LastUpgradeCheck = 610;
587
+				LastUpgradeCheck = 0820;
588
 				ORGANIZATIONNAME = Facebook;
588
 				ORGANIZATIONNAME = Facebook;
589
 				TargetAttributes = {
589
 				TargetAttributes = {
590
 					00E356ED1AD99517003FC87E = {
590
 					00E356ED1AD99517003FC87E = {

+ 1
- 1
Example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme View File

1
 <?xml version="1.0" encoding="UTF-8"?>
1
 <?xml version="1.0" encoding="UTF-8"?>
2
 <Scheme
2
 <Scheme
3
-   LastUpgradeVersion = "0620"
3
+   LastUpgradeVersion = "0820"
4
    version = "1.3">
4
    version = "1.3">
5
    <BuildAction
5
    <BuildAction
6
       parallelizeBuildables = "NO"
6
       parallelizeBuildables = "NO"

+ 2
- 1
RCTConvert+RNPStatus.h View File

25
     RNPTypeReminder,
25
     RNPTypeReminder,
26
     RNPTypeBluetooth,
26
     RNPTypeBluetooth,
27
     RNPTypeNotification,
27
     RNPTypeNotification,
28
-    RNPTypeBackgroundRefresh
28
+    RNPTypeBackgroundRefresh,
29
+    RNPTypeSpeechRecognition
29
 };
30
 };
30
 
31
 
31
 @interface RCTConvert (RNPStatus)
32
 @interface RCTConvert (RNPStatus)

+ 2
- 1
RCTConvert+RNPStatus.m View File

20
                                 @"reminder" : @(RNPTypeReminder),
20
                                 @"reminder" : @(RNPTypeReminder),
21
                                 @"bluetooth" : @(RNPTypeBluetooth),
21
                                 @"bluetooth" : @(RNPTypeBluetooth),
22
                                 @"notification" : @(RNPTypeNotification),
22
                                 @"notification" : @(RNPTypeNotification),
23
-                                @"backgroundRefresh": @(RNPTypeBackgroundRefresh)
23
+                                @"backgroundRefresh": @(RNPTypeBackgroundRefresh),
24
+                                @"speechRecognition": @(RNPTypeSpeechRecognition)
24
                                 }),
25
                                 }),
25
                                 RNPTypeUnknown, integerValue)
26
                                 RNPTypeUnknown, integerValue)
26
 
27
 

+ 17
- 14
README.md View File

12
 - Bluetooth *(iOS only)*
12
 - Bluetooth *(iOS only)*
13
 - Push Notifications *(iOS only)*
13
 - Push Notifications *(iOS only)*
14
 - Background Refresh *(iOS only)*
14
 - Background Refresh *(iOS only)*
15
+- Speech Recognition *(iOS only)*
15
 
16
 
16
 
17
 
17
 | Version | React Native Support |
18
 | Version | React Native Support |
56
     Permissions.checkMultiplePermissions(['camera', 'photo'])
57
     Permissions.checkMultiplePermissions(['camera', 'photo'])
57
       .then(response => {
58
       .then(response => {
58
         //response is an object mapping type to permission
59
         //response is an object mapping type to permission
59
-        this.setState({ 
60
+        this.setState({
60
           cameraPermission: response.camera,
61
           cameraPermission: response.camera,
61
           photoPermission: response.photo,
62
           photoPermission: response.photo,
62
         })
63
         })
64
   }
65
   }
65
 
66
 
66
   // this is a common pattern when asking for permissions.
67
   // this is a common pattern when asking for permissions.
67
-  // iOS only gives you once chance to show the permission dialog, 
68
+  // iOS only gives you once chance to show the permission dialog,
68
   // after which the user needs to manually enable them from settings.
69
   // after which the user needs to manually enable them from settings.
69
   // the idea here is to explain why we need access and determine if
70
   // the idea here is to explain why we need access and determine if
70
   // the user will say no, so that we don't blow our one chance.
71
   // the user will say no, so that we don't blow our one chance.
75
       'We need access so you can set your profile pic',
76
       'We need access so you can set your profile pic',
76
       [
77
       [
77
         {text: 'No way', onPress: () => console.log('permission denied'), style: 'cancel'},
78
         {text: 'No way', onPress: () => console.log('permission denied'), style: 'cancel'},
78
-        this.state.photoPermission == 'undetermined'? 
79
+        this.state.photoPermission == 'undetermined'?
79
           {text: 'OK', onPress: this._requestPermission.bind(this)}
80
           {text: 'OK', onPress: this._requestPermission.bind(this)}
80
           : {text: 'Open Settings', onPress: Permissions.openSettings}
81
           : {text: 'Open Settings', onPress: Permissions.openSettings}
81
       ]
82
       ]
110
 |`reminder`| ✔️ | ❌ |
111
 |`reminder`| ✔️ | ❌ |
111
 |`notification`| ✔️ | ❌ |
112
 |`notification`| ✔️ | ❌ |
112
 |`backgroundRefresh`| ✔️ | ❌ |
113
 |`backgroundRefresh`| ✔️ | ❌ |
114
+|`speechRecognition`| ✔️ | ❌ |
113
 |`storage`| ❌️ | ✔ |
115
 |`storage`| ❌️ | ✔ |
114
 
116
 
115
 ###Methods
117
 ###Methods
163
 
165
 
164
 Permissions are automatically accepted for targetSdkVersion < 23 but you can still use `getPermissionStatus` to check if the user has disabled them from Settings.
166
 Permissions are automatically accepted for targetSdkVersion < 23 but you can still use `getPermissionStatus` to check if the user has disabled them from Settings.
165
 
167
 
166
-Here's a map of types to Android system permissions names:  
167
-`location` -> `android.permission.ACCESS_FINE_LOCATION`  
168
-`camera` -> `android.permission.CAMERA`  
169
-`microphone` -> `android.permission.RECORD_AUDIO`  
170
-`photo` -> `android.permission.READ_EXTERNAL_STORAGE`  
171
-`storage` -> `android.permission.READ_EXTERNAL_STORAGE`  
172
-`contacts` -> `android.permission.READ_CONTACTS`  
173
-`event` -> `android.permission.READ_CALENDAR`  
168
+Here's a map of types to Android system permissions names:
169
+`location` -> `android.permission.ACCESS_FINE_LOCATION`
170
+`camera` -> `android.permission.CAMERA`
171
+`microphone` -> `android.permission.RECORD_AUDIO`
172
+`photo` -> `android.permission.READ_EXTERNAL_STORAGE`
173
+`storage` -> `android.permission.READ_EXTERNAL_STORAGE`
174
+`contacts` -> `android.permission.READ_CONTACTS`
175
+`event` -> `android.permission.READ_CALENDAR`
176
+
174
 
177
 
175
 You can request write access to any of these types by also including the appropriate write permission in the Manifest. Read more here: https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
178
 You can request write access to any of these types by also including the appropriate write permission in the Manifest. Read more here: https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
176
 
179
 
181
 rnpm link
184
 rnpm link
182
 ````
185
 ````
183
 
186
 
184
-###Or manualy linking   
187
+###Or manualy linking
185
 
188
 
186
 ####iOS
189
 ####iOS
187
 * Run open node_modules/react-native-permissions
190
 * Run open node_modules/react-native-permissions
233
 ##Troubleshooting
236
 ##Troubleshooting
234
 
237
 
235
 #### Q: Android - `undefined is not a object (evaluating 'RNPermissions.requestPermissions')`
238
 #### Q: Android - `undefined is not a object (evaluating 'RNPermissions.requestPermissions')`
236
-A: `rnpm` may not have linked correctly. Follow the manual linking steps and make sure the library is linked 
239
+A: `rnpm` may not have linked correctly. Follow the manual linking steps and make sure the library is linked
237
 
240
 
238
 #### Q: iOS - app crashes as soon as I request permission
241
 #### Q: iOS - app crashes as soon as I request permission
239
 A: starting with xcode 8, you need to add permission descriptions. see iOS notes for more details. Thanks to @jesperlndk for discovering this.
242
 A: starting with xcode 8, you need to add permission descriptions. see iOS notes for more details. Thanks to @jesperlndk for discovering this.
240
 
243
 
241
 #### Q: iOS - app crashes when I change permissions from settings
244
 #### Q: iOS - app crashes when I change permissions from settings
242
-A: This is normal. iOS restarts your app when your privacy settings change. Just google "ios crash permission change"
245
+A: This is normal. iOS restarts your app when your privacy settings change. Just google "ios crash permission change"

+ 1
- 0
ReactNativePermissions.js View File

16
 		'bluetooth',
16
 		'bluetooth',
17
 		'notification',
17
 		'notification',
18
 		'backgroundRefresh',
18
 		'backgroundRefresh',
19
+		'speechRecognition',
19
 	],
20
 	],
20
 	android: [
21
 	android: [
21
 		'location',
22
 		'location',

+ 6
- 0
ReactNativePermissions.m View File

22
 #import "RNPPhoto.h"
22
 #import "RNPPhoto.h"
23
 #import "RNPContacts.h"
23
 #import "RNPContacts.h"
24
 #import "RNPBackgroundRefresh.h"
24
 #import "RNPBackgroundRefresh.h"
25
+#import "RNPSpeechRecognition.h"
25
 
26
 
26
 @interface ReactNativePermissions()
27
 @interface ReactNativePermissions()
27
 @property (strong, nonatomic) RNPLocation *locationMgr;
28
 @property (strong, nonatomic) RNPLocation *locationMgr;
104
         case RNPTypeBackgroundRefresh:
105
         case RNPTypeBackgroundRefresh:
105
             status = [RNPBackgroundRefresh getStatus];
106
             status = [RNPBackgroundRefresh getStatus];
106
             break;
107
             break;
108
+        case RNPTypeSpeechRecognition:
109
+            status = [RNPSpeechRecognition getStatus];
110
+            break;
107
         default:
111
         default:
108
             break;
112
             break;
109
     }
113
     }
134
             return [self requestBluetooth:resolve];
138
             return [self requestBluetooth:resolve];
135
         case RNPTypeNotification:
139
         case RNPTypeNotification:
136
             return [self requestNotification:json resolve:resolve];
140
             return [self requestNotification:json resolve:resolve];
141
+        case RNPTypeSpeechRecognition:
142
+            return [RNPSpeechRecognition request:resolve];
137
         default:
143
         default:
138
             break;
144
             break;
139
     }
145
     }

+ 7
- 1
ReactNativePermissions.xcodeproj/project.pbxproj View File

7
 	objects = {
7
 	objects = {
8
 
8
 
9
 /* Begin PBXBuildFile section */
9
 /* Begin PBXBuildFile section */
10
+		281CD5911E26B0C8003A72B2 /* RNPSpeechRecognition.m in Sources */ = {isa = PBXBuildFile; fileRef = 281CD5901E26B0C7003A72B2 /* RNPSpeechRecognition.m */; };
10
 		9D46283E1D34719100346A5B /* RNPAudioVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D46282F1D34719100346A5B /* RNPAudioVideo.m */; };
11
 		9D46283E1D34719100346A5B /* RNPAudioVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D46282F1D34719100346A5B /* RNPAudioVideo.m */; };
11
 		9D46283F1D34719100346A5B /* RNPBackgroundRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628311D34719100346A5B /* RNPBackgroundRefresh.m */; };
12
 		9D46283F1D34719100346A5B /* RNPBackgroundRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628311D34719100346A5B /* RNPBackgroundRefresh.m */; };
12
 		9D4628401D34719100346A5B /* RNPBluetooth.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628331D34719100346A5B /* RNPBluetooth.m */; };
13
 		9D4628401D34719100346A5B /* RNPBluetooth.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628331D34719100346A5B /* RNPBluetooth.m */; };
32
 /* End PBXCopyFilesBuildPhase section */
33
 /* End PBXCopyFilesBuildPhase section */
33
 
34
 
34
 /* Begin PBXFileReference section */
35
 /* Begin PBXFileReference section */
36
+		281CD5901E26B0C7003A72B2 /* RNPSpeechRecognition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPSpeechRecognition.m; path = permissions/RNPSpeechRecognition.m; sourceTree = SOURCE_ROOT; };
37
+		281CD5921E26B266003A72B2 /* RNPSpeechRecognition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPSpeechRecognition.h; path = permissions/RNPSpeechRecognition.h; sourceTree = SOURCE_ROOT; };
35
 		9D23B34F1C767B80008B4819 /* libReactNativePermissions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativePermissions.a; sourceTree = BUILT_PRODUCTS_DIR; };
38
 		9D23B34F1C767B80008B4819 /* libReactNativePermissions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativePermissions.a; sourceTree = BUILT_PRODUCTS_DIR; };
36
 		9D46282E1D34719100346A5B /* RNPAudioVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPAudioVideo.h; path = permissions/RNPAudioVideo.h; sourceTree = SOURCE_ROOT; };
39
 		9D46282E1D34719100346A5B /* RNPAudioVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPAudioVideo.h; path = permissions/RNPAudioVideo.h; sourceTree = SOURCE_ROOT; };
37
 		9D46282F1D34719100346A5B /* RNPAudioVideo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPAudioVideo.m; path = permissions/RNPAudioVideo.m; sourceTree = SOURCE_ROOT; };
40
 		9D46282F1D34719100346A5B /* RNPAudioVideo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPAudioVideo.m; path = permissions/RNPAudioVideo.m; sourceTree = SOURCE_ROOT; };
113
 				9D46283B1D34719100346A5B /* RNPNotification.m */,
116
 				9D46283B1D34719100346A5B /* RNPNotification.m */,
114
 				9D46283C1D34719100346A5B /* RNPPhoto.h */,
117
 				9D46283C1D34719100346A5B /* RNPPhoto.h */,
115
 				9D46283D1D34719100346A5B /* RNPPhoto.m */,
118
 				9D46283D1D34719100346A5B /* RNPPhoto.m */,
119
+				281CD5921E26B266003A72B2 /* RNPSpeechRecognition.h */,
120
+				281CD5901E26B0C7003A72B2 /* RNPSpeechRecognition.m */,
116
 			);
121
 			);
117
 			name = permissions;
122
 			name = permissions;
118
 			sourceTree = "<group>";
123
 			sourceTree = "<group>";
143
 		9D23B3471C767B80008B4819 /* Project object */ = {
148
 		9D23B3471C767B80008B4819 /* Project object */ = {
144
 			isa = PBXProject;
149
 			isa = PBXProject;
145
 			attributes = {
150
 			attributes = {
146
-				LastUpgradeCheck = 0710;
151
+				LastUpgradeCheck = 0820;
147
 				ORGANIZATIONNAME = "Yonah Forst";
152
 				ORGANIZATIONNAME = "Yonah Forst";
148
 				TargetAttributes = {
153
 				TargetAttributes = {
149
 					9D23B34E1C767B80008B4819 = {
154
 					9D23B34E1C767B80008B4819 = {
175
 			files = (
180
 			files = (
176
 				9D46283F1D34719100346A5B /* RNPBackgroundRefresh.m in Sources */,
181
 				9D46283F1D34719100346A5B /* RNPBackgroundRefresh.m in Sources */,
177
 				9D4628451D34719100346A5B /* RNPPhoto.m in Sources */,
182
 				9D4628451D34719100346A5B /* RNPPhoto.m in Sources */,
183
+				281CD5911E26B0C8003A72B2 /* RNPSpeechRecognition.m in Sources */,
178
 				9D4628431D34719100346A5B /* RNPLocation.m in Sources */,
184
 				9D4628431D34719100346A5B /* RNPLocation.m in Sources */,
179
 				9D46283E1D34719100346A5B /* RNPAudioVideo.m in Sources */,
185
 				9D46283E1D34719100346A5B /* RNPAudioVideo.m in Sources */,
180
 				9D4628401D34719100346A5B /* RNPBluetooth.m in Sources */,
186
 				9D4628401D34719100346A5B /* RNPBluetooth.m in Sources */,

+ 17
- 0
permissions/RNPSpeechRecognition.h View File

1
+//
2
+//  RNPSpeechRecognition.h
3
+//  ReactNativePermissions
4
+//
5
+//  Created by Tres Trantham on 1/11/17.
6
+//  Copyright © 2017 Yonah Forst. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#import "RCTConvert+RNPStatus.h"
11
+
12
+@interface RNPSpeechRecognition : NSObject
13
+
14
++ (NSString *)getStatus;
15
++ (void)request:(void (^)(NSString *))completionHandler;
16
+
17
+@end

+ 44
- 0
permissions/RNPSpeechRecognition.m View File

1
+//
2
+//  RNPSpeechRecognition.m
3
+//  ReactNativePermissions
4
+//
5
+//  Created by Tres Trantham on 1/11/17.
6
+//  Copyright © 2017 Yonah Forst. All rights reserved.
7
+//
8
+
9
+#import "RNPSpeechRecognition.h"
10
+#import <Speech/Speech.h>
11
+
12
+@implementation RNPSpeechRecognition
13
+
14
++ (NSString *)getStatus
15
+{
16
+
17
+  int status = [SFSpeechRecognizer authorizationStatus];
18
+
19
+  switch (status) {
20
+      case SFSpeechRecognizerAuthorizationStatusAuthorized:
21
+          return RNPStatusAuthorized;
22
+      case SFSpeechRecognizerAuthorizationStatusDenied:
23
+          return RNPStatusDenied;
24
+      case SFSpeechRecognizerAuthorizationStatusRestricted:
25
+          return RNPStatusRestricted;
26
+      default:
27
+          return RNPStatusUndetermined;
28
+  }
29
+}
30
+
31
++ (void)request:(void (^)(NSString *))completionHandler
32
+{
33
+    void (^handler)(void) =  ^(void) {
34
+        dispatch_async(dispatch_get_main_queue(), ^{
35
+            completionHandler([self.class getStatus]);
36
+        });
37
+    };
38
+
39
+    [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
40
+        handler();
41
+    }];
42
+}
43
+
44
+@end