diff --git a/mlkit/app/build.gradle b/mlkit/app/build.gradle
index 7843b3beef..8396a3b800 100644
--- a/mlkit/app/build.gradle
+++ b/mlkit/app/build.gradle
@@ -1,4 +1,6 @@
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 27
@@ -22,6 +24,10 @@ android {
}
dependencies {
+ implementation project(":internal:lintchecks")
+ implementation project(':internal:chooser')
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.70"
+
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
diff --git a/mlkit/app/src/main/AndroidManifest.xml b/mlkit/app/src/main/AndroidManifest.xml
index 12a78f45e1..13a242865b 100644
--- a/mlkit/app/src/main/AndroidManifest.xml
+++ b/mlkit/app/src/main/AndroidManifest.xml
@@ -17,8 +17,16 @@
+
+
+
+
+
+
@@ -27,12 +35,19 @@
-
+
+
-
+
+
+
+
+
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/EntryChoiceActivity.kt b/mlkit/app/src/main/java/EntryChoiceActivity.kt
new file mode 100644
index 0000000000..351d4a6e22
--- /dev/null
+++ b/mlkit/app/src/main/java/EntryChoiceActivity.kt
@@ -0,0 +1,25 @@
+package com.google.firebase.samples.apps.mlkit
+
+import android.content.Intent
+import com.firebase.example.internal.BaseEntryChoiceActivity
+import com.firebase.example.internal.Choice
+
+class EntryChoiceActivity : BaseEntryChoiceActivity() {
+
+ override fun getChoices(): List {
+ return listOf(
+ Choice(
+ "Java",
+ "Run the Firebase ML Kit quickstart written in Java.",
+ Intent(this,
+ com.google.firebase.samples.apps.mlkit.java.ChooserActivity::class.java)),
+ Choice(
+ "Kotlin",
+ "Run the Firebase ML Kit quickstart written in Kotlin.",
+ Intent(
+ this,
+ com.google.firebase.samples.apps.mlkit.kotlin.ChooserActivity::class.java))
+ )
+ }
+
+}
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/CameraSource.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/CameraSource.java
similarity index 99%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/CameraSource.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/CameraSource.java
index 98922014e0..79816f4937 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/CameraSource.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/CameraSource.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit;
+package com.google.firebase.samples.apps.mlkit.common;
import android.Manifest;
import android.annotation.SuppressLint;
@@ -577,7 +577,7 @@ public void onPreviewFrame(byte[] data, Camera camera) {
}
}
- void setMachineLearningFrameProcessor(VisionImageProcessor processor) {
+ public void setMachineLearningFrameProcessor(VisionImageProcessor processor) {
synchronized (processorLock) {
cleanScreen();
if (frameProcessor != null) {
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/CameraSourcePreview.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/CameraSourcePreview.java
similarity index 98%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/CameraSourcePreview.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/CameraSourcePreview.java
index a45858076c..af8d9f239c 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/CameraSourcePreview.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/CameraSourcePreview.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit;
+package com.google.firebase.samples.apps.mlkit.common;
import android.annotation.SuppressLint;
import android.content.Context;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/FrameMetadata.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/FrameMetadata.java
similarity index 97%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/FrameMetadata.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/FrameMetadata.java
index c562fc27f8..74270b386c 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/FrameMetadata.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/FrameMetadata.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit;
+package com.google.firebase.samples.apps.mlkit.common;
/** Describing a frame info. */
public class FrameMetadata {
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/GraphicOverlay.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/GraphicOverlay.java
similarity index 98%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/GraphicOverlay.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/GraphicOverlay.java
index 450e848224..1f73d7a7e2 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/GraphicOverlay.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/GraphicOverlay.java
@@ -11,11 +11,10 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit;
+package com.google.firebase.samples.apps.mlkit.common;
import android.content.Context;
import android.graphics.Canvas;
-import android.hardware.camera2.CameraCharacteristics;
import android.util.AttributeSet;
import android.view.View;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/VisionImageProcessor.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/VisionImageProcessor.java
similarity index 96%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/VisionImageProcessor.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/VisionImageProcessor.java
index f9e0d82597..a0586eaeaa 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/VisionImageProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/VisionImageProcessor.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit;
+package com.google.firebase.samples.apps.mlkit.common;
import android.graphics.Bitmap;
import android.media.Image;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/ChooserActivity.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/ChooserActivity.java
similarity index 96%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/ChooserActivity.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/ChooserActivity.java
index e4a816e201..b5383ad2b9 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/ChooserActivity.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/ChooserActivity.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit;
+package com.google.firebase.samples.apps.mlkit.java;
import android.content.Context;
import android.content.Intent;
@@ -31,6 +31,8 @@
import android.widget.ListView;
import android.widget.TextView;
+import com.google.firebase.samples.apps.mlkit.R;
+
import java.util.ArrayList;
import java.util.List;
@@ -61,7 +63,7 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_chooser);
// Set up ListView and Adapter
- ListView listView = (ListView) findViewById(R.id.test_activity_list_view);
+ ListView listView = (ListView) findViewById(R.id.testActivityListView);
MyArrayAdapter adapter = new MyArrayAdapter(this, android.R.layout.simple_list_item_2, CLASSES);
adapter.setDescriptionIds(DESCRIPTION_IDS);
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/LivePreviewActivity.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/LivePreviewActivity.java
similarity index 92%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/LivePreviewActivity.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/LivePreviewActivity.java
index 8b4dbd0945..84bf6dd09e 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/LivePreviewActivity.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/LivePreviewActivity.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit;
+package com.google.firebase.samples.apps.mlkit.java;
import android.content.Context;
import android.content.pm.PackageInfo;
@@ -32,11 +32,15 @@
import com.google.android.gms.common.annotation.KeepName;
import com.google.firebase.ml.common.FirebaseMLException;
-import com.google.firebase.samples.apps.mlkit.barcodescanning.BarcodeScanningProcessor;
-import com.google.firebase.samples.apps.mlkit.custommodel.CustomImageClassifierProcessor;
-import com.google.firebase.samples.apps.mlkit.facedetection.FaceDetectionProcessor;
-import com.google.firebase.samples.apps.mlkit.imagelabeling.ImageLabelingProcessor;
-import com.google.firebase.samples.apps.mlkit.textrecognition.TextRecognitionProcessor;
+import com.google.firebase.samples.apps.mlkit.R;
+import com.google.firebase.samples.apps.mlkit.common.CameraSource;
+import com.google.firebase.samples.apps.mlkit.common.CameraSourcePreview;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.java.barcodescanning.BarcodeScanningProcessor;
+import com.google.firebase.samples.apps.mlkit.java.custommodel.CustomImageClassifierProcessor;
+import com.google.firebase.samples.apps.mlkit.java.facedetection.FaceDetectionProcessor;
+import com.google.firebase.samples.apps.mlkit.java.imagelabeling.ImageLabelingProcessor;
+import com.google.firebase.samples.apps.mlkit.java.textrecognition.TextRecognitionProcessor;
import java.io.IOException;
import java.util.ArrayList;
@@ -93,7 +97,7 @@ protected void onCreate(Bundle savedInstanceState) {
spinner.setAdapter(dataAdapter);
spinner.setOnItemSelectedListener(this);
- ToggleButton facingSwitch = (ToggleButton) findViewById(R.id.facingswitch);
+ ToggleButton facingSwitch = (ToggleButton) findViewById(R.id.facingSwitch);
facingSwitch.setOnCheckedChangeListener(this);
if (allPermissionsGranted()) {
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/StillImageActivity.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/StillImageActivity.java
similarity index 95%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/StillImageActivity.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/StillImageActivity.java
index 252195c3da..d3b3037d69 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/StillImageActivity.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/StillImageActivity.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit;
+package com.google.firebase.samples.apps.mlkit.java;
import android.content.ContentValues;
import android.content.Intent;
@@ -37,12 +37,15 @@
import android.widget.Spinner;
import com.google.android.gms.common.annotation.KeepName;
-import com.google.firebase.samples.apps.mlkit.cloudimagelabeling.CloudImageLabelingProcessor;
-import com.google.firebase.samples.apps.mlkit.cloudlandmarkrecognition.CloudLandmarkRecognitionProcessor;
-import com.google.firebase.samples.apps.mlkit.cloudtextrecognition.CloudDocumentTextRecognitionProcessor;
+import com.google.firebase.samples.apps.mlkit.R;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.VisionImageProcessor;
+import com.google.firebase.samples.apps.mlkit.java.cloudimagelabeling.CloudImageLabelingProcessor;
+import com.google.firebase.samples.apps.mlkit.java.cloudlandmarkrecognition.CloudLandmarkRecognitionProcessor;
+import com.google.firebase.samples.apps.mlkit.java.cloudtextrecognition.CloudDocumentTextRecognitionProcessor;
-import com.google.firebase.samples.apps.mlkit.cloudtextrecognition.CloudTextRecognitionProcessor;
+import com.google.firebase.samples.apps.mlkit.java.cloudtextrecognition.CloudTextRecognitionProcessor;
import java.io.IOException;
import java.util.ArrayList;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/VisionProcessorBase.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/VisionProcessorBase.java
similarity index 94%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/VisionProcessorBase.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/VisionProcessorBase.java
index 87ca938ce5..f0fd97ac71 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/VisionProcessorBase.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/VisionProcessorBase.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit;
+package com.google.firebase.samples.apps.mlkit.java;
import android.graphics.Bitmap;
import android.media.Image;
@@ -22,6 +22,9 @@
import com.google.android.gms.tasks.Task;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.common.FirebaseVisionImageMetadata;
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.VisionImageProcessor;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/barcodescanning/BarcodeGraphic.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/barcodescanning/BarcodeGraphic.java
similarity index 91%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/barcodescanning/BarcodeGraphic.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/barcodescanning/BarcodeGraphic.java
index 2e32e83f3c..48aea82345 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/barcodescanning/BarcodeGraphic.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/barcodescanning/BarcodeGraphic.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.barcodescanning;
+package com.google.firebase.samples.apps.mlkit.java.barcodescanning;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -19,8 +19,8 @@
import android.graphics.RectF;
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay.Graphic;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay.Graphic;
/** Graphic instance for rendering Barcode position and content information in an overlay view. */
public class BarcodeGraphic extends Graphic {
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/barcodescanning/BarcodeScanningProcessor.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/barcodescanning/BarcodeScanningProcessor.java
similarity index 90%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/barcodescanning/BarcodeScanningProcessor.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/barcodescanning/BarcodeScanningProcessor.java
index 1008daf80b..2c1290b27f 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/barcodescanning/BarcodeScanningProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/barcodescanning/BarcodeScanningProcessor.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.barcodescanning;
+package com.google.firebase.samples.apps.mlkit.java.barcodescanning;
import android.support.annotation.NonNull;
import android.util.Log;
@@ -21,9 +21,9 @@
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode;
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetector;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
-import com.google.firebase.samples.apps.mlkit.FrameMetadata;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.VisionProcessorBase;
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.java.VisionProcessorBase;
import java.io.IOException;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudimagelabeling/CloudImageLabelingProcessor.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudimagelabeling/CloudImageLabelingProcessor.java
similarity index 90%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudimagelabeling/CloudImageLabelingProcessor.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudimagelabeling/CloudImageLabelingProcessor.java
index 71fa75eb7f..a2a7856b92 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudimagelabeling/CloudImageLabelingProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudimagelabeling/CloudImageLabelingProcessor.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.cloudimagelabeling;
+package com.google.firebase.samples.apps.mlkit.java.cloudimagelabeling;
import android.support.annotation.NonNull;
import android.util.Log;
@@ -22,9 +22,9 @@
import com.google.firebase.ml.vision.cloud.label.FirebaseVisionCloudLabel;
import com.google.firebase.ml.vision.cloud.label.FirebaseVisionCloudLabelDetector;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
-import com.google.firebase.samples.apps.mlkit.FrameMetadata;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.VisionProcessorBase;
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.java.VisionProcessorBase;
import java.util.ArrayList;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudimagelabeling/CloudLabelGraphic.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudimagelabeling/CloudLabelGraphic.java
similarity index 87%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudimagelabeling/CloudLabelGraphic.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudimagelabeling/CloudLabelGraphic.java
index d091349ec4..07c6bffa78 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudimagelabeling/CloudLabelGraphic.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudimagelabeling/CloudLabelGraphic.java
@@ -11,14 +11,14 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.cloudimagelabeling;
+package com.google.firebase.samples.apps.mlkit.java.cloudimagelabeling;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay.Graphic;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay.Graphic;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudlandmarkrecognition/CloudLandmarkGraphic.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudlandmarkrecognition/CloudLandmarkGraphic.java
similarity index 92%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudlandmarkrecognition/CloudLandmarkGraphic.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudlandmarkrecognition/CloudLandmarkGraphic.java
index e5d6a4e3f5..a2a13b9e01 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudlandmarkrecognition/CloudLandmarkGraphic.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudlandmarkrecognition/CloudLandmarkGraphic.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.cloudlandmarkrecognition;
+package com.google.firebase.samples.apps.mlkit.java.cloudlandmarkrecognition;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -19,8 +19,8 @@
import android.graphics.RectF;
import com.google.firebase.ml.vision.cloud.landmark.FirebaseVisionCloudLandmark;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay.Graphic;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay.Graphic;
/** Graphic instance for rendering detected landmark. */
public class CloudLandmarkGraphic extends Graphic {
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudlandmarkrecognition/CloudLandmarkRecognitionProcessor.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudlandmarkrecognition/CloudLandmarkRecognitionProcessor.java
similarity index 90%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudlandmarkrecognition/CloudLandmarkRecognitionProcessor.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudlandmarkrecognition/CloudLandmarkRecognitionProcessor.java
index c5678fe4fe..6950cde8a8 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudlandmarkrecognition/CloudLandmarkRecognitionProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudlandmarkrecognition/CloudLandmarkRecognitionProcessor.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.cloudlandmarkrecognition;
+package com.google.firebase.samples.apps.mlkit.java.cloudlandmarkrecognition;
import android.support.annotation.NonNull;
import android.util.Log;
@@ -22,9 +22,9 @@
import com.google.firebase.ml.vision.cloud.landmark.FirebaseVisionCloudLandmark;
import com.google.firebase.ml.vision.cloud.landmark.FirebaseVisionCloudLandmarkDetector;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
-import com.google.firebase.samples.apps.mlkit.FrameMetadata;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.VisionProcessorBase;
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.java.VisionProcessorBase;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudDocumentTextGraphic.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudDocumentTextGraphic.java
similarity index 89%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudDocumentTextGraphic.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudDocumentTextGraphic.java
index 701a07911a..7ed6f89b24 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudDocumentTextGraphic.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudDocumentTextGraphic.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.cloudtextrecognition;
+package com.google.firebase.samples.apps.mlkit.java.cloudtextrecognition;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -19,9 +19,8 @@
import android.graphics.Rect;
import com.google.firebase.ml.vision.document.FirebaseVisionDocumentText;
-import com.google.firebase.ml.vision.text.FirebaseVisionText;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay.Graphic;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay.Graphic;
/**
* Graphic instance for rendering TextBlock position, size, and ID within an associated graphic
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudDocumentTextRecognitionProcessor.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudDocumentTextRecognitionProcessor.java
similarity index 89%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudDocumentTextRecognitionProcessor.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudDocumentTextRecognitionProcessor.java
index aab488197e..99e577707a 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudDocumentTextRecognitionProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudDocumentTextRecognitionProcessor.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.cloudtextrecognition;
+package com.google.firebase.samples.apps.mlkit.java.cloudtextrecognition;
import android.support.annotation.NonNull;
import android.util.Log;
@@ -21,10 +21,9 @@
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.document.FirebaseVisionDocumentTextRecognizer;
import com.google.firebase.ml.vision.document.FirebaseVisionDocumentText;
-import com.google.firebase.ml.vision.text.FirebaseVisionText;
-import com.google.firebase.samples.apps.mlkit.FrameMetadata;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.VisionProcessorBase;
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.java.VisionProcessorBase;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudTextGraphic.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudTextGraphic.java
similarity index 90%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudTextGraphic.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudTextGraphic.java
index 5151cbff9c..13eebe7ada 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudTextGraphic.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudTextGraphic.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.cloudtextrecognition;
+package com.google.firebase.samples.apps.mlkit.java.cloudtextrecognition;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -19,8 +19,8 @@
import android.graphics.Rect;
import com.google.firebase.ml.vision.text.FirebaseVisionText;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay.Graphic;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay.Graphic;
/**
* Graphic instance for rendering TextBlock position, size, and ID within an associated graphic
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudTextRecognitionProcessor.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudTextRecognitionProcessor.java
similarity index 90%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudTextRecognitionProcessor.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudTextRecognitionProcessor.java
index 51f074b7aa..32636bd8a0 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/cloudtextrecognition/CloudTextRecognitionProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/cloudtextrecognition/CloudTextRecognitionProcessor.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.cloudtextrecognition;
+package com.google.firebase.samples.apps.mlkit.java.cloudtextrecognition;
import android.support.annotation.NonNull;
import android.util.Log;
@@ -21,9 +21,9 @@
import com.google.firebase.ml.vision.text.FirebaseVisionText;
import com.google.firebase.ml.vision.text.FirebaseVisionTextRecognizer;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
-import com.google.firebase.samples.apps.mlkit.FrameMetadata;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.VisionProcessorBase;
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.java.VisionProcessorBase;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/custommodel/CustomImageClassifier.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/custommodel/CustomImageClassifier.java
similarity index 99%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/custommodel/CustomImageClassifier.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/custommodel/CustomImageClassifier.java
index 58b8aa9757..d46011f45a 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/custommodel/CustomImageClassifier.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/custommodel/CustomImageClassifier.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.custommodel;
+package com.google.firebase.samples.apps.mlkit.java.custommodel;
import android.app.Activity;
import android.graphics.Bitmap;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/custommodel/CustomImageClassifierProcessor.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/custommodel/CustomImageClassifierProcessor.java
similarity index 88%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/custommodel/CustomImageClassifierProcessor.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/custommodel/CustomImageClassifierProcessor.java
index 6506fc44c6..4c41ec51e8 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/custommodel/CustomImageClassifierProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/custommodel/CustomImageClassifierProcessor.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.custommodel;
+package com.google.firebase.samples.apps.mlkit.java.custommodel;
import android.app.Activity;
import android.graphics.Bitmap;
@@ -19,9 +19,9 @@
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.ml.common.FirebaseMLException;
-import com.google.firebase.samples.apps.mlkit.FrameMetadata;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.VisionImageProcessor;
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.VisionImageProcessor;
import java.nio.ByteBuffer;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/custommodel/LabelGraphic.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/custommodel/LabelGraphic.java
similarity index 87%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/custommodel/LabelGraphic.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/custommodel/LabelGraphic.java
index 7ec29e2735..e574656bab 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/custommodel/LabelGraphic.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/custommodel/LabelGraphic.java
@@ -11,15 +11,15 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.custommodel;
+package com.google.firebase.samples.apps.mlkit.java.custommodel;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay.Graphic;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay.Graphic;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/facedetection/FaceDetectionProcessor.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/facedetection/FaceDetectionProcessor.java
similarity index 90%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/facedetection/FaceDetectionProcessor.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/facedetection/FaceDetectionProcessor.java
index d386e8a246..993735b831 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/facedetection/FaceDetectionProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/facedetection/FaceDetectionProcessor.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.facedetection;
+package com.google.firebase.samples.apps.mlkit.java.facedetection;
import android.support.annotation.NonNull;
import android.util.Log;
@@ -22,9 +22,9 @@
import com.google.firebase.ml.vision.face.FirebaseVisionFace;
import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetector;
import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetectorOptions;
-import com.google.firebase.samples.apps.mlkit.FrameMetadata;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.VisionProcessorBase;
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.java.VisionProcessorBase;
import java.io.IOException;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/facedetection/FaceGraphic.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/facedetection/FaceGraphic.java
similarity index 96%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/facedetection/FaceGraphic.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/facedetection/FaceGraphic.java
index f7b63c5d27..8ab6f08cd6 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/facedetection/FaceGraphic.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/facedetection/FaceGraphic.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.facedetection;
+package com.google.firebase.samples.apps.mlkit.java.facedetection;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -22,8 +22,8 @@
import com.google.firebase.ml.vision.common.FirebaseVisionPoint;
import com.google.firebase.ml.vision.face.FirebaseVisionFace;
import com.google.firebase.ml.vision.face.FirebaseVisionFaceLandmark;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay.Graphic;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay.Graphic;
/**
* Graphic instance for rendering face position, orientation, and landmarks within an associated
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/imagelabeling/ImageLabelingProcessor.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/imagelabeling/ImageLabelingProcessor.java
similarity index 88%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/imagelabeling/ImageLabelingProcessor.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/imagelabeling/ImageLabelingProcessor.java
index e952aa0541..d2a3a21d08 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/imagelabeling/ImageLabelingProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/imagelabeling/ImageLabelingProcessor.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.imagelabeling;
+package com.google.firebase.samples.apps.mlkit.java.imagelabeling;
import android.support.annotation.NonNull;
import android.util.Log;
@@ -21,9 +21,9 @@
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.label.FirebaseVisionLabel;
import com.google.firebase.ml.vision.label.FirebaseVisionLabelDetector;
-import com.google.firebase.samples.apps.mlkit.FrameMetadata;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.VisionProcessorBase;
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.java.VisionProcessorBase;
import java.io.IOException;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/imagelabeling/LabelGraphic.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/imagelabeling/LabelGraphic.java
similarity index 88%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/imagelabeling/LabelGraphic.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/imagelabeling/LabelGraphic.java
index 444dcdc94f..442fc4a74d 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/imagelabeling/LabelGraphic.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/imagelabeling/LabelGraphic.java
@@ -11,15 +11,15 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.imagelabeling;
+package com.google.firebase.samples.apps.mlkit.java.imagelabeling;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import com.google.firebase.ml.vision.label.FirebaseVisionLabel;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay.Graphic;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay.Graphic;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/textrecognition/TextGraphic.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/textrecognition/TextGraphic.java
similarity index 91%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/textrecognition/TextGraphic.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/textrecognition/TextGraphic.java
index 0d8a9fcf76..78e084c20a 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/textrecognition/TextGraphic.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/textrecognition/TextGraphic.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.textrecognition;
+package com.google.firebase.samples.apps.mlkit.java.textrecognition;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -19,8 +19,8 @@
import android.graphics.RectF;
import com.google.firebase.ml.vision.text.FirebaseVisionText;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay.Graphic;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay.Graphic;
/**
* Graphic instance for rendering TextBlock position, size, and ID within an associated graphic
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/textrecognition/TextRecognitionProcessor.java b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/textrecognition/TextRecognitionProcessor.java
similarity index 90%
rename from mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/textrecognition/TextRecognitionProcessor.java
rename to mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/textrecognition/TextRecognitionProcessor.java
index cb48266362..4538160a6a 100644
--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/textrecognition/TextRecognitionProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/textrecognition/TextRecognitionProcessor.java
@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.firebase.samples.apps.mlkit.textrecognition;
+package com.google.firebase.samples.apps.mlkit.java.textrecognition;
import android.support.annotation.NonNull;
import android.util.Log;
@@ -21,9 +21,9 @@
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.text.FirebaseVisionText;
import com.google.firebase.ml.vision.text.FirebaseVisionTextRecognizer;
-import com.google.firebase.samples.apps.mlkit.FrameMetadata;
-import com.google.firebase.samples.apps.mlkit.GraphicOverlay;
-import com.google.firebase.samples.apps.mlkit.VisionProcessorBase;
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata;
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay;
+import com.google.firebase.samples.apps.mlkit.java.VisionProcessorBase;
import java.io.IOException;
import java.util.List;
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/ChooserActivity.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/ChooserActivity.kt
new file mode 100644
index 0000000000..ca8b3d5cd8
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/ChooserActivity.kt
@@ -0,0 +1,142 @@
+package com.google.firebase.samples.apps.mlkit.kotlin
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.support.v4.app.ActivityCompat
+import android.support.v4.content.ContextCompat
+import android.support.v7.app.AppCompatActivity
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.TextView
+import com.google.firebase.samples.apps.mlkit.R
+import java.util.ArrayList
+import kotlinx.android.synthetic.main.activity_chooser.*
+
+/**
+ * Demo app chooser which takes care of runtime permission requesting and allows you to pick from
+ * all available testing Activities.
+ */
+class ChooserActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsResultCallback,
+ AdapterView.OnItemClickListener {
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ Log.d(TAG, "onCreate")
+
+ setContentView(R.layout.activity_chooser)
+
+ // Set up ListView and Adapter
+ val adapter = MyArrayAdapter(this, android.R.layout.simple_list_item_2, CLASSES)
+ adapter.setDescriptionIds(DESCRIPTION_IDS)
+
+ testActivityListView.adapter = adapter
+ testActivityListView.onItemClickListener = this
+
+ if (!allPermissionsGranted()) {
+ getRuntimePermissions()
+ }
+
+ }
+
+ override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) {
+ val clicked = CLASSES[position]
+ startActivity(Intent(this, clicked))
+ }
+
+ private fun getRequiredPermissions(): Array {
+ return try {
+ val info = this.packageManager
+ .getPackageInfo(this.packageName, PackageManager.GET_PERMISSIONS)
+ val ps = info.requestedPermissions
+ if (ps != null && ps.isNotEmpty()) {
+ ps
+ } else {
+ arrayOfNulls(0)
+ }
+ } catch (e: Exception) {
+ arrayOfNulls(0)
+ }
+
+ }
+
+ private fun allPermissionsGranted(): Boolean {
+ for (permission in getRequiredPermissions()) {
+ permission?.let {
+ if (!isPermissionGranted(this, it)) {
+ return false
+ }
+ }
+ }
+ return true
+ }
+
+ private fun getRuntimePermissions() {
+ val allNeededPermissions = ArrayList()
+ for (permission in getRequiredPermissions()) {
+ permission?.let {
+ if (!isPermissionGranted(this, it)) {
+ allNeededPermissions.add(permission)
+ }
+ }
+ }
+
+ if (!allNeededPermissions.isEmpty()) {
+ ActivityCompat.requestPermissions(
+ this, allNeededPermissions.toTypedArray(), PERMISSION_REQUESTS)
+ }
+ }
+
+ private fun isPermissionGranted(context: Context, permission: String): Boolean {
+ if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) {
+ Log.i(TAG, "Permission granted: $permission")
+ return true
+ }
+ Log.i(TAG, "Permission NOT granted: $permission")
+ return false
+ }
+
+ private class MyArrayAdapter(
+ private val ctx: Context, resource: Int,
+ private val classes: Array>
+ ) : ArrayAdapter>(ctx, resource, classes) {
+ private var descriptionIds: IntArray? = null
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ var view = convertView
+
+ if (convertView == null) {
+ val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
+ view = inflater.inflate(android.R.layout.simple_list_item_2, null)
+ }
+
+ (view!!.findViewById(android.R.id.text1) as TextView).text = classes[position].simpleName
+ descriptionIds?.let {
+ (view.findViewById(android.R.id.text2) as TextView).setText(it[position])
+ }
+
+ return view
+ }
+
+ fun setDescriptionIds(descriptionIds: IntArray) {
+ this.descriptionIds = descriptionIds
+ }
+ }
+
+ companion object {
+ private const val TAG = "ChooserActivity"
+ private const val PERMISSION_REQUESTS = 1
+
+ private val CLASSES =
+ arrayOf>(LivePreviewActivity::class.java, StillImageActivity::class.java)
+
+ private val DESCRIPTION_IDS =
+ intArrayOf(R.string.desc_camera_source_activity, R.string.desc_still_image_activity)
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/LivePreviewActivity.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/LivePreviewActivity.kt
new file mode 100644
index 0000000000..77c1b756af
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/LivePreviewActivity.kt
@@ -0,0 +1,255 @@
+package com.google.firebase.samples.apps.mlkit.kotlin
+
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.support.v4.app.ActivityCompat
+import android.support.v4.content.ContextCompat
+import android.support.v7.app.AppCompatActivity
+import android.util.Log
+import android.view.View
+import android.widget.*
+import com.google.android.gms.common.annotation.KeepName
+import com.google.firebase.ml.common.FirebaseMLException
+import com.google.firebase.samples.apps.mlkit.R
+import com.google.firebase.samples.apps.mlkit.common.CameraSource
+import com.google.firebase.samples.apps.mlkit.common.CameraSourcePreview
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.kotlin.barcodescanning.BarcodeScanningProcessor
+import com.google.firebase.samples.apps.mlkit.kotlin.custommodel.CustomImageClassifierProcessor
+import com.google.firebase.samples.apps.mlkit.kotlin.facedetection.FaceDetectionProcessor
+import com.google.firebase.samples.apps.mlkit.kotlin.imagelabeling.ImageLabelingProcessor
+import com.google.firebase.samples.apps.mlkit.kotlin.textrecognition.TextRecognitionProcessor
+import java.io.IOException
+import java.util.*
+import kotlinx.android.synthetic.main.activity_live_preview.*
+
+/** Demo app showing the various features of ML Kit for Firebase. This class is used to
+ * set up continuous frame processing on frames from a camera source. */
+@KeepName
+class LivePreviewActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsResultCallback, AdapterView.OnItemSelectedListener, CompoundButton.OnCheckedChangeListener {
+
+ private var cameraSource: CameraSource? = null
+ private var selectedModel = FACE_DETECTION
+
+ private val requiredPermissions: Array
+ get() {
+ return try {
+ val info = this.packageManager
+ .getPackageInfo(this.packageName, PackageManager.GET_PERMISSIONS)
+ val ps = info.requestedPermissions
+ if (ps != null && ps.isNotEmpty()) {
+ ps
+ } else {
+ arrayOfNulls(0)
+ }
+ } catch (e: Exception) {
+ arrayOfNulls(0)
+ }
+
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ Log.d(TAG, "onCreate")
+
+ setContentView(R.layout.activity_live_preview)
+
+ if (firePreview == null) {
+ Log.d(TAG, "Preview is null")
+ }
+ if (fireFaceOverlay == null) {
+ Log.d(TAG, "graphicOverlay is null")
+ }
+
+ val options = arrayListOf(
+ FACE_DETECTION,
+ TEXT_DETECTION,
+ BARCODE_DETECTION,
+ IMAGE_LABEL_DETECTION,
+ CLASSIFICATION)
+ // Creating adapter for spinner
+ val dataAdapter = ArrayAdapter(this, R.layout.spinner_style, options)
+ // Drop down layout style - list view with radio button
+ dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+ // attaching data adapter to spinner
+ spinner.adapter = dataAdapter
+ spinner.onItemSelectedListener = this
+
+ facingSwitch.setOnCheckedChangeListener(this)
+
+ if (allPermissionsGranted()) {
+ createCameraSource(selectedModel)
+ } else {
+ getRuntimePermissions()
+ }
+ }
+
+ @Synchronized
+ override fun onItemSelected(parent: AdapterView<*>, view: View, pos: Int, id: Long) {
+ // An item was selected. You can retrieve the selected item using
+ // parent.getItemAtPosition(pos)
+ selectedModel = parent.getItemAtPosition(pos).toString()
+ Log.d(TAG, "Selected model: $selectedModel")
+ firePreview.stop()
+ if (allPermissionsGranted()) {
+ createCameraSource(selectedModel)
+ startCameraSource()
+ } else {
+ getRuntimePermissions()
+ }
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>) {
+ // Do nothing.
+ }
+
+ override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
+ Log.d(TAG, "Set facing")
+ cameraSource?.let {
+ if (isChecked) {
+ it.setFacing(CameraSource.CAMERA_FACING_FRONT)
+ } else {
+ it.setFacing(CameraSource.CAMERA_FACING_BACK)
+ }
+ }
+ firePreview.stop()
+ startCameraSource()
+ }
+
+ private fun createCameraSource(model: String) {
+ // If there's no existing cameraSource, create one.
+ if (cameraSource == null) {
+ cameraSource = CameraSource(this, fireFaceOverlay)
+ }
+
+ try {
+ cameraSource?.let {
+ when (model) {
+ CLASSIFICATION -> {
+ Log.i(TAG, "Using Custom Image Classifier Processor")
+ it.setMachineLearningFrameProcessor(CustomImageClassifierProcessor(this))
+ }
+ TEXT_DETECTION -> {
+ Log.i(TAG, "Using Text Detector Processor")
+ it.setMachineLearningFrameProcessor(TextRecognitionProcessor())
+ }
+ FACE_DETECTION -> {
+ Log.i(TAG, "Using Face Detector Processor")
+ it.setMachineLearningFrameProcessor(FaceDetectionProcessor())
+ }
+ BARCODE_DETECTION -> {
+ Log.i(TAG, "Using Barcode Detector Processor")
+ it.setMachineLearningFrameProcessor(BarcodeScanningProcessor())
+ }
+ IMAGE_LABEL_DETECTION -> {
+ Log.i(TAG, "Using Image Label Detector Processor")
+ it.setMachineLearningFrameProcessor(ImageLabelingProcessor())
+ }
+ else -> Log.e(TAG, "Unknown model: $model")
+ }
+ }
+ } catch (e: FirebaseMLException) {
+ Log.e(TAG, "can not create camera source: $model")
+ }
+
+ }
+
+ /**
+ * Starts or restarts the camera source, if it exists. If the camera source doesn't exist yet
+ * (e.g., because onResume was called before the camera source was created), this will be called
+ * again when the camera source is created.
+ */
+ private fun startCameraSource() {
+ cameraSource.let {
+ try {
+ if (firePreview == null) {
+ Log.d(TAG, "resume: Preview is null")
+ }
+ if (fireFaceOverlay == null) {
+ Log.d(TAG, "resume: graphOverlay is null")
+ }
+ firePreview.start(it, fireFaceOverlay)
+ } catch (e: IOException) {
+ Log.e(TAG, "Unable to start camera source.", e)
+ it?.release()
+ cameraSource = null
+ }
+
+ }
+ }
+
+ public override fun onResume() {
+ super.onResume()
+ Log.d(TAG, "onResume")
+ startCameraSource()
+ }
+
+ /** Stops the camera. */
+ override fun onPause() {
+ super.onPause()
+ firePreview.stop()
+ }
+
+ public override fun onDestroy() {
+ super.onDestroy()
+ cameraSource?.let {
+ it?.release()
+ }
+ }
+
+ private fun allPermissionsGranted(): Boolean {
+ for (permission in requiredPermissions) {
+ permission?.let {
+ if (!isPermissionGranted(this, it)) {
+ return false
+ }
+ }
+ }
+ return true
+ }
+
+ private fun getRuntimePermissions() {
+ val allNeededPermissions = ArrayList()
+ for (permission in requiredPermissions) {
+ permission?.let {
+ if (!isPermissionGranted(this, it)) {
+ allNeededPermissions.add(it)
+ }
+ }
+ }
+
+ if (!allNeededPermissions.isEmpty()) {
+ ActivityCompat.requestPermissions(
+ this, allNeededPermissions.toTypedArray(), PERMISSION_REQUESTS)
+ }
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int, permissions: Array, grantResults: IntArray) {
+ Log.i(TAG, "Permission granted!")
+ if (allPermissionsGranted()) {
+ createCameraSource(selectedModel)
+ }
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ }
+
+ companion object {
+ private const val FACE_DETECTION = "Face Detection"
+ private const val TEXT_DETECTION = "Text Detection"
+ private const val BARCODE_DETECTION = "Barcode Detection"
+ private const val IMAGE_LABEL_DETECTION = "Label Detection"
+ private const val CLASSIFICATION = "Classification"
+ private const val TAG = "LivePreviewActivity"
+ private const val PERMISSION_REQUESTS = 1
+
+ private fun isPermissionGranted(context: Context, permission: String): Boolean {
+ if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) {
+ Log.i(TAG, "Permission granted: $permission")
+ return true
+ }
+ Log.i(TAG, "Permission NOT granted: $permission")
+ return false
+ }
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/StillImageActivity.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/StillImageActivity.kt
new file mode 100644
index 0000000000..8955e5b757
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/StillImageActivity.kt
@@ -0,0 +1,320 @@
+package com.google.firebase.samples.apps.mlkit.kotlin
+
+import android.app.Activity
+import android.content.ContentValues
+import android.content.Intent
+import android.content.res.Configuration
+import android.graphics.Bitmap
+import android.net.Uri
+import android.os.Bundle
+import android.provider.MediaStore
+import android.support.v7.app.AppCompatActivity
+import android.util.Log
+import android.util.Pair
+import android.view.View
+import android.widget.*
+import com.google.android.gms.common.annotation.KeepName
+import com.google.firebase.samples.apps.mlkit.R
+import com.google.firebase.samples.apps.mlkit.common.VisionImageProcessor
+import com.google.firebase.samples.apps.mlkit.kotlin.cloudimagelabeling.CloudImageLabelingProcessor
+import com.google.firebase.samples.apps.mlkit.kotlin.cloudlandmarkrecognition.CloudLandmarkRecognitionProcessor
+import com.google.firebase.samples.apps.mlkit.kotlin.cloudtextrecognition.CloudDocumentTextRecognitionProcessor
+import com.google.firebase.samples.apps.mlkit.kotlin.cloudtextrecognition.CloudTextRecognitionProcessor
+import java.util.ArrayList
+import java.io.IOException
+
+import kotlinx.android.synthetic.main.activity_still_image.*
+
+/** Activity demonstrating different image detector features with a still image from camera. */
+@KeepName
+class StillImageActivity: AppCompatActivity() {
+
+ private var selectedMode = CLOUD_LABEL_DETECTION
+ private var selectedSize: String = SIZE_PREVIEW
+
+ private var isLandScape: Boolean = false
+
+ private var imageUri: Uri? = null
+ // Max width (portrait mode)
+ private var imageMaxWidth = 0
+ // Max height (portrait mode)
+ private var imageMaxHeight = 0
+ private var bitmapForDetection: Bitmap? = null
+ private var imageProcessor: VisionImageProcessor? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(R.layout.activity_still_image)
+
+ getImageButton.setOnClickListener{ view ->
+ // Menu for selecting either: a) take new photo b) select from existing
+ val popup = PopupMenu(this, view)
+ popup.setOnMenuItemClickListener { menuItem ->
+ when (menuItem.itemId) {
+ R.id.select_images_from_local -> {
+ startChooseImageIntentForResult()
+ true
+ }
+ R.id.take_photo_using_camera -> {
+ startCameraIntentForResult()
+ true
+ }
+ else -> false
+ }
+ }
+
+ val inflater = popup.menuInflater
+ inflater.inflate(R.menu.camera_button_menu, popup.menu)
+ popup.show()
+ }
+ if (previewPane == null) {
+ Log.d(TAG, "Preview is null")
+ }
+ if (previewOverlay == null) {
+ Log.d(TAG, "graphicOverlay is null")
+ }
+
+ populateFeatureSelector()
+ populateSizeSelector()
+
+ createImageProcessor()
+
+ isLandScape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
+
+ savedInstanceState?.let {
+ imageUri = it.getParcelable(KEY_IMAGE_URI)
+ imageMaxWidth = it.getInt(KEY_IMAGE_MAX_WIDTH)
+ imageMaxHeight = it.getInt(KEY_IMAGE_MAX_HEIGHT)
+ selectedSize = it.getString(KEY_SELECTED_SIZE)
+
+ imageUri?.let { _ ->
+ tryReloadAndDetectInImage()
+ }
+ }
+ }
+
+
+ private fun populateFeatureSelector() {
+ val options = ArrayList()
+ options.add(CLOUD_LABEL_DETECTION)
+ options.add(CLOUD_LANDMARK_DETECTION)
+ options.add(CLOUD_TEXT_DETECTION)
+ options.add(CLOUD_DOCUMENT_TEXT_DETECTION)
+ // Creating adapter for featureSpinner
+ val dataAdapter = ArrayAdapter(this, R.layout.spinner_style, options)
+ // Drop down layout style - list view with radio button
+ dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+ // attaching data adapter to spinner
+ featureSelector.adapter = dataAdapter
+ featureSelector.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+
+ override fun onItemSelected(
+ parentView: AdapterView<*>, selectedItemView: View, pos: Int, id: Long) {
+ selectedMode = parentView.getItemAtPosition(pos).toString()
+ createImageProcessor()
+ tryReloadAndDetectInImage()
+ }
+
+ override fun onNothingSelected(arg0: AdapterView<*>) {}
+ }
+ }
+
+ private fun populateSizeSelector() {
+ val options = ArrayList()
+ options.add(SIZE_PREVIEW)
+ options.add(SIZE_1024_768)
+ options.add(SIZE_640_480)
+
+ // Creating adapter for featureSpinner
+ val dataAdapter = ArrayAdapter(this, R.layout.spinner_style, options)
+ // Drop down layout style - list view with radio button
+ dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+ // attaching data adapter to spinner
+ sizeSelector.adapter = dataAdapter
+ sizeSelector.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+
+ override fun onItemSelected(
+ parentView: AdapterView<*>, selectedItemView: View, pos: Int, id: Long) {
+ selectedSize = parentView.getItemAtPosition(pos).toString()
+ tryReloadAndDetectInImage()
+ }
+
+ override fun onNothingSelected(arg0: AdapterView<*>) {}
+ }
+ }
+
+ public override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+
+ with(outState) {
+ putParcelable(KEY_IMAGE_URI, imageUri)
+ putInt(KEY_IMAGE_MAX_WIDTH, imageMaxWidth)
+ putInt(KEY_IMAGE_MAX_HEIGHT, imageMaxHeight)
+ putString(KEY_SELECTED_SIZE, selectedSize)
+ }
+ }
+
+ private fun startCameraIntentForResult() {
+ // Clean up last time's image
+ imageUri = null
+ previewPane?.setImageBitmap(null)
+
+ val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
+ takePictureIntent.resolveActivity(packageManager)?.let {
+ val values = ContentValues()
+ values.put(MediaStore.Images.Media.TITLE, "New Picture")
+ values.put(MediaStore.Images.Media.DESCRIPTION, "From Camera")
+ imageUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
+ takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
+ startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
+ }
+ }
+
+ private fun startChooseImageIntentForResult() {
+ val intent = Intent()
+ intent.type = "image/*"
+ intent.action = Intent.ACTION_GET_CONTENT
+ startActivityForResult(Intent.createChooser(intent, "Select Picture"), REQUEST_CHOOSE_IMAGE)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
+ if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
+ tryReloadAndDetectInImage()
+ } else if (requestCode == REQUEST_CHOOSE_IMAGE && resultCode == Activity.RESULT_OK) {
+ // In this case, imageUri is returned by the chooser, save it.
+ imageUri = data.data
+ tryReloadAndDetectInImage()
+ }
+ }
+
+ private fun tryReloadAndDetectInImage() {
+ try {
+ if (imageUri == null) {
+ return
+ }
+
+ // Clear the overlay first
+ previewOverlay?.clear()
+
+ val imageBitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri)
+
+ // Get the dimensions of the View
+ val targetedSize = getTargetedWidthHeight()
+
+ val targetWidth = targetedSize.first
+ val maxHeight = targetedSize.second
+
+ // Determine how much to scale down the image
+ val scaleFactor = Math.max(
+ imageBitmap.width.toFloat() / targetWidth.toFloat(),
+ imageBitmap.height.toFloat() / maxHeight.toFloat())
+
+ val resizedBitmap = Bitmap.createScaledBitmap(
+ imageBitmap,
+ (imageBitmap.width / scaleFactor).toInt(),
+ (imageBitmap.height / scaleFactor).toInt(),
+ true)
+
+ previewPane?.setImageBitmap(resizedBitmap)
+ bitmapForDetection = resizedBitmap
+ bitmapForDetection?.let {
+ imageProcessor?.process(it, previewOverlay)
+ }
+ } catch (e: IOException) {
+ Log.e(TAG, "Error retrieving saved image")
+ }
+
+ }
+
+ // Returns max image width, always for portrait mode. Caller needs to swap width / height for
+ // landscape mode.
+ private fun getImageMaxWidth(): Int {
+ if (imageMaxWidth == 0) {
+ // Calculate the max width in portrait mode. This is done lazily since we need to wait for
+ // a UI layout pass to get the right values. So delay it to first time image rendering time.
+ imageMaxWidth = if (isLandScape) {
+ (previewPane.parent as View).height - controlPanel.height
+ } else {
+ (previewPane.parent as View).width
+ }
+ }
+
+ return imageMaxWidth
+ }
+
+ // Returns max image height, always for portrait mode. Caller needs to swap width / height for
+ // landscape mode.
+ private fun getImageMaxHeight(): Int {
+ if (imageMaxHeight == 0) {
+ // Calculate the max width in portrait mode. This is done lazily since we need to wait for
+ // a UI layout pass to get the right values. So delay it to first time image rendering time.
+ imageMaxHeight = if (isLandScape) {
+ (previewPane.parent as View).width
+ } else {
+ (previewPane.parent as View).height - controlPanel.height
+ }
+ }
+
+ return imageMaxHeight
+ }
+
+ // Gets the targeted width / height.
+ private fun getTargetedWidthHeight(): Pair {
+ var targetWidth = 0
+ var targetHeight = 0
+
+ when (selectedSize) {
+ SIZE_PREVIEW -> {
+ val maxWidthForPortraitMode = getImageMaxWidth()
+ val maxHeightForPortraitMode = getImageMaxHeight()
+ targetWidth = if (isLandScape) maxHeightForPortraitMode else maxWidthForPortraitMode
+ targetHeight = if (isLandScape) maxWidthForPortraitMode else maxHeightForPortraitMode
+ }
+ SIZE_640_480 -> {
+ targetWidth = if (isLandScape) 640 else 480
+ targetHeight = if (isLandScape) 480 else 640
+ }
+ SIZE_1024_768 -> {
+ targetWidth = if (isLandScape) 1024 else 768
+ targetHeight = if (isLandScape) 768 else 1024
+ }
+ else -> throw IllegalStateException("Unknown size")
+ }
+
+ return Pair(targetWidth, targetHeight)
+ }
+
+ private fun createImageProcessor() {
+ imageProcessor = when (selectedMode) {
+ CLOUD_LABEL_DETECTION -> CloudImageLabelingProcessor()
+ CLOUD_LANDMARK_DETECTION -> CloudLandmarkRecognitionProcessor()
+ CLOUD_TEXT_DETECTION -> CloudTextRecognitionProcessor()
+ CLOUD_DOCUMENT_TEXT_DETECTION -> CloudDocumentTextRecognitionProcessor()
+ else -> throw IllegalStateException("Unknown selectedMode: $selectedMode")
+ }
+ }
+
+ companion object {
+
+ private const val TAG = "StillImageActivity"
+
+ private const val CLOUD_LABEL_DETECTION = "Cloud Label"
+ private const val CLOUD_LANDMARK_DETECTION = "Landmark"
+ private const val CLOUD_TEXT_DETECTION = "Cloud Text"
+ private const val CLOUD_DOCUMENT_TEXT_DETECTION = "Doc Text"
+
+ private const val SIZE_PREVIEW = "w:max" // Available on-screen width.
+ private const val SIZE_1024_768 = "w:1024" // ~1024*768 in a normal ratio
+ private const val SIZE_640_480 = "w:640" // ~640*480 in a normal ratio
+
+ private const val KEY_IMAGE_URI = "com.googletest.firebase.ml.demo.KEY_IMAGE_URI"
+ private const val KEY_IMAGE_MAX_WIDTH = "com.googletest.firebase.ml.demo.KEY_IMAGE_MAX_WIDTH"
+ private const val KEY_IMAGE_MAX_HEIGHT = "com.googletest.firebase.ml.demo.KEY_IMAGE_MAX_HEIGHT"
+ private const val KEY_SELECTED_SIZE = "com.googletest.firebase.ml.demo.KEY_SELECTED_SIZE"
+
+ private const val REQUEST_IMAGE_CAPTURE = 1001
+ private const val REQUEST_CHOOSE_IMAGE = 1002
+ }
+
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/VisionProcessorBase.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/VisionProcessorBase.kt
new file mode 100644
index 0000000000..ca577af926
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/VisionProcessorBase.kt
@@ -0,0 +1,100 @@
+package com.google.firebase.samples.apps.mlkit.kotlin
+
+import android.graphics.Bitmap
+import android.media.Image
+import com.google.android.gms.tasks.Task
+import com.google.firebase.ml.vision.common.FirebaseVisionImage
+import com.google.firebase.ml.vision.common.FirebaseVisionImageMetadata
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.common.VisionImageProcessor
+import java.nio.ByteBuffer
+import java.util.concurrent.atomic.AtomicBoolean
+
+/**
+ * Abstract base class for ML Kit frame processors. Subclasses need to implement {@link
+ * #onSuccess(T, FrameMetadata, GraphicOverlay)} to define what they want to with the detection
+ * results and {@link #detectInImage(FirebaseVisionImage)} to specify the detector object.
+ *
+ * @param The type of the detected feature.
+ */
+abstract class VisionProcessorBase : VisionImageProcessor {
+
+ // Whether we should ignore process(). This is usually caused by feeding input data faster than
+ // the model can handle.
+ private val shouldThrottle = AtomicBoolean(false)
+
+ override fun process(
+ data: ByteBuffer, frameMetadata: FrameMetadata, graphicOverlay: GraphicOverlay) {
+ if (shouldThrottle.get()) {
+ return
+ }
+ val metadata = FirebaseVisionImageMetadata.Builder()
+ .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
+ .setWidth(frameMetadata.width)
+ .setHeight(frameMetadata.height)
+ .setRotation(frameMetadata.rotation)
+ .build()
+
+ detectInVisionImage(
+ FirebaseVisionImage.fromByteBuffer(data, metadata), frameMetadata, graphicOverlay)
+ }
+
+ // Bitmap version
+ override fun process(bitmap: Bitmap, graphicOverlay: GraphicOverlay) {
+ if (shouldThrottle.get()) {
+ return
+ }
+ detectInVisionImage(FirebaseVisionImage.fromBitmap(bitmap), null, graphicOverlay)
+ }
+
+ /**
+ * Detects feature from given media.Image
+ *
+ * @return created FirebaseVisionImage
+ */
+ override fun process(image: Image, rotation:Int, graphicOverlay: GraphicOverlay) {
+ if (shouldThrottle.get()) {
+ return
+ }
+ // This is for overlay display's usage
+ val frameMetadata = FrameMetadata.Builder()
+ .setWidth(image.width)
+ .setHeight(image.height)
+ .build()
+ val fbVisionImage = FirebaseVisionImage.fromMediaImage(image, rotation)
+ detectInVisionImage(fbVisionImage, frameMetadata, graphicOverlay)
+ }
+
+ private fun detectInVisionImage(
+ image: FirebaseVisionImage,
+ metadata: FrameMetadata?,
+ graphicOverlay: GraphicOverlay) {
+ detectInImage(image)
+ .addOnSuccessListener { results ->
+ shouldThrottle.set(false)
+ metadata?.let {
+ onSuccess(results, it, graphicOverlay)
+ }
+ }
+ .addOnFailureListener { e ->
+ shouldThrottle.set(false)
+ this@VisionProcessorBase.onFailure(e)
+ }
+ // Begin throttling until this frame of input has been processed, either in onSuccess or
+ // onFailure.
+ shouldThrottle.set(true)
+ }
+
+ override fun stop() {}
+
+ protected abstract fun detectInImage(image: FirebaseVisionImage): Task
+
+ protected abstract fun onSuccess(
+ results:T,
+ frameMetadata: FrameMetadata,
+ graphicOverlay: GraphicOverlay)
+
+ protected abstract fun onFailure(e:Exception)
+
+}
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/barcodescanning/BarcodeGraphic.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/barcodescanning/BarcodeGraphic.kt
new file mode 100644
index 0000000000..ba569b5794
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/barcodescanning/BarcodeGraphic.kt
@@ -0,0 +1,56 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.barcodescanning
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.RectF
+import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+
+class BarcodeGraphic(overlay: GraphicOverlay, barcode: FirebaseVisionBarcode) : GraphicOverlay.Graphic(overlay) {
+
+ companion object {
+ private const val TEXT_COLOR = Color.WHITE
+ private const val TEXT_SIZE = 54.0f
+ private const val STROKE_WIDTH = 4.0f
+ }
+
+ private var rectPaint: Paint
+ private var barcodePaint: Paint
+ private val barcode: FirebaseVisionBarcode?
+
+ init {
+ this.barcode = barcode
+
+ rectPaint = Paint()
+ rectPaint.color = TEXT_COLOR
+ rectPaint.style = Paint.Style.STROKE
+ rectPaint.strokeWidth = STROKE_WIDTH
+
+ barcodePaint = Paint()
+ barcodePaint.color = TEXT_COLOR
+ barcodePaint.textSize = TEXT_SIZE
+ // Redraw the overlay, as this graphic has been added.
+ postInvalidate()
+ }
+
+ /**
+ * Draws the barcode block annotations for position, size, and raw value on the supplied canvas.
+ */
+ override fun draw(canvas: Canvas) {
+ if (barcode == null) {
+ throw IllegalStateException("Attempting to draw a null barcode.")
+ }
+
+ // Draws the bounding box around the BarcodeBlock.
+ val rect = RectF(barcode.boundingBox)
+ rect.left = translateX(rect.left)
+ rect.top = translateY(rect.top)
+ rect.right = translateX(rect.right)
+ rect.bottom = translateY(rect.bottom)
+ canvas.drawRect(rect, rectPaint)
+
+ // Renders the barcode at the bottom of the box.
+ canvas.drawText(barcode.rawValue, rect.left, rect.bottom, barcodePaint)
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/barcodescanning/BarcodeScanningProcessor.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/barcodescanning/BarcodeScanningProcessor.kt
new file mode 100644
index 0000000000..3ca0b5b1c9
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/barcodescanning/BarcodeScanningProcessor.kt
@@ -0,0 +1,58 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.barcodescanning
+
+import android.util.Log
+import com.google.android.gms.tasks.Task
+import com.google.firebase.ml.vision.FirebaseVision
+import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode
+import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetector
+import com.google.firebase.ml.vision.common.FirebaseVisionImage
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.kotlin.VisionProcessorBase
+import java.io.IOException
+
+/** Barcode Detector Demo. */
+class BarcodeScanningProcessor : VisionProcessorBase>() {
+
+ private val detector: FirebaseVisionBarcodeDetector
+
+ init {
+ // Note that if you know which format of barcode your app is dealing with, detection will be
+ // faster to specify the supported barcode formats one by one, e.g.
+ // FirebaseVisionBarcodeDetectorOptions.Builder()
+ // .setBarcodeFormats(FirebaseVisionBarcode.FORMAT_QR_CODE)
+ // .build()
+ detector = FirebaseVision.getInstance().visionBarcodeDetector
+ }
+
+ override fun stop() {
+ try {
+ detector.close()
+ } catch (e: IOException) {
+ Log.e(TAG, "Exception thrown while trying to close Barcode Detector: $e")
+ }
+
+ }
+
+ override fun detectInImage(image: FirebaseVisionImage): Task> {
+ return detector.detectInImage(image)
+ }
+
+ override fun onSuccess(barcodes: List, frameMetadata: FrameMetadata,
+ graphicOverlay: GraphicOverlay) {
+ graphicOverlay.clear()
+ for (i in barcodes.indices) {
+ val barcode = barcodes[i]
+ val barcodeGraphic = BarcodeGraphic(graphicOverlay, barcode)
+ graphicOverlay.add(barcodeGraphic)
+ }
+ }
+
+ override fun onFailure(e: Exception) {
+ Log.e(TAG, "Barcode detection failed $e")
+ }
+
+ companion object {
+ private const val TAG = "BarcodeScanProc"
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudimagelabeling/CloudImageLabellingProcessor.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudimagelabeling/CloudImageLabellingProcessor.kt
new file mode 100644
index 0000000000..76f060b019
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudimagelabeling/CloudImageLabellingProcessor.kt
@@ -0,0 +1,64 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.cloudimagelabeling
+
+import android.util.Log
+import com.google.android.gms.tasks.Task
+import com.google.firebase.ml.vision.FirebaseVision
+import com.google.firebase.ml.vision.cloud.FirebaseVisionCloudDetectorOptions
+import com.google.firebase.ml.vision.cloud.label.FirebaseVisionCloudLabel
+import com.google.firebase.ml.vision.cloud.label.FirebaseVisionCloudLabelDetector
+import com.google.firebase.ml.vision.common.FirebaseVisionImage
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.kotlin.VisionProcessorBase
+
+/** Cloud Label Detector Demo. */
+class CloudImageLabelingProcessor : VisionProcessorBase>() {
+
+ private val detector: FirebaseVisionCloudLabelDetector
+
+ init {
+ val options = FirebaseVisionCloudDetectorOptions.Builder()
+ .setMaxResults(10)
+ .setModelType(FirebaseVisionCloudDetectorOptions.STABLE_MODEL)
+ .build()
+
+ detector = FirebaseVision.getInstance().getVisionCloudLabelDetector(options)
+ }
+
+ override fun detectInImage(image: FirebaseVisionImage): Task> {
+ return detector.detectInImage(image)
+ }
+
+ override fun onSuccess(
+ labels: List,
+ frameMetadata: FrameMetadata,
+ graphicOverlay: GraphicOverlay) {
+
+ graphicOverlay.clear()
+
+ Log.d(TAG, "cloud label size: ${labels.size}")
+
+ val labelsStr = ArrayList()
+ for (i in labels.indices) {
+ val label = labels[i]
+
+ Log.d(TAG, "cloud label: $label")
+
+ label.label?.let {
+ labelsStr.add(it)
+ }
+ }
+
+ val cloudLabelGraphic = CloudLabelGraphic(graphicOverlay)
+ graphicOverlay.add(cloudLabelGraphic)
+ cloudLabelGraphic.updateLabel(labelsStr)
+ }
+
+ override fun onFailure(e: Exception) {
+ Log.e(TAG, "Cloud Label detection failed $e")
+ }
+
+ companion object {
+ private const val TAG = "CloudImgLabelProc"
+ }
+}
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudimagelabeling/CloudLabelGraphic.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudimagelabeling/CloudLabelGraphic.kt
new file mode 100644
index 0000000000..2b176f3691
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudimagelabeling/CloudLabelGraphic.kt
@@ -0,0 +1,36 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.cloudimagelabeling
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+
+/** Graphic instance for rendering detected label. */
+class CloudLabelGraphic(private val overlay: GraphicOverlay) : GraphicOverlay.Graphic(overlay) {
+ private val textPaint: Paint
+
+ private lateinit var labels: List
+
+ init {
+ textPaint = Paint()
+ textPaint.color = Color.WHITE
+ textPaint.textSize = 60.0f
+ }
+
+ @Synchronized
+ internal fun updateLabel(labels: List) {
+ this.labels = labels
+ postInvalidate()
+ }
+
+ @Synchronized
+ override fun draw(canvas: Canvas) {
+ val x = overlay.width / 4.0f
+ var y = overlay.height / 4.0f
+
+ for (label in labels) {
+ canvas.drawText(label, x, y, textPaint)
+ y -= 62.0f
+ }
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudlandmarkrecognition/CloudLandmarkGraphic.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudlandmarkrecognition/CloudLandmarkGraphic.kt
new file mode 100644
index 0000000000..6716fce53d
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudlandmarkrecognition/CloudLandmarkGraphic.kt
@@ -0,0 +1,69 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.cloudlandmarkrecognition
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.RectF
+import com.google.firebase.ml.vision.cloud.landmark.FirebaseVisionCloudLandmark
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+
+/** Graphic instance for rendering detected landmark. */
+class CloudLandmarkGraphic(overlay: GraphicOverlay) : GraphicOverlay.Graphic(overlay) {
+
+ private val rectPaint: Paint
+ private val landmarkPaint: Paint
+ private lateinit var landmark: FirebaseVisionCloudLandmark
+
+ init {
+
+ rectPaint = Paint()
+ rectPaint.color = TEXT_COLOR
+ rectPaint.style = Paint.Style.STROKE
+ rectPaint.strokeWidth = STROKE_WIDTH
+
+ landmarkPaint = Paint()
+ landmarkPaint.color = TEXT_COLOR
+ landmarkPaint.textSize = TEXT_SIZE
+ }
+
+ /**
+ * Updates the landmark instance from the detection of the most recent frame. Invalidates the
+ * relevant portions of the overlay to trigger a redraw.
+ */
+ internal fun updateLandmark(landmark: FirebaseVisionCloudLandmark) {
+ this.landmark = landmark
+ postInvalidate()
+ }
+
+ /**
+ * Draws the landmark block annotations for position, size, and raw value on the supplied canvas.
+ */
+ override fun draw(canvas: Canvas) {
+ if (landmark == null) {
+ throw IllegalStateException("Attempting to draw a null landmark.")
+ }
+ if (landmark.landmark == null || landmark.boundingBox == null) {
+ return
+ }
+
+ // Draws the bounding box around the LandmarkBlock.
+ val rect = RectF(landmark.boundingBox)
+ with(rect) {
+ left = translateX(left)
+ top = translateY(top)
+ right = translateX(right)
+ bottom = translateY(bottom)
+ canvas.drawRect(this, rectPaint)
+
+ // Renders the landmark at the bottom of the box.
+ canvas.drawText(landmark.landmark, left, bottom, landmarkPaint)
+ }
+
+ }
+
+ companion object {
+ private const val TEXT_COLOR = Color.WHITE
+ private const val TEXT_SIZE = 54.0f
+ private const val STROKE_WIDTH = 4.0f
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudlandmarkrecognition/CloudLandmarkRecognitionProcessor.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudlandmarkrecognition/CloudLandmarkRecognitionProcessor.kt
new file mode 100644
index 0000000000..4dc58498c4
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudlandmarkrecognition/CloudLandmarkRecognitionProcessor.kt
@@ -0,0 +1,54 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.cloudlandmarkrecognition
+
+import android.util.Log
+import com.google.android.gms.tasks.Task
+import com.google.firebase.ml.vision.FirebaseVision
+import com.google.firebase.ml.vision.cloud.FirebaseVisionCloudDetectorOptions
+import com.google.firebase.ml.vision.cloud.landmark.FirebaseVisionCloudLandmark
+import com.google.firebase.ml.vision.cloud.landmark.FirebaseVisionCloudLandmarkDetector
+import com.google.firebase.ml.vision.common.FirebaseVisionImage
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.kotlin.VisionProcessorBase
+
+/** Cloud Landmark Detector Demo. */
+class CloudLandmarkRecognitionProcessor : VisionProcessorBase>() {
+
+ private val detector: FirebaseVisionCloudLandmarkDetector
+
+ init {
+ val options = FirebaseVisionCloudDetectorOptions.Builder()
+ .setMaxResults(10)
+ .setModelType(FirebaseVisionCloudDetectorOptions.STABLE_MODEL)
+ .build()
+
+ detector = FirebaseVision.getInstance().getVisionCloudLandmarkDetector(options)
+ }
+
+ override fun detectInImage(image: FirebaseVisionImage): Task> {
+ return detector.detectInImage(image)
+ }
+
+ override fun onSuccess(
+ landmarks: List,
+ frameMetadata: FrameMetadata,
+ graphicOverlay: GraphicOverlay) {
+ graphicOverlay.clear()
+ Log.d(TAG, "cloud landmark size: ${landmarks.size}")
+ for (i in landmarks.indices) {
+ val landmark = landmarks[i]
+ Log.d(TAG, "cloud landmark: $landmark")
+ val cloudLandmarkGraphic = CloudLandmarkGraphic(graphicOverlay)
+ graphicOverlay.add(cloudLandmarkGraphic)
+ cloudLandmarkGraphic.updateLandmark(landmark)
+ }
+ }
+
+ override fun onFailure(e: Exception) {
+ Log.e(TAG, "Cloud Landmark detection failed $e")
+ }
+
+ companion object {
+ private const val TAG = "CloudLmkRecProc"
+ }
+}
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudDocumentTextGraphic.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudDocumentTextGraphic.kt
new file mode 100644
index 0000000000..a84556b0e7
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudDocumentTextGraphic.kt
@@ -0,0 +1,53 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.cloudtextrecognition
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import com.google.firebase.ml.vision.document.FirebaseVisionDocumentText
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+
+/**
+ * Graphic instance for rendering TextBlock position, size, and ID within an associated graphic
+ * overlay view.
+ */
+class CloudDocumentTextGraphic(
+ overlay: GraphicOverlay,
+ private val symbol: FirebaseVisionDocumentText.Symbol?
+) : GraphicOverlay.Graphic(overlay) {
+
+ private val rectPaint: Paint
+ private val textPaint: Paint
+
+ init {
+
+ rectPaint = Paint()
+ rectPaint.color = TEXT_COLOR
+ rectPaint.style = Paint.Style.STROKE
+ rectPaint.strokeWidth = STROKE_WIDTH
+
+ textPaint = Paint()
+ textPaint.color = TEXT_COLOR
+ textPaint.textSize = TEXT_SIZE
+ // Redraw the overlay, as this graphic has been added.
+ postInvalidate()
+ }
+
+ /** Draws the text block annotations for position, size, and raw value on the supplied canvas. */
+ override fun draw(canvas: Canvas) {
+ if (symbol == null) {
+ throw IllegalStateException("Attempting to draw a null text.")
+ }
+
+ val rect = symbol.boundingBox
+ rect?.let {
+ canvas.drawRect(it, rectPaint)
+ canvas.drawText(symbol.text, it.left.toFloat(), it.bottom.toFloat(), textPaint)
+ }
+ }
+
+ companion object {
+ private const val TEXT_COLOR = Color.WHITE
+ private const val TEXT_SIZE = 54.0f
+ private const val STROKE_WIDTH = 4.0f
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudDocumentTextRecognitionProcessor.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudDocumentTextRecognitionProcessor.kt
new file mode 100644
index 0000000000..284a69cfaa
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudDocumentTextRecognitionProcessor.kt
@@ -0,0 +1,57 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.cloudtextrecognition
+
+import android.util.Log
+import com.google.android.gms.tasks.Task
+import com.google.firebase.ml.vision.FirebaseVision
+import com.google.firebase.ml.vision.common.FirebaseVisionImage
+import com.google.firebase.ml.vision.document.FirebaseVisionDocumentText
+import com.google.firebase.ml.vision.document.FirebaseVisionDocumentTextRecognizer
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.kotlin.VisionProcessorBase
+
+/** Processor for the cloud document text detector demo. */
+class CloudDocumentTextRecognitionProcessor : VisionProcessorBase() {
+
+ private val detector: FirebaseVisionDocumentTextRecognizer
+
+ init {
+ detector = FirebaseVision.getInstance().cloudDocumentTextRecognizer
+ }
+
+ override fun detectInImage(image: FirebaseVisionImage): Task {
+ return detector.processImage(image)
+ }
+
+ override fun onSuccess(
+ text: FirebaseVisionDocumentText,
+ frameMetadata: FrameMetadata,
+ graphicOverlay: GraphicOverlay) {
+ graphicOverlay.clear()
+ Log.d(TAG, "detected text is: ${text.text}")
+ val blocks = text.blocks
+ for (i in blocks.indices) {
+ val paragraphs = blocks[i].paragraphs
+ for (j in paragraphs.indices) {
+ val words = paragraphs[j].words
+ for (l in words.indices) {
+ val symbols = words[l].symbols
+ for (m in symbols.indices) {
+ val cloudDocumentTextGraphic = CloudDocumentTextGraphic(graphicOverlay,
+ symbols[m])
+ graphicOverlay.add(cloudDocumentTextGraphic)
+ }
+ }
+ }
+ }
+ }
+
+ override fun onFailure(e: Exception) {
+ Log.w(TAG, "Cloud Document Text detection failed.$e")
+ }
+
+ companion object {
+
+ private const val TAG = "CloudDocTextRecProc"
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudTextGraphic.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudTextGraphic.kt
new file mode 100644
index 0000000000..b82767abcc
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudTextGraphic.kt
@@ -0,0 +1,53 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.cloudtextrecognition
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import com.google.firebase.ml.vision.text.FirebaseVisionText
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+
+/**
+ * Graphic instance for rendering TextBlock position, size, and ID within an associated graphic
+ * overlay view.
+ */
+class CloudTextGraphic(
+ overlay: GraphicOverlay,
+ private val element: FirebaseVisionText.Element?
+) : GraphicOverlay.Graphic(overlay) {
+
+ private val rectPaint: Paint
+ private val textPaint: Paint
+
+ init {
+
+ rectPaint = Paint()
+ rectPaint.color = TEXT_COLOR
+ rectPaint.style = Paint.Style.STROKE
+ rectPaint.strokeWidth = STROKE_WIDTH
+
+ textPaint = Paint()
+ textPaint.color = TEXT_COLOR
+ textPaint.textSize = TEXT_SIZE
+ // Redraw the overlay, as this graphic has been added.
+ postInvalidate()
+ }
+
+ /** Draws the text block annotations for position, size, and raw value on the supplied canvas. */
+ override fun draw(canvas: Canvas) {
+ if (element == null) {
+ throw IllegalStateException("Attempting to draw a null text.")
+ }
+
+ val rect = element.boundingBox
+ rect?.let {
+ canvas.drawRect(it, rectPaint)
+ canvas.drawText(element.text, it.left.toFloat(), it.bottom.toFloat(), textPaint)
+ }
+ }
+
+ companion object {
+ private const val TEXT_COLOR = Color.WHITE
+ private const val TEXT_SIZE = 54.0f
+ private const val STROKE_WIDTH = 4.0f
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudTextRecognitionProcessor.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudTextRecognitionProcessor.kt
new file mode 100644
index 0000000000..3bc31b3b02
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/cloudtextrecognition/CloudTextRecognitionProcessor.kt
@@ -0,0 +1,58 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.cloudtextrecognition
+
+import android.util.Log
+import com.google.android.gms.tasks.Task
+import com.google.firebase.ml.vision.FirebaseVision
+import com.google.firebase.ml.vision.common.FirebaseVisionImage
+import com.google.firebase.ml.vision.text.FirebaseVisionText
+import com.google.firebase.ml.vision.text.FirebaseVisionTextRecognizer
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.kotlin.VisionProcessorBase
+
+/**
+ * Processor for the cloud text detector demo.
+ */
+class CloudTextRecognitionProcessor : VisionProcessorBase() {
+
+ private val detector: FirebaseVisionTextRecognizer
+
+ init {
+ detector = FirebaseVision.getInstance().cloudTextRecognizer
+ }
+
+ override fun detectInImage(image: FirebaseVisionImage): Task {
+ return detector.processImage(image)
+ }
+
+ override fun onSuccess(
+ text: FirebaseVisionText,
+ frameMetadata: FrameMetadata,
+ graphicOverlay: GraphicOverlay) {
+ graphicOverlay.clear()
+ if (text == null) {
+ return // TODO: investigate why this is needed
+ }
+ val blocks = text.textBlocks
+ for (i in blocks.indices) {
+ val lines = blocks[i].lines
+ for (j in lines.indices) {
+ val elements = lines[j].elements
+ for (l in elements.indices) {
+ val cloudTextGraphic = CloudTextGraphic(graphicOverlay,
+ elements[l])
+ graphicOverlay.add(cloudTextGraphic)
+ }
+ }
+ }
+ }
+
+ override fun onFailure(e: Exception) {
+ Log.w(TAG, "Cloud Text detection failed.$e")
+ }
+
+ companion object {
+
+ private const val TAG = "CloudTextRecProc"
+ }
+}
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/custommodel/CustomImageClassifier.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/custommodel/CustomImageClassifier.kt
new file mode 100644
index 0000000000..927fe3e5d0
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/custommodel/CustomImageClassifier.kt
@@ -0,0 +1,202 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.custommodel
+
+import android.app.Activity
+import android.graphics.*
+import android.os.SystemClock
+import android.util.Log
+import com.google.android.gms.tasks.Task
+import com.google.android.gms.tasks.Tasks
+import com.google.firebase.ml.common.FirebaseMLException
+import com.google.firebase.ml.custom.*
+import com.google.firebase.ml.custom.model.FirebaseCloudModelSource
+import com.google.firebase.ml.custom.model.FirebaseLocalModelSource
+import com.google.firebase.ml.custom.model.FirebaseModelDownloadConditions
+import java.io.BufferedReader
+import java.io.ByteArrayOutputStream
+import java.io.IOException
+import java.io.InputStreamReader
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
+import java.util.*
+import kotlin.experimental.and
+
+/** A `FirebaseModelInterpreter` based image classifier. */
+class CustomImageClassifier
+/** Initializes an `CustomImageClassifier`. */
+@Throws(FirebaseMLException::class)
+constructor(activity: Activity) {
+
+ /* Preallocated buffers for storing image data in. */
+ private val intValues = IntArray(DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y)
+
+ /** An instance of the driver class to run model inference with Firebase. */
+ private val interpreter: FirebaseModelInterpreter?
+
+ /** Data configuration of input & output data of model. */
+ private val dataOptions: FirebaseModelInputOutputOptions
+
+ /** Labels corresponding to the output of the vision model. */
+ private val labelList: List
+
+ private val sortedLabels = PriorityQueue>(
+ RESULTS_TO_SHOW,
+ Comparator> { o1, o2 ->
+ o1.value.compareTo(o2.value)
+ })
+
+ init {
+ val modelOptions = FirebaseModelOptions.Builder()
+ .setCloudModelName(HOSTED_MODEL_NAME)
+ .setLocalModelName(LOCAL_MODEL_NAME)
+ .build()
+ val conditions = FirebaseModelDownloadConditions.Builder()
+ .requireWifi()
+ .build()
+ val localModelSource = FirebaseLocalModelSource.Builder(LOCAL_MODEL_NAME)
+ .setAssetFilePath(LOCAL_MODEL_PATH).build()
+ val cloudSource = FirebaseCloudModelSource.Builder(HOSTED_MODEL_NAME)
+ .enableModelUpdates(true)
+ .setInitialDownloadConditions(conditions)
+ .setUpdatesDownloadConditions(conditions) // You could also specify different
+ // conditions for updates.
+ .build()
+ val manager = FirebaseModelManager.getInstance()
+ manager.registerLocalModelSource(localModelSource)
+ manager.registerCloudModelSource(cloudSource)
+ interpreter = FirebaseModelInterpreter.getInstance(modelOptions)
+ labelList = loadLabelList(activity)
+ Log.d(TAG, "Created a Custom Image Classifier.")
+ val inputDims = intArrayOf(DIM_BATCH_SIZE, DIM_IMG_SIZE_X, DIM_IMG_SIZE_Y, DIM_PIXEL_SIZE)
+ val outputDims = intArrayOf(1, labelList.size)
+ dataOptions = FirebaseModelInputOutputOptions.Builder()
+ .setInputFormat(0, FirebaseModelDataType.BYTE, inputDims)
+ .setOutputFormat(0, FirebaseModelDataType.BYTE, outputDims)
+ .build()
+ Log.d(TAG, "Configured input & output data for the custom image classifier.")
+ }
+
+ /** Classifies a frame from the preview stream. */
+ @Throws(FirebaseMLException::class)
+ internal fun classifyFrame(buffer: ByteBuffer, width: Int, height: Int): Task> {
+ if (interpreter == null) {
+ Log.e(TAG, "Image classifier has not been initialized; Skipped.")
+ val uninitialized = ArrayList()
+ uninitialized.add("Uninitialized Classifier.")
+ Tasks.forResult>(uninitialized)
+ }
+ // Create input data.
+ val imgData = convertBitmapToByteBuffer(buffer, width, height)
+
+ val inputs = FirebaseModelInputs.Builder().add(imgData).build()
+ // Here's where the magic happens!!
+ return interpreter!!
+ .run(inputs, dataOptions)
+ .continueWith { task ->
+ val labelProbArray = task.result.getOutput>(0)
+ printTopKLabels(labelProbArray)
+ }
+ }
+
+ /** Reads label list from Assets. */
+ private fun loadLabelList(activity: Activity): List {
+ val labelList = ArrayList()
+ try {
+ BufferedReader(InputStreamReader(activity.assets.open(LABEL_PATH))).use { reader ->
+ var line = reader.readLine()
+ while (line != null) {
+ labelList.add(line)
+ line = reader.readLine()
+ }
+ }
+ } catch (e: IOException) {
+ Log.e(TAG, "Failed to read label list.", e)
+ }
+
+ return labelList
+ }
+
+ /** Writes Image data into a `ByteBuffer`. */
+ @Synchronized
+ private fun convertBitmapToByteBuffer(
+ buffer: ByteBuffer, width: Int, height: Int): ByteBuffer {
+ val imgData = ByteBuffer.allocateDirect(
+ DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE)
+ imgData.order(ByteOrder.nativeOrder())
+ val bitmap = createResizedBitmap(buffer, width, height)
+ imgData.rewind()
+ bitmap.getPixels(intValues, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
+ // Convert the image to int points.
+ var pixel = 0
+ val startTime = SystemClock.uptimeMillis()
+ for (i in 0 until DIM_IMG_SIZE_X) {
+ for (j in 0 until DIM_IMG_SIZE_Y) {
+ val value = intValues[pixel++]
+ imgData.put((value shr 16 and 0xFF).toByte())
+ imgData.put((value shr 8 and 0xFF).toByte())
+ imgData.put((value and 0xFF).toByte())
+ }
+ }
+ val endTime = SystemClock.uptimeMillis()
+ val timeCost = endTime - startTime
+ Log.d(TAG, "Timecost to put values into ByteBuffer: $timeCost")
+ return imgData
+ }
+
+ /** Resizes image data from `ByteBuffer`. */
+ private fun createResizedBitmap(buffer: ByteBuffer, width: Int, height: Int): Bitmap {
+ val img = YuvImage(buffer.array(), ImageFormat.NV21, width, height, null)
+ val out = ByteArrayOutputStream()
+ img.compressToJpeg(Rect(0, 0, img.width, img.height), 50, out)
+ val imageBytes = out.toByteArray()
+ val bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
+ return Bitmap.createScaledBitmap(bitmap, DIM_IMG_SIZE_X, DIM_IMG_SIZE_Y, true)
+ }
+
+ /** Prints top-K labels, to be shown in UI as the results. */
+ @Synchronized
+ private fun printTopKLabels(labelProbArray: Array): List {
+ for (i in labelList.indices) {
+ sortedLabels.add(
+ AbstractMap.SimpleEntry(labelList[i], (labelProbArray[0][i] and 0xff.toByte()) / 255.0f))
+ if (sortedLabels.size > RESULTS_TO_SHOW) {
+ sortedLabels.poll()
+ }
+ }
+ val result = ArrayList()
+ val size = sortedLabels.size
+ for (i in 0 until size) {
+ val label = sortedLabels.poll()
+ result.add("${label.key}:${label.value}")
+ }
+ return result
+ }
+
+ companion object {
+
+ /** Tag for the [Log]. */
+ private const val TAG = "MLKitDemoApp:Classifier"
+
+ /** Name of the model file. */
+ private const val LOCAL_MODEL_NAME = "mobilenet_quant_v1"
+
+ /** Path of the model file stored in Assets. */
+ private const val LOCAL_MODEL_PATH = "mobilenet_quant_v1_224.tflite"
+
+ /** Name of the model uploaded to the Firebase console. */
+ private const val HOSTED_MODEL_NAME = "mobilenet_v1"
+
+ /** Name of the label file stored in Assets. */
+ private const val LABEL_PATH = "labels.txt"
+
+ /** Number of results to show in the UI. */
+ private const val RESULTS_TO_SHOW = 3
+
+ /** Dimensions of inputs. */
+ private const val DIM_BATCH_SIZE = 1
+
+ private const val DIM_PIXEL_SIZE = 3
+
+ private const val DIM_IMG_SIZE_X = 224
+ private const val DIM_IMG_SIZE_Y = 224
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/custommodel/CustomImageClassifierProcessor.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/custommodel/CustomImageClassifierProcessor.kt
new file mode 100644
index 0000000000..a61a068059
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/custommodel/CustomImageClassifierProcessor.kt
@@ -0,0 +1,46 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.custommodel
+
+import android.app.Activity
+import android.graphics.Bitmap
+import android.media.Image
+import com.google.firebase.ml.common.FirebaseMLException
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.common.VisionImageProcessor
+import java.nio.ByteBuffer
+
+/** Custom Image Classifier Demo. */
+class CustomImageClassifierProcessor @Throws(FirebaseMLException::class)
+constructor(private val activity: Activity): VisionImageProcessor {
+
+ private val classifier: CustomImageClassifier
+
+ init{
+ classifier = CustomImageClassifier(activity)
+ }
+
+ @Throws(FirebaseMLException::class)
+ override fun process(data: ByteBuffer, frameMetadata: FrameMetadata, graphicOverlay: GraphicOverlay) {
+ classifier
+ .classifyFrame(data, frameMetadata.width, frameMetadata.height)
+ .addOnSuccessListener(
+ activity
+ ) { result ->
+ val labelGraphic = LabelGraphic(graphicOverlay)
+ graphicOverlay.clear()
+ graphicOverlay.add(labelGraphic)
+ labelGraphic.updateLabel(result)
+ }
+ }
+
+ override fun process(bitmap: Bitmap, graphicOverlay: GraphicOverlay) {
+ // nop
+ }
+
+ override fun process(bitmap: Image, rotation:Int, graphicOverlay: GraphicOverlay) {
+ // nop
+
+ }
+
+ override fun stop() {}
+}
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/custommodel/LabelGraphic.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/custommodel/LabelGraphic.kt
new file mode 100644
index 0000000000..ad839a128d
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/custommodel/LabelGraphic.kt
@@ -0,0 +1,37 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.custommodel
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+
+/** Graphic instance for rendering image labels. */
+class LabelGraphic(private val overlay: GraphicOverlay) : GraphicOverlay.Graphic(overlay) {
+
+ private val textPaint: Paint
+
+ private lateinit var labels: List
+
+ init {
+ textPaint = Paint()
+ textPaint.color = Color.WHITE
+ textPaint.textSize = 60.0f
+ }
+
+ @Synchronized
+ internal fun updateLabel(labels: List) {
+ this.labels = labels
+ postInvalidate()
+ }
+
+ @Synchronized
+ override fun draw(canvas: Canvas) {
+ val x = overlay.width / 4.0f
+ var y = overlay.height / 4.0f
+
+ for (label in labels) {
+ canvas.drawText(label, x, y, textPaint)
+ y -= 62.0f
+ }
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/facedetection/FaceDetectionProcessor.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/facedetection/FaceDetectionProcessor.kt
new file mode 100644
index 0000000000..4b76540057
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/facedetection/FaceDetectionProcessor.kt
@@ -0,0 +1,64 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.facedetection
+
+import android.util.Log
+import com.google.android.gms.tasks.Task
+import com.google.firebase.ml.vision.FirebaseVision
+import com.google.firebase.ml.vision.common.FirebaseVisionImage
+import com.google.firebase.ml.vision.face.FirebaseVisionFace
+import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetector
+import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetectorOptions
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.kotlin.VisionProcessorBase
+import java.io.IOException
+
+/** Face Detector Demo. */
+class FaceDetectionProcessor : VisionProcessorBase>() {
+
+ private val detector: FirebaseVisionFaceDetector
+
+ init {
+ val options = FirebaseVisionFaceDetectorOptions.Builder()
+ .setClassificationType(FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS)
+ .setLandmarkType(FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS)
+ .setTrackingEnabled(true)
+ .build()
+
+ detector = FirebaseVision.getInstance().getVisionFaceDetector(options)
+ }
+
+ override fun stop() {
+ try {
+ detector.close()
+ } catch (e: IOException) {
+ Log.e(TAG, "Exception thrown while trying to close Face Detector: $e")
+ }
+
+ }
+
+ override fun detectInImage(image: FirebaseVisionImage): Task> {
+ return detector.detectInImage(image)
+ }
+
+ override fun onSuccess(
+ faces: List,
+ frameMetadata: FrameMetadata,
+ graphicOverlay: GraphicOverlay) {
+ graphicOverlay.clear()
+ for (i in faces.indices) {
+ val face = faces[i]
+ val faceGraphic = FaceGraphic(graphicOverlay)
+ graphicOverlay.add(faceGraphic)
+ faceGraphic.updateFace(face, frameMetadata.cameraFacing)
+ }
+ }
+
+ override fun onFailure(e: Exception) {
+ Log.e(TAG, "Face detection failed $e")
+ }
+
+ companion object {
+
+ private const val TAG = "FaceDetectionProcessor"
+ }
+}
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/facedetection/FaceGraphic.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/facedetection/FaceGraphic.kt
new file mode 100644
index 0000000000..5f1a208dcc
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/facedetection/FaceGraphic.kt
@@ -0,0 +1,136 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.facedetection
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import com.google.android.gms.vision.CameraSource
+import com.google.firebase.ml.vision.face.FirebaseVisionFace
+import com.google.firebase.ml.vision.face.FirebaseVisionFaceLandmark
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+
+/**
+ * Graphic instance for rendering face position, orientation, and landmarks within an associated
+ * graphic overlay view.
+ */
+class FaceGraphic(overlay: GraphicOverlay) : GraphicOverlay.Graphic(overlay) {
+
+ private var facing: Int = 0
+
+ private val facePositionPaint: Paint
+ private val idPaint: Paint
+ private val boxPaint: Paint
+
+ @Volatile
+ private lateinit var firebaseVisionFace: FirebaseVisionFace
+
+ init {
+
+ currentColorIndex = (currentColorIndex + 1) % COLOR_CHOICES.size
+ val selectedColor = COLOR_CHOICES[currentColorIndex]
+
+ facePositionPaint = Paint()
+ facePositionPaint.color = selectedColor
+
+ idPaint = Paint()
+ idPaint.color = selectedColor
+ idPaint.textSize = ID_TEXT_SIZE
+
+ boxPaint = Paint()
+ boxPaint.color = selectedColor
+ boxPaint.style = Paint.Style.STROKE
+ boxPaint.strokeWidth = BOX_STROKE_WIDTH
+ }
+
+ /**
+ * Updates the face instance from the detection of the most recent frame. Invalidates the relevant
+ * portions of the overlay to trigger a redraw.
+ */
+ fun updateFace(face: FirebaseVisionFace, facing: Int) {
+ firebaseVisionFace = face
+ this.facing = facing
+ postInvalidate()
+ }
+
+ /** Draws the face annotations for position on the supplied canvas. */
+ override fun draw(canvas: Canvas) {
+ val face = firebaseVisionFace ?: return
+
+ // Draws a circle at the position of the detected face, with the face's track id below.
+ val x = translateX(face.boundingBox.centerX().toFloat())
+ val y = translateY(face.boundingBox.centerY().toFloat())
+ canvas.drawCircle(x, y, FACE_POSITION_RADIUS, facePositionPaint)
+ canvas.drawText("id: ${face.trackingId}" , x + ID_X_OFFSET, y + ID_Y_OFFSET, idPaint)
+ canvas.drawText(
+ "happiness: ${String.format("%.2f", face.smilingProbability)}",
+ x + ID_X_OFFSET * 3,
+ y - ID_Y_OFFSET,
+ idPaint)
+ if (facing == CameraSource.CAMERA_FACING_FRONT) {
+ canvas.drawText(
+ "right eye: ${String.format("%.2f", face.rightEyeOpenProbability)}",
+ x - ID_X_OFFSET,
+ y,
+ idPaint)
+ canvas.drawText(
+ "left eye: ${String.format("%.2f", face.leftEyeOpenProbability)}",
+ x + ID_X_OFFSET * 6,
+ y,
+ idPaint)
+ } else {
+ canvas.drawText(
+ "left eye: ${String.format("%.2f", face.leftEyeOpenProbability)}",
+ x - ID_X_OFFSET,
+ y,
+ idPaint)
+ canvas.drawText(
+ "right eye: ${String.format("%.2f", face.rightEyeOpenProbability)}",
+ x + ID_X_OFFSET * 6,
+ y,
+ idPaint)
+ }
+
+ // Draws a bounding box around the face.
+ val xOffset = scaleX(face.boundingBox.width() / 2.0f)
+ val yOffset = scaleY(face.boundingBox.height() / 2.0f)
+ val left = x - xOffset
+ val top = y - yOffset
+ val right = x + xOffset
+ val bottom = y + yOffset
+ canvas.drawRect(left, top, right, bottom, boxPaint)
+
+ // draw landmarks
+ drawLandmarkPosition(canvas, face, FirebaseVisionFaceLandmark.BOTTOM_MOUTH)
+ drawLandmarkPosition(canvas, face, FirebaseVisionFaceLandmark.LEFT_CHEEK)
+ drawLandmarkPosition(canvas, face, FirebaseVisionFaceLandmark.LEFT_EAR)
+ drawLandmarkPosition(canvas, face, FirebaseVisionFaceLandmark.LEFT_MOUTH)
+ drawLandmarkPosition(canvas, face, FirebaseVisionFaceLandmark.LEFT_EYE)
+ drawLandmarkPosition(canvas, face, FirebaseVisionFaceLandmark.NOSE_BASE)
+ drawLandmarkPosition(canvas, face, FirebaseVisionFaceLandmark.RIGHT_CHEEK)
+ drawLandmarkPosition(canvas, face, FirebaseVisionFaceLandmark.RIGHT_EAR)
+ drawLandmarkPosition(canvas, face, FirebaseVisionFaceLandmark.RIGHT_EYE)
+ drawLandmarkPosition(canvas, face, FirebaseVisionFaceLandmark.RIGHT_MOUTH)
+ }
+
+ private fun drawLandmarkPosition(canvas: Canvas, face: FirebaseVisionFace, landmarkID: Int) {
+ val landmark = face.getLandmark(landmarkID)
+ landmark?.let {
+ val point = landmark.position
+ canvas.drawCircle(
+ translateX(point.x),
+ translateY(point.y),
+ 10f, idPaint)
+ }
+ }
+
+ companion object {
+ private const val FACE_POSITION_RADIUS = 10.0f
+ private const val ID_TEXT_SIZE = 40.0f
+ private const val ID_Y_OFFSET = 50.0f
+ private const val ID_X_OFFSET = -50.0f
+ private const val BOX_STROKE_WIDTH = 5.0f
+
+ private val COLOR_CHOICES = intArrayOf(Color.BLUE, Color.CYAN, Color.GREEN, Color.MAGENTA,
+ Color.RED, Color.WHITE, Color.YELLOW)
+ private var currentColorIndex = 0
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/imagelabeling/ImageLabelingProcessor.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/imagelabeling/ImageLabelingProcessor.kt
new file mode 100644
index 0000000000..24e2d20923
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/imagelabeling/ImageLabelingProcessor.kt
@@ -0,0 +1,53 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.imagelabeling
+
+import android.util.Log
+import com.google.android.gms.tasks.Task
+import com.google.firebase.ml.vision.FirebaseVision
+import com.google.firebase.ml.vision.common.FirebaseVisionImage
+import com.google.firebase.ml.vision.label.FirebaseVisionLabel
+import com.google.firebase.ml.vision.label.FirebaseVisionLabelDetector
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.kotlin.VisionProcessorBase
+import java.io.IOException
+
+/** Custom Image Classifier Demo. */
+class ImageLabelingProcessor : VisionProcessorBase>() {
+
+ private val detector: FirebaseVisionLabelDetector
+
+ init {
+ detector = FirebaseVision.getInstance().visionLabelDetector
+ }
+
+ override fun stop() {
+ try {
+ detector.close()
+ } catch (e: IOException) {
+ Log.e(TAG, "Exception thrown while trying to close Text Detector: $e")
+ }
+
+ }
+
+ override fun detectInImage(image: FirebaseVisionImage): Task> {
+ return detector.detectInImage(image)
+ }
+
+ override fun onSuccess(
+ labels: List,
+ frameMetadata: FrameMetadata,
+ graphicOverlay: GraphicOverlay) {
+ graphicOverlay.clear()
+ val labelGraphic = LabelGraphic(graphicOverlay, labels)
+ graphicOverlay.add(labelGraphic)
+ }
+
+ override fun onFailure(e: Exception) {
+ Log.w(TAG, "Label detection failed.$e")
+ }
+
+ companion object {
+
+ private const val TAG = "ImageLabelingProcessor"
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/imagelabeling/LabelGraphic.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/imagelabeling/LabelGraphic.kt
new file mode 100644
index 0000000000..475484884e
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/imagelabeling/LabelGraphic.kt
@@ -0,0 +1,34 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.imagelabeling
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import com.google.firebase.ml.vision.label.FirebaseVisionLabel
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+
+/** Graphic instance for rendering a label within an associated graphic overlay view. */
+class LabelGraphic (
+ private val overlay: GraphicOverlay,
+ private val labels: List
+) : GraphicOverlay.Graphic(overlay) {
+
+ private val textPaint: Paint
+
+ init {
+ textPaint = Paint()
+ textPaint.color = Color.WHITE
+ textPaint.textSize = 60.0f
+ postInvalidate()
+ }
+
+ @Synchronized
+ override fun draw(canvas: Canvas) {
+ val x = overlay.width / 4.0f
+ var y = overlay.height / 2.0f
+
+ for (label in labels) {
+ canvas.drawText(label.label, x, y, textPaint)
+ y -= 62.0f
+ }
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/textrecognition/TextGraphic.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/textrecognition/TextGraphic.kt
new file mode 100644
index 0000000000..b53e32218a
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/textrecognition/TextGraphic.kt
@@ -0,0 +1,59 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.textrecognition
+
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.RectF
+import com.google.firebase.ml.vision.text.FirebaseVisionText
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+
+/**
+ * Graphic instance for rendering TextBlock position, size, and ID within an associated graphic
+ * overlay view.
+ */
+class TextGraphic(overlay: GraphicOverlay,
+ private val text: FirebaseVisionText.Element?
+) : GraphicOverlay.Graphic(overlay) {
+
+ private val rectPaint: Paint
+ private val textPaint: Paint
+
+ init {
+
+ rectPaint = Paint()
+ rectPaint.color = TEXT_COLOR
+ rectPaint.style = Paint.Style.STROKE
+ rectPaint.strokeWidth = STROKE_WIDTH
+
+ textPaint = Paint()
+ textPaint.color = TEXT_COLOR
+ textPaint.textSize = TEXT_SIZE
+ // Redraw the overlay, as this graphic has been added.
+ postInvalidate()
+ }
+
+ /** Draws the text block annotations for position, size, and raw value on the supplied canvas. */
+ override fun draw(canvas: Canvas) {
+ if (text == null) {
+ throw IllegalStateException("Attempting to draw a null text.")
+ }
+
+ // Draws the bounding box around the TextBlock.
+ val rect = RectF(text.boundingBox)
+ rect.left = translateX(rect.left)
+ rect.top = translateY(rect.top)
+ rect.right = translateX(rect.right)
+ rect.bottom = translateY(rect.bottom)
+ canvas.drawRect(rect, rectPaint)
+
+ // Renders the text at the bottom of the box.
+ canvas.drawText(text.text, rect.left, rect.bottom, textPaint)
+ }
+
+ companion object {
+
+ private const val TEXT_COLOR = Color.WHITE
+ private const val TEXT_SIZE = 54.0f
+ private const val STROKE_WIDTH = 4.0f
+ }
+}
\ No newline at end of file
diff --git a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/textrecognition/TextRecognitionProcessor.kt b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/textrecognition/TextRecognitionProcessor.kt
new file mode 100644
index 0000000000..19d7df9023
--- /dev/null
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/kotlin/textrecognition/TextRecognitionProcessor.kt
@@ -0,0 +1,63 @@
+package com.google.firebase.samples.apps.mlkit.kotlin.textrecognition
+
+import android.util.Log
+import com.google.android.gms.tasks.Task
+import com.google.firebase.ml.vision.FirebaseVision
+import com.google.firebase.ml.vision.common.FirebaseVisionImage
+import com.google.firebase.ml.vision.text.FirebaseVisionText
+import com.google.firebase.ml.vision.text.FirebaseVisionTextRecognizer
+import com.google.firebase.samples.apps.mlkit.common.FrameMetadata
+import com.google.firebase.samples.apps.mlkit.common.GraphicOverlay
+import com.google.firebase.samples.apps.mlkit.kotlin.VisionProcessorBase
+import java.io.IOException
+
+/** Processor for the text recognition demo. */
+class TextRecognitionProcessor : VisionProcessorBase() {
+
+ private val detector: FirebaseVisionTextRecognizer
+
+ init {
+ detector = FirebaseVision.getInstance().onDeviceTextRecognizer
+ }
+
+ override fun stop() {
+ try {
+ detector.close()
+ } catch (e: IOException) {
+ Log.e(TAG, "Exception thrown while trying to close Text Detector: $e")
+ }
+
+ }
+
+ override fun detectInImage(image: FirebaseVisionImage): Task {
+ return detector.processImage(image)
+ }
+
+ override fun onSuccess(
+ results: FirebaseVisionText,
+ frameMetadata: FrameMetadata,
+ graphicOverlay: GraphicOverlay) {
+ graphicOverlay.clear()
+ val blocks = results.textBlocks
+ for (i in blocks.indices) {
+ val lines = blocks[i].lines
+ for (j in lines.indices) {
+ val elements = lines[j].elements
+ for (k in elements.indices) {
+ val textGraphic = TextGraphic(graphicOverlay, elements[k])
+ graphicOverlay.add(textGraphic)
+
+ }
+ }
+ }
+ }
+
+ override fun onFailure(e: Exception) {
+ Log.w(TAG, "Text detection failed.$e")
+ }
+
+ companion object {
+
+ private const val TAG = "TextRecProc"
+ }
+}
diff --git a/mlkit/app/src/main/res/layout-land/activity_live_preview.xml b/mlkit/app/src/main/res/layout-land/activity_live_preview.xml
index 1c2df065a9..2e78a070fc 100644
--- a/mlkit/app/src/main/res/layout-land/activity_live_preview.xml
+++ b/mlkit/app/src/main/res/layout-land/activity_live_preview.xml
@@ -8,17 +8,17 @@
android:background="#000"
android:keepScreenOn="true">
-
-
-
+
diff --git a/mlkit/app/src/main/res/layout/activity_live_preview.xml b/mlkit/app/src/main/res/layout/activity_live_preview.xml
index 94864e9ece..eb040e459c 100644
--- a/mlkit/app/src/main/res/layout/activity_live_preview.xml
+++ b/mlkit/app/src/main/res/layout/activity_live_preview.xml
@@ -9,21 +9,21 @@
android:background="#000"
android:keepScreenOn="true">
-
-
-
+
-