packages = new PackageList(this).getPackages();
29 | // Packages that cannot be autolinked yet can be added manually here, for example:
30 | // packages.add(new MyReactNativePackage());
31 | return packages;
32 | }
33 |
34 | @Override
35 | protected String getJSMainModuleName() {
36 | return ".expo/.virtual-metro-entry";
37 | }
38 |
39 | @Override
40 | protected boolean isNewArchEnabled() {
41 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
42 | }
43 |
44 | @Override
45 | protected Boolean isHermesEnabled() {
46 | return BuildConfig.IS_HERMES_ENABLED;
47 | }
48 | });
49 |
50 | @Override
51 | public ReactNativeHost getReactNativeHost() {
52 | return mReactNativeHost;
53 | }
54 |
55 | @Override
56 | public void onCreate() {
57 | super.onCreate();
58 | SoLoader.init(this, /* native exopackage */ false);
59 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
60 | // If you opted-in for the New Architecture, we load the native entry point for this app.
61 | DefaultNewArchitectureEntryPoint.load();
62 | }
63 | ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
64 | ApplicationLifecycleDispatcher.onApplicationCreate(this);
65 | }
66 |
67 | @Override
68 | public void onConfigurationChanged(Configuration newConfig) {
69 | super.onConfigurationChanged(newConfig);
70 | ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
21 |
22 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RNMLKitExample
3 |
4 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/example/android/app/src/release/java/com/rnmlkitexample/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Meta Platforms, Inc. and affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.rnmlkitexample;
8 |
9 | import android.content.Context;
10 | import com.facebook.react.ReactInstanceManager;
11 |
12 | /**
13 | * Class responsible of loading Flipper inside your React Native application. This is the release
14 | * flavor of it so it's empty as we don't want to load Flipper.
15 | */
16 | public class ReactNativeFlipper {
17 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
18 | // Do nothing as we don't want to initialize Flipper on Release.
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = "33.0.0"
6 | minSdkVersion = 21
7 | compileSdkVersion = 33
8 | targetSdkVersion = 33
9 |
10 | // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
11 | ndkVersion = "23.1.7779620"
12 | }
13 | repositories {
14 | google()
15 | mavenCentral()
16 | }
17 | dependencies {
18 | classpath("com.android.tools.build:gradle")
19 | classpath("com.facebook.react:react-native-gradle-plugin")
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.182.0
29 |
30 | # Use this property to specify which architecture you want to build.
31 | # You can also override it from the CLI using
32 | # ./gradlew -PreactNativeArchitectures=x86_64
33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
34 |
35 | # Use this property to enable support to the new architecture.
36 | # This will allow you to use TurboModules and the Fabric render in
37 | # your application. You should enable this flag either if you want
38 | # to write custom TurboModules/Fabric components OR use libraries that
39 | # are providing them.
40 | newArchEnabled=false
41 |
42 | # Use this property to enable or disable the Hermes JS engine.
43 | # If set to false, you will be using JSC instead.
44 | hermesEnabled=true
45 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/a7medev/react-native-ml-kit/17d85166bca088baa3a62ed9d184e4e476c8b844/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'RNMLKitExample'
2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3 | include ':app'
4 | includeBuild('../node_modules/@react-native/gradle-plugin')
5 |
6 | apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle")
7 | useExpoModules()
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "RNMLKitExample",
3 | "displayName": "RNMLKitExample"
4 | }
5 |
--------------------------------------------------------------------------------
/example/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['babel-preset-expo'],
3 | };
4 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import {AppRegistry} from 'react-native';
2 | import App from './src/App';
3 | import {name as appName} from './app.json';
4 |
5 | AppRegistry.registerComponent(appName, () => App);
6 |
--------------------------------------------------------------------------------
/example/ios/.xcode.env:
--------------------------------------------------------------------------------
1 | export NODE_BINARY=$(command -v node)
2 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
2 | # Resolve react_native_pods.rb with node to allow for hoisting
3 | require Pod::Executable.execute_command('node', ['-p',
4 | 'require.resolve(
5 | "react-native/scripts/react_native_pods.rb",
6 | {paths: [process.argv[1]]},
7 | )', __dir__]).strip
8 |
9 | platform :ios, '13.0'
10 | prepare_react_native_project!
11 |
12 | # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
13 | # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
14 | #
15 | # To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
16 | # ```js
17 | # module.exports = {
18 | # dependencies: {
19 | # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
20 | # ```
21 | flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
22 |
23 | linkage = ENV['USE_FRAMEWORKS']
24 | if linkage != nil
25 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
26 | use_frameworks! :linkage => linkage.to_sym
27 | end
28 |
29 | target 'RNMLKitExample' do
30 | use_expo_modules!
31 | post_integrate do |installer|
32 | begin
33 | expo_patch_react_imports!(installer)
34 | rescue => e
35 | Pod::UI.warn e
36 | end
37 | end
38 | config = use_native_modules!
39 |
40 | # Flags change depending on the env values.
41 | flags = get_default_flags()
42 |
43 | use_react_native!(
44 | :path => config[:reactNativePath],
45 | # Hermes is now enabled by default. Disable by setting this flag to false.
46 | :hermes_enabled => flags[:hermes_enabled],
47 | :fabric_enabled => flags[:fabric_enabled],
48 | # Enables Flipper.
49 | #
50 | # Note that if you have use_frameworks! enabled, Flipper will not work and
51 | # you should disable the next line.
52 | :flipper_configuration => flipper_config,
53 | # An absolute path to your application root.
54 | :app_path => "#{Pod::Config.instance.installation_root}/.."
55 | )
56 |
57 | target 'RNMLKitExampleTests' do
58 | inherit! :complete
59 | # Pods for testing
60 | end
61 |
62 | post_install do |installer|
63 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
64 | react_native_post_install(
65 | installer,
66 | config[:reactNativePath],
67 | :mac_catalyst_enabled => false
68 | )
69 | __apply_Xcode_12_5_M1_post_install_workaround(installer)
70 |
71 | installer.pods_project.targets.each do |target|
72 | target.build_configurations.each do |config|
73 | config.build_settings["ONLY_ACTIVE_ARCH"] = "NO"
74 | end
75 | end
76 | end
77 | end
78 |
--------------------------------------------------------------------------------
/example/ios/RNMLKitExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/RNMLKitExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 |
5 | @interface AppDelegate : EXAppDelegateWrapper
6 |
7 | @end
8 |
--------------------------------------------------------------------------------
/example/ios/RNMLKitExample/AppDelegate.mm:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 |
5 | @implementation AppDelegate
6 |
7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
8 | {
9 | self.moduleName = @"RNMLKitExample";
10 | // You can add your custom initial props in the dictionary below.
11 | // They will be passed down to the ViewController used by React Native.
12 | self.initialProps = @{};
13 |
14 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
15 | }
16 |
17 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
18 | {
19 | #if DEBUG
20 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"];
21 | #else
22 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
23 | #endif
24 | }
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/example/ios/RNMLKitExample/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "scale" : "1x",
46 | "size" : "1024x1024"
47 | }
48 | ],
49 | "info" : {
50 | "author" : "xcode",
51 | "version" : 1
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/example/ios/RNMLKitExample/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/ios/RNMLKitExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | RNMLKitExample
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(CURRENT_PROJECT_VERSION)
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSExceptionDomains
30 |
31 | localhost
32 |
33 | NSExceptionAllowsInsecureHTTPLoads
34 |
35 |
36 |
37 |
38 | NSLocationWhenInUseUsageDescription
39 |
40 | UILaunchStoryboardName
41 | LaunchScreen
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UIViewControllerBasedStatusBarAppearance
53 |
54 | NSPhotoLibraryUsageDescription
55 | Give $(PRODUCT_NAME) permission to save photos
56 | NSCameraUsageDescription
57 | Give $(PRODUCT_NAME) permission to access your camera
58 | NSMicrophoneUsageDescription
59 | Give $(PRODUCT_NAME) permission to use your microphone
60 |
61 |
62 |
--------------------------------------------------------------------------------
/example/ios/RNMLKitExample/main.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char *argv[])
6 | {
7 | @autoreleasepool {
8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/example/ios/RNMLKitExampleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/example/ios/RNMLKitExampleTests/RNMLKitExampleTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to React"
9 |
10 | @interface RNMLKitExampleTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation RNMLKitExampleTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(
38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
39 | if (level >= RCTLogLevelError) {
40 | redboxError = message;
41 | }
42 | });
43 | #endif
44 |
45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
48 |
49 | foundElement = [self findSubviewInView:vc.view
50 | matching:^BOOL(UIView *view) {
51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
52 | return YES;
53 | }
54 | return NO;
55 | }];
56 | }
57 |
58 | #ifdef DEBUG
59 | RCTSetLogFunction(RCTDefaultLogFunction);
60 | #endif
61 |
62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/example/ios/_xcode.env:
--------------------------------------------------------------------------------
1 | # This `.xcode.env` file is versioned and is used to source the environment
2 | # used when running script phases inside Xcode.
3 | # To customize your local environment, you can create an `.xcode.env.local`
4 | # file that is not versioned.
5 |
6 | # NODE_BINARY variable contains the PATH to the node executable.
7 | #
8 | # Customize the NODE_BINARY variable here.
9 | # For example, to use nvm with brew, add the following line
10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use
11 | export NODE_BINARY=$(command -v node)
12 |
--------------------------------------------------------------------------------
/example/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'react-native',
3 | };
4 |
--------------------------------------------------------------------------------
/example/metro.config.js:
--------------------------------------------------------------------------------
1 | const {getDefaultConfig} = require('expo/metro-config');
2 | const {mergeConfig} = require('@react-native/metro-config');
3 | const path = require('path');
4 |
5 | /** @type {import('metro-config').MetroConfig} */
6 | const config = {
7 | watchFolders: [path.resolve(__dirname, '../')],
8 | resolver: {
9 | disableHierarchicalLookup: true,
10 | nodeModulesPaths: [path.resolve(__dirname, 'node_modules')],
11 | },
12 | };
13 |
14 | module.exports = mergeConfig(getDefaultConfig(__dirname), config);
15 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rnmlkitexample",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "lint": "eslint .",
9 | "start": "react-native start",
10 | "test": "jest"
11 | },
12 | "dependencies": {
13 | "@react-native-ml-kit/barcode-scanning": "link:../barcode-scanning",
14 | "@react-native-ml-kit/face-detection": "link:../face-detection",
15 | "@react-native-ml-kit/image-labeling": "link:../image-labeling",
16 | "@react-native-ml-kit/text-recognition": "link:../text-recognition",
17 | "@react-navigation/native": "^6.1.7",
18 | "@react-navigation/native-stack": "^6.9.13",
19 | "expo": "^49.0.0",
20 | "expo-image-picker": "~14.3.2",
21 | "react": "18.2.0",
22 | "react-native": "0.72.4",
23 | "react-native-safe-area-context": "^4.7.2",
24 | "react-native-screens": "^3.25.0",
25 | "react-native-svg": "^13.14.0"
26 | },
27 | "devDependencies": {
28 | "@babel/core": "^7.20.0",
29 | "@babel/preset-env": "^7.20.0",
30 | "@babel/runtime": "^7.22.15",
31 | "@react-native/eslint-config": "^0.72.2",
32 | "@react-native/metro-config": "^0.72.11",
33 | "@tsconfig/react-native": "^3.0.0",
34 | "@types/react": "^18.0.24",
35 | "@types/react-test-renderer": "^18.0.0",
36 | "babel-jest": "^29.2.1",
37 | "eslint": "^8.19.0",
38 | "jest": "^29.2.1",
39 | "metro-react-native-babel-preset": "0.76.8",
40 | "prettier": "^2.4.1",
41 | "react-test-renderer": "18.2.0",
42 | "typescript": "4.8.4"
43 | },
44 | "engines": {
45 | "node": ">=16"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/example/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {NavigationContainer} from '@react-navigation/native';
3 | import {createNativeStackNavigator} from '@react-navigation/native-stack';
4 | import TextRecognitionScreen from './text-recognition/TextRecognitionScreen';
5 | import FaceDetectionScreen from './face-detection/FaceDetectionScreen';
6 | import ImageLabelingScreen from './image-labeling/ImageLabelingScreen';
7 | import HomeScreen from './core/HomeScreen';
8 | import BarcodeScanningScreen from './barcode-scanning/BarcodeScanningScreen';
9 |
10 | export type ParamList = {
11 | Home: undefined;
12 | TextRecognition: undefined;
13 | BarcodeScanning: undefined;
14 | FaceDetection: undefined;
15 | ImageLabeling: undefined;
16 | };
17 |
18 | const Stack = createNativeStackNavigator();
19 |
20 | const App: React.FC = () => {
21 | return (
22 |
23 |
24 |
25 |
30 |
35 |
40 |
45 |
46 |
47 | );
48 | };
49 |
50 | export default App;
51 |
--------------------------------------------------------------------------------
/example/src/barcode-scanning/BarcodeScanningScreen.tsx:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react';
2 | import {Text, StyleSheet, View, FlatList} from 'react-native';
3 | import BarcodeScanning, {Barcode} from '@react-native-ml-kit/barcode-scanning';
4 | import ChooseImageButton, {ImageDetails} from '../core/ChooseImageButton';
5 | import LabelTile from '../core/LabelTile';
6 | import PreviewImage from '../core/PreviewImage';
7 |
8 | const BarcodeScanningScreen = () => {
9 | const [image, setImage] = useState();
10 | const [barcodes, setBarcodes] = useState([]);
11 |
12 | const handleChoose = async (currentImage: ImageDetails) => {
13 | setImage(currentImage);
14 |
15 | const result = await BarcodeScanning.scan(currentImage.path);
16 |
17 | setBarcodes(result);
18 | };
19 |
20 | return (
21 |
22 |
23 |
24 | {image && }
25 |
26 | {barcodes.length > 0 && (
27 | <>
28 | Barcodes
29 |
30 | `${barcode.format}-${barcode.value}`}
34 | renderItem={({item}) => (
35 |
36 | {item.value} - {item.format}
37 |
38 | )}
39 | />
40 | >
41 | )}
42 |
43 | );
44 | };
45 |
46 | const styles = StyleSheet.create({
47 | container: {
48 | flex: 1,
49 | justifyContent: 'center',
50 | alignItems: 'center',
51 | },
52 | heading: {
53 | fontSize: 20,
54 | marginBottom: 10,
55 | marginTop: 20,
56 | },
57 | list: {
58 | width: '100%',
59 | padding: 10,
60 | },
61 | });
62 |
63 | export default BarcodeScanningScreen;
64 |
--------------------------------------------------------------------------------
/example/src/core/ChooseImageButton.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Button} from 'react-native';
3 | import * as ImagePicker from 'expo-image-picker';
4 |
5 | export interface ImageDetails {
6 | path: string;
7 | height: number;
8 | width: number;
9 | }
10 |
11 | interface ChooseImageButtonProps {
12 | onChoose: (image: ImageDetails) => void;
13 | }
14 |
15 | const ChooseImageButton = ({onChoose}: ChooseImageButtonProps) => {
16 | const handlePress = async () => {
17 | const imageResult = await ImagePicker.launchImageLibraryAsync();
18 | if (imageResult.canceled) {
19 | return;
20 | }
21 |
22 | const asset = imageResult.assets![0];
23 | const currentImage = {
24 | path: asset.uri,
25 | width: asset.width,
26 | height: asset.height,
27 | };
28 |
29 | onChoose(currentImage);
30 | };
31 |
32 | return ;
33 | };
34 |
35 | export default ChooseImageButton;
36 |
--------------------------------------------------------------------------------
/example/src/core/HomeScreen.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {StyleSheet, View, Text} from 'react-native';
3 | import {NativeStackScreenProps} from '@react-navigation/native-stack';
4 | import ListTile from './ListTile';
5 | import type {ParamList} from '../App';
6 |
7 | const HomeScreen = ({navigation}: NativeStackScreenProps) => {
8 | return (
9 |
10 | React Native ML Kit
11 |
12 | navigation.navigate('TextRecognition')}
15 | />
16 | navigation.navigate('BarcodeScanning')}
19 | />
20 | navigation.navigate('FaceDetection')}
23 | />
24 | navigation.navigate('ImageLabeling')}
27 | />
28 |
29 | );
30 | };
31 |
32 | const styles = StyleSheet.create({
33 | title: {
34 | fontSize: 24,
35 | textAlign: 'center',
36 | fontWeight: 'bold',
37 | color: '#333',
38 | margin: 20,
39 | },
40 | });
41 |
42 | export default HomeScreen;
43 |
--------------------------------------------------------------------------------
/example/src/core/LabelTile.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {View, Text, StyleSheet} from 'react-native';
3 |
4 | interface LabelProps {
5 | children: React.ReactNode;
6 | }
7 |
8 | const LabelTile = ({children}: LabelProps) => {
9 | return (
10 |
11 | {children}
12 |
13 | );
14 | };
15 |
16 | const styles = StyleSheet.create({
17 | label: {
18 | backgroundColor: 'white',
19 | shadowColor: '#000',
20 | shadowOffset: {width: 0, height: 1},
21 | shadowOpacity: 0.2,
22 | shadowRadius: 1,
23 | elevation: 1,
24 | padding: 10,
25 | borderRadius: 5,
26 | marginBottom: 8,
27 | marginHorizontal: 10,
28 | alignItems: 'center',
29 | },
30 | });
31 |
32 | export default LabelTile;
33 |
--------------------------------------------------------------------------------
/example/src/core/ListTile.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {StyleSheet, Text, TouchableHighlight} from 'react-native';
3 |
4 | interface ListTileProps {
5 | title: string;
6 | onPress: () => void;
7 | }
8 |
9 | const ListTile = ({title, onPress}: ListTileProps) => {
10 | return (
11 |
15 | {title}
16 |
17 | );
18 | };
19 |
20 | const styles = StyleSheet.create({
21 | listTile: {
22 | paddingVertical: 16,
23 | paddingHorizontal: 24,
24 | borderBottomWidth: 1,
25 | borderBottomColor: '#ddd',
26 | backgroundColor: 'white',
27 | },
28 | title: {
29 | fontSize: 16,
30 | fontWeight: 'bold',
31 | color: '#333',
32 | },
33 | });
34 |
35 | export default ListTile;
36 |
--------------------------------------------------------------------------------
/example/src/core/OptionSwitch.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {StyleSheet, Switch, View, Text} from 'react-native';
3 |
4 | interface OptionSwitchProps {
5 | label: string;
6 | value: boolean;
7 | onChange: (value: boolean) => void;
8 | }
9 |
10 | const OptionSwitch = ({value, onChange, label}: OptionSwitchProps) => {
11 | return (
12 |
13 |
18 | {label}
19 |
20 | );
21 | };
22 |
23 | const styles = StyleSheet.create({
24 | switchContainer: {
25 | flexDirection: 'row',
26 | alignItems: 'center',
27 | marginTop: 10,
28 | },
29 | switchLabel: {
30 | color: '#333',
31 | marginLeft: 15,
32 | },
33 | });
34 |
35 | export default OptionSwitch;
36 |
--------------------------------------------------------------------------------
/example/src/core/PreviewImage.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {StyleSheet, Image} from 'react-native';
3 |
4 | interface PreviewImageProps {
5 | source: string;
6 | }
7 |
8 | const PreviewImage: React.FC = ({source}) => {
9 | return ;
10 | };
11 |
12 | const styles = StyleSheet.create({
13 | image: {
14 | aspectRatio: 1,
15 | width: '100%',
16 | objectFit: 'contain',
17 | backgroundColor: 'black',
18 | },
19 | });
20 |
21 | export default PreviewImage;
22 |
--------------------------------------------------------------------------------
/example/src/core/scaling.ts:
--------------------------------------------------------------------------------
1 | import {Frame, Point} from '@react-native-ml-kit/text-recognition';
2 |
3 | function rotateFrame(frame: Frame): Frame {
4 | return {
5 | top: frame.left,
6 | left: frame.top,
7 | width: frame.height,
8 | height: frame.width,
9 | };
10 | }
11 |
12 | function rotatePoint(point: Point): Point {
13 | return {x: point.y, y: point.x};
14 | }
15 |
16 | function shownDimensionsPortrait(
17 | screenWidth: number,
18 | imageWidth: number,
19 | imageHeight: number,
20 | ) {
21 | const shownHeight = screenWidth;
22 | const shownWidth = (imageWidth / imageHeight) * screenWidth;
23 |
24 | return {
25 | width: shownWidth,
26 | height: shownHeight,
27 | };
28 | }
29 |
30 | function scalePointPortrait(
31 | screenWidth: number,
32 | imageWidth: number,
33 | imageHeight: number,
34 | point: Point,
35 | ): Point {
36 | const shown = shownDimensionsPortrait(screenWidth, imageWidth, imageHeight);
37 | const xOffset = (screenWidth - shown.width) / 2;
38 |
39 | return {
40 | x: (shown.width / imageWidth) * point.x + xOffset,
41 | y: (shown.height / imageHeight) * point.y,
42 | };
43 | }
44 |
45 | export function scalePoint(
46 | imageWidth: number,
47 | imageHeight: number,
48 | screenWidth: number,
49 | ) {
50 | return function scaledPoint(point: Point): Point {
51 | const portrait = imageHeight > imageWidth;
52 |
53 | if (portrait) {
54 | return scalePointPortrait(screenWidth, imageWidth, imageHeight, point);
55 | }
56 |
57 | return rotatePoint(
58 | scalePointPortrait(
59 | screenWidth,
60 | imageHeight,
61 | imageWidth,
62 | rotatePoint(point),
63 | ),
64 | );
65 | };
66 | }
67 |
68 | function scaleFramePortrait(
69 | screenWidth: number,
70 | imageWidth: number,
71 | imageHeight: number,
72 | frame: Frame,
73 | ): Frame {
74 | const shown = shownDimensionsPortrait(screenWidth, imageWidth, imageHeight);
75 | const point = scalePointPortrait(screenWidth, imageWidth, imageHeight, {
76 | x: frame.left,
77 | y: frame.top,
78 | });
79 |
80 | return {
81 | left: point.x,
82 | top: point.y,
83 | width: (shown.width / imageWidth) * frame.width,
84 | height: (shown.height / imageHeight) * frame.height,
85 | };
86 | }
87 |
88 | export function scaleFrame(
89 | imageWidth: number,
90 | imageHeight: number,
91 | screenWidth: number,
92 | ) {
93 | return function scaledFrame(frame?: Frame): Frame | undefined {
94 | if (!frame) {
95 | return;
96 | }
97 |
98 | const portrait = imageHeight > imageWidth;
99 |
100 | if (portrait) {
101 | return scaleFramePortrait(screenWidth, imageWidth, imageHeight, frame);
102 | }
103 |
104 | return rotateFrame(
105 | scaleFramePortrait(
106 | screenWidth,
107 | imageHeight,
108 | imageWidth,
109 | rotateFrame(frame),
110 | ),
111 | );
112 | };
113 | }
114 |
--------------------------------------------------------------------------------
/example/src/face-detection/FaceDetectionScreen.tsx:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react';
2 | import {StyleSheet, View} from 'react-native';
3 | import FaceDetection, {Face} from '@react-native-ml-kit/face-detection';
4 |
5 | import FaceMap from './FaceMap';
6 | import ChooseImageButton, {ImageDetails} from '../core/ChooseImageButton';
7 | import OptionSwitch from '../core/OptionSwitch';
8 | import PreviewImage from '../core/PreviewImage';
9 |
10 | const FaceDetectionScreen = () => {
11 | const [image, setImage] = useState();
12 | const [faces, setFaces] = useState([]);
13 | const [showFrame, setShowFrame] = useState(true);
14 | const [showLandmarks, setShowLandmarks] = useState(false);
15 | const [showContours, setShowContours] = useState(false);
16 |
17 | const handleChoose = async (currentImage: ImageDetails) => {
18 | setImage(currentImage);
19 |
20 | const result = await FaceDetection.detect(currentImage.path, {
21 | landmarkMode: 'all',
22 | contourMode: 'all',
23 | });
24 |
25 | setFaces(result);
26 | };
27 |
28 | return (
29 |
30 |
31 |
32 | {image && (
33 |
34 |
35 |
36 | {faces.map(face => (
37 |
46 | ))}
47 |
48 |
53 |
58 |
63 |
64 | )}
65 |
66 | );
67 | };
68 |
69 | const styles = StyleSheet.create({
70 | container: {
71 | flex: 1,
72 | justifyContent: 'center',
73 | alignItems: 'center',
74 | },
75 | imageContainer: {
76 | marginTop: 15,
77 | marginBottom: 20,
78 | },
79 | });
80 |
81 | export default FaceDetectionScreen;
82 |
--------------------------------------------------------------------------------
/example/src/face-detection/FaceMap.tsx:
--------------------------------------------------------------------------------
1 | import {Face, Point} from '@react-native-ml-kit/face-detection';
2 | import React from 'react';
3 | import {StyleSheet, useWindowDimensions} from 'react-native';
4 | import Svg, {Circle, Path, Rect} from 'react-native-svg';
5 | import {scaleFrame, scalePoint} from '../core/scaling';
6 |
7 | interface FaceMapProps {
8 | face: Face;
9 | width: number;
10 | height: number;
11 | showLandmarks: boolean;
12 | showContours: boolean;
13 | showFrame: boolean;
14 | }
15 |
16 | const FaceMap = ({
17 | face,
18 | width,
19 | height,
20 | showLandmarks,
21 | showContours,
22 | showFrame,
23 | }: FaceMapProps) => {
24 | const screen = useWindowDimensions();
25 | const scaledFrame = scaleFrame(width, height, screen.width);
26 | const scaledPoint = scalePoint(width, height, screen.width);
27 |
28 | const {landmarks, contours} = face;
29 | const frame = scaledFrame(face.frame)!;
30 |
31 | function pointsToPath(points: Point[]) {
32 | return points
33 | .map(scaledPoint)
34 | .map(({x, y}, i) => `${i === 0 ? 'M' : 'L'} ${x} ${y} `)
35 | .join(' ');
36 | }
37 |
38 | return (
39 |
93 | );
94 | };
95 |
96 | const styles = StyleSheet.create({
97 | container: {
98 | position: 'absolute',
99 | },
100 | });
101 |
102 | export default FaceMap;
103 |
--------------------------------------------------------------------------------
/example/src/image-labeling/ImageLabelingScreen.tsx:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react';
2 | import {Text, StyleSheet, View, FlatList} from 'react-native';
3 | import ImageLabeling, {Label} from '@react-native-ml-kit/image-labeling';
4 | import ChooseImageButton, {ImageDetails} from '../core/ChooseImageButton';
5 | import PreviewImage from '../core/PreviewImage';
6 | import LabelTile from '../core/LabelTile';
7 |
8 | const ImageLabelingScreen = () => {
9 | const [image, setImage] = useState();
10 | const [labels, setLabels] = useState