Browse Source

Merge branch 'master' into master

Yonah Forst 8 years ago
parent
commit
f17836d0d5

+ 8 - 0
.gitignore

@@ -1,2 +1,10 @@
 android/react-native-permissions.iml
 android/react-native-permissions.iml
 android/build
 android/build
+android/.idea
+npm-debug.log
+gradlew
+gradle-wrapper.properties
+gradle-wrapper.jar
+local.properties
+gradlew.bat
+android.iml

+ 1 - 0
.npmignore

@@ -0,0 +1 @@
+Example

+ 3 - 0
Example/.babelrc

@@ -0,0 +1,3 @@
+{
+"presets": ["react-native"]
+}

+ 16 - 13
Example/.flowconfig

@@ -1,13 +1,18 @@
 [ignore]
 [ignore]
+; We fork some components by platform
+.*/*[.]android.js
 
 
-# We fork some components by platform.
-.*/*.android.js
+; Ignore "BUCK" generated dirs
+<PROJECT_ROOT>/\.buckd/
 
 
-# Ignore templates with `@flow` in header
-.*/local-cli/generator.*
+; Ignore unexpected extra "@providesModule"
+.*/node_modules/.*/node_modules/fbjs/.*
 
 
-# Ignore malformed json
-.*/node_modules/y18n/test/.*\.json
+; Ignore duplicate module providers
+; For RN Apps installed via npm, "Libraries" folder is inside
+; "node_modules/react-native" but in the source repo it is in the root
+.*/Libraries/react-native/React.js
+.*/Libraries/react-native/ReactNative.js
 
 
 [include]
 [include]
 
 
@@ -19,23 +24,21 @@ flow/
 [options]
 [options]
 module.system=haste
 module.system=haste
 
 
-esproposal.class_static_fields=enable
-esproposal.class_instance_fields=enable
-
 experimental.strict_type_args=true
 experimental.strict_type_args=true
 
 
 munge_underscores=true
 munge_underscores=true
 
 
-module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
 module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
 module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
 
 
 suppress_type=$FlowIssue
 suppress_type=$FlowIssue
 suppress_type=$FlowFixMe
 suppress_type=$FlowFixMe
 suppress_type=$FixMe
 suppress_type=$FixMe
 
 
-suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-7]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
-suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-7]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
+suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-7]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
+suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-7]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
 suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
 suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
 
 
+unsafe.enable_getters_and_setters=true
+
 [version]
 [version]
-^0.27.0
+^0.37.0

+ 1 - 0
Example/.gitattributes

@@ -0,0 +1 @@
+*.pbxproj -text

+ 16 - 3
Example/.gitignore

@@ -22,20 +22,33 @@ DerivedData
 *.xcuserstate
 *.xcuserstate
 project.xcworkspace
 project.xcworkspace
 
 
-# Android/IJ
+# Android/IntelliJ
 #
 #
-*.iml
+build/
 .idea
 .idea
 .gradle
 .gradle
 local.properties
 local.properties
+*.iml
 
 
 # node.js
 # node.js
 #
 #
 node_modules/
 node_modules/
 npm-debug.log
 npm-debug.log
+yarn-error.log
 
 
 # BUCK
 # BUCK
 buck-out/
 buck-out/
 \.buckd/
 \.buckd/
 android/app/libs
 android/app/libs
-android/keystores/debug.keystore
+*.keystore
+
+# fastlane
+#
+# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
+# screenshots whenever they are needed.
+# For more information about the recommended setup visit:
+# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
+
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots

+ 45 - 10
Example/Example.js

@@ -12,6 +12,7 @@ import {
   View,
   View,
   Alert,
   Alert,
   AppState,
   AppState,
+  Platform,
 } from 'react-native';
 } from 'react-native';
 
 
 import Permissions from 'react-native-permissions'
 import Permissions from 'react-native-permissions'
