Skip to content

Commit a4d3b24

Browse files
authored
[tfjs-react-native] add rn integration app (#1840)
INTERNAL Adds a react native app that can be used for integration testing.
1 parent b9e43bb commit a4d3b24

File tree

71 files changed

+10858
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+10858
-2
lines changed

tfjs-react-native/.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ tsconfig.json
2525
tslint.json
2626
yarn-error.log
2727
yarn.lock
28+
integration_rn59

tfjs-react-native/README.md

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,82 @@
11
# Platform Adapter for React Native
22

3-
Status: Early development.
3+
Status: __Early development__. This is still an unpublished experimental package.
4+
5+
## Adapter Docs
6+
7+
TODO
8+
9+
## Setting up a React Native app with tfjs-react-native
10+
11+
These instructions assume that you are generally familiar with [react native](https://facebook.github.io/react-native/) developement. This library has only been tested with React Native 0.58.X & 0.59.X. React Native 0.60 is not supported.
12+
13+
### Step 1. Create your react native app.
14+
15+
You can use the [React Native CLI](https://facebook.github.io/react-native/docs/getting-started) or [Expo](https://expo.io/). This library relies on a couple of dependencies from the Expo project so it may be convenient to use expo but is not mandatory.
16+
17+
On macOS (to develop iOS applications) You will also need to use Cocoapods to install these dependencies.
18+
19+
### Step 2: Install expo related libraries
20+
21+
Depending on which workflow you used to set up your app you will need to install different dependencies.
22+
23+
- React Native CLI App
24+
- Install and configure [react-native-unimodules](https://github.com/unimodules/react-native-unimodules)
25+
- Install and configure [expo-gl-cpp](https://github.com/expo/expo/tree/master/packages/expo-gl-cpp) and [expo-gl](https://github.com/expo/expo/tree/master/packages/expo-gl)
26+
- Expo Bare App
27+
- Install and configure [expo-gl-cpp](https://github.com/expo/expo/tree/master/packages/expo-gl-cpp) and [expo-gl](https://github.com/expo/expo/tree/master/packages/expo-gl)
28+
- Expo Managed App
29+
- Install and configure [expo-gl](https://github.com/expo/expo/tree/master/packages/expo-gl)
30+
31+
32+
Note if in a _managed_ expo application these libraries should be present and you should be able to skip this step.
33+
34+
Install and configure [react-native-unimodules](https://github.com/unimodules/react-native-unimodules)
35+
Install and configure [expo-gl-cpp](https://github.com/expo/expo/tree/master/packages/expo-gl-cpp) and [expo-gl](https://github.com/expo/expo/tree/master/packages/expo-gl)
36+
37+
> After this point, if you are using XCode to build for ios, you should use a ‘.workspace’ file instead of the ‘.xcodeproj’
38+
39+
### Step 3: Configure [Metro](https://facebook.github.io/metro/en/)
40+
41+
Edit your `metro.config.js` to look like the following. Changes are noted in
42+
the comments below.
43+
44+
```js
45+
// Change 1
46+
const blacklist = require('metro-config/src/defaults/blacklist');
47+
48+
module.exports = {
49+
transformer: {
50+
getTransformOptions: async () => ({
51+
transform: {
52+
experimentalImportSupport: false,
53+
inlineRequires: false,
54+
},
55+
}),
56+
},
57+
resolver: {
58+
// Change 2 (add 'bin' to assetExts)
59+
assetExts: ['bin', 'txt', 'jpg'],
60+
sourceExts: ['js', 'json', 'ts', 'tsx', 'jsx'],
61+
// Change 3
62+
blacklistRE: blacklist([/platform_node/])
63+
},
64+
};
65+
```
66+
67+
68+
### Step 4: Install TensorFlow.js and tfjs-react-native
69+
70+
- Install @tensorflow/tfjs - `npm install @tensorflow/tfjs`
71+
- Install @tensorflow/tfjs-react-native - coming soon
72+
73+
### Step 5: Test that it is working
74+
75+
TODO: Add some sample code.
76+
77+
For now take a look at `integration_rn59/App.tsx` for an example of what using tfjs-react-native looks like.
78+
79+
### Optional Steps
80+
81+
If you want use the `AsyncStorageHandler` to save and load models, add [async-storage](https://github.com/react-native-community/async-storage) to your project.
82+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
[android]
3+
target = Google Inc.:Google APIs:23
4+
5+
[maven_repositories]
6+
central = https://repo1.maven.org/maven2
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.pbxproj -text
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# OSX
2+
#
3+
.DS_Store
4+
5+
# Xcode
6+
#
7+
build/
8+
*.pbxuser
9+
!default.pbxuser
10+
*.mode1v3
11+
!default.mode1v3
12+
*.mode2v3
13+
!default.mode2v3
14+
*.perspectivev3
15+
!default.perspectivev3
16+
xcuserdata
17+
*.xccheckout
18+
*.moved-aside
19+
DerivedData
20+
*.hmap
21+
*.ipa
22+
*.xcuserstate
23+
project.xcworkspace
24+
25+
# Android/IntelliJ
26+
#
27+
build/
28+
.idea
29+
.gradle
30+
local.properties
31+
*.iml
32+
33+
# Visual Studio Code
34+
#
35+
.vscode/
36+
37+
# node.js
38+
#
39+
node_modules/
40+
npm-debug.log
41+
yarn-error.log
42+
43+
# BUCK
44+
buck-out/
45+
\.buckd/
46+
*.keystore
47+
48+
# fastlane
49+
#
50+
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
51+
# screenshots whenever they are needed.
52+
# For more information about the recommended setup visit:
53+
# https://docs.fastlane.tools/best-practices/source-control/
54+
55+
*/fastlane/report.xml
56+
*/fastlane/Preview.html
57+
*/fastlane/screenshots
58+
59+
# Bundle artifact
60+
*.jsbundle
61+
62+
# CocoaPods
63+
/ios/Pods/
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google LLC. All Rights Reserved.
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
* =============================================================================
16+
*/
17+
18+
import React, { Fragment } from 'react';
19+
import { Button, SafeAreaView, StyleSheet, ScrollView, View, Text, StatusBar } from 'react-native';
20+
21+
import * as tf from '@tensorflow/tfjs';
22+
import '@tensorflow/tfjs-react-native';
23+
24+
import { Diagnostic } from './components/diagnostic';
25+
import { MobilenetDemo } from './components/mobilenet_demo';
26+
27+
export type Screen = 'main' | 'diag' | 'demo';
28+
29+
interface AppState {
30+
isTfReady: boolean;
31+
currentScreen: Screen;
32+
}
33+
34+
export class App extends React.Component<{}, AppState> {
35+
constructor(props: {}) {
36+
super(props);
37+
this.state = {
38+
isTfReady: false,
39+
currentScreen: 'main'
40+
};
41+
42+
this.showDiagnosticScreen = this.showDiagnosticScreen.bind(this);
43+
this.showDemoScreen = this.showDemoScreen.bind(this);
44+
this.showMainScreen = this.showMainScreen.bind(this);
45+
}
46+
47+
async componentDidMount() {
48+
await tf.setBackend('rn-webgl');
49+
await tf.ready();
50+
this.setState({
51+
isTfReady: true,
52+
});
53+
}
54+
55+
showDiagnosticScreen() {
56+
this.setState({ currentScreen: 'diag' });
57+
}
58+
59+
showDemoScreen() {
60+
this.setState({ currentScreen: 'demo' });
61+
}
62+
63+
showMainScreen() {
64+
this.setState({ currentScreen: 'main' });
65+
}
66+
67+
renderMainScreen() {
68+
return <Fragment>
69+
<View style={styles.sectionContainer}>
70+
<Text style={styles.sectionTitle}>Diagnostic</Text>
71+
<Button
72+
onPress={this.showDiagnosticScreen}
73+
title='Show Diagnostic Screen'
74+
/>
75+
</View>
76+
<View style={styles.sectionContainer}>
77+
<Text style={styles.sectionTitle}>Demo</Text>
78+
<Button
79+
onPress={this.showDemoScreen}
80+
title='Show Demo Screen'
81+
/>
82+
</View>
83+
</Fragment>;
84+
}
85+
86+
renderDiagnosticScreen() {
87+
return <Fragment>
88+
<Diagnostic returnToMain={this.showMainScreen} />
89+
</Fragment>;
90+
}
91+
92+
renderDemoScreen() {
93+
const image = require('./assets/images/catsmall.jpg');
94+
return <Fragment>
95+
<MobilenetDemo
96+
image={image}
97+
returnToMain={this.showMainScreen} />
98+
</Fragment>;
99+
}
100+
101+
renderLoadingTF() {
102+
return <Fragment>
103+
<View style={styles.sectionContainer}>
104+
<Text style={styles.sectionTitle}>Loading TF</Text>
105+
</View>
106+
</Fragment>;
107+
}
108+
109+
renderContent() {
110+
const { currentScreen, isTfReady } = this.state;
111+
if (isTfReady) {
112+
switch (currentScreen) {
113+
case 'main':
114+
return this.renderMainScreen();
115+
case 'diag':
116+
return this.renderDiagnosticScreen();
117+
case 'demo':
118+
return this.renderDemoScreen();
119+
default:
120+
return this.renderMainScreen();
121+
}
122+
} else {
123+
return this.renderLoadingTF();
124+
}
125+
126+
}
127+
128+
render() {
129+
return (
130+
<Fragment>
131+
<StatusBar barStyle='dark-content' />
132+
<SafeAreaView>
133+
<ScrollView
134+
contentInsetAdjustmentBehavior='automatic'
135+
style={styles.scrollView}>
136+
<View style={styles.body}>
137+
{this.renderContent()}
138+
</View>
139+
</ScrollView>
140+
</SafeAreaView>
141+
</Fragment>
142+
);
143+
}
144+
}
145+
146+
const styles = StyleSheet.create({
147+
scrollView: {
148+
backgroundColor: 'white',
149+
},
150+
body: {
151+
backgroundColor: 'white',
152+
},
153+
sectionContainer: {
154+
marginTop: 32,
155+
paddingHorizontal: 24,
156+
},
157+
sectionTitle: {
158+
fontSize: 24,
159+
fontWeight: '600',
160+
color: 'black',
161+
marginBottom: 6,
162+
},
163+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This is an app that serves and an integration testbed for tfjs-react-native.
2+
3+
For more info please see the [README](../README.md) in the folder above this one.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# To learn about Buck see [Docs](https://buckbuild.com/).
2+
# To run your application with Buck:
3+
# - install Buck
4+
# - `npm start` - to start the packager
5+
# - `cd android`
6+
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7+
# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8+
# - `buck install -r android/app` - compile, install and run application
9+
#
10+
11+
load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12+
13+
lib_deps = []
14+
15+
create_aar_targets(glob(["libs/*.aar"]))
16+
17+
create_jar_targets(glob(["libs/*.jar"]))
18+
19+
android_library(
20+
name = "all-libs",
21+
exported_deps = lib_deps,
22+
)
23+
24+
android_library(
25+
name = "app-code",
26+
srcs = glob([
27+
"src/main/java/**/*.java",
28+
]),
29+
deps = [
30+
":all-libs",
31+
":build_config",
32+
":res",
33+
],
34+
)
35+
36+
android_build_config(
37+
name = "build_config",
38+
package = "com.integration_rn59",
39+
)
40+
41+
android_resource(
42+
name = "res",
43+
package = "com.integration_rn59",
44+
res = "src/main/res",
45+
)
46+
47+
android_binary(
48+
name = "app",
49+
keystore = "//android/keystores:debug",
50+
manifest = "src/main/AndroidManifest.xml",
51+
package_type = "debug",
52+
deps = [
53+
":app-code",
54+
],
55+
)

0 commit comments

Comments
 (0)