├── src ├── __tests__ │ └── index.test.tsx ├── NativeMlkitOcr.ts ├── index.ts └── index.d.ts ├── .gitattributes ├── tsconfig.build.json ├── example ├── app.json ├── android │ ├── app │ │ ├── debug.keystore │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ └── mipmap-xxxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── jni │ │ │ │ │ ├── MainApplicationModuleProvider.h │ │ │ │ │ ├── OnLoad.cpp │ │ │ │ │ ├── MainApplicationModuleProvider.cpp │ │ │ │ │ ├── MainComponentsRegistry.h │ │ │ │ │ ├── Android.mk │ │ │ │ │ ├── MainApplicationTurboModuleManagerDelegate.h │ │ │ │ │ ├── MainApplicationTurboModuleManagerDelegate.cpp │ │ │ │ │ └── MainComponentsRegistry.cpp │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── reactnativemlkitocr │ │ │ │ │ ├── newarchitecture │ │ │ │ │ ├── components │ │ │ │ │ │ └── MainComponentsRegistry.java │ │ │ │ │ ├── modules │ │ │ │ │ │ └── MainApplicationTurboModuleManagerDelegate.java │ │ │ │ │ └── MainApplicationReactNativeHost.java │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ └── debug │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── reactnativemlkitocr │ │ │ │ └── ReactNativeFlipper.java │ │ ├── proguard-rules.pro │ │ ├── build_defs.bzl │ │ ├── _BUCK │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ ├── gradle.properties │ ├── build.gradle │ ├── gradlew.bat │ └── gradlew ├── ios │ ├── MlkitOcrExample │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── AppDelegate.h │ │ ├── main.m │ │ ├── Info.plist │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ └── AppDelegate.mm │ ├── MlkitOcrExample.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Podfile │ ├── MlkitOcrExample.xcodeproj │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── MlkitOcrExample.xcscheme │ │ └── project.pbxproj │ └── Podfile.lock ├── index.js ├── babel.config.js ├── package.json ├── metro.config.js └── src │ └── App.tsx ├── babel.config.js ├── android ├── gradle.properties ├── src │ ├── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── reactnativemlkitocr │ │ │ ├── MlkitOcrPackage.kt │ │ │ └── MlkitOcrModuleImpl.kt │ ├── newarch │ │ └── java │ │ │ └── com │ │ │ └── reactnativemlkitocr │ │ │ └── MlkitOcrModule.kt │ └── oldarch │ │ └── java │ │ └── com │ │ └── reactnativemlkitocr │ │ └── MlkitOcrModule.kt └── build.gradle ├── ios ├── MlkitOcr.h ├── MlkitOcr.mm └── MlkitOcr.xcodeproj │ └── project.pbxproj ├── .editorconfig ├── .github └── FUNDING.yml ├── tsconfig.json ├── .gitignore ├── LICENSE ├── react-native-mlkit-ocr.podspec ├── README.md ├── .circleci └── config.yml ├── package.json └── CONTRIBUTING.md /src/__tests__/index.test.tsx: -------------------------------------------------------------------------------- 1 | it.todo('write a test'); 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["./example"] 4 | } 5 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MlkitOcrExample", 3 | "displayName": "MlkitOcr Example" 4 | } 5 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MlkitOcr Example 3 | 4 | -------------------------------------------------------------------------------- /example/ios/MlkitOcrExample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | MlkitOcr_kotlinVersion=1.6.10 2 | MlkitOcr_minSdkVersion=21 3 | MlkitOcr_compileSdkVersion=31 4 | MlkitOcr_targetSdkVersion=31 5 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agoldis/react-native-mlkit-ocr/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /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/MlkitOcrExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/MlkitOcr.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #ifdef RCT_NEW_ARCH_ENABLED 4 | 5 | #import "MlkitOcrSpec.h" 6 | @interface MlkitOcr : NSObject 7 | @end 8 | 9 | #else 10 | 11 | @interface MlkitOcr : NSObject 12 | @end 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/ios/MlkitOcrExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/MlkitOcrExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | indent_style = space 10 | indent_size = 2 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const pak = require('../package.json'); 3 | 4 | module.exports = { 5 | presets: ['module:metro-react-native-babel-preset'], 6 | plugins: [ 7 | [ 8 | 'module-resolver', 9 | { 10 | alias: { 11 | [pak.name]: path.join(__dirname, '..', pak.source), 12 | }, 13 | }, 14 | ], 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationModuleProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | std::shared_ptr MainApplicationModuleProvider( 12 | const std::string moduleName, 13 | const JavaTurboModule::InitParams ¶ms); 14 | 15 | } // namespace react 16 | } // namespace facebook 17 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/OnLoad.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "MainApplicationTurboModuleManagerDelegate.h" 3 | #include "MainComponentsRegistry.h" 4 | 5 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { 6 | return facebook::jni::initialize(vm, [] { 7 | facebook::react::MainApplicationTurboModuleManagerDelegate:: 8 | registerNatives(); 9 | facebook::react::MainComponentsRegistry::registerNatives(); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /example/ios/MlkitOcrExample/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/NativeMlkitOcr.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport'; 3 | import { TurboModuleRegistry } from 'react-native'; 4 | import type { MlkitOcrResult } from './index.d'; 5 | 6 | export interface Spec extends TurboModule { 7 | detectFromUri(imagePath: string): Promise; 8 | detectFromFile(imagePath: string): Promise; 9 | } 10 | 11 | // @ts-ignore 12 | export default TurboModuleRegistry.get('MlkitOcr'); 13 | -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [agoldis] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /example/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-mlkit-ocr-example", 3 | "description": "Example app for react-native-mlkit-ocr", 4 | "version": "0.0.1", 5 | "private": true, 6 | "scripts": { 7 | "android": "react-native run-android", 8 | "ios": "react-native run-ios", 9 | "start": "react-native start" 10 | }, 11 | "dependencies": { 12 | "react": "18.0.0", 13 | "react-native": "0.69.5", 14 | "react-native-image-picker": "^4.10.0", 15 | "react-native-mlkit-ocr": "link:../" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.12.9", 19 | "@babel/runtime": "^7.12.5", 20 | "babel-plugin-module-resolver": "^4.1.0", 21 | "metro-react-native-babel-preset": "^0.72.1", 22 | "pod-install": "^0.1.38" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "react-native-mlkit-ocr": ["./src/index"] 7 | }, 8 | "allowUnreachableCode": false, 9 | "allowUnusedLabels": false, 10 | "esModuleInterop": true, 11 | "importsNotUsedAsValues": "error", 12 | "forceConsistentCasingInFileNames": true, 13 | "jsx": "react", 14 | "lib": ["esnext"], 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "noFallthroughCasesInSwitch": true, 18 | "noImplicitReturns": true, 19 | "noImplicitUseStrict": false, 20 | "noStrictGenericChecks": false, 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "resolveJsonModule": true, 24 | "skipLibCheck": true, 25 | "strict": true, 26 | "target": "esnext" 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'MlkitOcrExample' 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 | if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") { 7 | include(":ReactAndroid") 8 | project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid') 9 | include(":ReactAndroid:hermes-engine") 10 | project(":ReactAndroid:hermes-engine").projectDir = file('../node_modules/react-native/ReactAndroid/hermes-engine') 11 | } 12 | 13 | include ':reactnativemlkitocr' 14 | project(':reactnativemlkitocr').projectDir = new File(rootProject.projectDir, '../../android') 15 | 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # XDE 6 | .expo/ 7 | 8 | # VSCode 9 | .vscode/ 10 | jsconfig.json 11 | 12 | # Xcode 13 | # 14 | build/ 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata 24 | *.xccheckout 25 | *.moved-aside 26 | DerivedData 27 | *.hmap 28 | *.ipa 29 | *.xcuserstate 30 | project.xcworkspace 31 | 32 | # Android/IJ 33 | # 34 | .idea 35 | .gradle 36 | local.properties 37 | android.iml 38 | 39 | # Cocoapods 40 | # 41 | example/ios/Pods 42 | 43 | # node.js 44 | # 45 | node_modules/ 46 | npm-debug.log 47 | yarn-debug.log 48 | yarn-error.log 49 | 50 | # BUCK 51 | buck-out/ 52 | \.buckd/ 53 | android/app/libs 54 | android/keystores/debug.keystore 55 | 56 | # Expo 57 | .expo/* 58 | 59 | # generated by bob 60 | lib/ 61 | -------------------------------------------------------------------------------- /android/src/newarch/java/com/reactnativemlkitocr/MlkitOcrModule.kt: -------------------------------------------------------------------------------- 1 | package com.reactnativemlkitocr 2 | 3 | import com.facebook.react.bridge.Promise 4 | import com.facebook.react.bridge.ReactApplicationContext 5 | 6 | class MlkitOcrModule(reactContext: ReactApplicationContext) : 7 | NativeMlkitOcrSpec(reactContext) { 8 | 9 | override fun getName(): String { 10 | return NAME 11 | } 12 | 13 | override fun detectFromUri(imagePath: String, promise: Promise) { 14 | return MlkitOcrModuleImpl.detectFromResource(this.reactApplicationContext, imagePath, promise) 15 | } 16 | 17 | override fun detectFromFile(imagePath: String, promise: Promise) { 18 | return MlkitOcrModuleImpl.detectFromResource(this.reactApplicationContext, imagePath, promise) 19 | } 20 | 21 | companion object { 22 | const val NAME = MlkitOcrModuleImpl.NAME 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationModuleProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "MainApplicationModuleProvider.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace facebook { 7 | namespace react { 8 | 9 | std::shared_ptr MainApplicationModuleProvider( 10 | const std::string moduleName, 11 | const JavaTurboModule::InitParams ¶ms) { 12 | // Here you can provide your own module provider for TurboModules coming from 13 | // either your application or from external libraries. The approach to follow 14 | // is similar to the following (for a library called `samplelibrary`: 15 | // 16 | auto module = mlkitocr_ModuleProvider(moduleName, params); 17 | if (module != nullptr) { 18 | return module; 19 | } 20 | return rncore_ModuleProvider(moduleName, params); 21 | } 22 | 23 | } // namespace react 24 | } // namespace facebook 25 | -------------------------------------------------------------------------------- /android/src/oldarch/java/com/reactnativemlkitocr/MlkitOcrModule.kt: -------------------------------------------------------------------------------- 1 | package com.reactnativemlkitocr 2 | 3 | import com.facebook.react.bridge.Promise 4 | import com.facebook.react.bridge.ReactApplicationContext 5 | import com.facebook.react.bridge.ReactContextBaseJavaModule 6 | import com.facebook.react.bridge.ReactMethod 7 | 8 | class MlkitOcrModule internal constructor(context: ReactApplicationContext?) : 9 | ReactContextBaseJavaModule(context) { 10 | 11 | override fun getName(): String { 12 | return MlkitOcrModuleImpl.NAME 13 | } 14 | 15 | @ReactMethod 16 | fun detectFromUri(imagePath: String, promise: Promise) { 17 | return MlkitOcrModuleImpl.detectFromResource(this.reactApplicationContext, imagePath, promise) 18 | } 19 | 20 | @ReactMethod 21 | fun detectFromFile(imagePath: String, promise: Promise) { 22 | return MlkitOcrModuleImpl.detectFromResource(this.reactApplicationContext, imagePath, promise) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules } from 'react-native'; 2 | import type { MlkitOcrResult } from './index.d'; 3 | 4 | export * from './index.d'; 5 | 6 | type MlkitOcrModule = { 7 | detectFromUri(uri: string): Promise; 8 | detectFromFile(path: string): Promise; 9 | }; 10 | 11 | // @ts-ignore 12 | const isTurboModuleEnabled = global.__turboModuleProxy != null; 13 | 14 | const MlkitOcr: MlkitOcrModule = isTurboModuleEnabled 15 | ? require('./NativeMlkitOcr').default 16 | : NativeModules.MlkitOcr; 17 | 18 | const MLKit: MlkitOcrModule = { 19 | detectFromUri: async (uri: string) => { 20 | const result = await MlkitOcr.detectFromUri(uri); 21 | if (!result) { 22 | return []; 23 | } 24 | return result; 25 | }, 26 | detectFromFile: async (path: string) => { 27 | const result = await MlkitOcr.detectFromFile(path); 28 | if (!result) { 29 | return []; 30 | } 31 | return result; 32 | }, 33 | }; 34 | 35 | export default MLKit; 36 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainComponentsRegistry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | class MainComponentsRegistry 12 | : public facebook::jni::HybridClass { 13 | public: 14 | // Adapt it to the package you used for your Java class. 15 | constexpr static auto kJavaDescriptor = 16 | "Lcom/example/reactnativemlkitocr/newarchitecture/components/MainComponentsRegistry;"; 17 | 18 | static void registerNatives(); 19 | 20 | MainComponentsRegistry(ComponentFactory *delegate); 21 | 22 | private: 23 | static std::shared_ptr 24 | sharedProviderRegistry(); 25 | 26 | static jni::local_ref initHybrid( 27 | jni::alias_ref, 28 | ComponentFactory *delegate); 29 | }; 30 | 31 | } // namespace react 32 | } // namespace facebook 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Andrew Goldis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /example/ios/MlkitOcrExample/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/metro.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const blacklist = require('metro-config/src/defaults/blacklist'); 3 | const escape = require('escape-string-regexp'); 4 | const pak = require('../package.json'); 5 | 6 | const root = path.resolve(__dirname, '..'); 7 | 8 | const modules = Object.keys({ 9 | ...pak.peerDependencies, 10 | }); 11 | 12 | module.exports = { 13 | projectRoot: __dirname, 14 | watchFolders: [root], 15 | 16 | // We need to make sure that only one version is loaded for peerDependencies 17 | // So we blacklist them at the root, and alias them to the versions in example's node_modules 18 | resolver: { 19 | blacklistRE: blacklist( 20 | modules.map( 21 | (m) => 22 | new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`) 23 | ) 24 | ), 25 | 26 | extraNodeModules: modules.reduce((acc, name) => { 27 | acc[name] = path.join(__dirname, 'node_modules', name); 28 | return acc; 29 | }, {}), 30 | }, 31 | 32 | transformer: { 33 | getTransformOptions: async () => ({ 34 | transform: { 35 | experimentalImportSupport: false, 36 | inlineRequires: true, 37 | }, 38 | }), 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/Android.mk: -------------------------------------------------------------------------------- 1 | THIS_DIR := $(call my-dir) 2 | 3 | include $(REACT_ANDROID_DIR)/Android-prebuilt.mk 4 | 5 | # MLKitOCR 6 | include $(REACT_ANDROID_DIR)/../../react-native-mlkit-ocr/android/build/generated/source/codegen/jni/Android.mk 7 | 8 | include $(CLEAR_VARS) 9 | 10 | LOCAL_PATH := $(THIS_DIR) 11 | 12 | # You can customize the name of your application .so file here. 13 | LOCAL_MODULE := mlkitocrexample_appmodules 14 | 15 | LOCAL_C_INCLUDES := $(LOCAL_PATH) 16 | LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) 17 | LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) 18 | 19 | LOCAL_SHARED_LIBRARIES := \ 20 | libfabricjni \ 21 | libfbjni \ 22 | libfolly_runtime \ 23 | libglog \ 24 | libjsi \ 25 | libreact_codegen_rncore \ 26 | libreact_debug \ 27 | libreact_nativemodule_core \ 28 | libreact_render_componentregistry \ 29 | libreact_render_core \ 30 | libreact_render_debug \ 31 | libreact_render_graphics \ 32 | librrc_view \ 33 | libruntimeexecutor \ 34 | libturbomodulejsijni \ 35 | libyoga 36 | 37 | # MLKitOCR 38 | LOCAL_SHARED_LIBRARIES += libreact_codegen_mlkitocr 39 | 40 | LOCAL_CFLAGS := -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++17 -Wall 41 | 42 | include $(BUILD_SHARED_LIBRARY) 43 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | namespace facebook { 8 | namespace react { 9 | 10 | class MainApplicationTurboModuleManagerDelegate 11 | : public jni::HybridClass< 12 | MainApplicationTurboModuleManagerDelegate, 13 | TurboModuleManagerDelegate> { 14 | public: 15 | // Adapt it to the package you used for your Java class. 16 | static constexpr auto kJavaDescriptor = 17 | "Lcom/example/reactnativemlkitocr/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;"; 18 | 19 | static jni::local_ref initHybrid(jni::alias_ref); 20 | 21 | static void registerNatives(); 22 | 23 | std::shared_ptr getTurboModule( 24 | const std::string name, 25 | const std::shared_ptr jsInvoker) override; 26 | std::shared_ptr getTurboModule( 27 | const std::string name, 28 | const JavaTurboModule::InitParams ¶ms) override; 29 | 30 | /** 31 | * Test-only method. Allows user to verify whether a TurboModule can be 32 | * created by instances of this class. 33 | */ 34 | bool canCreateTurboModule(std::string name); 35 | }; 36 | 37 | } // namespace react 38 | } // namespace facebook 39 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/reactnativemlkitocr/newarchitecture/components/MainComponentsRegistry.java: -------------------------------------------------------------------------------- 1 | package com.example.reactnativemlkitocr.newarchitecture.components; 2 | 3 | import com.facebook.jni.HybridData; 4 | import com.facebook.proguard.annotations.DoNotStrip; 5 | import com.facebook.react.fabric.ComponentFactory; 6 | import com.facebook.soloader.SoLoader; 7 | 8 | /** 9 | * Class responsible to load the custom Fabric Components. This class has native methods and needs a 10 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ 11 | * folder for you). 12 | * 13 | *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the 14 | * `newArchEnabled` property). Is ignored otherwise. 15 | */ 16 | @DoNotStrip 17 | public class MainComponentsRegistry { 18 | static { 19 | SoLoader.loadLibrary("fabricjni"); 20 | } 21 | 22 | @DoNotStrip private final HybridData mHybridData; 23 | 24 | @DoNotStrip 25 | private native HybridData initHybrid(ComponentFactory componentFactory); 26 | 27 | @DoNotStrip 28 | private MainComponentsRegistry(ComponentFactory componentFactory) { 29 | mHybridData = initHybrid(componentFactory); 30 | } 31 | 32 | @DoNotStrip 33 | public static MainComponentsRegistry register(ComponentFactory componentFactory) { 34 | return new MainComponentsRegistry(componentFactory); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /android/src/main/java/com/reactnativemlkitocr/MlkitOcrPackage.kt: -------------------------------------------------------------------------------- 1 | package com.reactnativemlkitocr 2 | 3 | import com.facebook.react.TurboReactPackage 4 | import com.facebook.react.bridge.NativeModule 5 | import com.facebook.react.bridge.ReactApplicationContext 6 | import com.facebook.react.module.annotations.ReactModule 7 | import com.facebook.react.module.model.ReactModuleInfo 8 | import com.facebook.react.module.model.ReactModuleInfoProvider 9 | import com.facebook.react.turbomodule.core.interfaces.TurboModule 10 | import java.util.* 11 | 12 | class MlkitOcrPackage : TurboReactPackage() { 13 | 14 | override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { 15 | return if (name == MlkitOcrModuleImpl.NAME) { 16 | MlkitOcrModule(reactContext) 17 | } else { 18 | null 19 | } 20 | } 21 | 22 | override fun getReactModuleInfoProvider(): ReactModuleInfoProvider { 23 | return ReactModuleInfoProvider { 24 | val moduleInfos: MutableMap = 25 | HashMap() 26 | val isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 27 | moduleInfos[MlkitOcrModuleImpl.NAME] = ReactModuleInfo( 28 | MlkitOcrModuleImpl.NAME, 29 | MlkitOcrModuleImpl.NAME, 30 | false, // canOverrideExistingModule 31 | false, // needsEagerInit 32 | true, // hasConstants 33 | false, // isCxxModule 34 | isTurboModule // isTurboModule 35 | ) 36 | moduleInfos 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | // https://developers.google.com/ml-kit/reference/android 2 | 3 | export type Point = { 4 | x: number; 5 | y: number; 6 | }; 7 | /** 8 | * The four corner points of the text block / line / element in 9 | * clockwise order starting with the top left 10 | * point relative to the image in the default 11 | * coordinate space. 12 | **/ 13 | export type CornerPoints = Array; 14 | 15 | /** 16 | * The rectangle that contains the text block / line / element 17 | * relative to the image in the default coordinate space. 18 | */ 19 | export type Bounding = { 20 | left: number; 21 | top: number; 22 | height: number; 23 | width: number; 24 | }; 25 | 26 | /** 27 | * A text element recognized in an image. 28 | * A text element is roughly equivalent to 29 | * a space-separated word in most Latin-script languages. 30 | */ 31 | export type MLKTextElement = { 32 | text: string; 33 | cornerPoints: CornerPoints; 34 | bounding: Bounding; 35 | }; 36 | 37 | /** 38 | * A text line recognized in an image that consists of an array of elements. 39 | * */ 40 | export type MLKTextLine = { 41 | text: string; 42 | elements: Array; 43 | cornerPoints: CornerPoints; 44 | bounding: Bounding; 45 | }; 46 | 47 | /** 48 | * A text block recognized in an image that consists of an array of text lines. 49 | */ 50 | export type MKLBlock = { 51 | text: string; 52 | lines: MLKTextLine[]; 53 | cornerPoints: CornerPoints; 54 | bounding: Bounding; 55 | }; 56 | 57 | export type MlkitOcrResult = MKLBlock[]; 58 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/reactnativemlkitocr/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.reactnativemlkitocr; 2 | 3 | import com.facebook.react.ReactActivity; 4 | import com.facebook.react.ReactActivityDelegate; 5 | import com.facebook.react.ReactRootView; 6 | 7 | public class MainActivity extends ReactActivity { 8 | 9 | /** 10 | * Returns the name of the main component registered from JavaScript. This is used to schedule 11 | * rendering of the component. 12 | */ 13 | @Override 14 | protected String getMainComponentName() { 15 | return "MlkitOcrExample"; 16 | } 17 | 18 | /** 19 | * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and 20 | * you can specify the rendered you wish to use (Fabric or the older renderer). 21 | */ 22 | @Override 23 | protected ReactActivityDelegate createReactActivityDelegate() { 24 | return new MainActivityDelegate(this, getMainComponentName()); 25 | } 26 | 27 | public static class MainActivityDelegate extends ReactActivityDelegate { 28 | public MainActivityDelegate(ReactActivity activity, String mainComponentName) { 29 | super(activity, mainComponentName); 30 | } 31 | 32 | @Override 33 | protected ReactRootView createRootView() { 34 | ReactRootView reactRootView = new ReactRootView(getContext()); 35 | // If you opted-in for the New Architecture, we enable the Fabric Renderer. 36 | reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED); 37 | return reactRootView; 38 | } 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /react-native-mlkit-ocr.podspec: -------------------------------------------------------------------------------- 1 | require "json" 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = package["name"] 7 | s.version = package["version"] 8 | s.summary = package["description"] 9 | s.description = package["description"] 10 | s.homepage = package["homepage"] 11 | s.license = package["license"] 12 | s.author = package["author"] 13 | 14 | s.platforms = { :ios => "10.0" } 15 | s.source = { :git => "https://github.com/agoldis/react-native-mlkit-ocr.git", :tag => "#{s.version}" } 16 | 17 | s.source_files = "ios/**/*.{h,m,mm}" 18 | 19 | s.dependency "GoogleMLKit/TextRecognition", "2.6.0" 20 | 21 | if ENV['RCT_NEW_ARCH_ENABLED'] == '1' 22 | folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' 23 | 24 | s.pod_target_xcconfig = { 25 | 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/boost" "$(PODS_ROOT)/boost-for-react-native" "$(PODS_ROOT)/RCT-Folly"', 26 | 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17', 27 | } 28 | 29 | s.compiler_flags = folly_compiler_flags + ' -DRN_FABRIC_ENABLED' 30 | 31 | s.dependency "React" 32 | s.dependency "React-RCTFabric" # This is for fabric component 33 | s.dependency "React-Codegen" 34 | s.dependency "RCT-Folly" 35 | s.dependency "RCTRequired" 36 | s.dependency "RCTTypeSafety" 37 | s.dependency "ReactCommon/turbomodule/core" 38 | else 39 | s.dependency "React-Core" 40 | end 41 | end 42 | 43 | -------------------------------------------------------------------------------- /example/android/app/_BUCK: -------------------------------------------------------------------------------- 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.example.reactnativemlkitocr", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.example.reactnativemlkitocr", 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 | ) 56 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | platform :ios, '12.4' 5 | install! 'cocoapods', :deterministic_uuids => false 6 | 7 | production = ENV["PRODUCTION"] == "1" 8 | 9 | target 'MlkitOcrExample' do 10 | config = use_native_modules! 11 | 12 | # Flags change depending on the env values. 13 | flags = get_default_flags() 14 | 15 | use_react_native!( 16 | :path => config[:reactNativePath], 17 | # to enable hermes on iOS, change `false` to `true` and then install pods 18 | :production => production, 19 | :hermes_enabled => flags[:hermes_enabled], 20 | :fabric_enabled => flags[:fabric_enabled], 21 | :flipper_configuration => FlipperConfiguration.enabled, 22 | # An absolute path to your application root. 23 | :app_path => "#{Pod::Config.instance.installation_root}/.." 24 | ) 25 | 26 | post_install do |installer| 27 | react_native_post_install(installer) 28 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 29 | 30 | # Apple M1 fix 31 | installer.pods_project.targets.each do |target| 32 | target.build_configurations.each do |config| 33 | config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' 34 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION'] 35 | # Disable arm64 builds for the simulator 36 | config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64' 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp: -------------------------------------------------------------------------------- 1 | #include "MainApplicationTurboModuleManagerDelegate.h" 2 | #include "MainApplicationModuleProvider.h" 3 | 4 | namespace facebook { 5 | namespace react { 6 | 7 | jni::local_ref 8 | MainApplicationTurboModuleManagerDelegate::initHybrid( 9 | jni::alias_ref) { 10 | return makeCxxInstance(); 11 | } 12 | 13 | void MainApplicationTurboModuleManagerDelegate::registerNatives() { 14 | registerHybrid({ 15 | makeNativeMethod( 16 | "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid), 17 | makeNativeMethod( 18 | "canCreateTurboModule", 19 | MainApplicationTurboModuleManagerDelegate::canCreateTurboModule), 20 | }); 21 | } 22 | 23 | std::shared_ptr 24 | MainApplicationTurboModuleManagerDelegate::getTurboModule( 25 | const std::string name, 26 | const std::shared_ptr jsInvoker) { 27 | // Not implemented yet: provide pure-C++ NativeModules here. 28 | return nullptr; 29 | } 30 | 31 | std::shared_ptr 32 | MainApplicationTurboModuleManagerDelegate::getTurboModule( 33 | const std::string name, 34 | const JavaTurboModule::InitParams ¶ms) { 35 | return MainApplicationModuleProvider(name, params); 36 | } 37 | 38 | bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule( 39 | std::string name) { 40 | return getTurboModule(name, nullptr) != nullptr || 41 | getTurboModule(name, {.moduleName = name}) != nullptr; 42 | } 43 | 44 | } // namespace react 45 | } // namespace facebook 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-mlkit-ocr 2 | 3 | > ⚠️ The project is not active anymore. I moved on to building [currents.dev](https://currents.dev) - All-in-one Dashboard for Playwright Testing. 4 | > 5 | 6 | > Consider using [rn-mlkit-ocr](https://github.com/ahmeterenodaci/rn-mlkit-ocr). 7 | 8 | > Cheers! 9 | 10 | --- 11 | 12 |

13 | Google on-device MLKit text recognition for React Native 14 |

15 | 16 |

17 | 18 |

19 | 20 | 21 | ## Installation 22 | 23 | ```sh 24 | npm install react-native-mlkit-ocr 25 | ``` 26 | ## Post-install Steps 27 | 28 | ### iOS 29 | Run 30 | 31 | ```js 32 | cd ios && pod install 33 | ``` 34 | 35 | ## Usage 36 | 37 | ```js 38 | import MlkitOcr from 'react-native-mlkit-ocr'; 39 | 40 | // ... 41 | 42 | const resultFromUri = await MlkitOcr.detectFromUri(uri); 43 | const resultFromFile = await MlkitOcr.detectFromFile(path); 44 | ``` 45 | 46 | 47 | ## Example 48 | 49 | To get started with the project, run `yarn bootstrap` in the root directory to install the required dependencies for each package: 50 | 51 | ```sh 52 | yarn bootstrap 53 | ``` 54 | 55 | To start the packager: 56 | 57 | ```sh 58 | yarn example start 59 | ``` 60 | 61 | To run the example app on Android: 62 | 63 | ```sh 64 | yarn example android 65 | ``` 66 | 67 | To run the example app on iOS: 68 | 69 | ```sh 70 | yarn example ios 71 | ``` 72 | 73 | ## Contributing 74 | 75 | See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. 76 | 77 | ## License 78 | 79 | MIT 80 | -------------------------------------------------------------------------------- /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.125.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 | -------------------------------------------------------------------------------- /example/ios/MlkitOcrExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | MlkitOcr Example 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 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationWhenInUseUsageDescription 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | NSPhotoLibraryUsageDescription 55 | Please allow use photo lib 56 | UIViewControllerBasedStatusBarAppearance 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/reactnativemlkitocr/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java: -------------------------------------------------------------------------------- 1 | package com.example.reactnativemlkitocr.newarchitecture.modules; 2 | 3 | import com.facebook.jni.HybridData; 4 | import com.facebook.react.ReactPackage; 5 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.soloader.SoLoader; 8 | import java.util.List; 9 | 10 | /** 11 | * Class responsible to load the TurboModules. This class has native methods and needs a 12 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ 13 | * folder for you). 14 | * 15 | *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the 16 | * `newArchEnabled` property). Is ignored otherwise. 17 | */ 18 | public class MainApplicationTurboModuleManagerDelegate 19 | extends ReactPackageTurboModuleManagerDelegate { 20 | 21 | private static volatile boolean sIsSoLibraryLoaded; 22 | 23 | protected MainApplicationTurboModuleManagerDelegate( 24 | ReactApplicationContext reactApplicationContext, List packages) { 25 | super(reactApplicationContext, packages); 26 | } 27 | 28 | protected native HybridData initHybrid(); 29 | 30 | native boolean canCreateTurboModule(String moduleName); 31 | 32 | public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder { 33 | protected MainApplicationTurboModuleManagerDelegate build( 34 | ReactApplicationContext context, List packages) { 35 | return new MainApplicationTurboModuleManagerDelegate(context, packages); 36 | } 37 | } 38 | 39 | @Override 40 | protected synchronized void maybeLoadOtherSoLibraries() { 41 | if (!sIsSoLibraryLoaded) { 42 | // If you change the name of your application .so file in the Android.mk file, 43 | // make sure you update the name here as well. 44 | SoLoader.loadLibrary("mlkitocrexample_appmodules"); 45 | sIsSoLibraryLoaded = true; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | import org.apache.tools.ant.taskdefs.condition.Os 2 | 3 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 4 | 5 | buildscript { 6 | ext { 7 | buildToolsVersion = "31.0.0" 8 | minSdkVersion = 21 9 | compileSdkVersion = 31 10 | targetSdkVersion = 31 11 | 12 | if (System.properties['os.arch'] == "aarch64") { 13 | // For M1 Users we need to use the NDK 24 which added support for aarch64 14 | ndkVersion = "24.0.8215888" 15 | } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { 16 | // For Android Users, we need to use NDK 23, otherwise the build will 17 | // fail due to paths longer than the OS limit 18 | ndkVersion = "23.1.7779620" 19 | } else { 20 | // Otherwise we default to the side-by-side NDK version from AGP. 21 | ndkVersion = "21.4.7075529" 22 | } 23 | } 24 | repositories { 25 | google() 26 | mavenCentral() 27 | } 28 | dependencies { 29 | classpath("com.android.tools.build:gradle:7.2.2") 30 | classpath("com.facebook.react:react-native-gradle-plugin") 31 | classpath("de.undercouch:gradle-download-task:5.0.1") 32 | // NOTE: Do not place your application dependencies here; they belong 33 | // in the individual module build.gradle files 34 | } 35 | } 36 | 37 | allprojects { 38 | repositories { 39 | maven { 40 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 41 | url("$rootDir/../node_modules/react-native/android") 42 | } 43 | maven { 44 | // Android JSC is installed from npm 45 | url("$rootDir/../node_modules/jsc-android/dist") 46 | } 47 | mavenCentral { 48 | // We don't want to fetch react-native from Maven Central as there are 49 | // older versions over there. 50 | content { 51 | excludeGroup "com.facebook.react" 52 | } 53 | } 54 | google() 55 | maven { url 'https://www.jitpack.io' } 56 | } 57 | } 58 | 59 | wrapper { 60 | gradleVersion = "7.3.3" 61 | distributionType = Wrapper.DistributionType.ALL 62 | } 63 | -------------------------------------------------------------------------------- /example/android/app/src/main/jni/MainComponentsRegistry.cpp: -------------------------------------------------------------------------------- 1 | #include "MainComponentsRegistry.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace facebook { 9 | namespace react { 10 | 11 | MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {} 12 | 13 | std::shared_ptr 14 | MainComponentsRegistry::sharedProviderRegistry() { 15 | auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry(); 16 | 17 | // Custom Fabric Components go here. You can register custom 18 | // components coming from your App or from 3rd party libraries here. 19 | // 20 | // providerRegistry->add(concreteComponentDescriptorProvider< 21 | // AocViewerComponentDescriptor>()); 22 | return providerRegistry; 23 | } 24 | 25 | jni::local_ref 26 | MainComponentsRegistry::initHybrid( 27 | jni::alias_ref, 28 | ComponentFactory *delegate) { 29 | auto instance = makeCxxInstance(delegate); 30 | 31 | auto buildRegistryFunction = 32 | [](EventDispatcher::Weak const &eventDispatcher, 33 | ContextContainer::Shared const &contextContainer) 34 | -> ComponentDescriptorRegistry::Shared { 35 | auto registry = MainComponentsRegistry::sharedProviderRegistry() 36 | ->createComponentDescriptorRegistry( 37 | {eventDispatcher, contextContainer}); 38 | 39 | auto mutableRegistry = 40 | std::const_pointer_cast(registry); 41 | 42 | mutableRegistry->setFallbackComponentDescriptor( 43 | std::make_shared( 44 | ComponentDescriptorParameters{ 45 | eventDispatcher, contextContainer, nullptr})); 46 | 47 | return registry; 48 | }; 49 | 50 | delegate->buildRegistryFunction = buildRegistryFunction; 51 | return instance; 52 | } 53 | 54 | void MainComponentsRegistry::registerNatives() { 55 | registerHybrid({ 56 | makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid), 57 | }); 58 | } 59 | 60 | } // namespace react 61 | } // namespace facebook 62 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | executors: 4 | default: 5 | docker: 6 | - image: circleci/node:10 7 | working_directory: ~/project 8 | 9 | commands: 10 | attach_project: 11 | steps: 12 | - attach_workspace: 13 | at: ~/project 14 | 15 | jobs: 16 | install-dependencies: 17 | executor: default 18 | steps: 19 | - checkout 20 | - attach_project 21 | - restore_cache: 22 | keys: 23 | - dependencies-{{ checksum "package.json" }} 24 | - dependencies- 25 | - restore_cache: 26 | keys: 27 | - dependencies-example-{{ checksum "example/package.json" }} 28 | - dependencies-example- 29 | - run: 30 | name: Install dependencies 31 | command: | 32 | yarn install --cwd example --frozen-lockfile 33 | yarn install --frozen-lockfile 34 | - save_cache: 35 | key: dependencies-{{ checksum "package.json" }} 36 | paths: node_modules 37 | - save_cache: 38 | key: dependencies-example-{{ checksum "example/package.json" }} 39 | paths: example/node_modules 40 | - persist_to_workspace: 41 | root: . 42 | paths: . 43 | 44 | lint: 45 | executor: default 46 | steps: 47 | - attach_project 48 | - run: 49 | name: Lint files 50 | command: | 51 | yarn lint 52 | 53 | typescript: 54 | executor: default 55 | steps: 56 | - attach_project 57 | - run: 58 | name: Typecheck files 59 | command: | 60 | yarn typescript 61 | 62 | unit-tests: 63 | executor: default 64 | steps: 65 | - attach_project 66 | - run: 67 | name: Run unit tests 68 | command: | 69 | yarn test --coverage 70 | - store_artifacts: 71 | path: coverage 72 | destination: coverage 73 | 74 | build-package: 75 | executor: default 76 | steps: 77 | - attach_project 78 | - run: 79 | name: Build package 80 | command: | 81 | yarn prepare 82 | 83 | workflows: 84 | build-and-test: 85 | jobs: 86 | - install-dependencies 87 | - lint: 88 | requires: 89 | - install-dependencies 90 | - typescript: 91 | requires: 92 | - install-dependencies 93 | - unit-tests: 94 | requires: 95 | - install-dependencies 96 | - build-package: 97 | requires: 98 | - install-dependencies 99 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/reactnativemlkitocr/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.reactnativemlkitocr; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import com.facebook.react.PackageList; 7 | import com.facebook.react.ReactApplication; 8 | import com.facebook.react.ReactInstanceManager; 9 | import com.facebook.react.ReactNativeHost; 10 | import com.facebook.react.ReactPackage; 11 | import com.facebook.react.config.ReactFeatureFlags; 12 | import com.facebook.soloader.SoLoader; 13 | import com.example.reactnativemlkitocr.newarchitecture.MainApplicationReactNativeHost; 14 | 15 | import java.lang.reflect.InvocationTargetException; 16 | import java.util.List; 17 | 18 | 19 | public class MainApplication extends Application implements ReactApplication { 20 | 21 | private final ReactNativeHost mReactNativeHost = 22 | new ReactNativeHost(this) { 23 | @Override 24 | public boolean getUseDeveloperSupport() { 25 | return BuildConfig.DEBUG; 26 | } 27 | 28 | @Override 29 | protected List getPackages() { 30 | @SuppressWarnings("UnnecessaryLocalVariable") 31 | List packages = new PackageList(this).getPackages(); 32 | // Packages that cannot be autolinked yet can be added manually here, for example: 33 | // packages.add(new MyReactNativePackage()); 34 | return packages; 35 | } 36 | 37 | @Override 38 | protected String getJSMainModuleName() { 39 | return "index"; 40 | } 41 | }; 42 | 43 | private final ReactNativeHost mNewArchitectureNativeHost = 44 | new MainApplicationReactNativeHost(this); 45 | 46 | @Override 47 | public ReactNativeHost getReactNativeHost() { 48 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 49 | return mNewArchitectureNativeHost; 50 | } else { 51 | return mReactNativeHost; 52 | } 53 | } 54 | 55 | @Override 56 | public void onCreate() { 57 | super.onCreate(); 58 | // If you opted-in for the New Architecture, we enable the TurboModule system 59 | ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; 60 | SoLoader.init(this, /* native exopackage */ false); 61 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 62 | } 63 | 64 | /** 65 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like 66 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 67 | * 68 | * @param context 69 | * @param reactInstanceManager 70 | */ 71 | private static void initializeFlipper( 72 | Context context, ReactInstanceManager reactInstanceManager) { 73 | if (BuildConfig.DEBUG) { 74 | try { 75 | /* 76 | We use reflection here to pick up the class that initializes Flipper, 77 | since Flipper library is not available in release mode 78 | */ 79 | Class aClass = Class.forName("com.example.reactnativemlkitocr.ReactNativeFlipper"); 80 | aClass 81 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) 82 | .invoke(null, context, reactInstanceManager); 83 | } catch (ClassNotFoundException e) { 84 | e.printStackTrace(); 85 | } catch (NoSuchMethodException e) { 86 | e.printStackTrace(); 87 | } catch (IllegalAccessException e) { 88 | e.printStackTrace(); 89 | } catch (InvocationTargetException e) { 90 | e.printStackTrace(); 91 | } 92 | } 93 | } 94 | } 95 | 96 | -------------------------------------------------------------------------------- /example/android/app/src/debug/java/com/example/reactnativemlkitocr/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.example.reactnativemlkitocr; 8 | 9 | import android.content.Context; 10 | import com.facebook.flipper.android.AndroidFlipperClient; 11 | import com.facebook.flipper.android.utils.FlipperUtils; 12 | import com.facebook.flipper.core.FlipperClient; 13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; 14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; 15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; 16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping; 17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; 18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; 19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; 20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin; 21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 22 | import com.facebook.react.ReactInstanceEventListener; 23 | import com.facebook.react.ReactInstanceManager; 24 | import com.facebook.react.bridge.ReactContext; 25 | import com.facebook.react.modules.network.NetworkingModule; 26 | import okhttp3.OkHttpClient; 27 | 28 | public class ReactNativeFlipper { 29 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 30 | if (FlipperUtils.shouldEnableFlipper(context)) { 31 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 32 | 33 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 34 | client.addPlugin(new ReactFlipperPlugin()); 35 | client.addPlugin(new DatabasesFlipperPlugin(context)); 36 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 37 | client.addPlugin(CrashReporterPlugin.getInstance()); 38 | 39 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 40 | NetworkingModule.setCustomClientBuilder( 41 | new NetworkingModule.CustomClientBuilder() { 42 | @Override 43 | public void apply(OkHttpClient.Builder builder) { 44 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 45 | } 46 | }); 47 | client.addPlugin(networkFlipperPlugin); 48 | client.start(); 49 | 50 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 51 | // Hence we run if after all native modules have been initialized 52 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 53 | if (reactContext == null) { 54 | reactInstanceManager.addReactInstanceEventListener( 55 | new ReactInstanceEventListener() { 56 | @Override 57 | public void onReactContextInitialized(ReactContext reactContext) { 58 | reactInstanceManager.removeReactInstanceEventListener(this); 59 | reactContext.runOnNativeModulesQueueThread( 60 | new Runnable() { 61 | @Override 62 | public void run() { 63 | client.addPlugin(new FrescoFlipperPlugin()); 64 | } 65 | }); 66 | } 67 | }); 68 | } else { 69 | client.addPlugin(new FrescoFlipperPlugin()); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /example/src/App.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react-native/no-inline-styles */ 2 | import * as React from 'react'; 3 | import { 4 | StyleSheet, 5 | View, 6 | Button, 7 | SafeAreaView, 8 | ScrollView, 9 | Text, 10 | Dimensions, 11 | ActivityIndicator, 12 | } from 'react-native'; 13 | import { Asset, launchImageLibrary } from 'react-native-image-picker'; 14 | import MlkitOcr, { MlkitOcrResult } from 'react-native-mlkit-ocr'; 15 | 16 | export default function App() { 17 | const [loading, setLoading] = React.useState(false); 18 | const [result, setResult] = React.useState(); 19 | const [image, setImage] = React.useState(); 20 | 21 | if (loading) { 22 | return ( 23 | 24 | 25 | 26 | ); 27 | } 28 | return ( 29 | 30 | {!!result?.length && ( 31 | 40 | {result?.map((block) => { 41 | return block.lines.map((line) => { 42 | return ( 43 | 54 | {line.text} 55 | 56 | ); 57 | }); 58 | })} 59 | 60 | )} 61 | 62 |