@@ -42,11 +43,24 @@ export default class Example extends Component {
 
 
   _updatePermissions(types) {
   _updatePermissions(types) {
     Permissions.checkMultiplePermissions(types)
     Permissions.checkMultiplePermissions(types)
+      .then(status => {
+        if (this.state.isAlways) {
+          return Permissions.getPermissionStatus('location', 'always')
+            .then(location => ({...status, location}))
+        }
+        return status
+      })
       .then(status => this.setState({ status }))
       .then(status => this.setState({ status }))
   }
   }
 
 
   _requestPermission(permission) {
   _requestPermission(permission) {
-    Permissions.requestPermission(permission)
+    var options
+
+    if (permission == 'location') {
+      options = this.state.isAlways ? 'always' : 'whenInUse'
+    }
+
+    Permissions.requestPermission(permission, options)
       .then(res => {
       .then(res => {
         this.setState({
         this.setState({
           status: {...this.state.status, [permission]: res}
           status: {...this.state.status, [permission]: res}
@@ -64,9 +78,15 @@ export default class Example extends Component {
       }).catch(e => console.warn(e))
       }).catch(e => console.warn(e))
   }
   }
 
 
+  _onLocationSwitchChange() {
+    this.setState({ isAlways: !this.state.isAlways })
+    this._updatePermissions(this.state.types)
+  }
+
   render() {
   render() {
     return (
     return (
       <View style={styles.container}>
       <View style={styles.container}>
+
         {this.state.types.map(p => (
         {this.state.types.map(p => (
           <TouchableHighlight 
           <TouchableHighlight 
             style={[styles.button, styles[this.state.status[p]]]}
             style={[styles.button, styles[this.state.status[p]]]}
@@ -74,7 +94,7 @@ export default class Example extends Component {
             onPress={this._requestPermission.bind(this, p)}>
             onPress={this._requestPermission.bind(this, p)}>
             <View>
             <View>
               <Text style={styles.text}>
               <Text style={styles.text}>
-                {p}
+                {Platform.OS == 'ios' && p == 'location' ? `location ${this.state.isAlways ? 'always' : 'whenInUse'}` : p}
               </Text>
               </Text>
               <Text style={styles.subtext}>
               <Text style={styles.subtext}>
                 {this.state.status[p]}
                 {this.state.status[p]}
@@ -83,13 +103,23 @@ export default class Example extends Component {
           </TouchableHighlight>
           </TouchableHighlight>
           )
           )
         )}
         )}
-        <TouchableHighlight 
-          style={styles.openSettings}
-          onPress={Permissions.openSettings}>
-          <Text style={styles.text}>Open settings</Text>
-        </TouchableHighlight>
+        <View style={styles.footer}>
+          <TouchableHighlight 
+            style={styles['footer_'+Platform.OS]}
+            onPress={this._onLocationSwitchChange.bind(this)}>
+            <Text style={styles.text}>Toggle location type</Text>
+          </TouchableHighlight>
 
 
-        <Text>Note: microphone permissions may not work on iOS simulator. Also, toggling permissions from the settings menu may cause the app to crash. This is normal on iOS. Google "ios crash permission change"</Text>
+          <TouchableHighlight 
+            onPress={Permissions.openSettings}>
+            <Text style={styles.text}>Open settings</Text>
+          </TouchableHighlight>
+        </View>
+
+
+        <Text style={styles['footer_'+Platform.OS]}>
+          Note: microphone permissions may not work on iOS simulator. Also, toggling permissions from the settings menu may cause the app to crash. This is normal on iOS. Google "ios crash permission change"
+        </Text>
       </View>
       </View>
     );
     );
   }
   }
@@ -130,8 +160,13 @@ const styles = StyleSheet.create({
   restricted: {
   restricted: {
     backgroundColor: '#FFAB91'
     backgroundColor: '#FFAB91'
   },
   },
-  openSettings: {
+  footer: {
     padding: 10,
     padding: 10,
-    alignSelf: 'flex-end',
+    flexDirection: 'row',
+    justifyContent: 'space-between',
+  },
+  footer_android: {
+    height: 0,
+    width: 0,
   }
   }
 })
 })

+ 12 - 0
Example/__tests__/index.android.js

@@ -0,0 +1,12 @@
+import 'react-native';
+import React from 'react';
+import Index from '../index.android.js';
+
+// Note: test renderer must be required after react-native.
+import renderer from 'react-test-renderer';
+
+it('renders correctly', () => {
+  const tree = renderer.create(
+    <Index />
+  );
+});

+ 12 - 0
Example/__tests__/index.ios.js

@@ -0,0 +1,12 @@
+import 'react-native';
+import React from 'react';
+import Index from '../index.ios.js';
+
+// Note: test renderer must be required after react-native.
+import renderer from 'react-test-renderer';
+
+it('renders correctly', () => {
+  const tree = renderer.create(
+    <Index />
+  );
+});

+ 3 - 3
Example/android/app/build.gradle

@@ -88,7 +88,7 @@ android {
 
 
     defaultConfig {
     defaultConfig {
         applicationId "com.example"
         applicationId "com.example"
-        minSdkVersion 22
+        minSdkVersion 21
         targetSdkVersion 23
         targetSdkVersion 23
         versionCode 1
         versionCode 1
         versionName "1.0"
         versionName "1.0"
@@ -135,6 +135,6 @@ dependencies {
 // Run this once to be able to run the application with BUCK
 // Run this once to be able to run the application with BUCK
 // puts all compile dependencies into folder libs for BUCK to use
 // puts all compile dependencies into folder libs for BUCK to use
 task copyDownloadableDepsToLibs(type: Copy) {
 task copyDownloadableDepsToLibs(type: Copy) {
-  from configurations.compile
-  into 'libs'
+    from configurations.compile
+    into 'libs'
 }
 }

+ 1 - 3
Example/android/app/src/main/AndroidManifest.xml

@@ -9,12 +9,10 @@
     <uses-permission android:name="android.permission.CAMERA"/>
     <uses-permission android:name="android.permission.CAMERA"/>
     <uses-permission android:name="android.permission.RECORD_AUDIO"/>
     <uses-permission android:name="android.permission.RECORD_AUDIO"/>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.READ_CONTACTS"/>
     <uses-permission android:name="android.permission.READ_CONTACTS"/>
     <uses-permission android:name="android.permission.READ_CALENDAR"/>
     <uses-permission android:name="android.permission.READ_CALENDAR"/>
 
 
-    <uses-sdk
-        android:minSdkVersion="18"
-        android:targetSdkVersion="23" />
 
 
     <application
     <application
       android:name=".MainApplication"
       android:name=".MainApplication"

+ 9 - 2
Example/android/app/src/main/java/com/example/MainApplication.java

@@ -9,6 +9,7 @@ import com.facebook.react.ReactNativeHost;
 import com.facebook.react.ReactPackage;
 import com.facebook.react.ReactPackage;
 import com.facebook.react.shell.MainReactPackage;
 import com.facebook.react.shell.MainReactPackage;
 import com.joshblour.reactnativepermissions.ReactNativePermissionsPackage;
 import com.joshblour.reactnativepermissions.ReactNativePermissionsPackage;
+import com.facebook.soloader.SoLoader;
 
 
 import java.util.Arrays;
 import java.util.Arrays;
 import java.util.List;
 import java.util.List;
@@ -17,7 +18,7 @@ public class MainApplication extends Application implements ReactApplication {
 
 
   private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
   private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
     @Override
     @Override
-    protected boolean getUseDeveloperSupport() {
+    public boolean getUseDeveloperSupport() {
       return BuildConfig.DEBUG;
       return BuildConfig.DEBUG;
     }
     }
 
 
@@ -32,6 +33,12 @@ public class MainApplication extends Application implements ReactApplication {
 
 
   @Override
   @Override
   public ReactNativeHost getReactNativeHost() {
   public ReactNativeHost getReactNativeHost() {
-      return mReactNativeHost;
+    return mReactNativeHost;
+  }
+
+  @Override
+  public void onCreate() {
+    super.onCreate();
+    SoLoader.init(this, /* native exopackage */ false);
   }
   }
 }
 }

+ 1 - 1
Example/android/build.gradle

@@ -5,7 +5,7 @@ buildscript {
         jcenter()
         jcenter()
     }
     }
     dependencies {
     dependencies {
-        classpath 'com.android.tools.build:gradle:1.3.1'
+        classpath 'com.android.tools.build:gradle:2.1.2'
 
 
         // NOTE: Do not place your application dependencies here; they belong
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
         // in the individual module build.gradle files

+ 2 - 1
Example/android/gradle/wrapper/gradle-wrapper.properties

@@ -1,5 +1,6 @@
+#Fri Feb 03 16:27:32 CET 2017
 distributionBase=GRADLE_USER_HOME
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip

+ 54 - 0
Example/ios/Example-tvOS/Info.plist

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UIViewControllerBasedStatusBarAppearance</key>
+	<false/>
+	<key>NSLocationWhenInUseUsageDescription</key>
+	<string></string>
+	<key>NSAppTransportSecurity</key>
+	<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
+	<dict>
+		<key>NSExceptionDomains</key>
+		<dict>
+			<key>localhost</key>
+			<dict>
+				<key>NSExceptionAllowsInsecureHTTPLoads</key>
+				<true/>
+			</dict>
+		</dict>
+	</dict>
+</dict>
+</plist>

+ 24 - 0
Example/ios/Example-tvOSTests/Info.plist

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>

+ 540 - 43
Example/ios/Example.xcodeproj/project.pbxproj

@@ -22,7 +22,20 @@
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
 		140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
 		140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
 		146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
 		146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
-		50F9604CB69B4BA6A44EA44F /* libReactNativePermissions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9820CCF930F4ED1BE137DA6 /* libReactNativePermissions.a */; };
+		14902CDAB1064113A6B4C970 /* libReactNativePermissions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B27CA08432F04FFCB0256EA1 /* libReactNativePermissions.a */; };
+		2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
+		2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
+		2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
+		2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */; };
+		2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */; };
+		2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */; };
+		2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */; };
+		2D02E4C61E0B4AEC006451C7 /* libRCTSettings-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */; };
+		2D02E4C71E0B4AEC006451C7 /* libRCTText-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */; };
+		2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */; };
+		2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3EA31DF850E9000B6D8A /* libReact.a */; };
+		2DCD954D1E0B4F2C00145EB5 /* ExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ExampleTests.m */; };
+		5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; };
 		832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
 		832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
 /* End PBXBuildFile section */
 /* End PBXBuildFile section */
 
 
@@ -90,6 +103,118 @@
 			remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
 			remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
 			remoteInfo = React;
 			remoteInfo = React;
 		};
 		};
+		2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7;
+			remoteInfo = "Example-tvOS";
+		};
+		3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 2D2A283A1D9B042B00D4039D;
+			remoteInfo = "RCTImage-tvOS";
+		};
+		3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 2D2A28471D9B043800D4039D;
+			remoteInfo = "RCTLinking-tvOS";
+		};
+		3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 2D2A28541D9B044C00D4039D;
+			remoteInfo = "RCTNetwork-tvOS";
+		};
+		3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 2D2A28611D9B046600D4039D;
+			remoteInfo = "RCTSettings-tvOS";
+		};
+		3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 2D2A287B1D9B048500D4039D;
+			remoteInfo = "RCTText-tvOS";
+		};
+		3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 2D2A28881D9B049200D4039D;
+			remoteInfo = "RCTWebSocket-tvOS";
+		};
+		3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 2D2A28131D9B038B00D4039D;
+			remoteInfo = "React-tvOS";
+		};
+		3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 3D3C059A1DE3340900C268FA;
+			remoteInfo = yoga;
+		};
+		3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 3D3C06751DE3340C00C268FA;
+			remoteInfo = "yoga-tvOS";
+		};
+		3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 3D3CD9251DE5FBEC00167DC4;
+			remoteInfo = cxxreact;
+		};
+		3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4;
+			remoteInfo = "cxxreact-tvOS";
+		};
+		3DAD3EAC1DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 3D3CD90B1DE5FBD600167DC4;
+			remoteInfo = jschelpers;
+		};
+		3DAD3EAE1DF850E9000B6D8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 3D3CD9181DE5FBD800167DC4;
+			remoteInfo = "jschelpers-tvOS";
+		};
+		5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 134814201AA4EA6300B7C361;
+			remoteInfo = RCTAnimation;
+		};
+		5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 2D2A28201D9B03D100D4039D;
+			remoteInfo = "RCTAnimation-tvOS";
+		};
 		78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
 		78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			isa = PBXContainerItemProxy;
 			containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
 			containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
