Skip to content

Commit

Permalink
feat: migrate android to google ML Kit (react-native-camera#3272)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: migrate to Google ML Kit

* migrate to google ML Kit

* refactor: migrate android to google ML Kit

* refactor: migrate android general flavor to mlkit

* docs: update docs for MLKit

* docs: update installation doc

Co-authored-by: Mike Duminy <[email protected]>
Co-authored-by: Zhang Xuan <[email protected]>
  • Loading branch information
3 people authored Jul 16, 2021
1 parent 670b973 commit f72289f
Show file tree
Hide file tree
Showing 25 changed files with 490 additions and 532 deletions.
10 changes: 5 additions & 5 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,16 @@ repositories {
}

dependencies {
def googlePlayServicesVisionVersion = safeExtGet('googlePlayServicesVisionVersion', safeExtGet('googlePlayServicesVersion', '17.0.2'))

//noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+' // From node_modules
implementation "com.google.zxing:core:3.3.3"
implementation "com.drewnoakes:metadata-extractor:2.11.0"
generalImplementation "com.google.android.gms:play-services-vision:$googlePlayServicesVisionVersion"
implementation "androidx.exifinterface:exifinterface:1.3.2"
implementation "androidx.annotation:annotation:1.0.0"
implementation "androidx.legacy:legacy-support-v4:1.0.0"
mlkitImplementation "com.google.firebase:firebase-ml-vision:${safeExtGet('firebase-ml-vision', '19.0.3')}"
mlkitImplementation "com.google.firebase:firebase-ml-vision-face-model:${safeExtGet('firebase-ml-vision-face-model', '17.0.2')}"
implementation "com.google.android.gms:play-services-mlkit-text-recognition:16.3.0"
generalImplementation "com.google.android.gms:play-services-mlkit-barcode-scanning:16.2.0"
generalImplementation "com.google.android.gms:play-services-mlkit-face-detection:16.2.0"
mlkitImplementation "com.google.mlkit:barcode-scanning:16.2.0"
mlkitImplementation "com.google.mlkit:face-detection:16.1.2"
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.reactnative.barcodedetector;

import android.util.SparseArray;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.mlkit.vision.barcode.Barcode;

import java.util.Collections;
import java.util.HashMap;
Expand All @@ -18,33 +18,32 @@ public class BarcodeFormatUtils {
static {
// Initialize integer to string map
SparseArray<String> map = new SparseArray<>();
map.put(Barcode.CODE_128, "CODE_128");
map.put(Barcode.CODE_39, "CODE_39");
map.put(Barcode.CODE_93, "CODE_93");
map.put(Barcode.CODABAR, "CODABAR");
map.put(Barcode.DATA_MATRIX, "DATA_MATRIX");
map.put(Barcode.EAN_13, "EAN_13");
map.put(Barcode.EAN_8, "EAN_8");
map.put(Barcode.ITF, "ITF");
map.put(Barcode.QR_CODE, "QR_CODE");
map.put(Barcode.UPC_A, "UPC_A");
map.put(Barcode.UPC_E, "UPC_E");
map.put(Barcode.PDF417, "PDF417");
map.put(Barcode.AZTEC, "AZTEC");
map.put(Barcode.ALL_FORMATS, "ALL");
map.put(Barcode.CALENDAR_EVENT, "CALENDAR_EVENT");
map.put(Barcode.CONTACT_INFO, "CONTACT_INFO");
map.put(Barcode.DRIVER_LICENSE, "DRIVER_LICENSE");
map.put(Barcode.EMAIL, "EMAIL");
map.put(Barcode.GEO, "GEO");
map.put(Barcode.ISBN, "ISBN");
map.put(Barcode.PHONE, "PHONE");
map.put(Barcode.PRODUCT, "PRODUCT");
map.put(Barcode.SMS, "SMS");
map.put(Barcode.TEXT, "TEXT");
map.put(Barcode.UPC_A, "UPC_A");
map.put(Barcode.URL, "URL");
map.put(Barcode.WIFI, "WIFI");
map.put(Barcode.FORMAT_CODE_128, "CODE_128");
map.put(Barcode.FORMAT_CODE_39, "CODE_39");
map.put(Barcode.FORMAT_CODE_93, "CODE_93");
map.put(Barcode.FORMAT_CODABAR, "CODABAR");
map.put(Barcode.FORMAT_DATA_MATRIX, "DATA_MATRIX");
map.put(Barcode.FORMAT_EAN_13, "EAN_13");
map.put(Barcode.FORMAT_EAN_8, "EAN_8");
map.put(Barcode.FORMAT_ITF, "ITF");
map.put(Barcode.FORMAT_QR_CODE, "QR_CODE");
map.put(Barcode.FORMAT_UPC_A, "UPC_A");
map.put(Barcode.FORMAT_UPC_E, "UPC_E");
map.put(Barcode.FORMAT_PDF417, "PDF417");
map.put(Barcode.FORMAT_AZTEC, "AZTEC");
map.put(Barcode.FORMAT_ALL_FORMATS, "ALL");
map.put(Barcode.TYPE_CALENDAR_EVENT, "CALENDAR_EVENT");
map.put(Barcode.TYPE_CONTACT_INFO, "CONTACT_INFO");
map.put(Barcode.TYPE_DRIVER_LICENSE, "DRIVER_LICENSE");
map.put(Barcode.TYPE_EMAIL, "EMAIL");
map.put(Barcode.TYPE_GEO, "GEO");
map.put(Barcode.TYPE_ISBN, "ISBN");
map.put(Barcode.TYPE_PHONE, "PHONE");
map.put(Barcode.TYPE_PRODUCT, "PRODUCT");
map.put(Barcode.TYPE_SMS, "SMS");
map.put(Barcode.TYPE_TEXT, "TEXT");
map.put(Barcode.TYPE_URL, "URL");
map.put(Barcode.TYPE_WIFI, "WIFI");
map.put(-1, "None");
FORMATS = map;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
package org.reactnative.barcodedetector;

import android.content.Context;
import android.util.SparseArray;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;
import com.google.mlkit.vision.barcode.Barcode;
import com.google.mlkit.vision.barcode.BarcodeScanner;
import com.google.mlkit.vision.barcode.BarcodeScannerOptions;
import com.google.mlkit.vision.barcode.BarcodeScanning;

import org.reactnative.camera.utils.ImageDimensions;
import org.reactnative.frame.RNFrame;

import java.util.List;

public class RNBarcodeDetector {

public static int NORMAL_MODE = 0;
public static int ALTERNATE_MODE = 1;
public static int INVERTED_MODE = 2;
public static int ALL_FORMATS = Barcode.ALL_FORMATS;
public static int ALL_FORMATS = Barcode.FORMAT_ALL_FORMATS;

private BarcodeDetector mBarcodeDetector = null;
private BarcodeScanner mBarcodeDetector = null;
private ImageDimensions mPreviousDimensions;
private BarcodeDetector.Builder mBuilder;

private int mBarcodeType = Barcode.ALL_FORMATS;
private int mBarcodeType = Barcode.FORMAT_ALL_FORMATS;
private BarcodeScannerOptions.Builder mBuilder;

public RNBarcodeDetector(Context context) {
mBuilder = new BarcodeDetector.Builder(context)
mBuilder = new BarcodeScannerOptions.Builder()
.setBarcodeFormats(mBarcodeType);
}

Expand All @@ -32,10 +36,10 @@ public boolean isOperational() {
createBarcodeDetector();
}

return mBarcodeDetector.isOperational();
return true;
}

public SparseArray<Barcode> detect(RNFrame frame) {
public List<Barcode> detect(RNFrame frame) {
// If the frame has different dimensions, create another barcode detector.
// Otherwise we will most likely get nasty "inconsistent image dimensions" error from detector
// and no barcode will be detected.
Expand All @@ -48,7 +52,7 @@ public SparseArray<Barcode> detect(RNFrame frame) {
mPreviousDimensions = frame.getDimensions();
}

return mBarcodeDetector.detect(frame.getFrame());
return mBarcodeDetector.process(frame.getFrame()).getResult();
}

public void setBarcodeType(int barcodeType) {
Expand All @@ -69,12 +73,12 @@ public void release() {

private void releaseBarcodeDetector() {
if (mBarcodeDetector != null) {
mBarcodeDetector.release();
mBarcodeDetector.close();
mBarcodeDetector = null;
}
}

private void createBarcodeDetector() {
mBarcodeDetector = mBuilder.build();
mBarcodeDetector = BarcodeScanning.getClient(mBuilder.build());
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
package org.reactnative.camera.tasks;

import android.graphics.Rect;
import android.util.SparseArray;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.mlkit.vision.barcode.Barcode;

import org.reactnative.barcodedetector.BarcodeFormatUtils;
import org.reactnative.camera.utils.ImageDimensions;
import org.reactnative.frame.RNFrame;
import org.reactnative.frame.RNFrameFactory;
import org.reactnative.barcodedetector.RNBarcodeDetector;

public class BarcodeDetectorAsyncTask extends android.os.AsyncTask<Void, Void, SparseArray<Barcode>> {
import java.util.List;

public class BarcodeDetectorAsyncTask extends android.os.AsyncTask<Void, Void, List<Barcode>> {

private byte[] mImageData;
private int mWidth;
Expand Down Expand Up @@ -55,7 +56,7 @@ public BarcodeDetectorAsyncTask(
}

@Override
protected SparseArray<Barcode> doInBackground(Void... ignored) {
protected List<Barcode> doInBackground(Void... ignored) {
if (isCancelled() || mDelegate == null || mBarcodeDetector == null || !mBarcodeDetector.isOperational()) {
return null;
}
Expand All @@ -65,7 +66,7 @@ protected SparseArray<Barcode> doInBackground(Void... ignored) {
}

@Override
protected void onPostExecute(SparseArray<Barcode> barcodes) {
protected void onPostExecute(List<Barcode> barcodes) {
super.onPostExecute(barcodes);

if (barcodes == null) {
Expand All @@ -78,16 +79,16 @@ protected void onPostExecute(SparseArray<Barcode> barcodes) {
}
}

private WritableArray serializeEventData(SparseArray<Barcode> barcodes) {
private WritableArray serializeEventData(List<Barcode> barcodes) {
WritableArray barcodesList = Arguments.createArray();

for (int i = 0; i < barcodes.size(); i++) {
Barcode barcode = barcodes.valueAt(i);
Barcode barcode = barcodes.get(i);
WritableMap serializedBarcode = Arguments.createMap();

serializedBarcode.putString("data", barcode.displayValue);
serializedBarcode.putString("rawData", barcode.rawValue);
serializedBarcode.putString("type", BarcodeFormatUtils.get(barcode.format));
serializedBarcode.putString("data", barcode.getDisplayValue());
serializedBarcode.putString("rawData", barcode.getRawValue());
serializedBarcode.putString("type", BarcodeFormatUtils.get(barcode.getFormat()));
serializedBarcode.putMap("bounds", processBounds(barcode.getBoundingBox()));
barcodesList.pushMap(serializedBarcode);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package org.reactnative.camera.tasks;

import android.util.SparseArray;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.google.android.cameraview.CameraView;
import com.google.android.gms.vision.face.Face;
import com.google.mlkit.vision.face.Face;

import org.reactnative.camera.utils.ImageDimensions;
import org.reactnative.facedetector.FaceDetectorUtils;
import org.reactnative.frame.RNFrame;
import org.reactnative.frame.RNFrameFactory;
import org.reactnative.facedetector.RNFaceDetector;

public class FaceDetectorAsyncTask extends android.os.AsyncTask<Void, Void, SparseArray<Face>> {
import java.util.List;

public class FaceDetectorAsyncTask extends android.os.AsyncTask<Void, Void, List<Face>> {
private byte[] mImageData;
private int mWidth;
private int mHeight;
Expand Down Expand Up @@ -55,7 +55,7 @@ public FaceDetectorAsyncTask(
}

@Override
protected SparseArray<Face> doInBackground(Void... ignored) {
protected List<Face> doInBackground(Void... ignored) {
if (isCancelled() || mDelegate == null || mFaceDetector == null || !mFaceDetector.isOperational()) {
return null;
}
Expand All @@ -65,7 +65,7 @@ protected SparseArray<Face> doInBackground(Void... ignored) {
}

@Override
protected void onPostExecute(SparseArray<Face> faces) {
protected void onPostExecute(List<Face> faces) {
super.onPostExecute(faces);

if (faces == null) {
Expand All @@ -78,11 +78,11 @@ protected void onPostExecute(SparseArray<Face> faces) {
}
}

private WritableArray serializeEventData(SparseArray<Face> faces) {
private WritableArray serializeEventData(List<Face> faces) {
WritableArray facesList = Arguments.createArray();

for(int i = 0; i < faces.size(); i++) {
Face face = faces.valueAt(i);
Face face = faces.get(i);
WritableMap serializedFace = FaceDetectorUtils.serializeFace(face, mScaleX, mScaleY, mWidth, mHeight, mPaddingLeft, mPaddingTop);
if (mImageDimensions.getFacing() == CameraView.FACING_FRONT) {
serializedFace = FaceDetectorUtils.rotateFaceX(serializedFace, mImageDimensions.getWidth(), mScaleX);
Expand Down
Loading

0 comments on commit f72289f

Please sign in to comment.