Skip to content

Commit f401e69

Browse files
authored
Merge pull request #70 from trestrantham/master
Add support for iOS 10 speech recognition permission requests
2 parents 32260fa + 8f65b34 commit f401e69

File tree

10 files changed

+98
-19
lines changed

10 files changed

+98
-19
lines changed

Example/ios/Example.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@
584584
83CBB9F71A601CBA00E9B192 /* Project object */ = {
585585
isa = PBXProject;
586586
attributes = {
587-
LastUpgradeCheck = 610;
587+
LastUpgradeCheck = 0820;
588588
ORGANIZATIONNAME = Facebook;
589589
TargetAttributes = {
590590
00E356ED1AD99517003FC87E = {

Example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "0620"
3+
LastUpgradeVersion = "0820"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "NO"

RCTConvert+RNPStatus.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ typedef NS_ENUM(NSInteger, RNPType) {
2525
RNPTypeReminder,
2626
RNPTypeBluetooth,
2727
RNPTypeNotification,
28-
RNPTypeBackgroundRefresh
28+
RNPTypeBackgroundRefresh,
29+
RNPTypeSpeechRecognition
2930
};
3031

3132
@interface RCTConvert (RNPStatus)

RCTConvert+RNPStatus.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ @implementation RCTConvert (RNPStatus)
2020
@"reminder" : @(RNPTypeReminder),
2121
@"bluetooth" : @(RNPTypeBluetooth),
2222
@"notification" : @(RNPTypeNotification),
23-
@"backgroundRefresh": @(RNPTypeBackgroundRefresh)
23+
@"backgroundRefresh": @(RNPTypeBackgroundRefresh),
24+
@"speechRecognition": @(RNPTypeSpeechRecognition)
2425
}),
2526
RNPTypeUnknown, integerValue)
2627

README.md

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ The current supported permissions are:
1212
- Bluetooth *(iOS only)*
1313
- Push Notifications *(iOS only)*
1414
- Background Refresh *(iOS only)*
15+
- Speech Recognition *(iOS only)*
1516

1617

1718
| Version | React Native Support |
@@ -56,15 +57,15 @@ const Permissions = require('react-native-permissions');
5657
Permissions.checkMultiplePermissions(['camera', 'photo'])
5758
.then(response => {
5859
//response is an object mapping type to permission
59-
this.setState({
60+
this.setState({
6061
cameraPermission: response.camera,
6162
photoPermission: response.photo,
6263
})
6364
});
6465
}
6566

6667
// 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,
6869
// after which the user needs to manually enable them from settings.
6970
// the idea here is to explain why we need access and determine if
7071
// the user will say no, so that we don't blow our one chance.
@@ -75,7 +76,7 @@ const Permissions = require('react-native-permissions');
7576
'We need access so you can set your profile pic',
7677
[
7778
{text: 'No way', onPress: () => console.log('permission denied'), style: 'cancel'},
78-
this.state.photoPermission == 'undetermined'?
79+
this.state.photoPermission == 'undetermined'?
7980
{text: 'OK', onPress: this._requestPermission.bind(this)}
8081
: {text: 'Open Settings', onPress: Permissions.openSettings}
8182
]
@@ -110,6 +111,7 @@ Promises resolve into one of these statuses
110111
|`reminder`| ✔️ ||
111112
|`notification`| ✔️ ||
112113
|`backgroundRefresh`| ✔️ ||
114+
|`speechRecognition`| ✔️ ||
113115
|`storage`| ❌️ ||
114116

115117
###Methods
@@ -163,14 +165,15 @@ All required permissions also need to be included in the Manifest before they ca
163165

164166
Permissions are automatically accepted for targetSdkVersion < 23 but you can still use `getPermissionStatus` to check if the user has disabled them from Settings.
165167

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+
174177

175178
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
176179

@@ -181,7 +184,7 @@ npm install --save react-native-permissions
181184
rnpm link
182185
````
183186

184-
###Or manualy linking
187+
###Or manualy linking
185188

186189
####iOS
187190
* Run open node_modules/react-native-permissions
@@ -233,10 +236,10 @@ public class MainApplication extends Application implements ReactApplication {
233236
##Troubleshooting
234237

235238
#### 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
237240

238241
#### Q: iOS - app crashes as soon as I request permission
239242
A: starting with xcode 8, you need to add permission descriptions. see iOS notes for more details. Thanks to @jesperlndk for discovering this.
240243

241244
#### 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"

ReactNativePermissions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const RNPTypes = {
1616
'bluetooth',
1717
'notification',
1818
'backgroundRefresh',
19+
'speechRecognition',
1920
],
2021
android: [
2122
'location',

ReactNativePermissions.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#import "RNPPhoto.h"
2323
#import "RNPContacts.h"
2424
#import "RNPBackgroundRefresh.h"
25+
#import "RNPSpeechRecognition.h"
2526

2627
@interface ReactNativePermissions()
2728
@property (strong, nonatomic) RNPLocation *locationMgr;
@@ -104,6 +105,9 @@ - (dispatch_queue_t)methodQueue {
104105
case RNPTypeBackgroundRefresh:
105106
status = [RNPBackgroundRefresh getStatus];
106107
break;
108+
case RNPTypeSpeechRecognition:
109+
status = [RNPSpeechRecognition getStatus];
110+
break;
107111
default:
108112
break;
109113
}
@@ -134,6 +138,8 @@ - (dispatch_queue_t)methodQueue {
134138
return [self requestBluetooth:resolve];
135139
case RNPTypeNotification:
136140
return [self requestNotification:json resolve:resolve];
141+
case RNPTypeSpeechRecognition:
142+
return [RNPSpeechRecognition request:resolve];
137143
default:
138144
break;
139145
}

ReactNativePermissions.xcodeproj/project.pbxproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
281CD5911E26B0C8003A72B2 /* RNPSpeechRecognition.m in Sources */ = {isa = PBXBuildFile; fileRef = 281CD5901E26B0C7003A72B2 /* RNPSpeechRecognition.m */; };
1011
9D46283E1D34719100346A5B /* RNPAudioVideo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D46282F1D34719100346A5B /* RNPAudioVideo.m */; };
1112
9D46283F1D34719100346A5B /* RNPBackgroundRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628311D34719100346A5B /* RNPBackgroundRefresh.m */; };
1213
9D4628401D34719100346A5B /* RNPBluetooth.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D4628331D34719100346A5B /* RNPBluetooth.m */; };
@@ -32,6 +33,8 @@
3233
/* End PBXCopyFilesBuildPhase section */
3334

3435
/* 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; };
3538
9D23B34F1C767B80008B4819 /* libReactNativePermissions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativePermissions.a; sourceTree = BUILT_PRODUCTS_DIR; };
3639
9D46282E1D34719100346A5B /* RNPAudioVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNPAudioVideo.h; path = permissions/RNPAudioVideo.h; sourceTree = SOURCE_ROOT; };
3740
9D46282F1D34719100346A5B /* RNPAudioVideo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPAudioVideo.m; path = permissions/RNPAudioVideo.m; sourceTree = SOURCE_ROOT; };
@@ -113,6 +116,8 @@
113116
9D46283B1D34719100346A5B /* RNPNotification.m */,
114117
9D46283C1D34719100346A5B /* RNPPhoto.h */,
115118
9D46283D1D34719100346A5B /* RNPPhoto.m */,
119+
281CD5921E26B266003A72B2 /* RNPSpeechRecognition.h */,
120+
281CD5901E26B0C7003A72B2 /* RNPSpeechRecognition.m */,
116121
);
117122
name = permissions;
118123
sourceTree = "<group>";
@@ -143,7 +148,7 @@
143148
9D23B3471C767B80008B4819 /* Project object */ = {
144149
isa = PBXProject;
145150
attributes = {
146-
LastUpgradeCheck = 0710;
151+
LastUpgradeCheck = 0820;
147152
ORGANIZATIONNAME = "Yonah Forst";
148153
TargetAttributes = {
149154
9D23B34E1C767B80008B4819 = {
@@ -175,6 +180,7 @@
175180
files = (
176181
9D46283F1D34719100346A5B /* RNPBackgroundRefresh.m in Sources */,
177182
9D4628451D34719100346A5B /* RNPPhoto.m in Sources */,
183+
281CD5911E26B0C8003A72B2 /* RNPSpeechRecognition.m in Sources */,
178184
9D4628431D34719100346A5B /* RNPLocation.m in Sources */,
179185
9D46283E1D34719100346A5B /* RNPAudioVideo.m in Sources */,
180186
9D4628401D34719100346A5B /* RNPBluetooth.m in Sources */,

permissions/RNPSpeechRecognition.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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

permissions/RNPSpeechRecognition.m

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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

0 commit comments

Comments
 (0)