@@ -104,9 +229,9 @@
 			remoteGlobalIDString = 58B5119B1A9E6C1200147676;
 			remoteGlobalIDString = 58B5119B1A9E6C1200147676;
 			remoteInfo = RCTText;
 			remoteInfo = RCTText;
 		};
 		};
-		9D1B45CC1D49EE8400459C66 /* PBXContainerItemProxy */ = {
+		9D8131C41E44834800F4B1D3 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			isa = PBXContainerItemProxy;
-			containerPortal = 783F116470084EEB95DCA092 /* ReactNativePermissions.xcodeproj */;
+			containerPortal = 8068EB7451414340B0AC0D03 /* ReactNativePermissions.xcodeproj */;
 			proxyType = 2;
 			proxyType = 2;
 			remoteGlobalIDString = 9D23B34F1C767B80008B4819;
 			remoteGlobalIDString = 9D23B34F1C767B80008B4819;
 			remoteInfo = ReactNativePermissions;
 			remoteInfo = ReactNativePermissions;
@@ -133,10 +258,13 @@
 		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Example/Info.plist; sourceTree = "<group>"; };
 		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Example/Info.plist; sourceTree = "<group>"; };
 		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Example/main.m; sourceTree = "<group>"; };
 		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Example/main.m; sourceTree = "<group>"; };
 		146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
 		146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
-		783F116470084EEB95DCA092 /* ReactNativePermissions.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = ReactNativePermissions.xcodeproj; path = "../node_modules/react-native-permissions/ReactNativePermissions.xcodeproj"; sourceTree = "<group>"; };
+		2D02E47B1E0B4A5D006451C7 /* Example-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+		2D02E4901E0B4A5D006451C7 /* Example-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Example-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+		5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
 		78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
 		78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
+		8068EB7451414340B0AC0D03 /* ReactNativePermissions.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = ReactNativePermissions.xcodeproj; path = "../node_modules/react-native-permissions/ReactNativePermissions.xcodeproj"; sourceTree = "<group>"; };
 		832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
 		832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
-		D9820CCF930F4ED1BE137DA6 /* libReactNativePermissions.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libReactNativePermissions.a; sourceTree = "<group>"; };
+		B27CA08432F04FFCB0256EA1 /* libReactNativePermissions.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libReactNativePermissions.a; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 /* End PBXFileReference section */
 
 
 /* Begin PBXFrameworksBuildPhase section */
 /* Begin PBXFrameworksBuildPhase section */
@@ -153,6 +281,7 @@
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
 				146834051AC3E58100842450 /* libReact.a in Frameworks */,
 				146834051AC3E58100842450 /* libReact.a in Frameworks */,
+				5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */,
 				00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
 				00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
 				00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
 				00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
 				00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
 				00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
@@ -162,7 +291,29 @@
 				832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
 				832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
 				00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
 				00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
 				139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
 				139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
-				50F9604CB69B4BA6A44EA44F /* libReactNativePermissions.a in Frameworks */,
+				14902CDAB1064113A6B4C970 /* libReactNativePermissions.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2D02E4781E0B4A5D006451C7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */,
+				2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */,
+				2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */,
+				2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */,
+				2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */,
+				2D02E4C61E0B4AEC006451C7 /* libRCTSettings-tvOS.a in Frameworks */,
+				2D02E4C71E0B4AEC006451C7 /* libRCTText-tvOS.a in Frameworks */,
+				2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2D02E48D1E0B4A5D006451C7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -189,6 +340,7 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,
 				00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,
+				3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */,
 			);
 			);
 			name = Products;
 			name = Products;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -197,6 +349,7 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,
 				00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,
+				3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */,
 			);
 			);
 			name = Products;
 			name = Products;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -230,6 +383,7 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,
 				139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,
+				3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */,
 			);
 			);
 			name = Products;
 			name = Products;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -238,6 +392,7 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
 				139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
+				3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */,
 			);
 			);
 			name = Products;
 			name = Products;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -260,6 +415,22 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				146834041AC3E56700842450 /* libReact.a */,
 				146834041AC3E56700842450 /* libReact.a */,
+				3DAD3EA31DF850E9000B6D8A /* libReact.a */,
+				3DAD3EA51DF850E9000B6D8A /* libyoga.a */,
+				3DAD3EA71DF850E9000B6D8A /* libyoga.a */,
+				3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */,
+				3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */,
+				3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */,
+				3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		5E91572E1DD0AC6500FF2AA8 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */,
+				5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */,
 			);
 			);
 			name = Products;
 			name = Products;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -268,6 +439,7 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				78C398B91ACF4ADC00677621 /* libRCTLinking.a */,
 				78C398B91ACF4ADC00677621 /* libRCTLinking.a */,
+				3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */,
 			);
 			);
 			name = Products;
 			name = Products;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -275,6 +447,7 @@
 		832341AE1AAA6A7D00B99B32 /* Libraries */ = {
 		832341AE1AAA6A7D00B99B32 /* Libraries */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */,
 				146833FF1AC3E56700842450 /* React.xcodeproj */,
 				146833FF1AC3E56700842450 /* React.xcodeproj */,
 				00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
 				00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
 				00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
 				00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
@@ -285,7 +458,7 @@
 				832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
 				832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
 				00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
 				00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
 				139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
 				139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
-				783F116470084EEB95DCA092 /* ReactNativePermissions.xcodeproj */,
+				8068EB7451414340B0AC0D03 /* ReactNativePermissions.xcodeproj */,
 			);
 			);
 			name = Libraries;
 			name = Libraries;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -294,6 +467,7 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				832341B51AAA6A8300B99B32 /* libRCTText.a */,
 				832341B51AAA6A8300B99B32 /* libRCTText.a */,
+				3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */,
 			);
 			);
 			name = Products;
 			name = Products;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -315,14 +489,16 @@
 			children = (
 			children = (
 				13B07F961A680F5B00A75B9A /* Example.app */,
 				13B07F961A680F5B00A75B9A /* Example.app */,
 				00E356EE1AD99517003FC87E /* ExampleTests.xctest */,
 				00E356EE1AD99517003FC87E /* ExampleTests.xctest */,
+				2D02E47B1E0B4A5D006451C7 /* Example-tvOS.app */,
+				2D02E4901E0B4A5D006451C7 /* Example-tvOSTests.xctest */,
 			);
 			);
 			name = Products;
 			name = Products;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
-		9D1B45BF1D49EE8300459C66 /* Products */ = {
+		9D8131A81E44834700F4B1D3 /* Products */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				9D1B45CD1D49EE8400459C66 /* libReactNativePermissions.a */,
+				9D8131C51E44834800F4B1D3 /* libReactNativePermissions.a */,
 			);
 			);
 			name = Products;
 			name = Products;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -366,6 +542,42 @@
 			productReference = 13B07F961A680F5B00A75B9A /* Example.app */;
 			productReference = 13B07F961A680F5B00A75B9A /* Example.app */;
 			productType = "com.apple.product-type.application";
 			productType = "com.apple.product-type.application";
 		};
 		};
+		2D02E47A1E0B4A5D006451C7 /* Example-tvOS */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "Example-tvOS" */;
+			buildPhases = (
+				2D02E4771E0B4A5D006451C7 /* Sources */,
+				2D02E4781E0B4A5D006451C7 /* Frameworks */,
+				2D02E4791E0B4A5D006451C7 /* Resources */,
+				2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "Example-tvOS";
+			productName = "Example-tvOS";
+			productReference = 2D02E47B1E0B4A5D006451C7 /* Example-tvOS.app */;
+			productType = "com.apple.product-type.application";
+		};
+		2D02E48F1E0B4A5D006451C7 /* Example-tvOSTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "Example-tvOSTests" */;
+			buildPhases = (
+				2D02E48C1E0B4A5D006451C7 /* Sources */,
+				2D02E48D1E0B4A5D006451C7 /* Frameworks */,
+				2D02E48E1E0B4A5D006451C7 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */,
+			);
+			name = "Example-tvOSTests";
+			productName = "Example-tvOSTests";
+			productReference = 2D02E4901E0B4A5D006451C7 /* Example-tvOSTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
 /* End PBXNativeTarget section */
 /* End PBXNativeTarget section */
 
 
 /* Begin PBXProject section */
 /* Begin PBXProject section */
@@ -386,6 +598,15 @@
 							};
 							};
 						};
 						};
 					};
 					};
+					2D02E47A1E0B4A5D006451C7 = {
+						CreatedOnToolsVersion = 8.2.1;
+						ProvisioningStyle = Automatic;
+					};
+					2D02E48F1E0B4A5D006451C7 = {
+						CreatedOnToolsVersion = 8.2.1;
+						ProvisioningStyle = Automatic;
+						TestTargetID = 2D02E47A1E0B4A5D006451C7;
+					};
 				};
 				};
 			};
 			};
 			buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Example" */;
 			buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Example" */;
@@ -404,6 +625,10 @@
 					ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
 					ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
 					ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
 					ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
 				},
 				},
+				{
+					ProductGroup = 5E91572E1DD0AC6500FF2AA8 /* Products */;
+					ProjectRef = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */;
+				},
 				{
 				{
 					ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
 					ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
 					ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
 					ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
@@ -441,14 +666,16 @@
 					ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
 					ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
 				},
 				},
 				{
 				{
-					ProductGroup = 9D1B45BF1D49EE8300459C66 /* Products */;
-					ProjectRef = 783F116470084EEB95DCA092 /* ReactNativePermissions.xcodeproj */;
+					ProductGroup = 9D8131A81E44834700F4B1D3 /* Products */;
+					ProjectRef = 8068EB7451414340B0AC0D03 /* ReactNativePermissions.xcodeproj */;
 				},
 				},
 			);
 			);
 			projectRoot = "";
 			projectRoot = "";
 			targets = (
 			targets = (
 				13B07F861A680F5B00A75B9A /* Example */,
 				13B07F861A680F5B00A75B9A /* Example */,
 				00E356ED1AD99517003FC87E /* ExampleTests */,
 				00E356ED1AD99517003FC87E /* ExampleTests */,
+				2D02E47A1E0B4A5D006451C7 /* Example-tvOS */,
+				2D02E48F1E0B4A5D006451C7 /* Example-tvOSTests */,
 			);
 			);
 		};
 		};
 /* End PBXProject section */
 /* End PBXProject section */
@@ -510,6 +737,111 @@
 			remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
 			remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
 			sourceTree = BUILT_PRODUCTS_DIR;
 			sourceTree = BUILT_PRODUCTS_DIR;
 		};
 		};
+		3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = "libRCTImage-tvOS.a";
+			remoteRef = 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = "libRCTLinking-tvOS.a";
+			remoteRef = 3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = "libRCTNetwork-tvOS.a";
+			remoteRef = 3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = "libRCTSettings-tvOS.a";
+			remoteRef = 3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = "libRCTText-tvOS.a";
+			remoteRef = 3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = "libRCTWebSocket-tvOS.a";
+			remoteRef = 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3EA31DF850E9000B6D8A /* libReact.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libReact.a;
+			remoteRef = 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3EA51DF850E9000B6D8A /* libyoga.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libyoga.a;
+			remoteRef = 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3EA71DF850E9000B6D8A /* libyoga.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libyoga.a;
+			remoteRef = 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libcxxreact.a;
+			remoteRef = 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libcxxreact.a;
+			remoteRef = 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libjschelpers.a;
+			remoteRef = 3DAD3EAC1DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libjschelpers.a;
+			remoteRef = 3DAD3EAE1DF850E9000B6D8A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libRCTAnimation.a;
+			remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = "libRCTAnimation-tvOS.a";
+			remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
 		78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
 		78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
 			isa = PBXReferenceProxy;
 			isa = PBXReferenceProxy;
 			fileType = archive.ar;
 			fileType = archive.ar;
@@ -524,11 +856,11 @@
 			remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
 			remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
 			sourceTree = BUILT_PRODUCTS_DIR;
 			sourceTree = BUILT_PRODUCTS_DIR;
 		};
 		};
-		9D1B45CD1D49EE8400459C66 /* libReactNativePermissions.a */ = {
+		9D8131C51E44834800F4B1D3 /* libReactNativePermissions.a */ = {
 			isa = PBXReferenceProxy;
 			isa = PBXReferenceProxy;
 			fileType = archive.ar;
 			fileType = archive.ar;
 			path = libReactNativePermissions.a;
 			path = libReactNativePermissions.a;
-			remoteRef = 9D1B45CC1D49EE8400459C66 /* PBXContainerItemProxy */;
+			remoteRef = 9D8131C41E44834800F4B1D3 /* PBXContainerItemProxy */;
 			sourceTree = BUILT_PRODUCTS_DIR;
 			sourceTree = BUILT_PRODUCTS_DIR;
 		};
 		};
 /* End PBXReferenceProxy section */
 /* End PBXReferenceProxy section */
@@ -550,6 +882,21 @@
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
+		2D02E4791E0B4A5D006451C7 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2D02E48E1E0B4A5D006451C7 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXResourcesBuildPhase section */
 /* End PBXResourcesBuildPhase section */
 
 
 /* Begin PBXShellScriptBuildPhase section */
 /* Begin PBXShellScriptBuildPhase section */
@@ -567,6 +914,20 @@
 			shellPath = /bin/sh;
 			shellPath = /bin/sh;
 			shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
 			shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
 		};
 		};
+		2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Bundle React Native Code And Images";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
+		};
 /* End PBXShellScriptBuildPhase section */
 /* End PBXShellScriptBuildPhase section */
 
 
 /* Begin PBXSourcesBuildPhase section */
 /* Begin PBXSourcesBuildPhase section */
@@ -587,6 +948,23 @@
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
+		2D02E4771E0B4A5D006451C7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */,
+				2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2D02E48C1E0B4A5D006451C7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2DCD954D1E0B4F2C00145EB5 /* ExampleTests.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXSourcesBuildPhase section */
 /* End PBXSourcesBuildPhase section */
 
 
 /* Begin PBXTargetDependency section */
 /* Begin PBXTargetDependency section */
@@ -595,6 +973,11 @@
 			target = 13B07F861A680F5B00A75B9A /* Example */;
 			target = 13B07F861A680F5B00A75B9A /* Example */;
 			targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
 			targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
 		};
 		};
+		2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 2D02E47A1E0B4A5D006451C7 /* Example-tvOS */;
+			targetProxy = 2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */;
+		};
 /* End PBXTargetDependency section */
 /* End PBXTargetDependency section */
 
 
 /* Begin PBXVariantGroup section */
 /* Begin PBXVariantGroup section */
@@ -619,12 +1002,16 @@
 					"$(inherited)",
 					"$(inherited)",
 				);
 				);
 				INFOPLIST_FILE = ExampleTests/Info.plist;
 				INFOPLIST_FILE = ExampleTests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 8.2;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				LIBRARY_SEARCH_PATHS = (
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
 					"\"$(SRCROOT)/$(TARGET_NAME)\"",
 					"\"$(SRCROOT)/$(TARGET_NAME)\"",
 				);
 				);
+				OTHER_LDFLAGS = (
+					"-ObjC",
+					"-lc++",
+				);
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
 				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
 			};
 			};
@@ -636,12 +1023,16 @@
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				COPY_PHASE_STRIP = NO;
 				COPY_PHASE_STRIP = NO;
 				INFOPLIST_FILE = ExampleTests/Info.plist;
 				INFOPLIST_FILE = ExampleTests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 8.2;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				LIBRARY_SEARCH_PATHS = (
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
 					"\"$(SRCROOT)/$(TARGET_NAME)\"",
 					"\"$(SRCROOT)/$(TARGET_NAME)\"",
 				);
 				);
+				OTHER_LDFLAGS = (
+					"-ObjC",
+					"-lc++",
+				);
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
 				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
 			};
 			};
@@ -651,15 +1042,9 @@
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CURRENT_PROJECT_VERSION = 1;
 				DEAD_CODE_STRIPPING = NO;
 				DEAD_CODE_STRIPPING = NO;
-				HEADER_SEARCH_PATHS = (
-					"$(inherited)",
-					/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
-					"$(SRCROOT)/../node_modules/react-native/React/**",
-					"$(SRCROOT)/../node_modules/react-native-permissions/**",
-				);
 				INFOPLIST_FILE = Example/Info.plist;
 				INFOPLIST_FILE = Example/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				OTHER_LDFLAGS = (
 				OTHER_LDFLAGS = (
 					"$(inherited)",
 					"$(inherited)",
@@ -667,6 +1052,7 @@
 					"-lc++",
 					"-lc++",
 				);
 				);
 				PRODUCT_NAME = Example;
 				PRODUCT_NAME = Example;
+				VERSIONING_SYSTEM = "apple-generic";
 			};
 			};
 			name = Debug;
 			name = Debug;
 		};
 		};
@@ -674,14 +1060,8 @@
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				HEADER_SEARCH_PATHS = (
-					"$(inherited)",
-					/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
-					"$(SRCROOT)/../node_modules/react-native/React/**",
-					"$(SRCROOT)/../node_modules/react-native-permissions/**",
-				);
+				CURRENT_PROJECT_VERSION = 1;
 				INFOPLIST_FILE = Example/Info.plist;
 				INFOPLIST_FILE = Example/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				OTHER_LDFLAGS = (
 				OTHER_LDFLAGS = (
 					"$(inherited)",
 					"$(inherited)",
@@ -689,6 +1069,117 @@
 					"-lc++",
 					"-lc++",
 				);
 				);
 				PRODUCT_NAME = Example;
 				PRODUCT_NAME = Example;
+				VERSIONING_SYSTEM = "apple-generic";
+			};
+			name = Release;
+		};
+		2D02E4971E0B4A5E006451C7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_TESTABILITY = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Example-tvOS/Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SRCROOT)/$(TARGET_NAME)\"",
+				);
+				OTHER_LDFLAGS = (
+					"-ObjC",
+					"-lc++",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.Example-tvOS";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = appletvos;
+				TARGETED_DEVICE_FAMILY = 3;
+				TVOS_DEPLOYMENT_TARGET = 9.2;
+			};
+			name = Debug;
+		};
+		2D02E4981E0B4A5E006451C7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Example-tvOS/Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SRCROOT)/$(TARGET_NAME)\"",
+				);
+				OTHER_LDFLAGS = (
+					"-ObjC",
+					"-lc++",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.Example-tvOS";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = appletvos;
+				TARGETED_DEVICE_FAMILY = 3;
+				TVOS_DEPLOYMENT_TARGET = 9.2;
+			};
+			name = Release;
+		};
+		2D02E4991E0B4A5E006451C7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_TESTABILITY = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Example-tvOSTests/Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SRCROOT)/$(TARGET_NAME)\"",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.Example-tvOSTests";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = appletvos;
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example-tvOS.app/Example-tvOS";
+				TVOS_DEPLOYMENT_TARGET = 10.1;
+			};
+			name = Debug;
+		};
+		2D02E49A1E0B4A5E006451C7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Example-tvOSTests/Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SRCROOT)/$(TARGET_NAME)\"",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.Example-tvOSTests";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = appletvos;
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example-tvOS.app/Example-tvOS";
+				TVOS_DEPLOYMENT_TARGET = 10.1;
 			};
 			};
 			name = Release;
 			name = Release;
 		};
 		};
@@ -726,13 +1217,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				HEADER_SEARCH_PATHS = (
-					"$(inherited)",
-					/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
-					"$(SRCROOT)/../node_modules/react-native/React/**",
-					"$(SRCROOT)/../node_modules/react-native-permissions/**",
-				);
-				IPHONEOS_DEPLOYMENT_TARGET = 7.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = iphoneos;
 				SDKROOT = iphoneos;
@@ -767,13 +1252,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				HEADER_SEARCH_PATHS = (
-					"$(inherited)",
-					/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
-					"$(SRCROOT)/../node_modules/react-native/React/**",
-					"$(SRCROOT)/../node_modules/react-native-permissions/**",
-				);
-				IPHONEOS_DEPLOYMENT_TARGET = 7.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				SDKROOT = iphoneos;
 				SDKROOT = iphoneos;
 				VALIDATE_PRODUCT = YES;
 				VALIDATE_PRODUCT = YES;
@@ -801,6 +1280,24 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 			defaultConfigurationName = Release;
 		};
 		};
+		2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "Example-tvOS" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2D02E4971E0B4A5E006451C7 /* Debug */,
+				2D02E4981E0B4A5E006451C7 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "Example-tvOSTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2D02E4991E0B4A5E006451C7 /* Debug */,
+				2D02E49A1E0B4A5E006451C7 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Example" */ = {
 		83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Example" */ = {
 			isa = XCConfigurationList;
 			isa = XCConfigurationList;
 			buildConfigurations = (
 			buildConfigurations = (

+ 129 - 0
Example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example-tvOS.xcscheme

@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0820"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "NO"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "2D2A28121D9B038B00D4039D"
+               BuildableName = "libReact.a"
+               BlueprintName = "React-tvOS"
+               ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
+               BuildableName = "Example-tvOS.app"
+               BlueprintName = "Example-tvOS"
+               ReferencedContainer = "container:Example.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "NO"
+            buildForArchiving = "NO"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "2D02E48F1E0B4A5D006451C7"
+               BuildableName = "Example-tvOSTests.xctest"
+               BlueprintName = "Example-tvOSTests"
+               ReferencedContainer = "container:Example.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "2D02E48F1E0B4A5D006451C7"
+               BuildableName = "Example-tvOSTests.xctest"
+               BlueprintName = "Example-tvOSTests"
+               ReferencedContainer = "container:Example.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
+            BuildableName = "Example-tvOS.app"
+            BlueprintName = "Example-tvOS"
+            ReferencedContainer = "container:Example.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
+            BuildableName = "Example-tvOS.app"
+            BlueprintName = "Example-tvOS"
+            ReferencedContainer = "container:Example.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
+            BuildableName = "Example-tvOS.app"
+            BlueprintName = "Example-tvOS"
+            ReferencedContainer = "container:Example.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 15 - 1
Example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme

@@ -3,9 +3,23 @@
    LastUpgradeVersion = "0820"
    LastUpgradeVersion = "0820"
    version = "1.3">
    version = "1.3">
    <BuildAction
    <BuildAction
-      parallelizeBuildables = "YES"
+      parallelizeBuildables = "NO"
       buildImplicitDependencies = "YES">
       buildImplicitDependencies = "YES">
       <BuildActionEntries>
       <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
+               BuildableName = "libReact.a"
+               BlueprintName = "React"
+               ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
          <BuildActionEntry
          <BuildActionEntry
             buildForTesting = "YES"
             buildForTesting = "YES"
             buildForRunning = "YES"
             buildForRunning = "YES"

+ 2 - 2
Example/ios/Example/AppDelegate.m

@@ -9,8 +9,8 @@
 
 
 #import "AppDelegate.h"
 #import "AppDelegate.h"
 
 
-#import "RCTBundleURLProvider.h"
-#import "RCTRootView.h"
+#import <React/RCTBundleURLProvider.h>
+#import <React/RCTRootView.h>
 
 
 @implementation AppDelegate
 @implementation AppDelegate
 
 

+ 20 - 4
Example/ios/Example/Info.plist

@@ -8,8 +8,6 @@
 	<string>$(EXECUTABLE_NAME)</string>
 	<string>$(EXECUTABLE_NAME)</string>
 	<key>CFBundleIdentifier</key>
 	<key>CFBundleIdentifier</key>
 	<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
 	<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
 	<key>CFBundleName</key>
 	<key>CFBundleName</key>
 	<string>$(PRODUCT_NAME)</string>
 	<string>$(PRODUCT_NAME)</string>
 	<key>CFBundlePackageType</key>
 	<key>CFBundlePackageType</key>
@@ -28,13 +26,31 @@
 		<dict>
 		<dict>
 			<key>localhost</key>
 			<key>localhost</key>
 			<dict>
 			<dict>
-				<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
+				<key>NSExceptionAllowsInsecureHTTPLoads</key>
 				<true/>
 				<true/>
 			</dict>
 			</dict>
 		</dict>
 		</dict>
 	</dict>
 	</dict>
+	<key>NSAppleMusicUsageDescription</key>
+	<string>test</string>
+	<key>NSBluetoothPeripheralUsageDescription</key>
+	<string>test</string>
+	<key>NSCalendarsUsageDescription</key>
+	<string>test</string>
+	<key>NSCameraUsageDescription</key>
+	<string>test</string>
+	<key>NSContactsUsageDescription</key>
+	<string>test</string>
+	<key>NSLocationAlwaysUsageDescription</key>
+	<string>test</string>
 	<key>NSLocationWhenInUseUsageDescription</key>
 	<key>NSLocationWhenInUseUsageDescription</key>
-	<string>We need your location</string>
+	<string>test</string>
+	<key>NSMicrophoneUsageDescription</key>
+	<string>6.0</string>
+	<key>NSPhotoLibraryUsageDescription</key>
+	<string>test</string>
+	<key>NSRemindersUsageDescription</key>
+	<string>test</string>
 	<key>UIBackgroundModes</key>
 	<key>UIBackgroundModes</key>
 	<array>
 	<array>
 		<string>bluetooth-peripheral</string>
 		<string>bluetooth-peripheral</string>

+ 1 - 1
Example/ios/Example/main.m

@@ -1,4 +1,4 @@
-  /**
+/**
  * Copyright (c) 2015-present, Facebook, Inc.
  * Copyright (c) 2015-present, Facebook, Inc.
  * All rights reserved.
  * All rights reserved.
  *
  *

+ 2 - 2
Example/ios/ExampleTests/ExampleTests.m

@@ -10,8 +10,8 @@
 #import <UIKit/UIKit.h>
 #import <UIKit/UIKit.h>
 #import <XCTest/XCTest.h>
 #import <XCTest/XCTest.h>
 
 
-#import "RCTLog.h"
-#import "RCTRootView.h"
+#import <React/RCTLog.h>
+#import <React/RCTRootView.h>
 
 
 #define TIMEOUT_SECONDS 600
 #define TIMEOUT_SECONDS 600
 #define TEXT_TO_LOOK_FOR @"Welcome to React Native!"
 #define TEXT_TO_LOOK_FOR @"Welcome to React Native!"

+ 21 - 11
Example/package.json

@@ -1,13 +1,23 @@
 {
 {
-  "name": "Example",
-  "version": "0.0.1",
-  "private": true,
-  "scripts": {
-    "start": "react-native start"
-  },
-  "dependencies": {
-    "react": "15.2.1",
-    "react-native": "^0.30.0",
+	"name": "Example",
+	"version": "0.0.1",
+	"private": true,
+	"scripts": {
+		"start": "react-native start",
+		"test": "jest"
+	},
+	"dependencies": {
+		"react": "15.4.2",
+		"react-native": "^0.41.0",
     "react-native-permissions": "../"
     "react-native-permissions": "../"
-  }
-}
+	},
+	"devDependencies": {
+		"babel-jest": "18.0.0",
+		"babel-preset-react-native": "1.9.1",
+		"jest": "18.1.0",
+		"react-test-renderer": "15.4.2"
+	},
+	"jest": {
+		"preset": "react-native"
+	}
+}

+ 1 - 1
RCTConvert+RNPStatus.h

@@ -6,7 +6,7 @@
 //  Copyright © 2016 Yonah Forst. All rights reserved.
 //  Copyright © 2016 Yonah Forst. All rights reserved.
 //
 //
 
 
-#import "RCTConvert.h"
+#import <React/RCTConvert.h>
 
 
 static NSString* RNPStatusUndetermined = @"undetermined";
 static NSString* RNPStatusUndetermined = @"undetermined";
 static NSString* RNPStatusDenied = @"denied";
 static NSString* RNPStatusDenied = @"denied";

+ 23 - 8
README.md

@@ -15,9 +15,11 @@ The current supported permissions are:
 - Speech Recognition *(iOS only)*
 - Speech Recognition *(iOS only)*
 
 
 
 
-###New in version 0.2.X
-- Android support 🎉🎉🍾
-- Example app
+| Version | React Native Support |
+|---|---|
+| 0.2.7 | 0.40.0 - 0.41.0 |
+| 0.2.5 | 0.33.0 - 0.39.0 |
+*Complies with [react-native-version-support-table](https://github.com/dangnelson/react-native-version-support-table)*
 
 
 ##General Usage
 ##General Usage
 ```
 ```
@@ -52,7 +54,7 @@ const Permissions = require('react-native-permissions');
 
 
   //check the status of multiple permissions
   //check the status of multiple permissions
   _checkCameraAndPhotos() {
   _checkCameraAndPhotos() {
-    Permissions.checkMultiplePermissions(['camera', 'photo', 'speechRecognition'])
+    Permissions.checkMultiplePermissions(['camera', 'photo'])
       .then(response => {
       .then(response => {
         //response is an object mapping type to permission
         //response is an object mapping type to permission
         this.setState({
         this.setState({
@@ -110,11 +112,12 @@ Promises resolve into one of these statuses
 |`notification`| ✔️ | ❌ |
 |`notification`| ✔️ | ❌ |
 |`backgroundRefresh`| ✔️ | ❌ |
 |`backgroundRefresh`| ✔️ | ❌ |
 |`speechRecognition`| ✔️ | ❌ |
 |`speechRecognition`| ✔️ | ❌ |
+|`storage`| ❌️ | ✔ |
 
 
 ###Methods
 ###Methods
 | Method Name | Arguments | Notes
 | Method Name | Arguments | Notes
 |---|---|---|
 |---|---|---|
-| `getPermissionStatus` | `type` | - Returns a promise with the permission status. Note: for type `location`, iOS `AuthorizedAlways` and `AuthorizedWhenInUse` both return `authorized` |
+| `getPermissionStatus` | `type` | - Returns a promise with the permission status. See iOS Notes for special cases |
 | `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. See iOS Notes for special cases|
 | `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. See iOS Notes for special cases|
 | `checkMultiplePermissions` | `[types]` | - Accepts an array of permission types and returns a promise with an object mapping permission types to statuses |
 | `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  |
 | `getPermissionTypes` | *none* | - Returns an array of valid permission types  |
@@ -124,11 +127,17 @@ Promises resolve into one of these statuses
 ###iOS Notes
 ###iOS Notes
 Permission type `bluetooth` represents the status of the `CBPeripheralManager`. Don't use this if only need `CBCentralManager`
 Permission type `bluetooth` represents the status of the `CBPeripheralManager`. Don't use this if only need `CBCentralManager`
 
 
-`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)
+Permission type `location` accepts a second parameter for `requestPermission` and `getPermissionStatus`;  the second parameter is a string, either `always` or `whenInUse`(default).
+
+Permission type `notification` accepts a second parameter for `requestPermission`. The second parameter is an array with the desired alert types. Any combination of `alert`, `badge` and `sound` (default requests all three)
+
 ```js
 ```js
 ///example
 ///example
+    Permissions.getPermissionStatus('location', 'always')
+      .then(response => {
+        this.setState({ locationPermission: response })
+      })
+
     Permissions.requestPermission('location', 'always')
     Permissions.requestPermission('location', 'always')
       .then(response => {
       .then(response => {
         this.setState({ locationPermission: response })
         this.setState({ locationPermission: response })
@@ -140,6 +149,8 @@ Permission type `bluetooth` represents the status of the `CBPeripheralManager`.
       })
       })
 ```
 ```
 
 
+You cannot request microphone permissions on the simulator.
+
 With Xcode 8, you now need to add usage descriptions for each permission you will request. Open Xcode > Info.plist > Add a key (starting with "Privacy - ...") with your kit specific permission.
 With Xcode 8, you now need to add usage descriptions for each permission you will request. Open Xcode > Info.plist > Add a key (starting with "Privacy - ...") with your kit specific permission.
 
 
 Example:
 Example:
@@ -162,6 +173,7 @@ Here's a map of types to Android system permissions names:
 `contacts` -> `android.permission.READ_CONTACTS`
 `contacts` -> `android.permission.READ_CONTACTS`
 `event` -> `android.permission.READ_CALENDAR`
 `event` -> `android.permission.READ_CALENDAR`
 
 
+
 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
 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
 
 
 ##Setup
 ##Setup
@@ -227,3 +239,6 @@ A: `rnpm` may not have linked correctly. Follow the manual linking steps and mak
 
 
 #### Q: iOS - app crashes as soon as I request permission
 #### Q: iOS - app crashes as soon as I request permission
 A: starting with xcode 8, you need to add permission descriptions. see iOS notes for more details. Thanks to @jesperlndk for discovering this.
 A: starting with xcode 8, you need to add permission descriptions. see iOS notes for more details. Thanks to @jesperlndk for discovering this.
+
+#### Q: iOS - app crashes when I change permissions from settings
+A: This is normal. iOS restarts your app when your privacy settings change. Just google "ios crash permission change"

+ 1 - 1
ReactNativePermissions.h

@@ -5,7 +5,7 @@
 //  Created by Yonah Forst on 18/02/16.
 //  Created by Yonah Forst on 18/02/16.
 //  Copyright © 2016 Yonah Forst. All rights reserved.
 //  Copyright © 2016 Yonah Forst. All rights reserved.
 //
 //
-#import "RCTBridgeModule.h"
+#import <React/RCTBridgeModule.h>
 
 
 #import <Foundation/Foundation.h>
 #import <Foundation/Foundation.h>
 
 

+ 5 - 4
ReactNativePermissions.js

@@ -25,6 +25,7 @@ const RNPTypes = {
 		'contacts',
 		'contacts',
 		'event',
 		'event',
 		'photo',
 		'photo',
+		'storage'
 	]
 	]
 }
 }
 
 
@@ -58,9 +59,9 @@ class ReactNativePermissions {
 	}
 	}
 
 
 
 
-	getPermissionStatus(permission) {
+	getPermissionStatus(permission, type) {
   	if (this.getPermissionTypes().indexOf(permission) >= 0) {
   	if (this.getPermissionTypes().indexOf(permission) >= 0) {
-			return RNPermissions.getPermissionStatus(permission)
+			return RNPermissions.getPermissionStatus(permission, type)
 		} else {
 		} else {
 			return Promise.reject(`ReactNativePermissions: ${permission} is not a valid permission type on ${Platform.OS}`)
 			return Promise.reject(`ReactNativePermissions: ${permission} is not a valid permission type on ${Platform.OS}`)
 		}
 		}
@@ -68,7 +69,7 @@ class ReactNativePermissions {
 
 
 	requestPermission(permission, type) {
 	requestPermission(permission, type) {
 		let options;
 		let options;
-		
+
 		if (this.getPermissionTypes().indexOf(permission) === -1) {
 		if (this.getPermissionTypes().indexOf(permission) === -1) {
 			return Promise.reject(`ReactNativePermissions: ${permission} is not a valid permission type on ${Platform.OS}`)
 			return Promise.reject(`ReactNativePermissions: ${permission} is not a valid permission type on ${Platform.OS}`)
 		} else if (permission == 'backgroundRefresh'){
 		} else if (permission == 'backgroundRefresh'){
@@ -90,7 +91,7 @@ class ReactNativePermissions {
 		function processNext() {
 		function processNext() {
 			i--
 			i--
 			let p = permissions[i]
 			let p = permissions[i]
-			
+
 			if (!p) {
 			if (!p) {
 				return Promise.resolve(obj)
 				return Promise.resolve(obj)
 			}
 			}

+ 8 - 7
ReactNativePermissions.m

@@ -10,9 +10,9 @@
 
 
 #import "ReactNativePermissions.h"
 #import "ReactNativePermissions.h"
 
 
-#import "RCTBridge.h"
-#import "RCTConvert.h"
-#import "RCTEventDispatcher.h"
+#import <React/RCTBridge.h>
+#import <React/RCTConvert.h>
+#import <React/RCTEventDispatcher.h>
 
 
 #import "RNPLocation.h"
 #import "RNPLocation.h"
 #import "RNPBluetooth.h"
 #import "RNPBluetooth.h"
@@ -67,15 +67,17 @@ RCT_EXPORT_METHOD(openSettings)
     }
     }
 }
 }
 
 
-RCT_REMAP_METHOD(getPermissionStatus, getPermissionStatus:(RNPType)type resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+RCT_REMAP_METHOD(getPermissionStatus, getPermissionStatus:(RNPType)type json:(id)json resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
 {
 {
     NSString *status;
     NSString *status;
     
     
     switch (type) {
     switch (type) {
             
             
-        case RNPTypeLocation:
-            status = [RNPLocation getStatus];
+        case RNPTypeLocation: {
+            NSString *locationPermissionType = [RCTConvert NSString:json];
+            status = [RNPLocation getStatusForType:locationPermissionType];
             break;
             break;
+        }
         case RNPTypeCamera:
         case RNPTypeCamera:
             status = [RNPAudioVideo getStatus:@"video"];
             status = [RNPAudioVideo getStatus:@"video"];
             break;
             break;
@@ -145,7 +147,6 @@ RCT_REMAP_METHOD(requestPermission, permissionType:(RNPType)type json:(id)json r
 
 
 }
 }
 
 
-
 - (void) requestLocation:(id)json resolve:(RCTPromiseResolveBlock)resolve
 - (void) requestLocation:(id)json resolve:(RCTPromiseResolveBlock)resolve
 {
 {
     if (self.locationMgr == nil) {
     if (self.locationMgr == nil) {

+ 6 - 3
android/src/main/java/com/joshblour/reactnativepermissions/ReactNativePermissionsModule.java

@@ -30,6 +30,7 @@ public class ReactNativePermissionsModule extends ReactContextBaseJavaModule {
     MICROPHONE,
     MICROPHONE,
     CONTACTS,
     CONTACTS,
     EVENT,
     EVENT,
+    STORAGE,
     PHOTO;
     PHOTO;
   }
   }
 
 
@@ -45,7 +46,7 @@ public class ReactNativePermissionsModule extends ReactContextBaseJavaModule {
   }
   }
 
 
   @ReactMethod
   @ReactMethod
-  public void getPermissionStatus(String permissionString, Promise promise) {
+  public void getPermissionStatus(String permissionString, String nullForiOSCompat, Promise promise) {
     String permission = permissionForString(permissionString);
     String permission = permissionForString(permissionString);
 
 
     // check if permission is valid
     // check if permission is valid
@@ -84,7 +85,7 @@ public class ReactNativePermissionsModule extends ReactContextBaseJavaModule {
     Callback resolve = new Callback() {
     Callback resolve = new Callback() {
       @Override
       @Override
       public void invoke(Object... args) {
       public void invoke(Object... args) {
-        getPermissionStatus(permissionString, promise);
+        getPermissionStatus(permissionString, "", promise);
       }
       }
     };
     };
     Callback reject = new Callback() {
     Callback reject = new Callback() {
@@ -93,7 +94,8 @@ public class ReactNativePermissionsModule extends ReactContextBaseJavaModule {
         // NOOP
         // NOOP
       }
       }
     };
     };
-    mPermissionsModule.requestPermission(permission, resolve, reject);
+
+    mPermissionsModule.requestPermission(permission, new PromiseImpl(resolve, reject));
   }
   }
 
 
 
 
@@ -126,6 +128,7 @@ public class ReactNativePermissionsModule extends ReactContextBaseJavaModule {
         return Manifest.permission.READ_CONTACTS;
         return Manifest.permission.READ_CONTACTS;
       case EVENT:
       case EVENT:
         return Manifest.permission.READ_CALENDAR;
         return Manifest.permission.READ_CALENDAR;
+      case STORAGE:
       case PHOTO:
       case PHOTO:
         return Manifest.permission.READ_EXTERNAL_STORAGE;
         return Manifest.permission.READ_EXTERNAL_STORAGE;
       default:
       default:

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "react-native-permissions",
   "name": "react-native-permissions",
-  "version": "0.2.4",
+  "version": "0.2.7",
   "repository": {
   "repository": {
     "type": "git",
     "type": "git",
     "url": "https://github.com/joshblour/react-native-permissions.git"
     "url": "https://github.com/joshblour/react-native-permissions.git"

+ 1 - 1
permissions/RNPLocation.h

@@ -11,7 +11,7 @@
 
 
 @interface RNPLocation : NSObject
 @interface RNPLocation : NSObject
 
 
-+ (NSString *)getStatus;
++ (NSString *)getStatusForType:(NSString *)type;
 - (void)request:(NSString *)type completionHandler:(void (^)(NSString *))completionHandler;
 - (void)request:(NSString *)type completionHandler:(void (^)(NSString *))completionHandler;
 
 
 @end
 @end

+ 14 - 9
permissions/RNPLocation.m

@@ -17,13 +17,14 @@
 
 
 @implementation RNPLocation
 @implementation RNPLocation
 
 
-+ (NSString *)getStatus
++ (NSString *)getStatusForType:(NSString *)type
 {
 {
     int status = [CLLocationManager authorizationStatus];
     int status = [CLLocationManager authorizationStatus];
     switch (status) {
     switch (status) {
         case kCLAuthorizationStatusAuthorizedAlways:
         case kCLAuthorizationStatusAuthorizedAlways:
-        case kCLAuthorizationStatusAuthorizedWhenInUse:
             return RNPStatusAuthorized;
             return RNPStatusAuthorized;
+        case kCLAuthorizationStatusAuthorizedWhenInUse:
+            return [type isEqualToString:@"always"] ? RNPStatusDenied : RNPStatusAuthorized;
         case kCLAuthorizationStatusDenied:
         case kCLAuthorizationStatusDenied:
             return RNPStatusDenied;
             return RNPStatusDenied;
         case kCLAuthorizationStatusRestricted:
         case kCLAuthorizationStatusRestricted:
@@ -35,22 +36,26 @@
 
 
 - (void)request:(NSString*)type completionHandler:(void (^)(NSString *))completionHandler
 - (void)request:(NSString*)type completionHandler:(void (^)(NSString *))completionHandler
 {
 {
-    NSString *status = [RNPLocation getStatus];
+    NSString *status = [RNPLocation getStatusForType:nil];
     if (status == RNPStatusUndetermined) {
     if (status == RNPStatusUndetermined) {
         self.completionHandler = completionHandler;
         self.completionHandler = completionHandler;
-        
+
         if (self.locationManager == nil) {
         if (self.locationManager == nil) {
             self.locationManager = [[CLLocationManager alloc] init];
             self.locationManager = [[CLLocationManager alloc] init];
             self.locationManager.delegate = self;
             self.locationManager.delegate = self;
         }
         }
-        
+
         if ([type isEqualToString:@"always"]) {
         if ([type isEqualToString:@"always"]) {
             [self.locationManager requestAlwaysAuthorization];
             [self.locationManager requestAlwaysAuthorization];
         } else {
         } else {
             [self.locationManager requestWhenInUseAuthorization];
             [self.locationManager requestWhenInUseAuthorization];
         }
         }
     } else {
     } else {
-        completionHandler(status);
+        if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse && [type isEqualToString:@"always"]) {
+            completionHandler(RNPStatusDenied);
+        } else {
+            completionHandler(status);
+        }
     }
     }
 }
 }
 
 
@@ -60,14 +65,14 @@
             self.locationManager.delegate = nil;
             self.locationManager.delegate = nil;
             self.locationManager = nil;
             self.locationManager = nil;
         }
         }
-        
+
         if (self.completionHandler) {
         if (self.completionHandler) {
             //for some reason, checking permission right away returns denied. need to wait a tiny bit
             //for some reason, checking permission right away returns denied. need to wait a tiny bit
             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
-                self.completionHandler([RNPLocation getStatus]);
+                self.completionHandler([RNPLocation getStatusForType:nil]);
                 self.completionHandler = nil;
                 self.completionHandler = nil;
             });
             });
-        }        
+        }
     }
     }
 }
 }
 @end
 @end

+ 12 - 31
permissions/RNPNotification.m

@@ -19,35 +19,21 @@ static NSString* RNPDidAskForNotification = @"RNPDidAskForNotification";
 + (NSString *)getStatus
 + (NSString *)getStatus
 {
 {
     BOOL didAskForPermission = [[NSUserDefaults standardUserDefaults] boolForKey:RNPDidAskForNotification];
     BOOL didAskForPermission = [[NSUserDefaults standardUserDefaults] boolForKey:RNPDidAskForNotification];
+    BOOL isRegistered = [[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
+    BOOL isEnabled = [[[UIApplication sharedApplication] currentUserNotificationSettings] types] != UIUserNotificationTypeNone;
     
     
-    if (didAskForPermission) {
-        if ([[UIApplication sharedApplication] respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
-            // iOS8+
-            BOOL isRegistered = [[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
-            BOOL isEnabled = [[[UIApplication sharedApplication] currentUserNotificationSettings] types] != UIUserNotificationTypeNone;
-            if (isRegistered || isEnabled) {
-                return isEnabled ? RNPStatusAuthorized : RNPStatusDenied;
-            }
-            else {
-                return RNPStatusDenied;
-            }
-        } else {
-            if ([[UIApplication sharedApplication] enabledRemoteNotificationTypes] == UIRemoteNotificationTypeNone) {
-                return RNPStatusDenied;
-            }
-            else {
-                return RNPStatusAuthorized;
-            }
-        }
+    if (isRegistered || isEnabled) {
+        return isEnabled ? RNPStatusAuthorized : RNPStatusDenied;
     } else {
     } else {
-        return RNPStatusUndetermined;
+        return didAskForPermission ? RNPStatusDenied : RNPStatusUndetermined;
     }
     }
 }
 }
 
 
 - (void)request:(UIUserNotificationType)types completionHandler:(void (^)(NSString*))completionHandler
 - (void)request:(UIUserNotificationType)types completionHandler:(void (^)(NSString*))completionHandler
 {
 {
-    BOOL didAskForPermission = [[NSUserDefaults standardUserDefaults] boolForKey:RNPDidAskForNotification];
-    if (!didAskForPermission) {
+    NSString *status = [self.class getStatus];
+    
+    if (status == RNPStatusUndetermined) {
         self.completionHandler = completionHandler;
         self.completionHandler = completionHandler;
         
         
         [[NSNotificationCenter defaultCenter] addObserver:self
         [[NSNotificationCenter defaultCenter] addObserver:self
@@ -55,19 +41,14 @@ static NSString* RNPDidAskForNotification = @"RNPDidAskForNotification";
                                                      name:UIApplicationDidBecomeActiveNotification
                                                      name:UIApplicationDidBecomeActiveNotification
                                                    object:nil];
                                                    object:nil];
         
         
-        if ([[UIApplication sharedApplication] respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
-            // iOS8+
-            UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
-            [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
-            [[UIApplication sharedApplication] registerForRemoteNotifications];
-        } else {
-            [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationType)types];
-        }
+        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
+        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
+        [[UIApplication sharedApplication] registerForRemoteNotifications];
         
         
         [[NSUserDefaults standardUserDefaults] setBool:YES forKey:RNPDidAskForNotification];
         [[NSUserDefaults standardUserDefaults] setBool:YES forKey:RNPDidAskForNotification];
         [[NSUserDefaults standardUserDefaults] synchronize];
         [[NSUserDefaults standardUserDefaults] synchronize];
     } else {
     } else {
-        completionHandler([self.class getStatus]);
+        completionHandler(status);
     }
     }
 }
 }