From c0303b385d0228a3954c24df375c46c281cda24f Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 11 Jun 2018 15:56:14 -0700 Subject: [PATCH 01/34] Initial 'fluter create' for Firebase ML Vision plugin --- packages/firebase_ml_vision/CHANGELOG.md | 3 + packages/firebase_ml_vision/LICENSE | 1 + packages/firebase_ml_vision/README.md | 10 + .../firebase_ml_vision/android/build.gradle | 34 ++ .../android/gradle.properties | 1 + .../android/settings.gradle | 1 + .../android/src/main/AndroidManifest.xml | 3 + .../FirebaseMlVisionPlugin.java | 25 + packages/firebase_ml_vision/example/.metadata | 8 + packages/firebase_ml_vision/example/README.md | 8 + .../example/android/app/build.gradle | 61 +++ .../android/app/src/main/AndroidManifest.xml | 39 ++ .../firebasemlvisionexample/MainActivity.java | 13 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values/styles.xml | 8 + .../example/android/build.gradle | 29 ++ .../example/android/gradle.properties | 1 + .../gradle/wrapper/gradle-wrapper.properties | 6 + .../example/android/settings.gradle | 15 + .../ios/Flutter/AppFrameworkInfo.plist | 26 ++ .../example/ios/Flutter/Debug.xcconfig | 2 + .../example/ios/Flutter/Release.xcconfig | 2 + .../ios/Runner.xcodeproj/project.pbxproj | 438 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Runner.xcscheme | 93 ++++ .../contents.xcworkspacedata | 7 + .../example/ios/Runner/AppDelegate.h | 6 + .../example/ios/Runner/AppDelegate.m | 13 + .../AppIcon.appiconset/Contents.json | 122 +++++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 11112 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 ++ .../ios/Runner/Base.lproj/Main.storyboard | 26 ++ .../example/ios/Runner/Info.plist | 45 ++ .../example/ios/Runner/main.m | 9 + .../firebase_ml_vision/example/lib/main.dart | 56 +++ .../firebase_ml_vision/example/pubspec.yaml | 67 +++ .../example/test/widget_test.dart | 25 + .../firebase_ml_vision/ios/Assets/.gitkeep | 0 .../ios/Classes/FirebaseMlVisionPlugin.h | 4 + .../ios/Classes/FirebaseMlVisionPlugin.m | 20 + .../ios/firebase_ml_vision.podspec | 21 + .../lib/firebase_ml_vision.dart | 13 + packages/firebase_ml_vision/pubspec.yaml | 49 ++ 67 files changed, 1394 insertions(+) create mode 100644 packages/firebase_ml_vision/CHANGELOG.md create mode 100644 packages/firebase_ml_vision/LICENSE create mode 100644 packages/firebase_ml_vision/README.md create mode 100644 packages/firebase_ml_vision/android/build.gradle create mode 100644 packages/firebase_ml_vision/android/gradle.properties create mode 100644 packages/firebase_ml_vision/android/settings.gradle create mode 100644 packages/firebase_ml_vision/android/src/main/AndroidManifest.xml create mode 100644 packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java create mode 100644 packages/firebase_ml_vision/example/.metadata create mode 100644 packages/firebase_ml_vision/example/README.md create mode 100644 packages/firebase_ml_vision/example/android/app/build.gradle create mode 100644 packages/firebase_ml_vision/example/android/app/src/main/AndroidManifest.xml create mode 100644 packages/firebase_ml_vision/example/android/app/src/main/java/io/flutter/plugins/firebasemlvisionexample/MainActivity.java create mode 100644 packages/firebase_ml_vision/example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 packages/firebase_ml_vision/example/android/app/src/main/res/values/styles.xml create mode 100644 packages/firebase_ml_vision/example/android/build.gradle create mode 100644 packages/firebase_ml_vision/example/android/gradle.properties create mode 100644 packages/firebase_ml_vision/example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 packages/firebase_ml_vision/example/android/settings.gradle create mode 100644 packages/firebase_ml_vision/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/firebase_ml_vision/example/ios/Flutter/Debug.xcconfig create mode 100644 packages/firebase_ml_vision/example/ios/Flutter/Release.xcconfig create mode 100644 packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/firebase_ml_vision/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/firebase_ml_vision/example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/firebase_ml_vision/example/ios/Runner/AppDelegate.h create mode 100644 packages/firebase_ml_vision/example/ios/Runner/AppDelegate.m create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 packages/firebase_ml_vision/example/ios/Runner/Info.plist create mode 100644 packages/firebase_ml_vision/example/ios/Runner/main.m create mode 100644 packages/firebase_ml_vision/example/lib/main.dart create mode 100644 packages/firebase_ml_vision/example/pubspec.yaml create mode 100644 packages/firebase_ml_vision/example/test/widget_test.dart create mode 100644 packages/firebase_ml_vision/ios/Assets/.gitkeep create mode 100644 packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.h create mode 100644 packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m create mode 100644 packages/firebase_ml_vision/ios/firebase_ml_vision.podspec create mode 100644 packages/firebase_ml_vision/lib/firebase_ml_vision.dart create mode 100644 packages/firebase_ml_vision/pubspec.yaml diff --git a/packages/firebase_ml_vision/CHANGELOG.md b/packages/firebase_ml_vision/CHANGELOG.md new file mode 100644 index 000000000000..41cc7d8192ec --- /dev/null +++ b/packages/firebase_ml_vision/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/packages/firebase_ml_vision/LICENSE b/packages/firebase_ml_vision/LICENSE new file mode 100644 index 000000000000..ba75c69f7f21 --- /dev/null +++ b/packages/firebase_ml_vision/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/packages/firebase_ml_vision/README.md b/packages/firebase_ml_vision/README.md new file mode 100644 index 000000000000..8f088e9ea1d9 --- /dev/null +++ b/packages/firebase_ml_vision/README.md @@ -0,0 +1,10 @@ +# firebase_ml_vision + +A new Flutter plugin. + +## Getting Started + +For help getting started with Flutter, view our online +[documentation](https://flutter.io/). + +For help on editing plugin code, view the [documentation](https://flutter.io/platform-plugins/#edit-code). \ No newline at end of file diff --git a/packages/firebase_ml_vision/android/build.gradle b/packages/firebase_ml_vision/android/build.gradle new file mode 100644 index 000000000000..657ce5942335 --- /dev/null +++ b/packages/firebase_ml_vision/android/build.gradle @@ -0,0 +1,34 @@ +group 'io.flutter.plugins.firebasemlvision' +version '1.0-SNAPSHOT' + +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.1.2' + } +} + +rootProject.allprojects { + repositories { + google() + jcenter() + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 27 + + defaultConfig { + minSdkVersion 16 + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } +} diff --git a/packages/firebase_ml_vision/android/gradle.properties b/packages/firebase_ml_vision/android/gradle.properties new file mode 100644 index 000000000000..8bd86f680510 --- /dev/null +++ b/packages/firebase_ml_vision/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/packages/firebase_ml_vision/android/settings.gradle b/packages/firebase_ml_vision/android/settings.gradle new file mode 100644 index 000000000000..66876748f77c --- /dev/null +++ b/packages/firebase_ml_vision/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'firebase_ml_vision' diff --git a/packages/firebase_ml_vision/android/src/main/AndroidManifest.xml b/packages/firebase_ml_vision/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..d43e3337d812 --- /dev/null +++ b/packages/firebase_ml_vision/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java new file mode 100644 index 000000000000..27566b06bd70 --- /dev/null +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java @@ -0,0 +1,25 @@ +package io.flutter.plugins.firebasemlvision; + +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry.Registrar; + +/** FirebaseMlVisionPlugin */ +public class FirebaseMlVisionPlugin implements MethodCallHandler { + /** Plugin registration. */ + public static void registerWith(Registrar registrar) { + final MethodChannel channel = new MethodChannel(registrar.messenger(), "firebase_ml_vision"); + channel.setMethodCallHandler(new FirebaseMlVisionPlugin()); + } + + @Override + public void onMethodCall(MethodCall call, Result result) { + if (call.method.equals("getPlatformVersion")) { + result.success("Android " + android.os.Build.VERSION.RELEASE); + } else { + result.notImplemented(); + } + } +} diff --git a/packages/firebase_ml_vision/example/.metadata b/packages/firebase_ml_vision/example/.metadata new file mode 100644 index 000000000000..9ce49c5dcc70 --- /dev/null +++ b/packages/firebase_ml_vision/example/.metadata @@ -0,0 +1,8 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: d454629a0646fcbd0f5a8d61998d0ea801d52909 + channel: master diff --git a/packages/firebase_ml_vision/example/README.md b/packages/firebase_ml_vision/example/README.md new file mode 100644 index 000000000000..fcb429d16af2 --- /dev/null +++ b/packages/firebase_ml_vision/example/README.md @@ -0,0 +1,8 @@ +# firebase_ml_vision_example + +Demonstrates how to use the firebase_ml_vision plugin. + +## Getting Started + +For help getting started with Flutter, view our online +[documentation](https://flutter.io/). diff --git a/packages/firebase_ml_vision/example/android/app/build.gradle b/packages/firebase_ml_vision/example/android/app/build.gradle new file mode 100644 index 000000000000..2695367985e5 --- /dev/null +++ b/packages/firebase_ml_vision/example/android/app/build.gradle @@ -0,0 +1,61 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + throw new GradleException("versionCode not found. Define flutter.versionCode in the local.properties file.") +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + throw new GradleException("versionName not found. Define flutter.versionName in the local.properties file.") +} + +apply plugin: 'com.android.application' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 27 + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "io.flutter.plugins.firebasemlvisionexample" + minSdkVersion 16 + targetSdkVersion 27 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} diff --git a/packages/firebase_ml_vision/example/android/app/src/main/AndroidManifest.xml b/packages/firebase_ml_vision/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..f1ccc8c12c80 --- /dev/null +++ b/packages/firebase_ml_vision/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + diff --git a/packages/firebase_ml_vision/example/android/app/src/main/java/io/flutter/plugins/firebasemlvisionexample/MainActivity.java b/packages/firebase_ml_vision/example/android/app/src/main/java/io/flutter/plugins/firebasemlvisionexample/MainActivity.java new file mode 100644 index 000000000000..f5bfd378a945 --- /dev/null +++ b/packages/firebase_ml_vision/example/android/app/src/main/java/io/flutter/plugins/firebasemlvisionexample/MainActivity.java @@ -0,0 +1,13 @@ +package io.flutter.plugins.firebasemlvisionexample; + +import android.os.Bundle; +import io.flutter.app.FlutterActivity; +import io.flutter.plugins.GeneratedPluginRegistrant; + +public class MainActivity extends FlutterActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + GeneratedPluginRegistrant.registerWith(this); + } +} diff --git a/packages/firebase_ml_vision/example/android/app/src/main/res/drawable/launch_background.xml b/packages/firebase_ml_vision/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000000..304732f88420 --- /dev/null +++ b/packages/firebase_ml_vision/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/firebase_ml_vision/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/android/app/src/main/res/values/styles.xml b/packages/firebase_ml_vision/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000000..00fa4417cfbe --- /dev/null +++ b/packages/firebase_ml_vision/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/packages/firebase_ml_vision/example/android/build.gradle b/packages/firebase_ml_vision/example/android/build.gradle new file mode 100644 index 000000000000..d4225c7905bc --- /dev/null +++ b/packages/firebase_ml_vision/example/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.1.2' + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/packages/firebase_ml_vision/example/android/gradle.properties b/packages/firebase_ml_vision/example/android/gradle.properties new file mode 100644 index 000000000000..8bd86f680510 --- /dev/null +++ b/packages/firebase_ml_vision/example/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/packages/firebase_ml_vision/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/firebase_ml_vision/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..9372d0f3f41a --- /dev/null +++ b/packages/firebase_ml_vision/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/packages/firebase_ml_vision/example/android/settings.gradle b/packages/firebase_ml_vision/example/android/settings.gradle new file mode 100644 index 000000000000..5a2f14fb18f6 --- /dev/null +++ b/packages/firebase_ml_vision/example/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/packages/firebase_ml_vision/example/ios/Flutter/AppFrameworkInfo.plist b/packages/firebase_ml_vision/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000000..9367d483e44e --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/packages/firebase_ml_vision/example/ios/Flutter/Debug.xcconfig b/packages/firebase_ml_vision/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000000..e8efba114687 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/firebase_ml_vision/example/ios/Flutter/Release.xcconfig b/packages/firebase_ml_vision/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000000..399e9340e6f6 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..d9b5e9017514 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,438 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; + 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; }; + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; + 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, + 3B80C3931E831B6300D905FE /* App.framework */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEBA1CF902C7004384FC /* Flutter.framework */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 97C146F21CF9000F007C117D /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0910; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, + 97C146F31CF9000F007C117D /* main.m in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebaseMlVisionExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebaseMlVisionExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..1d526a16ed0f --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000000..1263ac84b105 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/firebase_ml_vision/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/firebase_ml_vision/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..1d526a16ed0f --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/firebase_ml_vision/example/ios/Runner/AppDelegate.h b/packages/firebase_ml_vision/example/ios/Runner/AppDelegate.h new file mode 100644 index 000000000000..36e21bbf9cf4 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner/AppDelegate.h @@ -0,0 +1,6 @@ +#import +#import + +@interface AppDelegate : FlutterAppDelegate + +@end diff --git a/packages/firebase_ml_vision/example/ios/Runner/AppDelegate.m b/packages/firebase_ml_vision/example/ios/Runner/AppDelegate.m new file mode 100644 index 000000000000..59a72e90be12 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner/AppDelegate.m @@ -0,0 +1,13 @@ +#include "AppDelegate.h" +#include "GeneratedPluginRegistrant.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [GeneratedPluginRegistrant registerWithRegistry:self]; + // Override point for customization after application launch. + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +@end diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000000..d36b1fab2d9d --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..3d43d11e66f4de3da27ed045ca4fe38ad8b48094 GIT binary patch literal 11112 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 P-1+_A+?hGkL;m(J7kc&K literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..28c6bf03016f6c994b70f38d1b7346e5831b531f GIT binary patch literal 564 zcmV-40?Yl0P)Px$?ny*JR5%f>l)FnDQ543{x%ZCiu33$Wg!pQFfT_}?5Q|_VSlIbLC`dpoMXL}9 zHfd9&47Mo(7D231gb+kjFxZHS4-m~7WurTH&doVX2KI5sU4v(sJ1@T9eCIKPjsqSr z)C01LsCxk=72-vXmX}CQD#BD;Cthymh&~=f$Q8nn0J<}ZrusBy4PvRNE}+1ceuj8u z0mW5k8fmgeLnTbWHGwfKA3@PdZxhn|PypR&^p?weGftrtCbjF#+zk_5BJh7;0`#Wr zgDpM_;Ax{jO##IrT`Oz;MvfwGfV$zD#c2xckpcXC6oou4ML~ezCc2EtnsQTB4tWNg z?4bkf;hG7IMfhgNI(FV5Gs4|*GyMTIY0$B=_*mso9Ityq$m^S>15>-?0(zQ<8Qy<_TjHE33(?_M8oaM zyc;NxzRVK@DL6RJnX%U^xW0Gpg(lXp(!uK1v0YgHjs^ZXSQ|m#lV7ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000000..89c2725b70f1 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/firebase_ml_vision/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/firebase_ml_vision/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000000..f2e259c7c939 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/firebase_ml_vision/example/ios/Runner/Base.lproj/Main.storyboard b/packages/firebase_ml_vision/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000000..f3c28516fb38 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/firebase_ml_vision/example/ios/Runner/Info.plist b/packages/firebase_ml_vision/example/ios/Runner/Info.plist new file mode 100644 index 000000000000..c1ced7a4355b --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + firebase_ml_vision_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/packages/firebase_ml_vision/example/ios/Runner/main.m b/packages/firebase_ml_vision/example/ios/Runner/main.m new file mode 100644 index 000000000000..dff6597e4513 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner/main.m @@ -0,0 +1,9 @@ +#import +#import +#import "AppDelegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart new file mode 100644 index 000000000000..09f71960cc94 --- /dev/null +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:firebase_ml_vision/firebase_ml_vision.dart'; + +void main() => runApp(new MyApp()); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => new _MyAppState(); +} + +class _MyAppState extends State { + String _platformVersion = 'Unknown'; + + @override + void initState() { + super.initState(); + initPlatformState(); + } + + // Platform messages are asynchronous, so we initialize in an async method. + Future initPlatformState() async { + String platformVersion; + // Platform messages may fail, so we use a try/catch PlatformException. + try { + platformVersion = await FirebaseMlVision.platformVersion; + } on PlatformException { + platformVersion = 'Failed to get platform version.'; + } + + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. + if (!mounted) return; + + setState(() { + _platformVersion = platformVersion; + }); + } + + @override + Widget build(BuildContext context) { + return new MaterialApp( + home: new Scaffold( + appBar: new AppBar( + title: const Text('Plugin example app'), + ), + body: new Center( + child: new Text('Running on: $_platformVersion\n'), + ), + ), + ); + } +} diff --git a/packages/firebase_ml_vision/example/pubspec.yaml b/packages/firebase_ml_vision/example/pubspec.yaml new file mode 100644 index 000000000000..7a34b8dff6b8 --- /dev/null +++ b/packages/firebase_ml_vision/example/pubspec.yaml @@ -0,0 +1,67 @@ +name: firebase_ml_vision_example +description: Demonstrates how to use the firebase_ml_vision plugin. + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# Read more about versioning at semver.org. +version: 1.0.0+1 + +dependencies: + flutter: + sdk: flutter + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^0.1.2 + +dev_dependencies: + flutter_test: + sdk: flutter + + firebase_ml_vision: + path: ../ + +# For information on the generic Dart part of this file, see the +# following page: https://www.dartlang.org/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.io/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.io/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.io/custom-fonts/#from-packages diff --git a/packages/firebase_ml_vision/example/test/widget_test.dart b/packages/firebase_ml_vision/example/test/widget_test.dart new file mode 100644 index 000000000000..d586708bce13 --- /dev/null +++ b/packages/firebase_ml_vision/example/test/widget_test.dart @@ -0,0 +1,25 @@ +// This is a basic Flutter widget test. +// To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter +// provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to +// find child widgets in the widget tree, read text, and verify that the values of widget properties +// are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:firebase_ml_vision_example/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(new MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && widget.data.startsWith('Running on:'), + ), + findsOneWidget); + }); +} diff --git a/packages/firebase_ml_vision/ios/Assets/.gitkeep b/packages/firebase_ml_vision/ios/Assets/.gitkeep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.h b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.h new file mode 100644 index 000000000000..0526078937d8 --- /dev/null +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface FirebaseMlVisionPlugin : NSObject +@end diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m new file mode 100644 index 000000000000..0580d157f23f --- /dev/null +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -0,0 +1,20 @@ +#import "FirebaseMlVisionPlugin.h" + +@implementation FirebaseMlVisionPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + FlutterMethodChannel* channel = [FlutterMethodChannel + methodChannelWithName:@"firebase_ml_vision" + binaryMessenger:[registrar messenger]]; + FirebaseMlVisionPlugin* instance = [[FirebaseMlVisionPlugin alloc] init]; + [registrar addMethodCallDelegate:instance channel:channel]; +} + +- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + if ([@"getPlatformVersion" isEqualToString:call.method]) { + result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); + } else { + result(FlutterMethodNotImplemented); + } +} + +@end diff --git a/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec b/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec new file mode 100644 index 000000000000..c4eac467064b --- /dev/null +++ b/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec @@ -0,0 +1,21 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'firebase_ml_vision' + s.version = '0.0.1' + s.summary = 'A new Flutter plugin.' + s.description = <<-DESC +A new Flutter plugin. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + + s.ios.deployment_target = '8.0' +end + diff --git a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart new file mode 100644 index 000000000000..a06c5d3930ac --- /dev/null +++ b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart @@ -0,0 +1,13 @@ +import 'dart:async'; + +import 'package:flutter/services.dart'; + +class FirebaseMlVision { + static const MethodChannel _channel = + const MethodChannel('firebase_ml_vision'); + + static Future get platformVersion async { + final String version = await _channel.invokeMethod('getPlatformVersion'); + return version; + } +} diff --git a/packages/firebase_ml_vision/pubspec.yaml b/packages/firebase_ml_vision/pubspec.yaml new file mode 100644 index 000000000000..a92e96aa6b9e --- /dev/null +++ b/packages/firebase_ml_vision/pubspec.yaml @@ -0,0 +1,49 @@ +name: firebase_ml_vision +description: A new Flutter plugin. +version: 0.0.1 +author: +homepage: + +dependencies: + flutter: + sdk: flutter + +# For information on the generic Dart part of this file, see the +# following page: https://www.dartlang.org/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + plugin: + androidPackage: io.flutter.plugins.firebasemlvision + pluginClass: FirebaseMlVisionPlugin + + # To add assets to your plugin package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.io/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.io/assets-and-images/#resolution-aware. + + # To add custom fonts to your plugin package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.io/custom-fonts/#from-packages From cbe3715a5da660ec77cede205de6e95d5a62f647 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 11 Jun 2018 16:05:37 -0700 Subject: [PATCH 02/34] Formatting --- .../firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index 0580d157f23f..d2232120e670 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -2,9 +2,9 @@ @implementation FirebaseMlVisionPlugin + (void)registerWithRegistrar:(NSObject*)registrar { - FlutterMethodChannel* channel = [FlutterMethodChannel - methodChannelWithName:@"firebase_ml_vision" - binaryMessenger:[registrar messenger]]; + FlutterMethodChannel* channel = + [FlutterMethodChannel methodChannelWithName:@"firebase_ml_vision" + binaryMessenger:[registrar messenger]]; FirebaseMlVisionPlugin* instance = [[FirebaseMlVisionPlugin alloc] init]; [registrar addMethodCallDelegate:instance channel:channel]; } From d6c20cded0f1e93c545614a74795f69bd2799150 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 11 Jun 2018 16:10:40 -0700 Subject: [PATCH 03/34] More Formatting --- .../firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index d2232120e670..418c956c4517 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -4,7 +4,7 @@ @implementation FirebaseMlVisionPlugin + (void)registerWithRegistrar:(NSObject*)registrar { FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:@"firebase_ml_vision" - binaryMessenger:[registrar messenger]]; + binaryMessenger:[registrar messenger]]; FirebaseMlVisionPlugin* instance = [[FirebaseMlVisionPlugin alloc] init]; [registrar addMethodCallDelegate:instance channel:channel]; } From e00295340c7dec5787221f8af089f97d8ae62609 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 11 Jun 2018 16:13:57 -0700 Subject: [PATCH 04/34] Import ordering --- packages/firebase_ml_vision/example/lib/main.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart index 09f71960cc94..b8df91b7f91d 100644 --- a/packages/firebase_ml_vision/example/lib/main.dart +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -1,8 +1,8 @@ -import 'package:flutter/material.dart'; import 'dart:async'; -import 'package:flutter/services.dart'; import 'package:firebase_ml_vision/firebase_ml_vision.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; void main() => runApp(new MyApp()); From 79c085ffffd137059a858d963d3a8d252c6c56c9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 11 Jun 2018 16:39:58 -0700 Subject: [PATCH 05/34] Added android app to firebase --- .../example/android/app/build.gradle | 22 +-- .../example/android/app/google-services.json | 179 ++++++++++++++++++ .../example/android/build.gradle | 2 + 3 files changed, 183 insertions(+), 20 deletions(-) create mode 100644 packages/firebase_ml_vision/example/android/app/google-services.json diff --git a/packages/firebase_ml_vision/example/android/app/build.gradle b/packages/firebase_ml_vision/example/android/app/build.gradle index 2695367985e5..affb47e6f50e 100644 --- a/packages/firebase_ml_vision/example/android/app/build.gradle +++ b/packages/firebase_ml_vision/example/android/app/build.gradle @@ -11,16 +11,6 @@ if (flutterRoot == null) { throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") } -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - throw new GradleException("versionCode not found. Define flutter.versionCode in the local.properties file.") -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - throw new GradleException("versionName not found. Define flutter.versionName in the local.properties file.") -} - apply plugin: 'com.android.application' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" @@ -32,19 +22,12 @@ android { } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "io.flutter.plugins.firebasemlvisionexample" minSdkVersion 16 - targetSdkVersion 27 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug } } @@ -55,7 +38,6 @@ flutter { } dependencies { - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } + +apply plugin: 'com.google.gms.google-services' diff --git a/packages/firebase_ml_vision/example/android/app/google-services.json b/packages/firebase_ml_vision/example/android/app/google-services.json new file mode 100644 index 000000000000..91e7b73c106c --- /dev/null +++ b/packages/firebase_ml_vision/example/android/app/google-services.json @@ -0,0 +1,179 @@ +{ + "project_info": { + "project_number": "479882132969", + "firebase_url": "https://my-flutter-proj.firebaseio.com", + "project_id": "my-flutter-proj", + "storage_bucket": "my-flutter-proj.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:479882132969:android:632cdf3fc0a17139", + "android_client_info": { + "package_name": "io.flutter.plugins.firebasedynamiclinksexample" + } + }, + "oauth_client": [ + { + "client_id": "479882132969-32qusitiag53931ck80h121ajhlc5a7e.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "io.flutter.plugins.firebasedynamiclinksexample", + "certificate_hash": "e733b7a303250b63e06de6f7c9767c517d69cfa0" + } + }, + { + "client_id": "479882132969-0d20fkjtr1p8evfomfkf3vmi50uajml2.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "479882132969-0d20fkjtr1p8evfomfkf3vmi50uajml2.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCrZz9T0Pg0rDnpxfNuPBrOxGhXskfebXs" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 2, + "other_platform_oauth_client": [ + { + "client_id": "479882132969-0d20fkjtr1p8evfomfkf3vmi50uajml2.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "479882132969-pn2ancg65o0e7r5ikte1qiciuvdghqf9.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.google.FirebaseCppDynamicLinksTestApp.dev", + "app_store_id": "1009116743" + } + } + ] + }, + "ads_service": { + "status": 2 + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:479882132969:android:ae50362b4bc06086", + "android_client_info": { + "package_name": "io.flutter.plugins.firebasemlvisionexample" + } + }, + "oauth_client": [ + { + "client_id": "479882132969-9pp74fkgmtvt47t9rikc1p861v7n85tn.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "io.flutter.plugins.firebasemlvisionexample", + "certificate_hash": "e733b7a303250b63e06de6f7c9767c517d69cfa0" + } + }, + { + "client_id": "479882132969-0d20fkjtr1p8evfomfkf3vmi50uajml2.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "479882132969-0d20fkjtr1p8evfomfkf3vmi50uajml2.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCrZz9T0Pg0rDnpxfNuPBrOxGhXskfebXs" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 2, + "other_platform_oauth_client": [ + { + "client_id": "479882132969-0d20fkjtr1p8evfomfkf3vmi50uajml2.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "479882132969-pn2ancg65o0e7r5ikte1qiciuvdghqf9.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.google.FirebaseCppDynamicLinksTestApp.dev", + "app_store_id": "1009116743" + } + } + ] + }, + "ads_service": { + "status": 2 + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:479882132969:android:215a22700e1b466b", + "android_client_info": { + "package_name": "io.flutter.plugins.firebaseperformanceexample" + } + }, + "oauth_client": [ + { + "client_id": "479882132969-8h4kiv8m7ho4tvn6uuujsfcrf69unuf7.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "io.flutter.plugins.firebaseperformanceexample", + "certificate_hash": "e733b7a303250b63e06de6f7c9767c517d69cfa0" + } + }, + { + "client_id": "479882132969-0d20fkjtr1p8evfomfkf3vmi50uajml2.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "479882132969-0d20fkjtr1p8evfomfkf3vmi50uajml2.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCrZz9T0Pg0rDnpxfNuPBrOxGhXskfebXs" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 2, + "other_platform_oauth_client": [ + { + "client_id": "479882132969-0d20fkjtr1p8evfomfkf3vmi50uajml2.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "479882132969-pn2ancg65o0e7r5ikte1qiciuvdghqf9.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.google.FirebaseCppDynamicLinksTestApp.dev", + "app_store_id": "1009116743" + } + } + ] + }, + "ads_service": { + "status": 2 + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/packages/firebase_ml_vision/example/android/build.gradle b/packages/firebase_ml_vision/example/android/build.gradle index d4225c7905bc..aa8e5258c61e 100644 --- a/packages/firebase_ml_vision/example/android/build.gradle +++ b/packages/firebase_ml_vision/example/android/build.gradle @@ -6,6 +6,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.1.2' + classpath 'com.google.gms:google-services:3.1.2' } } @@ -13,6 +14,7 @@ allprojects { repositories { google() jcenter() + mavenLocal() } } From a1775e870931922421e0a3de7ec765e272f918c5 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 11 Jun 2018 16:50:09 -0700 Subject: [PATCH 06/34] Added ios app to firebase --- .../ios/Runner/GoogleService-Info.plist | 40 +++++++++++++++++++ .../ios/Classes/FirebaseMlVisionPlugin.m | 12 ++++++ .../ios/firebase_ml_vision.podspec | 3 +- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 packages/firebase_ml_vision/example/ios/Runner/GoogleService-Info.plist diff --git a/packages/firebase_ml_vision/example/ios/Runner/GoogleService-Info.plist b/packages/firebase_ml_vision/example/ios/Runner/GoogleService-Info.plist new file mode 100644 index 000000000000..0562b2ee756f --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,40 @@ + + + + + AD_UNIT_ID_FOR_BANNER_TEST + ca-app-pub-3940256099942544/2934735716 + AD_UNIT_ID_FOR_INTERSTITIAL_TEST + ca-app-pub-3940256099942544/4411468910 + CLIENT_ID + 479882132969-gjp4e63ogu2h6guttj2ie6t3f10ic7i8.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.479882132969-gjp4e63ogu2h6guttj2ie6t3f10ic7i8 + API_KEY + AIzaSyBECOwLTAN6PU4Aet1b2QLGIb3kRK8Xjew + GCM_SENDER_ID + 479882132969 + PLIST_VERSION + 1 + BUNDLE_ID + io.flutter.plugins.firebaseMlVisionExample + PROJECT_ID + my-flutter-proj + STORAGE_BUCKET + my-flutter-proj.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:479882132969:ios:249503bd2f4091a3 + DATABASE_URL + https://my-flutter-proj.firebaseio.com + + \ No newline at end of file diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index 418c956c4517..4d247506ce6b 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -1,5 +1,7 @@ #import "FirebaseMlVisionPlugin.h" +#import "Firebase/Firebase.h" + @implementation FirebaseMlVisionPlugin + (void)registerWithRegistrar:(NSObject*)registrar { FlutterMethodChannel* channel = @@ -9,6 +11,16 @@ + (void)registerWithRegistrar:(NSObject*)registrar { [registrar addMethodCallDelegate:instance channel:channel]; } +- (instancetype)init { + self = [super init]; + if (self) { + if (![FIRApp defaultApp]) { + [FIRApp configure]; + } + } + return self; +} + - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if ([@"getPlatformVersion" isEqualToString:call.method]) { result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); diff --git a/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec b/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec index c4eac467064b..69f8ba389ea2 100644 --- a/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec +++ b/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec @@ -15,7 +15,8 @@ A new Flutter plugin. s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' - + s.dependency 'Firebase/Core' s.ios.deployment_target = '8.0' + s.static_framework = true end From a6734f156df9581c501f5a90ed21b8d6ff01fa46 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 12 Jun 2018 10:51:44 -0700 Subject: [PATCH 07/34] Added ml vision to android and ios --- .../firebase_ml_vision/android/build.gradle | 3 + .../ios/Runner.xcodeproj/project.pbxproj | 82 ++++++++++++++++++- .../contents.xcworkspacedata | 3 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++ .../ios/firebase_ml_vision.podspec | 3 +- 5 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 packages/firebase_ml_vision/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/packages/firebase_ml_vision/android/build.gradle b/packages/firebase_ml_vision/android/build.gradle index 657ce5942335..2d0d116e51ad 100644 --- a/packages/firebase_ml_vision/android/build.gradle +++ b/packages/firebase_ml_vision/android/build.gradle @@ -31,4 +31,7 @@ android { lintOptions { disable 'InvalidPackage' } + dependencies { + api 'com.google.firebase:firebase-ml-vision:15.+' + } } diff --git a/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.pbxproj index d9b5e9017514..bd47eafb95e9 100644 --- a/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_ml_vision/example/ios/Runner.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 8FDA56F920D046020020E776 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 8FDA56F820D046020020E776 /* GoogleService-Info.plist */; }; 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; @@ -21,6 +22,7 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + D8D4CC03A45432EE564AF6EC /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 47511359F254D1FA05DF3B06 /* libPods-Runner.a */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -44,9 +46,11 @@ 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 47511359F254D1FA05DF3B06 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 8FDA56F820D046020020E776 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; @@ -65,12 +69,21 @@ files = ( 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + D8D4CC03A45432EE564AF6EC /* libPods-Runner.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 060D02122DE17098607AD6EA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 47511359F254D1FA05DF3B06 /* libPods-Runner.a */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -91,7 +104,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, + FC90A70078657ED2825B5943 /* Pods */, + 060D02122DE17098607AD6EA /* Frameworks */, ); sourceTree = ""; }; @@ -106,6 +120,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 8FDA56F820D046020020E776 /* GoogleService-Info.plist */, 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 97C146FA1CF9000F007C117D /* Main.storyboard */, @@ -127,6 +142,13 @@ name = "Supporting Files"; sourceTree = ""; }; + FC90A70078657ED2825B5943 /* Pods */ = { + isa = PBXGroup; + children = ( + ); + name = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -134,12 +156,15 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 96E46CF45834A6C37B9BB190 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 76593FE57A112D467FCA6E60 /* [CP] Embed Pods Frameworks */, + A29312BDBCEC3EBFF001E62D /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -188,6 +213,7 @@ buildActionMask = 2147483647; files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 8FDA56F920D046020020E776 /* GoogleService-Info.plist in Resources */, 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, @@ -214,6 +240,42 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; }; + 76593FE57A112D467FCA6E60 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 96E46CF45834A6C37B9BB190 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -228,6 +290,24 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + A29312BDBCEC3EBFF001E62D /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/GoogleMobileVision/GoogleMVTextDetectorResources.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleMVTextDetectorResources.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/packages/firebase_ml_vision/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/firebase_ml_vision/example/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed0f..21a3cc14c74e 100644 --- a/packages/firebase_ml_vision/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/packages/firebase_ml_vision/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/packages/firebase_ml_vision/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/firebase_ml_vision/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/firebase_ml_vision/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec b/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec index 69f8ba389ea2..83ce77d3f643 100644 --- a/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec +++ b/packages/firebase_ml_vision/ios/firebase_ml_vision.podspec @@ -16,7 +16,8 @@ A new Flutter plugin. s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' s.dependency 'Firebase/Core' + s.dependency 'Firebase/MLVision' + s.dependency 'Firebase/MLVisionTextModel' s.ios.deployment_target = '8.0' s.static_framework = true end - From 84ac21f7982787cf8e3f8dc600999593cc043b80 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 12 Jun 2018 16:15:30 -0700 Subject: [PATCH 08/34] WIP dart side of ml vision --- .../FirebaseMlVisionPlugin.java | 2 +- .../firebase_ml_vision/example/lib/main.dart | 2 +- .../ios/Classes/FirebaseMlVisionPlugin.m | 2 +- .../lib/firebase_ml_vision.dart | 16 ++++----- .../lib/src/firebase_vision.dart | 36 +++++++++++++++++++ 5 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 packages/firebase_ml_vision/lib/src/firebase_vision.dart diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java index 27566b06bd70..5fca13b9bfc9 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java @@ -10,7 +10,7 @@ public class FirebaseMlVisionPlugin implements MethodCallHandler { /** Plugin registration. */ public static void registerWith(Registrar registrar) { - final MethodChannel channel = new MethodChannel(registrar.messenger(), "firebase_ml_vision"); + final MethodChannel channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_ml_vision"); channel.setMethodCallHandler(new FirebaseMlVisionPlugin()); } diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart index b8df91b7f91d..751307261f13 100644 --- a/packages/firebase_ml_vision/example/lib/main.dart +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -25,7 +25,7 @@ class _MyAppState extends State { String platformVersion; // Platform messages may fail, so we use a try/catch PlatformException. try { - platformVersion = await FirebaseMlVision.platformVersion; + platformVersion = await FirebaseVision.platformVersion; } on PlatformException { platformVersion = 'Failed to get platform version.'; } diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index 4d247506ce6b..2f73d7cc65d3 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -5,7 +5,7 @@ @implementation FirebaseMlVisionPlugin + (void)registerWithRegistrar:(NSObject*)registrar { FlutterMethodChannel* channel = - [FlutterMethodChannel methodChannelWithName:@"firebase_ml_vision" + [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_ml_vision" binaryMessenger:[registrar messenger]]; FirebaseMlVisionPlugin* instance = [[FirebaseMlVisionPlugin alloc] init]; [registrar addMethodCallDelegate:instance channel:channel]; diff --git a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart index a06c5d3930ac..fb154bea6b7f 100644 --- a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart +++ b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart @@ -1,13 +1,11 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +library firebase_ml_vision; + import 'dart:async'; import 'package:flutter/services.dart'; -class FirebaseMlVision { - static const MethodChannel _channel = - const MethodChannel('firebase_ml_vision'); - - static Future get platformVersion async { - final String version = await _channel.invokeMethod('getPlatformVersion'); - return version; - } -} +part 'src/firebase_vision.dart'; diff --git a/packages/firebase_ml_vision/lib/src/firebase_vision.dart b/packages/firebase_ml_vision/lib/src/firebase_vision.dart new file mode 100644 index 000000000000..78d35d4083f2 --- /dev/null +++ b/packages/firebase_ml_vision/lib/src/firebase_vision.dart @@ -0,0 +1,36 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of firebase_ml_vision; + +class FirebaseVision { + FirebaseVision._(); + + //@visibleForTesting + static const MethodChannel _channel = + const MethodChannel('plugins.flutter.io/firebase_ml_vision'); + + static final FirebaseVision instance = new FirebaseVision._(); + + static Future get platformVersion async { + final String version = await _channel.invokeMethod('getPlatformVersion'); + return version; + } +} + +class VisionImage { + + final File _image; + + VisionImage(this._image); + + File get image => this._image; +} + +abstract class VisionDetector { + static const MethodChannel channel = + const MethodChannel('plugins.flutter.io/firebase_ml_kit'); + + Future detectInImage(VisionImage visionImage); +} From e193edf5952f3e82588dade59491a59f8533fae3 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 13 Jun 2018 15:10:28 -0700 Subject: [PATCH 09/34] finish dart side of ml vision and text detector --- .../firebase_ml_vision/example/lib/main.dart | 27 +------ .../lib/firebase_ml_vision.dart | 5 ++ .../lib/src/firebase_vision.dart | 21 ++---- .../lib/src/text_detector.dart | 74 +++++++++++++++++++ 4 files changed, 87 insertions(+), 40 deletions(-) create mode 100644 packages/firebase_ml_vision/lib/src/text_detector.dart diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart index 751307261f13..e948d1e796a7 100644 --- a/packages/firebase_ml_vision/example/lib/main.dart +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -12,32 +12,9 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { - String _platformVersion = 'Unknown'; - @override void initState() { super.initState(); - initPlatformState(); - } - - // Platform messages are asynchronous, so we initialize in an async method. - Future initPlatformState() async { - String platformVersion; - // Platform messages may fail, so we use a try/catch PlatformException. - try { - platformVersion = await FirebaseVision.platformVersion; - } on PlatformException { - platformVersion = 'Failed to get platform version.'; - } - - // If the widget was removed from the tree while the asynchronous platform - // message was in flight, we want to discard the reply rather than calling - // setState to update our non-existent appearance. - if (!mounted) return; - - setState(() { - _platformVersion = platformVersion; - }); } @override @@ -47,8 +24,8 @@ class _MyAppState extends State { appBar: new AppBar( title: const Text('Plugin example app'), ), - body: new Center( - child: new Text('Running on: $_platformVersion\n'), + body: const Center( + child: const Text('Hello, World!'), ), ), ); diff --git a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart index fb154bea6b7f..0a57d5b4fa17 100644 --- a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart +++ b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart @@ -5,7 +5,12 @@ library firebase_ml_vision; import 'dart:async'; +import 'dart:io'; +import 'dart:math'; +import 'dart:ui'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; part 'src/firebase_vision.dart'; +part 'src/text_detector.dart'; diff --git a/packages/firebase_ml_vision/lib/src/firebase_vision.dart b/packages/firebase_ml_vision/lib/src/firebase_vision.dart index 78d35d4083f2..d9e038b80e64 100644 --- a/packages/firebase_ml_vision/lib/src/firebase_vision.dart +++ b/packages/firebase_ml_vision/lib/src/firebase_vision.dart @@ -7,30 +7,21 @@ part of firebase_ml_vision; class FirebaseVision { FirebaseVision._(); - //@visibleForTesting + @visibleForTesting static const MethodChannel _channel = const MethodChannel('plugins.flutter.io/firebase_ml_vision'); static final FirebaseVision instance = new FirebaseVision._(); - - static Future get platformVersion async { - final String version = await _channel.invokeMethod('getPlatformVersion'); - return version; - } } -class VisionImage { +class FirebaseVisionImage { + FirebaseVisionImage(this._image); final File _image; - VisionImage(this._image); - - File get image => this._image; + File get image => _image; } -abstract class VisionDetector { - static const MethodChannel channel = - const MethodChannel('plugins.flutter.io/firebase_ml_kit'); - - Future detectInImage(VisionImage visionImage); +abstract class FirebaseVisionDetector { + Future detectInImage(FirebaseVisionImage visionImage); } diff --git a/packages/firebase_ml_vision/lib/src/text_detector.dart b/packages/firebase_ml_vision/lib/src/text_detector.dart new file mode 100644 index 000000000000..13f1d65a8291 --- /dev/null +++ b/packages/firebase_ml_vision/lib/src/text_detector.dart @@ -0,0 +1,74 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of firebase_ml_vision; + +class TextDetector implements FirebaseVisionDetector { + @override + Future> detectInImage(FirebaseVisionImage visionImage) async { + final List reply = + await FirebaseVision._channel.invokeMethod( + 'TextDetector#detectInImage', + visionImage.image.path, + ); + + final List containers = []; + reply.forEach((dynamic data) { + containers.add(new TextBlock._(data)); + }); + + return containers; + } +} + +abstract class TextContainer { + TextContainer._(Map data) + : text = data['text'], + boundingBox = Rect.fromLTRB( + data['left'], + data['top'], + data['right'], + data['bottom'], + ), + cornerPoints = data['points'] == null + ? null + : data['points'] + .map>((dynamic item) => Point( + item['x'], + item['y'], + )) + .toList(); + + final String text; + final Rect boundingBox; + final List> cornerPoints; +} + +class TextBlock extends TextContainer { + final List lines; + + TextBlock._(Map data) + : lines = data['lines'] == null + ? null + : data['lines'] + .map((dynamic item) => TextLine._(item)) + .toList(), + super._(data); +} + +class TextLine extends TextContainer { + final List elements; + + TextLine._(Map data) + : elements = data['elements'] == null + ? null + : data['elements'] + .map((dynamic item) => TextElement._(item)) + .toList(), + super._(data); +} + +class TextElement extends TextContainer { + TextElement._(Map data) : super._(data); +} From ef0a43f1ef760cc4405ca9ca59edfe1f18c501fe Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 13 Jun 2018 16:30:12 -0700 Subject: [PATCH 10/34] Added TextDetector tests --- .../lib/src/firebase_vision.dart | 4 +- .../lib/src/text_detector.dart | 22 ++-- packages/firebase_ml_vision/pubspec.yaml | 37 +----- .../test/firebase_ml_vision_test.dart | 121 ++++++++++++++++++ 4 files changed, 139 insertions(+), 45 deletions(-) create mode 100644 packages/firebase_ml_vision/test/firebase_ml_vision_test.dart diff --git a/packages/firebase_ml_vision/lib/src/firebase_vision.dart b/packages/firebase_ml_vision/lib/src/firebase_vision.dart index d9e038b80e64..4d63b316d227 100644 --- a/packages/firebase_ml_vision/lib/src/firebase_vision.dart +++ b/packages/firebase_ml_vision/lib/src/firebase_vision.dart @@ -8,10 +8,12 @@ class FirebaseVision { FirebaseVision._(); @visibleForTesting - static const MethodChannel _channel = + static const MethodChannel channel = const MethodChannel('plugins.flutter.io/firebase_ml_vision'); static final FirebaseVision instance = new FirebaseVision._(); + + TextDetector getTextDetector() => new TextDetector._(); } class FirebaseVisionImage { diff --git a/packages/firebase_ml_vision/lib/src/text_detector.dart b/packages/firebase_ml_vision/lib/src/text_detector.dart index 13f1d65a8291..217a23277762 100644 --- a/packages/firebase_ml_vision/lib/src/text_detector.dart +++ b/packages/firebase_ml_vision/lib/src/text_detector.dart @@ -5,43 +5,45 @@ part of firebase_ml_vision; class TextDetector implements FirebaseVisionDetector { + TextDetector._(); + @override Future> detectInImage(FirebaseVisionImage visionImage) async { final List reply = - await FirebaseVision._channel.invokeMethod( + await FirebaseVision.channel.invokeMethod( 'TextDetector#detectInImage', visionImage.image.path, ); - final List containers = []; + final List blocks = []; reply.forEach((dynamic data) { - containers.add(new TextBlock._(data)); + blocks.add(new TextBlock._(data)); }); - return containers; + return blocks; } } abstract class TextContainer { TextContainer._(Map data) : text = data['text'], - boundingBox = Rect.fromLTRB( + boundingBox = Rectangle( data['left'], data['top'], - data['right'], - data['bottom'], + data['width'], + data['height'], ), cornerPoints = data['points'] == null ? null : data['points'] .map>((dynamic item) => Point( - item['x'], - item['y'], + item[0], + item[1], )) .toList(); final String text; - final Rect boundingBox; + final Rectangle boundingBox; final List> cornerPoints; } diff --git a/packages/firebase_ml_vision/pubspec.yaml b/packages/firebase_ml_vision/pubspec.yaml index a92e96aa6b9e..d80fbff047cc 100644 --- a/packages/firebase_ml_vision/pubspec.yaml +++ b/packages/firebase_ml_vision/pubspec.yaml @@ -8,42 +8,11 @@ dependencies: flutter: sdk: flutter -# For information on the generic Dart part of this file, see the -# following page: https://www.dartlang.org/tools/pub/pubspec +dev_dependencies: + flutter_test: + sdk: flutter -# The following section is specific to Flutter. flutter: plugin: androidPackage: io.flutter.plugins.firebasemlvision pluginClass: FirebaseMlVisionPlugin - - # To add assets to your plugin package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.io/assets-and-images/#from-packages - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.io/assets-and-images/#resolution-aware. - - # To add custom fonts to your plugin package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.io/custom-fonts/#from-packages diff --git a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart new file mode 100644 index 000000000000..f7dd6c2fc152 --- /dev/null +++ b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart @@ -0,0 +1,121 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; +import 'dart:math'; + +import 'package:flutter/services.dart'; + +import 'package:firebase_ml_vision/firebase_ml_vision.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$FirebaseVision', () { + final List log = []; + dynamic returnValue; + + setUp(() { + FirebaseVision.channel + .setMockMethodCallHandler((MethodCall methodCall) async { + log.add(methodCall); + + switch (methodCall.method) { + case 'TextDetector#detectInImage': + return returnValue; + default: + throw new PlatformException( + code: 'Method not implemted: ${methodCall.method}'); + } + }); + log.clear(); + }); + + group('$TextDetector', () { + test('detectInImage', () async { + final Map textElement = { + 'text': 'hello', + 'left': 1, + 'top': 2, + 'width': 3, + 'height': 4, + 'points': [ + [5, 6], + [7, 8], + ], + }; + + final Map textLine = { + 'text': 'my', + 'left': 5, + 'top': 6, + 'width': 7, + 'height': 8, + 'points': [ + [9.0, 10.0], + [11.0, 12.0], + ], + 'elements': [ + textElement, + ], + }; + + final List textBlocks = [ + { + 'text': 'friend', + 'left': 13, + 'top': 14, + 'width': 15, + 'height': 16, + 'points': [ + [17, 18], + [19, 20], + ], + 'lines': [ + textLine, + ], + }, + ]; + + returnValue = textBlocks; + + final TextDetector detector = FirebaseVision.instance.getTextDetector(); + final FirebaseVisionImage image = + new FirebaseVisionImage(File('empty')); + + final List blocks = await detector.detectInImage(image); + + expect(log, [ + isMethodCall( + 'TextDetector#detectInImage', + arguments: 'empty', + ), + ]); + + final TextBlock block = blocks[0]; + expect(block.boundingBox, const Rectangle(13, 14, 15, 16)); + expect(block.text, 'friend'); + expect(block.cornerPoints, >[ + const Point(17, 18), + const Point(19, 20), + ]); + + final TextLine line = block.lines[0]; + expect(line.boundingBox, const Rectangle(5, 6, 7, 8)); + expect(line.text, 'my'); + expect(line.cornerPoints, >[ + const Point(9, 10), + const Point(11, 12), + ]); + + final TextElement element = line.elements[0]; + expect(element.boundingBox, const Rectangle(1, 2, 3, 4)); + expect(element.text, 'hello'); + expect(element.cornerPoints, >[ + const Point(5, 6), + const Point(7, 8), + ]); + }); + }); + }); +} From 1b098f7a5cb1481cba5edb2c0e7dff01130425c1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 13 Jun 2018 17:16:29 -0700 Subject: [PATCH 11/34] Added some comments --- .../lib/firebase_ml_vision.dart | 1 - .../lib/src/firebase_vision.dart | 32 +++++++++- .../lib/src/text_detector.dart | 59 ++++++++++++++----- .../test/firebase_ml_vision_test.dart | 2 +- 4 files changed, 73 insertions(+), 21 deletions(-) diff --git a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart index 0a57d5b4fa17..82c7b77605f8 100644 --- a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart +++ b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart @@ -7,7 +7,6 @@ library firebase_ml_vision; import 'dart:async'; import 'dart:io'; import 'dart:math'; -import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; diff --git a/packages/firebase_ml_vision/lib/src/firebase_vision.dart b/packages/firebase_ml_vision/lib/src/firebase_vision.dart index 4d63b316d227..a1789174945a 100644 --- a/packages/firebase_ml_vision/lib/src/firebase_vision.dart +++ b/packages/firebase_ml_vision/lib/src/firebase_vision.dart @@ -4,6 +4,14 @@ part of firebase_ml_vision; +/// The Firebase machine learning vision API. +/// +/// You can get an instance by calling [FirebaseVision.instance] and then get +/// a detector from the instance: +/// +/// ```dart +/// TextDetector textDetector = FirebaseVision.instance.getTextDetector(); +/// ``` class FirebaseVision { FirebaseVision._(); @@ -11,19 +19,37 @@ class FirebaseVision { static const MethodChannel channel = const MethodChannel('plugins.flutter.io/firebase_ml_vision'); + /// Singleton of [FirebaseVision]. + /// + /// Use this get an instance of a detector: + /// + /// ```dart + /// TextDetector textDetector = FirebaseVision.instance.getTextDetector(); + /// ``` static final FirebaseVision instance = new FirebaseVision._(); + /// Creates an instance of [TextDetector]; TextDetector getTextDetector() => new TextDetector._(); } +/// Represents an image object used for both on-device and cloud API detectors. +/// +/// Create an instance by calling one the factory constructors. class FirebaseVisionImage { - FirebaseVisionImage(this._image); + FirebaseVisionImage._(this.imageFile); - final File _image; + factory FirebaseVisionImage.fromFile(File imageFile) { + return FirebaseVisionImage._(imageFile); + } - File get image => _image; + factory FirebaseVisionImage.fromFilePath(String imagePath) { + return FirebaseVisionImage._(new File(imagePath)); + } + + final File imageFile; } +/// Abstract class for detectors in [FirebaseVision] API. abstract class FirebaseVisionDetector { Future detectInImage(FirebaseVisionImage visionImage); } diff --git a/packages/firebase_ml_vision/lib/src/text_detector.dart b/packages/firebase_ml_vision/lib/src/text_detector.dart index 217a23277762..9237c7be351b 100644 --- a/packages/firebase_ml_vision/lib/src/text_detector.dart +++ b/packages/firebase_ml_vision/lib/src/text_detector.dart @@ -4,15 +4,25 @@ part of firebase_ml_vision; +/// Detector for performing optical character recognition(OCR) on an input image. +/// +/// A text detector is created via getVisionTextDetector() in [FirebaseVision]: +/// +/// ```dart +/// TextDetector textDetector = FirebaseVision.instance.getTextDetector(); +/// ``` class TextDetector implements FirebaseVisionDetector { TextDetector._(); + /// Detects text in the input image. + /// + /// The OCR is performed asynchronously. @override Future> detectInImage(FirebaseVisionImage visionImage) async { final List reply = await FirebaseVision.channel.invokeMethod( 'TextDetector#detectInImage', - visionImage.image.path, + visionImage.imageFile.path, ); final List blocks = []; @@ -42,33 +52,50 @@ abstract class TextContainer { )) .toList(); - final String text; + /// Axis-aligned bounding rectangle of the detected text. final Rectangle boundingBox; + + /// The four corner points in clockwise direction starting with top-left. + /// + /// Due to the possible perspective distortions, this is not necessarily a + /// rectangle. Parts of the region could be outside of the image. final List> cornerPoints; + + /// The recognized text as a string. + /// + /// Returned in reading order for the language. For Latin, this is top to + /// bottom within a Block, and left-to-right within a Line. + final String text; } +/// A block of text (think of it as a paragraph) as deemed by the OCR engine. class TextBlock extends TextContainer { - final List lines; - TextBlock._(Map data) - : lines = data['lines'] == null - ? null - : data['lines'] - .map((dynamic item) => TextLine._(item)) - .toList(), + : _lines = data['lines'] == null + ? null + : data['lines'] + .map((dynamic item) => TextLine._(item)) + .toList(), super._(data); + + final List _lines; + + List get lines => List.from(_lines); } -class TextLine extends TextContainer { - final List elements; +class TextLine extends TextContainer { TextLine._(Map data) - : elements = data['elements'] == null - ? null - : data['elements'] - .map((dynamic item) => TextElement._(item)) - .toList(), + : _elements = data['elements'] == null + ? null + : data['elements'] + .map((dynamic item) => TextElement._(item)) + .toList(), super._(data); + + final List _elements; + + List get elements => List.from(_elements); } class TextElement extends TextContainer { diff --git a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart index f7dd6c2fc152..206e6e9d7275 100644 --- a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart +++ b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart @@ -81,7 +81,7 @@ void main() { final TextDetector detector = FirebaseVision.instance.getTextDetector(); final FirebaseVisionImage image = - new FirebaseVisionImage(File('empty')); + new FirebaseVisionImage.fromFilePath('empty'); final List blocks = await detector.detectInImage(image); From 3475f1769ec7444e86fcf01dd7dc5de833915d26 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 14 Jun 2018 11:08:31 -0700 Subject: [PATCH 12/34] Finished comments --- .../example/test/widget_test.dart | 25 -------- .../lib/src/firebase_vision.dart | 2 +- .../lib/src/text_detector.dart | 57 ++++++++++--------- 3 files changed, 30 insertions(+), 54 deletions(-) delete mode 100644 packages/firebase_ml_vision/example/test/widget_test.dart diff --git a/packages/firebase_ml_vision/example/test/widget_test.dart b/packages/firebase_ml_vision/example/test/widget_test.dart deleted file mode 100644 index d586708bce13..000000000000 --- a/packages/firebase_ml_vision/example/test/widget_test.dart +++ /dev/null @@ -1,25 +0,0 @@ -// This is a basic Flutter widget test. -// To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter -// provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to -// find child widgets in the widget tree, read text, and verify that the values of widget properties -// are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:firebase_ml_vision_example/main.dart'; - -void main() { - testWidgets('Verify Platform version', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(new MyApp()); - - // Verify that platform version is retrieved. - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is Text && widget.data.startsWith('Running on:'), - ), - findsOneWidget); - }); -} diff --git a/packages/firebase_ml_vision/lib/src/firebase_vision.dart b/packages/firebase_ml_vision/lib/src/firebase_vision.dart index a1789174945a..b15d9c1a04bf 100644 --- a/packages/firebase_ml_vision/lib/src/firebase_vision.dart +++ b/packages/firebase_ml_vision/lib/src/firebase_vision.dart @@ -34,7 +34,7 @@ class FirebaseVision { /// Represents an image object used for both on-device and cloud API detectors. /// -/// Create an instance by calling one the factory constructors. +/// Create an instance by calling one of the factory constructors. class FirebaseVisionImage { FirebaseVisionImage._(this.imageFile); diff --git a/packages/firebase_ml_vision/lib/src/text_detector.dart b/packages/firebase_ml_vision/lib/src/text_detector.dart index 9237c7be351b..ff5e6ca63808 100644 --- a/packages/firebase_ml_vision/lib/src/text_detector.dart +++ b/packages/firebase_ml_vision/lib/src/text_detector.dart @@ -19,8 +19,7 @@ class TextDetector implements FirebaseVisionDetector { /// The OCR is performed asynchronously. @override Future> detectInImage(FirebaseVisionImage visionImage) async { - final List reply = - await FirebaseVision.channel.invokeMethod( + final List reply = await FirebaseVision.channel.invokeMethod( 'TextDetector#detectInImage', visionImage.imageFile.path, ); @@ -34,23 +33,22 @@ class TextDetector implements FirebaseVisionDetector { } } +/// Abstract class representing dimensions of recognized text in an image. abstract class TextContainer { TextContainer._(Map data) - : text = data['text'], - boundingBox = Rectangle( + : boundingBox = Rectangle( data['left'], data['top'], data['width'], data['height'], ), - cornerPoints = data['points'] == null - ? null - : data['points'] - .map>((dynamic item) => Point( - item[0], - item[1], - )) - .toList(); + cornerPoints = data['points'] + .map>((dynamic item) => Point( + item[0], + item[1], + )) + .toList(), + text = data['text']; /// Axis-aligned bounding rectangle of the detected text. final Rectangle boundingBox; @@ -70,34 +68,37 @@ abstract class TextContainer { /// A block of text (think of it as a paragraph) as deemed by the OCR engine. class TextBlock extends TextContainer { - TextBlock._(Map data) - : _lines = data['lines'] == null - ? null - : data['lines'] - .map((dynamic item) => TextLine._(item)) - .toList(), - super._(data); + TextBlock._(Map block) + : _lines = block['lines'] + .map((dynamic line) => TextLine._(line)) + .toList(), + super._(block); final List _lines; List get lines => List.from(_lines); } - +/// Represents a line of text. class TextLine extends TextContainer { - TextLine._(Map data) - : _elements = data['elements'] == null - ? null - : data['elements'] - .map((dynamic item) => TextElement._(item)) - .toList(), - super._(data); + TextLine._(Map line) + : _elements = line['elements'] + .map((dynamic element) => TextElement._(element)) + .toList(), + super._(line); final List _elements; List get elements => List.from(_elements); } +/// Roughly equivalent to a space-separated "word." +/// +/// Separates elements into words in most Latin languages, but could separate +/// by characters in others. +/// +/// If a word is split between two lines by a hyphen, each part is encoded as a +/// separate element. class TextElement extends TextContainer { - TextElement._(Map data) : super._(data); + TextElement._(Map element) : super._(element); } From fe05e345832ee355f90be6f44f33d80885ddfcd2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 14 Jun 2018 11:11:35 -0700 Subject: [PATCH 13/34] Removed usused dependency --- packages/firebase_ml_vision/test/firebase_ml_vision_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart index 206e6e9d7275..83d2ec8d32d2 100644 --- a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart +++ b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:io'; import 'dart:math'; import 'package:flutter/services.dart'; From e8faf7996853ea15a3acbe380c0c2f14c1f37535 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 14 Jun 2018 11:29:16 -0700 Subject: [PATCH 14/34] Formatting and unused imports --- .../plugins/firebasemlvision/FirebaseMlVisionPlugin.java | 3 ++- packages/firebase_ml_vision/example/lib/main.dart | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java index 5fca13b9bfc9..7e9760b9e979 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java @@ -10,7 +10,8 @@ public class FirebaseMlVisionPlugin implements MethodCallHandler { /** Plugin registration. */ public static void registerWith(Registrar registrar) { - final MethodChannel channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_ml_vision"); + final MethodChannel channel = + new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_ml_vision"); channel.setMethodCallHandler(new FirebaseMlVisionPlugin()); } diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart index e948d1e796a7..06433baeadf6 100644 --- a/packages/firebase_ml_vision/example/lib/main.dart +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -1,8 +1,8 @@ -import 'dart:async'; +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -import 'package:firebase_ml_vision/firebase_ml_vision.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; void main() => runApp(new MyApp()); From a634645d3f0c7d9b9de17b8dacc3d76f10f1f6c0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 14 Jun 2018 15:00:01 -0700 Subject: [PATCH 15/34] Changed variable name to restart WIP test --- packages/firebase_ml_vision/lib/src/text_detector.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/firebase_ml_vision/lib/src/text_detector.dart b/packages/firebase_ml_vision/lib/src/text_detector.dart index ff5e6ca63808..4df383273e25 100644 --- a/packages/firebase_ml_vision/lib/src/text_detector.dart +++ b/packages/firebase_ml_vision/lib/src/text_detector.dart @@ -25,8 +25,8 @@ class TextDetector implements FirebaseVisionDetector { ); final List blocks = []; - reply.forEach((dynamic data) { - blocks.add(new TextBlock._(data)); + reply.forEach((dynamic block) { + blocks.add(new TextBlock._(block)); }); return blocks; From bb2c0b5e42c9fbebfbbebc47a9a41dc771716d79 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 14 Jun 2018 16:15:37 -0700 Subject: [PATCH 16/34] Start of android text detection --- .../FirebaseMlVisionPlugin.java | 81 ++++++++++++++++++- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java index 7e9760b9e979..772c0bfa05af 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java @@ -1,5 +1,25 @@ package io.flutter.plugins.firebasemlvision; +import android.graphics.Point; +import android.graphics.Rect; +import android.net.Uri; +import android.support.annotation.NonNull; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +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.FirebaseVisionTextDetector; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; @@ -8,19 +28,74 @@ /** FirebaseMlVisionPlugin */ public class FirebaseMlVisionPlugin implements MethodCallHandler { + private Registrar registrar; + + private FirebaseMlVisionPlugin(Registrar registrar) { + this.registrar = registrar; + } + /** Plugin registration. */ public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_ml_vision"); - channel.setMethodCallHandler(new FirebaseMlVisionPlugin()); + channel.setMethodCallHandler(new FirebaseMlVisionPlugin(registrar)); } @Override public void onMethodCall(MethodCall call, Result result) { - if (call.method.equals("getPlatformVersion")) { - result.success("Android " + android.os.Build.VERSION.RELEASE); + if (call.method.equals("TextDetector#detectInImage")) { + handleTextDetectionResult(call, result); } else { result.notImplemented(); } } + + private void handleTextDetectionResult(MethodCall call, final Result result) { + Uri file = Uri.parse((String) call.arguments); + + FirebaseVisionImage image; + try { + image = FirebaseVisionImage.fromFilePath(registrar.context(), file); + } catch (IOException exception) { + result.error("TextDetector#detectInImage", exception.getLocalizedMessage(), null); + return; + } + + FirebaseVisionTextDetector detector = FirebaseVision.getInstance().getVisionTextDetector(); + detector.detectInImage(image).addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(FirebaseVisionText firebaseVisionText) { + List> blocks = new ArrayList<>(); + for (FirebaseVisionText.Block block : firebaseVisionText.getBlocks()) { + Map blockData = new HashMap<>(); + + blockData.put("left", block.getBoundingBox().left); + blockData.put("top", block.getBoundingBox().top); + blockData.put("width", block.getBoundingBox().width()); + blockData.put("height", block.getBoundingBox().height()); + blockData.put("text", block.getText()); + + List blockPoints = new ArrayList<>(); + for (Point point : block.getCornerPoints()) { + blockPoints.add(new int[]{point.x, point.y}); + } + blockData.put("points", blockPoints); + + List> lines = new ArrayList<>(); + for (FirebaseVisionText.Line line : block.getLines()) { + + List> elements = new ArrayList<>(); + for (FirebaseVisionText.Element element : line.getElements()) { + + } + } + } + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + result.error("TextDetector#detectInImage", e.getLocalizedMessage(), null); + } + }); + } } From 76e7917fb913cf037293d63794a4f06041d3d6d7 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 14 Jun 2018 18:33:53 -0700 Subject: [PATCH 17/34] Added text recognition to android channel --- .../FirebaseMlVisionPlugin.java | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java index 772c0bfa05af..16c238afb49c 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java @@ -5,10 +5,8 @@ import android.net.Uri; import android.support.annotation.NonNull; -import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; -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; @@ -68,28 +66,24 @@ public void onSuccess(FirebaseVisionText firebaseVisionText) { List> blocks = new ArrayList<>(); for (FirebaseVisionText.Block block : firebaseVisionText.getBlocks()) { Map blockData = new HashMap<>(); - - blockData.put("left", block.getBoundingBox().left); - blockData.put("top", block.getBoundingBox().top); - blockData.put("width", block.getBoundingBox().width()); - blockData.put("height", block.getBoundingBox().height()); - blockData.put("text", block.getText()); - - List blockPoints = new ArrayList<>(); - for (Point point : block.getCornerPoints()) { - blockPoints.add(new int[]{point.x, point.y}); - } - blockData.put("points", blockPoints); + addTextData(blockData, block.getBoundingBox(), block.getCornerPoints(), block.getText()); List> lines = new ArrayList<>(); for (FirebaseVisionText.Line line : block.getLines()) { + Map lineData = new HashMap<>(); + addTextData(lineData, line.getBoundingBox(), line.getCornerPoints(), line.getText()); List> elements = new ArrayList<>(); for (FirebaseVisionText.Element element : line.getElements()) { - + Map elementData = new HashMap<>(); + addTextData(elementData, element.getBoundingBox(), element.getCornerPoints(), element.getText()); + elements.add(elementData); } + lines.add(lineData); } + blocks.add(blockData); } + result.success(blocks); } }).addOnFailureListener(new OnFailureListener() { @Override @@ -98,4 +92,19 @@ public void onFailure(@NonNull Exception e) { } }); } + + private void addTextData(Map addTo, Rect boundingBox, Point[] cornerPoints, String text) { + addTo.put("text", text); + + addTo.put("left", boundingBox.left); + addTo.put("top", boundingBox.top); + addTo.put("width", boundingBox.width()); + addTo.put("height", boundingBox.height()); + + List points = new ArrayList<>(); + for (Point point : cornerPoints) { + points.add(new int[]{point.x, point.y}); + } + addTo.put("points", points); + } } From 636cdc67c53787d653ff24b53c43556444660ebd Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Fri, 15 Jun 2018 10:36:05 -0700 Subject: [PATCH 18/34] Create dart test app --- .../FirebaseMlVisionPlugin.java | 6 ++- .../firebase_ml_vision/example/lib/main.dart | 53 +++++++++++++------ .../firebase_ml_vision/example/pubspec.yaml | 51 +----------------- .../lib/src/text_detector.dart | 16 +++--- 4 files changed, 53 insertions(+), 73 deletions(-) diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java index 16c238afb49c..30407d0cc6c8 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java @@ -12,6 +12,7 @@ import com.google.firebase.ml.vision.text.FirebaseVisionText; import com.google.firebase.ml.vision.text.FirebaseVisionTextDetector; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -49,12 +50,13 @@ public void onMethodCall(MethodCall call, Result result) { } private void handleTextDetectionResult(MethodCall call, final Result result) { - Uri file = Uri.parse((String) call.arguments); + File file = new File((String) call.arguments); FirebaseVisionImage image; try { - image = FirebaseVisionImage.fromFilePath(registrar.context(), file); + image = FirebaseVisionImage.fromFilePath(registrar.context(), Uri.fromFile(file)); } catch (IOException exception) { + exception.printStackTrace(); result.error("TextDetector#detectInImage", exception.getLocalizedMessage(), null); return; } diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart index 06433baeadf6..e18e980864fb 100644 --- a/packages/firebase_ml_vision/example/lib/main.dart +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -2,31 +2,54 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:firebase_ml_vision/firebase_ml_vision.dart'; -void main() => runApp(new MyApp()); +void main() => runApp(new MaterialApp(home: _MyHomePage())); -class MyApp extends StatefulWidget { +class _MyHomePage extends StatefulWidget { @override - _MyAppState createState() => new _MyAppState(); + _MyHomePageState createState() => new _MyHomePageState(); } -class _MyAppState extends State { - @override - void initState() { - super.initState(); +class _MyHomePageState extends State<_MyHomePage> { + File _image; + + Future getImage() async { + final File image = await ImagePicker.pickImage(source: ImageSource.camera); + + final FirebaseVisionImage visionImage = FirebaseVisionImage.fromFile(image); + final TextDetector detector = FirebaseVision.instance.getTextDetector(); + final List blocks = await detector.detectInImage(visionImage); + + for (TextBlock block in blocks) { + print(block.text); + } + + setState(() { + _image = image; + }); } @override Widget build(BuildContext context) { - return new MaterialApp( - home: new Scaffold( - appBar: new AppBar( - title: const Text('Plugin example app'), - ), - body: const Center( - child: const Text('Hello, World!'), - ), + return new Scaffold( + appBar: new AppBar( + title: const Text('Image Picker Example'), + ), + body: new Center( + child: _image == null + ? const Text('No image selected.') + : new Image.file(_image), + ), + floatingActionButton: new FloatingActionButton( + onPressed: getImage, + tooltip: 'Pick Image', + child: const Icon(Icons.add_a_photo), ), ); } diff --git a/packages/firebase_ml_vision/example/pubspec.yaml b/packages/firebase_ml_vision/example/pubspec.yaml index 7a34b8dff6b8..5bf287f73e79 100644 --- a/packages/firebase_ml_vision/example/pubspec.yaml +++ b/packages/firebase_ml_vision/example/pubspec.yaml @@ -1,67 +1,18 @@ name: firebase_ml_vision_example description: Demonstrates how to use the firebase_ml_vision plugin. -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# Read more about versioning at semver.org. version: 1.0.0+1 dependencies: flutter: sdk: flutter - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. + image_picker: "^0.4.5" cupertino_icons: ^0.1.2 dev_dependencies: - flutter_test: - sdk: flutter - firebase_ml_vision: path: ../ -# For information on the generic Dart part of this file, see the -# following page: https://www.dartlang.org/tools/pub/pubspec - -# The following section is specific to Flutter. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.io/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.io/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.io/custom-fonts/#from-packages diff --git a/packages/firebase_ml_vision/lib/src/text_detector.dart b/packages/firebase_ml_vision/lib/src/text_detector.dart index 4df383273e25..7a54fb417b9c 100644 --- a/packages/firebase_ml_vision/lib/src/text_detector.dart +++ b/packages/firebase_ml_vision/lib/src/text_detector.dart @@ -69,9 +69,11 @@ abstract class TextContainer { /// A block of text (think of it as a paragraph) as deemed by the OCR engine. class TextBlock extends TextContainer { TextBlock._(Map block) - : _lines = block['lines'] - .map((dynamic line) => TextLine._(line)) - .toList(), + : _lines = block['lines'] != null + ? block['lines'] + .map((dynamic line) => TextLine._(line)) + .toList() + : null, super._(block); final List _lines; @@ -82,9 +84,11 @@ class TextBlock extends TextContainer { /// Represents a line of text. class TextLine extends TextContainer { TextLine._(Map line) - : _elements = line['elements'] - .map((dynamic element) => TextElement._(element)) - .toList(), + : _elements = line['elements'] != null + ? line['elements'] + .map((dynamic element) => TextElement._(element)) + .toList() + : null, super._(line); final List _elements; From 418f646ba6ce9dce3a639dcde499d684a2a24769 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Fri, 15 Jun 2018 15:46:57 -0700 Subject: [PATCH 19/34] Added to test app --- .../android/app/src/main/AndroidManifest.xml | 3 + .../firebase_ml_vision/example/lib/main.dart | 87 ++++++++++++++++--- 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/packages/firebase_ml_vision/example/android/app/src/main/AndroidManifest.xml b/packages/firebase_ml_vision/example/android/app/src/main/AndroidManifest.xml index f1ccc8c12c80..722f90740a4c 100644 --- a/packages/firebase_ml_vision/example/android/app/src/main/AndroidManifest.xml +++ b/packages/firebase_ml_vision/example/android/app/src/main/AndroidManifest.xml @@ -35,5 +35,8 @@ + diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart index e18e980864fb..7228406983dd 100644 --- a/packages/firebase_ml_vision/example/lib/main.dart +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -17,37 +17,98 @@ class _MyHomePage extends StatefulWidget { } class _MyHomePageState extends State<_MyHomePage> { - File _image; + Image _image; + List _blocks; - Future getImage() async { + Future _getImage() async { final File image = await ImagePicker.pickImage(source: ImageSource.camera); final FirebaseVisionImage visionImage = FirebaseVisionImage.fromFile(image); final TextDetector detector = FirebaseVision.instance.getTextDetector(); final List blocks = await detector.detectInImage(visionImage); - for (TextBlock block in blocks) { - print(block.text); - } - setState(() { - _image = image; + _image = Image.file(image); + _blocks = blocks; }); } + Future _getImageSize(Image image) { + final Completer completer = new Completer(); + image.image + .resolve(const ImageConfiguration()) + .addListener((ImageInfo info, bool _) => completer.complete(Size( + info.image.width.toDouble(), + info.image.height.toDouble(), + ))); + return completer.future; + } + + List buildTextDetectionStack(Size imageSize) { + final List textDetection = []; + textDetection.add(_image); + + final Size screenSize = MediaQuery.of(context).size; + final Size scale = new Size( + screenSize.width / imageSize.width, + screenSize.height / imageSize.height, + ); + + for (TextBlock block in _blocks) { + print('Text block text: ${block.text}'); + + textDetection.add(new Positioned( + left: block.boundingBox.left * scale.width, + top: block.boundingBox.top * scale.height, + right: screenSize.width - (block.boundingBox.right * scale.width), + bottom: screenSize.height - (block.boundingBox.bottom * scale.height), + child: new Container( + decoration: new BoxDecoration( + color: Colors.transparent, + border: new Border.all( + width: 2.0, + color: Colors.red, + ), + ), + ), + )); + } + + return textDetection; + } + + Future _buildStack() async { + final Size size = await _getImageSize(_image); + + return new Stack( + children: buildTextDetectionStack(size), + ); + } + @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: const Text('Image Picker Example'), ), - body: new Center( - child: _image == null - ? const Text('No image selected.') - : new Image.file(_image), - ), + body: _image == null + ? const Center( + child: const Text("No image selected."), + ) + : new FutureBuilder( + future: _buildStack(), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + return snapshot.data; + } else { + return const Center( + child: const Text("Scanning for text..."), + ); + } + }, + ), floatingActionButton: new FloatingActionButton( - onPressed: getImage, + onPressed: _getImage, tooltip: 'Pick Image', child: const Icon(Icons.add_a_photo), ), From e3f5a02149a64adeb2356147600cdbbcbda63a94 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Jun 2018 12:46:27 -0700 Subject: [PATCH 20/34] Finished example ml vision app --- .../FirebaseMlVisionPlugin.java | 2 + .../firebase_ml_vision/example/lib/main.dart | 158 +++++++++++------- .../lib/src/text_detector.dart | 16 +- 3 files changed, 105 insertions(+), 71 deletions(-) diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java index 30407d0cc6c8..f6b4544e3a00 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java @@ -81,8 +81,10 @@ public void onSuccess(FirebaseVisionText firebaseVisionText) { addTextData(elementData, element.getBoundingBox(), element.getCornerPoints(), element.getText()); elements.add(elementData); } + lineData.put("elements", elements); lines.add(lineData); } + blockData.put("lines", lines); blocks.add(blockData); } result.success(blocks); diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart index 7228406983dd..e4e017367169 100644 --- a/packages/firebase_ml_vision/example/lib/main.dart +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -17,19 +17,37 @@ class _MyHomePage extends StatefulWidget { } class _MyHomePageState extends State<_MyHomePage> { - Image _image; - List _blocks; + File _imageFile; + Size _imageSize; + List _textLocations; Future _getImage() async { - final File image = await ImagePicker.pickImage(source: ImageSource.camera); + setState(() { + _imageFile = null; + _imageSize = null; + _textLocations = null; + }); + + final File imageFile = + await ImagePicker.pickImage(source: ImageSource.camera); + + setState(() { + _imageFile = imageFile; + }); + } - final FirebaseVisionImage visionImage = FirebaseVisionImage.fromFile(image); + Future _scanImage() async { + final FirebaseVisionImage visionImage = + FirebaseVisionImage.fromFile(_imageFile); final TextDetector detector = FirebaseVision.instance.getTextDetector(); final List blocks = await detector.detectInImage(visionImage); + final Image image = Image.file(_imageFile); + final Size imageSize = await _getImageSize(image); + setState(() { - _image = Image.file(image); - _blocks = blocks; + _textLocations = blocks; + _imageSize = imageSize; }); } @@ -44,44 +62,27 @@ class _MyHomePageState extends State<_MyHomePage> { return completer.future; } - List buildTextDetectionStack(Size imageSize) { - final List textDetection = []; - textDetection.add(_image); - - final Size screenSize = MediaQuery.of(context).size; - final Size scale = new Size( - screenSize.width / imageSize.width, - screenSize.height / imageSize.height, - ); - - for (TextBlock block in _blocks) { - print('Text block text: ${block.text}'); - - textDetection.add(new Positioned( - left: block.boundingBox.left * scale.width, - top: block.boundingBox.top * scale.height, - right: screenSize.width - (block.boundingBox.right * scale.width), - bottom: screenSize.height - (block.boundingBox.bottom * scale.height), - child: new Container( - decoration: new BoxDecoration( - color: Colors.transparent, - border: new Border.all( - width: 2.0, - color: Colors.red, - ), - ), + Widget _buildImage() { + return new Container( + constraints: const BoxConstraints.expand(), + decoration: new BoxDecoration( + image: new DecorationImage( + image: Image.file(_imageFile).image, + fit: BoxFit.fill, ), - )); - } - - return textDetection; - } - - Future _buildStack() async { - final Size size = await _getImageSize(_image); - - return new Stack( - children: buildTextDetectionStack(size), + ), + child: _imageSize == null || _textLocations == null + ? const Center( + child: const Text( + "Scanning...", + style: const TextStyle( + color: Colors.green, + fontSize: 30.0, + ), + )) + : new CustomPaint( + painter: new ScannedTextPainter(_imageSize, _textLocations), + ), ); } @@ -89,29 +90,64 @@ class _MyHomePageState extends State<_MyHomePage> { Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( - title: const Text('Image Picker Example'), + title: const Text('ML Vision Example'), ), - body: _image == null - ? const Center( - child: const Text("No image selected."), - ) - : new FutureBuilder( - future: _buildStack(), - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - return snapshot.data; - } else { - return const Center( - child: const Text("Scanning for text..."), - ); - } - }, - ), + body: _imageFile == null + ? const Center(child: const Text("No image selected.")) + : _buildImage(), floatingActionButton: new FloatingActionButton( - onPressed: _getImage, + onPressed: () async { + await _getImage(); + _scanImage(); + }, tooltip: 'Pick Image', child: const Icon(Icons.add_a_photo), ), ); } } + +class ScannedTextPainter extends CustomPainter { + ScannedTextPainter(this.absoluteImageSize, this.textLocations); + + final Size absoluteImageSize; + final List textLocations; + + @override + void paint(Canvas canvas, Size size) { + final double scaleX = size.width / absoluteImageSize.width; + final double scaleY = size.height / absoluteImageSize.height; + + Rect scaleRect(TextContainer container) { + return new Rect.fromLTRB( + container.boundingBox.left * scaleX, + container.boundingBox.top * scaleY, + container.boundingBox.right * scaleX, + container.boundingBox.bottom * scaleY, + ); + } + + final Paint paint = new Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = 2.0; + + for (TextBlock block in textLocations) { + for (TextLine line in block.lines) { + + for (TextElement element in line.elements) { + paint.color = Colors.green; + canvas.drawRect(scaleRect(element), paint); + } + + paint.color = Colors.yellow; + canvas.drawRect(scaleRect(line), paint); + } + + paint.color = Colors.red; + canvas.drawRect(scaleRect(block), paint); + } + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) => false; +} diff --git a/packages/firebase_ml_vision/lib/src/text_detector.dart b/packages/firebase_ml_vision/lib/src/text_detector.dart index 7a54fb417b9c..4df383273e25 100644 --- a/packages/firebase_ml_vision/lib/src/text_detector.dart +++ b/packages/firebase_ml_vision/lib/src/text_detector.dart @@ -69,11 +69,9 @@ abstract class TextContainer { /// A block of text (think of it as a paragraph) as deemed by the OCR engine. class TextBlock extends TextContainer { TextBlock._(Map block) - : _lines = block['lines'] != null - ? block['lines'] - .map((dynamic line) => TextLine._(line)) - .toList() - : null, + : _lines = block['lines'] + .map((dynamic line) => TextLine._(line)) + .toList(), super._(block); final List _lines; @@ -84,11 +82,9 @@ class TextBlock extends TextContainer { /// Represents a line of text. class TextLine extends TextContainer { TextLine._(Map line) - : _elements = line['elements'] != null - ? line['elements'] - .map((dynamic element) => TextElement._(element)) - .toList() - : null, + : _elements = line['elements'] + .map((dynamic element) => TextElement._(element)) + .toList(), super._(line); final List _elements; From 2a5b22381693e31a5043b95b8a2cc98839d8ef00 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Jun 2018 13:02:10 -0700 Subject: [PATCH 21/34] Formatting --- .../FirebaseMlVisionPlugin.java | 95 ++++++++++--------- .../firebase_ml_vision/example/lib/main.dart | 1 - 2 files changed, 52 insertions(+), 44 deletions(-) diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java index f6b4544e3a00..4b821e721eb8 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java @@ -4,14 +4,17 @@ import android.graphics.Rect; import android.net.Uri; import android.support.annotation.NonNull; - import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; 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.FirebaseVisionTextDetector; - +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry.Registrar; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -19,12 +22,6 @@ import java.util.List; import java.util.Map; -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; -import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugin.common.PluginRegistry.Registrar; - /** FirebaseMlVisionPlugin */ public class FirebaseMlVisionPlugin implements MethodCallHandler { private Registrar registrar; @@ -62,42 +59,54 @@ private void handleTextDetectionResult(MethodCall call, final Result result) { } FirebaseVisionTextDetector detector = FirebaseVision.getInstance().getVisionTextDetector(); - detector.detectInImage(image).addOnSuccessListener(new OnSuccessListener() { - @Override - public void onSuccess(FirebaseVisionText firebaseVisionText) { - List> blocks = new ArrayList<>(); - for (FirebaseVisionText.Block block : firebaseVisionText.getBlocks()) { - Map blockData = new HashMap<>(); - addTextData(blockData, block.getBoundingBox(), block.getCornerPoints(), block.getText()); - - List> lines = new ArrayList<>(); - for (FirebaseVisionText.Line line : block.getLines()) { - Map lineData = new HashMap<>(); - addTextData(lineData, line.getBoundingBox(), line.getCornerPoints(), line.getText()); - - List> elements = new ArrayList<>(); - for (FirebaseVisionText.Element element : line.getElements()) { - Map elementData = new HashMap<>(); - addTextData(elementData, element.getBoundingBox(), element.getCornerPoints(), element.getText()); - elements.add(elementData); - } - lineData.put("elements", elements); - lines.add(lineData); - } - blockData.put("lines", lines); - blocks.add(blockData); - } - result.success(blocks); - } - }).addOnFailureListener(new OnFailureListener() { - @Override - public void onFailure(@NonNull Exception e) { - result.error("TextDetector#detectInImage", e.getLocalizedMessage(), null); - } - }); + detector + .detectInImage(image) + .addOnSuccessListener( + new OnSuccessListener() { + @Override + public void onSuccess(FirebaseVisionText firebaseVisionText) { + List> blocks = new ArrayList<>(); + for (FirebaseVisionText.Block block : firebaseVisionText.getBlocks()) { + Map blockData = new HashMap<>(); + addTextData( + blockData, block.getBoundingBox(), block.getCornerPoints(), block.getText()); + + List> lines = new ArrayList<>(); + for (FirebaseVisionText.Line line : block.getLines()) { + Map lineData = new HashMap<>(); + addTextData( + lineData, line.getBoundingBox(), line.getCornerPoints(), line.getText()); + + List> elements = new ArrayList<>(); + for (FirebaseVisionText.Element element : line.getElements()) { + Map elementData = new HashMap<>(); + addTextData( + elementData, + element.getBoundingBox(), + element.getCornerPoints(), + element.getText()); + elements.add(elementData); + } + lineData.put("elements", elements); + lines.add(lineData); + } + blockData.put("lines", lines); + blocks.add(blockData); + } + result.success(blocks); + } + }) + .addOnFailureListener( + new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + result.error("TextDetector#detectInImage", e.getLocalizedMessage(), null); + } + }); } - private void addTextData(Map addTo, Rect boundingBox, Point[] cornerPoints, String text) { + private void addTextData( + Map addTo, Rect boundingBox, Point[] cornerPoints, String text) { addTo.put("text", text); addTo.put("left", boundingBox.left); @@ -107,7 +116,7 @@ private void addTextData(Map addTo, Rect boundingBox, Point[] co List points = new ArrayList<>(); for (Point point : cornerPoints) { - points.add(new int[]{point.x, point.y}); + points.add(new int[] {point.x, point.y}); } addTo.put("points", points); } diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart index e4e017367169..e673ec5eabaa 100644 --- a/packages/firebase_ml_vision/example/lib/main.dart +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -133,7 +133,6 @@ class ScannedTextPainter extends CustomPainter { for (TextBlock block in textLocations) { for (TextLine line in block.lines) { - for (TextElement element in line.elements) { paint.color = Colors.green; canvas.drawRect(scaleRect(element), paint); From e91584a4027b121bd8817c599c2aa8a2cbe4cbc1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Jun 2018 14:14:11 -0700 Subject: [PATCH 22/34] Fixed crash --- packages/firebase_ml_vision/example/lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart index e673ec5eabaa..0be4ceb00799 100644 --- a/packages/firebase_ml_vision/example/lib/main.dart +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -98,7 +98,7 @@ class _MyHomePageState extends State<_MyHomePage> { floatingActionButton: new FloatingActionButton( onPressed: () async { await _getImage(); - _scanImage(); + if (_imageFile != null) _scanImage(); }, tooltip: 'Pick Image', child: const Icon(Icons.add_a_photo), From 98de4cf856de891b09639e90f98be4796d2f0547 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Jun 2018 14:31:25 -0700 Subject: [PATCH 23/34] Add permssions --- packages/firebase_ml_vision/example/ios/Runner/Info.plist | 6 ++++++ .../firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/firebase_ml_vision/example/ios/Runner/Info.plist b/packages/firebase_ml_vision/example/ios/Runner/Info.plist index c1ced7a4355b..dfd64cadb213 100644 --- a/packages/firebase_ml_vision/example/ios/Runner/Info.plist +++ b/packages/firebase_ml_vision/example/ios/Runner/Info.plist @@ -2,6 +2,12 @@ + NSCameraUsageDescription + + NSPhotoLibraryUsageDescription + + LSApplicationCategoryType + CFBundleDevelopmentRegion en CFBundleExecutable diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index 2f73d7cc65d3..f6872a0d886e 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -22,8 +22,8 @@ - (instancetype)init { } - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if ([@"getPlatformVersion" isEqualToString:call.method]) { - result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); + if ([@"TextDetector#detectInImage" isEqualToString:call.method]) { + result(@[]); } else { result(FlutterMethodNotImplemented); } From c1b7114cd70bc66dbb2f8ba44e49c9fb8b376d41 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Mon, 18 Jun 2018 18:37:42 -0700 Subject: [PATCH 24/34] Setup iOS side of text detector --- .../ios/Classes/FirebaseMlVisionPlugin.h | 2 +- .../ios/Classes/FirebaseMlVisionPlugin.m | 117 +++++++++++++++++- packages/firebase_ml_vision/pubspec.yaml | 1 + 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.h b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.h index 0526078937d8..393e4ba44c54 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.h +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.h @@ -1,4 +1,4 @@ #import -@interface FirebaseMlVisionPlugin : NSObject +@interface FLTFirebaseMlVisionPlugin : NSObject @end diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index f6872a0d886e..fd7b32fa9051 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -2,12 +2,28 @@ #import "Firebase/Firebase.h" -@implementation FirebaseMlVisionPlugin +@interface NSError (FlutterError) +@property(readonly, nonatomic) FlutterError *flutterError; +@end + +@implementation NSError (FlutterError) +- (FlutterError *)flutterError { + return [FlutterError errorWithCode:[NSString stringWithFormat:@"Error %d", (int)self.code] + message:self.domain + details:self.localizedDescription]; +} +@end + +@interface FLTFirebaseMlVisionPlugin () +@property(nonatomic, retain) FIRVisionTextDetector *textDetector; +@end + +@implementation FLTFirebaseMlVisionPlugin + (void)registerWithRegistrar:(NSObject*)registrar { FlutterMethodChannel* channel = - [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_ml_vision" - binaryMessenger:[registrar messenger]]; - FirebaseMlVisionPlugin* instance = [[FirebaseMlVisionPlugin alloc] init]; + [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_ml_vision" + binaryMessenger:[registrar messenger]]; + FLTFirebaseMlVisionPlugin* instance = [[FLTFirebaseMlVisionPlugin alloc] init]; [registrar addMethodCallDelegate:instance channel:channel]; } @@ -22,11 +38,102 @@ - (instancetype)init { } - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + NSString *filePath = call.arguments; + UIImage *image = [UIImage imageWithContentsOfFile:filePath]; + FIRVisionImage *visionImage = [[FIRVisionImage alloc] initWithImage:image]; + if ([@"TextDetector#detectInImage" isEqualToString:call.method]) { - result(@[]); + [self handleTextDetectionResult:visionImage result:result]; } else { result(FlutterMethodNotImplemented); } } +- (void)handleTextDetectionResult:(FIRVisionImage*)image result:(FlutterResult)result { + FIRVision *vision = [FIRVision vision]; + if (_textDetector == nil) _textDetector = [vision textDetector]; + + [_textDetector detectInImage:image completion:^(NSArray> * _Nullable features, NSError * _Nullable error) { + if (error) { + result([error flutterError]); + return; + } else if (!features) { + result(@[]); + return; + } + + NSMutableArray *blocks = [NSMutableArray array]; + for (id feature in features) { + NSMutableDictionary *blockData = [NSMutableDictionary dictionary]; + + if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { + FIRVisionTextBlock *block = (FIRVisionTextBlock *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:block.frame cornerPoints:block.cornerPoints text:block.text]]; + blockData[@"lines"] = [self getLineData:block.lines]; + } else if ([feature isKindOfClass:[FIRVisionTextLine class]]) { + FIRVisionTextLine *line = (FIRVisionTextLine *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:line.frame cornerPoints:line.cornerPoints text:line.text]]; + NSArray *lines = @[line]; + blockData[@"lines"] = [self getLineData:lines]; + } else if ([feature isKindOfClass:[FIRVisionTextElement class]]) { + FIRVisionTextElement *element = (FIRVisionTextElement *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:element.frame cornerPoints:element.cornerPoints text:element.text]]; + + NSMutableDictionary *lineData = [NSMutableDictionary dictionary]; + [lineData addEntriesFromDictionary:[self getTextData:element.frame cornerPoints:element.cornerPoints text:element.text]]; + + NSArray *elements = @[element]; + lineData[@"elements"] = [self getElementData:elements]; + + blockData[@"lines"] = lineData; + } + + [blocks addObject:blockData]; + } + + result(blocks); + }]; +} + +- (NSDictionary*)getTextData:(CGRect)frame + cornerPoints:(NSArray*)cornerPoints + text:(NSString*)text { + __block NSMutableArray *points = [NSMutableArray array]; + [cornerPoints enumerateObjectsUsingBlock:^(NSValue * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [points addObject:@[@(((__bridge CGPoint *)obj)->x), @(((__bridge CGPoint *)obj)->y)]]; + }]; + + return @{ + @"text" : text, + @"left" : @(frame.origin.x), + @"top" : @(frame.origin.y), + @"width" : @(frame.size.width), + @"height" : @(frame.size.height), + @"points" : points, + }; +} + +- (NSMutableArray*)getLineData:(NSArray*)lines { + NSMutableArray *lineDataArray = [NSMutableArray array]; + + [lines enumerateObjectsUsingBlock:^(FIRVisionTextLine * _Nonnull line, NSUInteger idx, BOOL * _Nonnull stop) { + NSMutableDictionary *lineData = [NSMutableDictionary dictionary]; + [lineData addEntriesFromDictionary:[self getTextData:line.frame cornerPoints:line.cornerPoints text:line.text]]; + lineData[@"elements"] = [self getElementData:line.elements]; + [lineDataArray addObject:lineData]; + }]; + + return lineDataArray; +} + +- (NSMutableArray*)getElementData:(NSArray*)elements { + NSMutableArray *elementDataArray = [NSMutableArray array]; + [elements enumerateObjectsUsingBlock:^(FIRVisionTextElement * _Nonnull element, NSUInteger idx, BOOL * _Nonnull stop) { + [elementDataArray addObject:[self getTextData:element.frame cornerPoints:element.cornerPoints text:element.text]]; + }]; + return elementDataArray; +} @end diff --git a/packages/firebase_ml_vision/pubspec.yaml b/packages/firebase_ml_vision/pubspec.yaml index d80fbff047cc..d6613aaf62ce 100644 --- a/packages/firebase_ml_vision/pubspec.yaml +++ b/packages/firebase_ml_vision/pubspec.yaml @@ -15,4 +15,5 @@ dev_dependencies: flutter: plugin: androidPackage: io.flutter.plugins.firebasemlvision + iosPrefix: FLT pluginClass: FirebaseMlVisionPlugin From 0bcc44b77620d55d807a794bdb77ff336ad2c8d6 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 19 Jun 2018 10:42:45 -0700 Subject: [PATCH 25/34] Formatting and comments --- .../ios/Classes/FirebaseMlVisionPlugin.m | 155 ++++++++++-------- 1 file changed, 87 insertions(+), 68 deletions(-) diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index fd7b32fa9051..539722ed6e48 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -21,9 +21,9 @@ @interface FLTFirebaseMlVisionPlugin () @implementation FLTFirebaseMlVisionPlugin + (void)registerWithRegistrar:(NSObject*)registrar { FlutterMethodChannel* channel = - [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_ml_vision" - binaryMessenger:[registrar messenger]]; - FLTFirebaseMlVisionPlugin* instance = [[FLTFirebaseMlVisionPlugin alloc] init]; + [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_ml_vision" + binaryMessenger:[registrar messenger]]; + FLTFirebaseMlVisionPlugin *instance = [[FLTFirebaseMlVisionPlugin alloc] init]; [registrar addMethodCallDelegate:instance channel:channel]; } @@ -37,7 +37,7 @@ - (instancetype)init { return self; } -- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { NSString *filePath = call.arguments; UIImage *image = [UIImage imageWithContentsOfFile:filePath]; FIRVisionImage *visionImage = [[FIRVisionImage alloc] initWithImage:image]; @@ -49,79 +49,95 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } } -- (void)handleTextDetectionResult:(FIRVisionImage*)image result:(FlutterResult)result { +- (void)handleTextDetectionResult:(FIRVisionImage *)image result:(FlutterResult)result { FIRVision *vision = [FIRVision vision]; if (_textDetector == nil) _textDetector = [vision textDetector]; - [_textDetector detectInImage:image completion:^(NSArray> * _Nullable features, NSError * _Nullable error) { - if (error) { - result([error flutterError]); - return; - } else if (!features) { - result(@[]); - return; - } - - NSMutableArray *blocks = [NSMutableArray array]; - for (id feature in features) { - NSMutableDictionary *blockData = [NSMutableDictionary dictionary]; - - if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { - FIRVisionTextBlock *block = (FIRVisionTextBlock *)feature; - - [blockData addEntriesFromDictionary:[self getTextData:block.frame cornerPoints:block.cornerPoints text:block.text]]; - blockData[@"lines"] = [self getLineData:block.lines]; - } else if ([feature isKindOfClass:[FIRVisionTextLine class]]) { - FIRVisionTextLine *line = (FIRVisionTextLine *)feature; - - [blockData addEntriesFromDictionary:[self getTextData:line.frame cornerPoints:line.cornerPoints text:line.text]]; - NSArray *lines = @[line]; - blockData[@"lines"] = [self getLineData:lines]; - } else if ([feature isKindOfClass:[FIRVisionTextElement class]]) { - FIRVisionTextElement *element = (FIRVisionTextElement *)feature; - - [blockData addEntriesFromDictionary:[self getTextData:element.frame cornerPoints:element.cornerPoints text:element.text]]; - - NSMutableDictionary *lineData = [NSMutableDictionary dictionary]; - [lineData addEntriesFromDictionary:[self getTextData:element.frame cornerPoints:element.cornerPoints text:element.text]]; - - NSArray *elements = @[element]; - lineData[@"elements"] = [self getElementData:elements]; - - blockData[@"lines"] = lineData; - } - - [blocks addObject:blockData]; - } - - result(blocks); - }]; + [_textDetector + detectInImage:image + completion:^(NSArray> * _Nullable features, NSError * _Nullable error) { + if (error) { + result([error flutterError]); + return; + } else if (!features) { + result(@[]); + return; + } + + NSMutableArray *blocks = [NSMutableArray array]; + for (id feature in features) { + NSMutableDictionary *blockData = [NSMutableDictionary dictionary]; + if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { + FIRVisionTextBlock *block = (FIRVisionTextBlock *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:block.frame + cornerPoints:block.cornerPoints + text:block.text]]; + blockData[@"lines"] = [self getLineData:block.lines]; + } else if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { + // We structure the return data to have the line be inside a FIRVisionTextBlock. + FIRVisionTextLine *line = (FIRVisionTextLine *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:line.frame + cornerPoints:line.cornerPoints + text:line.text]]; + NSArray *lines = @[line]; + blockData[@"lines"] = [self getLineData:lines]; + } else if ([feature isKindOfClass:[FIRVisionTextElement class]]) { + // We structure the return data to have the element inside a FIRVisionTextLine + // that is inside a FIRVisionTextBlock. + FIRVisionTextElement *element = (FIRVisionTextElement *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:element.frame + cornerPoints:element.cornerPoints + text:element.text]]; + + NSMutableDictionary *lineData = [NSMutableDictionary dictionary]; + [lineData addEntriesFromDictionary:[self getTextData:element.frame + cornerPoints:element.cornerPoints + text:element.text]]; + + NSArray *elements = @[element]; + lineData[@"elements"] = [self getElementData:elements]; + + blockData[@"lines"] = lineData; + } + + [blocks addObject:blockData]; + } + + result(blocks); + }]; } -- (NSDictionary*)getTextData:(CGRect)frame - cornerPoints:(NSArray*)cornerPoints - text:(NSString*)text { - __block NSMutableArray *points = [NSMutableArray array]; - [cornerPoints enumerateObjectsUsingBlock:^(NSValue * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { - [points addObject:@[@(((__bridge CGPoint *)obj)->x), @(((__bridge CGPoint *)obj)->y)]]; - }]; +- (NSDictionary *)getTextData:(CGRect)frame + cornerPoints:(NSArray *)cornerPoints + text:(NSString *)text { + __block NSMutableArray *points = [NSMutableArray array]; + [cornerPoints + enumerateObjectsUsingBlock:^(NSValue *_Nonnull point, NSUInteger idx, BOOL *_Nonnull stop) { + [points addObject:@[@(((__bridge CGPoint *)point)->x), @(((__bridge CGPoint *)point)->y)]]; + }]; return @{ - @"text" : text, - @"left" : @(frame.origin.x), - @"top" : @(frame.origin.y), - @"width" : @(frame.size.width), - @"height" : @(frame.size.height), - @"points" : points, - }; + @"text" : text, + @"left" : @(frame.origin.x), + @"top" : @(frame.origin.y), + @"width" : @(frame.size.width), + @"height" : @(frame.size.height), + @"points" : points, + }; } -- (NSMutableArray*)getLineData:(NSArray*)lines { +- (NSMutableArray *)getLineData:(NSArray *)lines { NSMutableArray *lineDataArray = [NSMutableArray array]; - [lines enumerateObjectsUsingBlock:^(FIRVisionTextLine * _Nonnull line, NSUInteger idx, BOOL * _Nonnull stop) { + [lines enumerateObjectsUsingBlock:^(FIRVisionTextLine * _Nonnull line, NSUInteger idx, + BOOL * _Nonnull stop) { NSMutableDictionary *lineData = [NSMutableDictionary dictionary]; - [lineData addEntriesFromDictionary:[self getTextData:line.frame cornerPoints:line.cornerPoints text:line.text]]; + [lineData addEntriesFromDictionary:[self getTextData:line.frame + cornerPoints:line.cornerPoints + text:line.text]]; lineData[@"elements"] = [self getElementData:line.elements]; [lineDataArray addObject:lineData]; }]; @@ -129,10 +145,13 @@ - (NSMutableArray*)getLineData:(NSArray*)lines { return lineDataArray; } -- (NSMutableArray*)getElementData:(NSArray*)elements { +- (NSMutableArray *)getElementData:(NSArray *)elements { NSMutableArray *elementDataArray = [NSMutableArray array]; - [elements enumerateObjectsUsingBlock:^(FIRVisionTextElement * _Nonnull element, NSUInteger idx, BOOL * _Nonnull stop) { - [elementDataArray addObject:[self getTextData:element.frame cornerPoints:element.cornerPoints text:element.text]]; + [elements enumerateObjectsUsingBlock:^(FIRVisionTextElement * _Nonnull element, NSUInteger idx, + BOOL * _Nonnull stop) { + [elementDataArray addObject:[self getTextData:element.frame + cornerPoints:element.cornerPoints + text:element.text]]; }]; return elementDataArray; } From c6113043341c405f42458262636a0a777e5c7a05 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 19 Jun 2018 10:56:02 -0700 Subject: [PATCH 26/34] More formattign --- .../ios/Classes/FirebaseMlVisionPlugin.m | 101 +++++++++--------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index 539722ed6e48..23b66a2cabc4 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -20,7 +20,7 @@ @interface FLTFirebaseMlVisionPlugin () @implementation FLTFirebaseMlVisionPlugin + (void)registerWithRegistrar:(NSObject*)registrar { - FlutterMethodChannel* channel = + FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_ml_vision" binaryMessenger:[registrar messenger]]; FLTFirebaseMlVisionPlugin *instance = [[FLTFirebaseMlVisionPlugin alloc] init]; @@ -55,69 +55,69 @@ - (void)handleTextDetectionResult:(FIRVisionImage *)image result:(FlutterResult) [_textDetector detectInImage:image - completion:^(NSArray> * _Nullable features, NSError * _Nullable error) { + completion:^(NSArray> *_Nullable features, NSError *_Nullable error) { if (error) { result([error flutterError]); return; } else if (!features) { - result(@[]); - return; + result(@[]); + return; } - NSMutableArray *blocks = [NSMutableArray array]; - for (id feature in features) { - NSMutableDictionary *blockData = [NSMutableDictionary dictionary]; - if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { - FIRVisionTextBlock *block = (FIRVisionTextBlock *)feature; - - [blockData addEntriesFromDictionary:[self getTextData:block.frame - cornerPoints:block.cornerPoints - text:block.text]]; - blockData[@"lines"] = [self getLineData:block.lines]; - } else if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { - // We structure the return data to have the line be inside a FIRVisionTextBlock. - FIRVisionTextLine *line = (FIRVisionTextLine *)feature; - - [blockData addEntriesFromDictionary:[self getTextData:line.frame - cornerPoints:line.cornerPoints - text:line.text]]; - NSArray *lines = @[line]; - blockData[@"lines"] = [self getLineData:lines]; - } else if ([feature isKindOfClass:[FIRVisionTextElement class]]) { - // We structure the return data to have the element inside a FIRVisionTextLine - // that is inside a FIRVisionTextBlock. - FIRVisionTextElement *element = (FIRVisionTextElement *)feature; - - [blockData addEntriesFromDictionary:[self getTextData:element.frame + NSMutableArray *blocks = [NSMutableArray array]; + for (id feature in features) { + NSMutableDictionary *blockData = [NSMutableDictionary dictionary]; + if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { + FIRVisionTextBlock *block = (FIRVisionTextBlock *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:block.frame + cornerPoints:block.cornerPoints + text:block.text]]; + blockData[@"lines"] = [self getLineData:block.lines]; + } else if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { + // We structure the return data to have the line be inside a FIRVisionTextBlock. + FIRVisionTextLine *line = (FIRVisionTextLine *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:line.frame + cornerPoints:line.cornerPoints + text:line.text]]; + NSArray *lines = @[ line ]; + blockData[@"lines"] = [self getLineData:lines]; + } else if ([feature isKindOfClass:[FIRVisionTextElement class]]) { + // We structure the return data to have the element inside a FIRVisionTextLine + // that is inside a FIRVisionTextBlock. + FIRVisionTextElement *element = (FIRVisionTextElement *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:element.frame + cornerPoints:element.cornerPoints + text:element.text]]; + + NSMutableDictionary *lineData = [NSMutableDictionary dictionary]; + [lineData addEntriesFromDictionary:[self getTextData:element.frame cornerPoints:element.cornerPoints text:element.text]]; - NSMutableDictionary *lineData = [NSMutableDictionary dictionary]; - [lineData addEntriesFromDictionary:[self getTextData:element.frame - cornerPoints:element.cornerPoints - text:element.text]]; - - NSArray *elements = @[element]; - lineData[@"elements"] = [self getElementData:elements]; + NSArray *elements = @[ element ]; + lineData[@"elements"] = [self getElementData:elements]; - blockData[@"lines"] = lineData; - } + blockData[@"lines"] = lineData; + } - [blocks addObject:blockData]; - } + [blocks addObject:blockData]; + } - result(blocks); - }]; + result(blocks); + }]; } - (NSDictionary *)getTextData:(CGRect)frame cornerPoints:(NSArray *)cornerPoints text:(NSString *)text { __block NSMutableArray *points = [NSMutableArray array]; - [cornerPoints - enumerateObjectsUsingBlock:^(NSValue *_Nonnull point, NSUInteger idx, BOOL *_Nonnull stop) { - [points addObject:@[@(((__bridge CGPoint *)point)->x), @(((__bridge CGPoint *)point)->y)]]; - }]; + [cornerPoints enumerateObjectsUsingBlock:^(NSValue *_Nonnull point, NSUInteger idx, + BOOL *_Nonnull stop) { + [points addObject:@[@(((__bridge CGPoint *)point)->x), @(((__bridge CGPoint *)point)->y)]]; + }]; return @{ @"text" : text, @@ -132,8 +132,8 @@ - (NSDictionary *)getTextData:(CGRect)frame - (NSMutableArray *)getLineData:(NSArray *)lines { NSMutableArray *lineDataArray = [NSMutableArray array]; - [lines enumerateObjectsUsingBlock:^(FIRVisionTextLine * _Nonnull line, NSUInteger idx, - BOOL * _Nonnull stop) { + [lines enumerateObjectsUsingBlock:^(FIRVisionTextLine *_Nonnull line, NSUInteger idx, + BOOL *_Nonnull stop) { NSMutableDictionary *lineData = [NSMutableDictionary dictionary]; [lineData addEntriesFromDictionary:[self getTextData:line.frame cornerPoints:line.cornerPoints @@ -147,12 +147,13 @@ - (NSMutableArray *)getLineData:(NSArray *)lines { - (NSMutableArray *)getElementData:(NSArray *)elements { NSMutableArray *elementDataArray = [NSMutableArray array]; - [elements enumerateObjectsUsingBlock:^(FIRVisionTextElement * _Nonnull element, NSUInteger idx, - BOOL * _Nonnull stop) { + [elements enumerateObjectsUsingBlock:^(FIRVisionTextElement *_Nonnull element, NSUInteger idx, + BOOL *_Nonnull stop) { [elementDataArray addObject:[self getTextData:element.frame cornerPoints:element.cornerPoints text:element.text]]; }]; + return elementDataArray; } @end From 501b85aa9c2fc602346e2c56029cfcbf8c2b324c Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 19 Jun 2018 11:03:10 -0700 Subject: [PATCH 27/34] More More Formatting --- .../ios/Classes/FirebaseMlVisionPlugin.m | 86 +++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index 23b66a2cabc4..cef55474ed07 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -19,7 +19,7 @@ @interface FLTFirebaseMlVisionPlugin () @end @implementation FLTFirebaseMlVisionPlugin -+ (void)registerWithRegistrar:(NSObject*)registrar { ++ (void)registerWithRegistrar:(NSObject *)registrar { FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_ml_vision" binaryMessenger:[registrar messenger]]; @@ -65,58 +65,58 @@ - (void)handleTextDetectionResult:(FIRVisionImage *)image result:(FlutterResult) } NSMutableArray *blocks = [NSMutableArray array]; - for (id feature in features) { + for (id feature in features) { NSMutableDictionary *blockData = [NSMutableDictionary dictionary]; - if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { - FIRVisionTextBlock *block = (FIRVisionTextBlock *)feature; - - [blockData addEntriesFromDictionary:[self getTextData:block.frame - cornerPoints:block.cornerPoints - text:block.text]]; - blockData[@"lines"] = [self getLineData:block.lines]; - } else if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { - // We structure the return data to have the line be inside a FIRVisionTextBlock. - FIRVisionTextLine *line = (FIRVisionTextLine *)feature; - - [blockData addEntriesFromDictionary:[self getTextData:line.frame - cornerPoints:line.cornerPoints - text:line.text]]; - NSArray *lines = @[ line ]; - blockData[@"lines"] = [self getLineData:lines]; - } else if ([feature isKindOfClass:[FIRVisionTextElement class]]) { - // We structure the return data to have the element inside a FIRVisionTextLine - // that is inside a FIRVisionTextBlock. - FIRVisionTextElement *element = (FIRVisionTextElement *)feature; - - [blockData addEntriesFromDictionary:[self getTextData:element.frame - cornerPoints:element.cornerPoints - text:element.text]]; - - NSMutableDictionary *lineData = [NSMutableDictionary dictionary]; - [lineData addEntriesFromDictionary:[self getTextData:element.frame - cornerPoints:element.cornerPoints - text:element.text]]; - - NSArray *elements = @[ element ]; - lineData[@"elements"] = [self getElementData:elements]; - - blockData[@"lines"] = lineData; - } - - [blocks addObject:blockData]; + if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { + FIRVisionTextBlock *block = (FIRVisionTextBlock *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:block.frame + cornerPoints:block.cornerPoints + text:block.text]]; + blockData[@"lines"] = [self getLineData:block.lines]; + } else if ([feature isKindOfClass:[FIRVisionTextBlock class]]) { + // We structure the return data to have the line be inside a FIRVisionTextBlock. + FIRVisionTextLine *line = (FIRVisionTextLine *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:line.frame + cornerPoints:line.cornerPoints + text:line.text]]; + NSArray *lines = @[ line ]; + blockData[@"lines"] = [self getLineData:lines]; + } else if ([feature isKindOfClass:[FIRVisionTextElement class]]) { + // We structure the return data to have the element inside a FIRVisionTextLine + // that is inside a FIRVisionTextBlock. + FIRVisionTextElement *element = (FIRVisionTextElement *)feature; + + [blockData addEntriesFromDictionary:[self getTextData:element.frame + cornerPoints:element.cornerPoints + text:element.text]]; + + NSMutableDictionary *lineData = [NSMutableDictionary dictionary]; + [lineData addEntriesFromDictionary:[self getTextData:element.frame + cornerPoints:element.cornerPoints + text:element.text]]; + + NSArray *elements = @[ element ]; + lineData[@"elements"] = [self getElementData:elements]; + + blockData[@"lines"] = lineData; } - result(blocks); - }]; + [blocks addObject:blockData]; + } + + result(blocks); + }]; } - (NSDictionary *)getTextData:(CGRect)frame cornerPoints:(NSArray *)cornerPoints text:(NSString *)text { - __block NSMutableArray *points = [NSMutableArray array]; + __block NSMutableArray *points = [NSMutableArray array]; [cornerPoints enumerateObjectsUsingBlock:^(NSValue *_Nonnull point, NSUInteger idx, BOOL *_Nonnull stop) { - [points addObject:@[@(((__bridge CGPoint *)point)->x), @(((__bridge CGPoint *)point)->y)]]; + [points addObject:@[ @(((__bridge CGPoint *)point)->x), @(((__bridge CGPoint *)point)->y) ]]; }]; return @{ From 2aa05b8060b6e7ea2174124e355c377e8d2d3e62 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 21 Jun 2018 11:43:06 -0700 Subject: [PATCH 28/34] Code cleanup and added necessary metadata --- FlutterFire.md | 6 ++ README.md | 1 + packages/firebase_ml_vision/CHANGELOG.md | 2 +- packages/firebase_ml_vision/LICENSE | 28 +++++++- packages/firebase_ml_vision/README.md | 72 +++++++++++++++++-- .../FirebaseMlVisionPlugin.java | 47 ++++++++---- packages/firebase_ml_vision/example/README.md | 6 +- .../firebase_ml_vision/example/lib/main.dart | 34 +++++---- .../ios/Classes/FirebaseMlVisionPlugin.m | 16 +++-- .../lib/src/firebase_vision.dart | 7 ++ .../lib/src/text_detector.dart | 46 ++++++++---- packages/firebase_ml_vision/pubspec.yaml | 11 ++- .../test/firebase_ml_vision_test.dart | 65 +++++++++++++++++ 13 files changed, 280 insertions(+), 61 deletions(-) diff --git a/FlutterFire.md b/FlutterFire.md index 1245ae6a8736..fb5fb21b6221 100644 --- a/FlutterFire.md +++ b/FlutterFire.md @@ -25,6 +25,7 @@ The plugins are still under development, and some APIs might not be available ye | [firebase_storage][storage_pub] | ![pub package][storage_badge] | [Firebase Cloud Storage][storage_product] | [`packages/firebase_storage`][storage_code] | | [firebase_performance][performance_pub] | ![pub package][performance_badge] | [Firebase Performance Monitoring][performance_product] | [`packages/firebase_performance`][performance_code] | | [firebase_remote_config][remote_config_pub] | ![pub package][remote_config_badge] | [Firebase Remote Config][remote_config_product] | [`packages/firebase_remote_config`][remote_config_code] | +| [firebase_ml_vision][ml_vision_pub] | ![pub package][ml_vision_badge] | [Firebase ML Kit][ml_vision_product] | [`packages/firebase_ml_vision`][ml_vision_code] | [admob_pub]: https://pub.dartlang.org/packages/firebase_admob [admob_product]: https://firebase.google.com/docs/admob/ @@ -80,3 +81,8 @@ The plugins are still under development, and some APIs might not be available ye [dynamic_links_product]: https://firebase.google.com/products/dynamic-links/ [dynamic_links_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_dynamic_links [dynamic_links_badge]: https://img.shields.io/pub/v/firebase_dynamic_links.svg + +[ml_vision_pub]: https://pub.dartlang.org/packages/firebase_ml_vision +[ml_vision_product]: https://firebase.google.com/products/ml-kit/ +[ml_vision_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_ml_vision +[ml_vision_badge]: https://img.shields.io/pub/v/firebase_ml_vision.svg diff --git a/README.md b/README.md index 6db91eab4dff..e42946381003 100644 --- a/README.md +++ b/README.md @@ -69,5 +69,6 @@ These are the available plugins in this repository. | [firebase_performance](./packages/firebase_performance/) | [![pub package](https://img.shields.io/pub/v/firebase_performance.svg)](https://pub.dartlang.org/packages/firebase_performance) | | [firebase_remote_config](./packages/firebase_remote_config/) | [![pub package](https://img.shields.io/pub/v/firebase_remote_config.svg)](https://pub.dartlang.org/packages/firebase_remote_config) | | [firebase_dynamic_links](./packages/firebase_dynamic_links/) | [![pub package](https://img.shields.io/pub/v/firebase_dynamic_links.svg)](https://pub.dartlang.org/packages/firebase_dynamic_links) | +| [firebase_ml_vision](./packages/firebase_ml_vision/) | [![pub package](https://img.shields.io/pub/v/firebase_ml_vision.svg)](https://pub.dartlang.org/packages/firebase_ml_vision) | Learn more about [FlutterFire](https://github.com/flutter/plugins/blob/master/FlutterFire.md). diff --git a/packages/firebase_ml_vision/CHANGELOG.md b/packages/firebase_ml_vision/CHANGELOG.md index 41cc7d8192ec..57dbea109e21 100644 --- a/packages/firebase_ml_vision/CHANGELOG.md +++ b/packages/firebase_ml_vision/CHANGELOG.md @@ -1,3 +1,3 @@ ## 0.0.1 -* TODO: Describe initial release. +* Initial release with text detector. diff --git a/packages/firebase_ml_vision/LICENSE b/packages/firebase_ml_vision/LICENSE index ba75c69f7f21..8940a4be1b58 100644 --- a/packages/firebase_ml_vision/LICENSE +++ b/packages/firebase_ml_vision/LICENSE @@ -1 +1,27 @@ -TODO: Add your license here. +// Copyright 2018 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/firebase_ml_vision/README.md b/packages/firebase_ml_vision/README.md index 8f088e9ea1d9..6f2c7375ab1f 100644 --- a/packages/firebase_ml_vision/README.md +++ b/packages/firebase_ml_vision/README.md @@ -1,10 +1,70 @@ -# firebase_ml_vision +# Google ML Kit for Firebase -A new Flutter plugin. +[![pub package](https://img.shields.io/pub/v/firebase_ml_vision.svg)](https://pub.dartlang.org/packages/firebase_ml_vision) -## Getting Started +A Flutter plugin to use the [Google ML Kit for Firebase API](https://firebase.google.com/docs/ml-kit/). + +For Flutter plugins for other Firebase products, see [FlutterFire.md](https://github.com/flutter/plugins/blob/master/FlutterFire.md). + +*Note*: This plugin is still under development, and some APIs might not be available yet. [Feedback](https://github.com/flutter/flutter/issues) and [Pull Requests](https://github.com/flutter/plugins/pulls) are most welcome! + +## Usage + +To use this plugin, add `firebase_ml_vision` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/). You must also configure firebase for each platform project: Android and iOS (see the example folder or https://codelabs.developers.google.com/codelabs/flutter-firebase/#4 for step by step details). + +### Android +Optional but recommended: If you use the on-device API, configure your app to automatically download the ML model to the device after your app is installed from the Play Store. To do so, add the following declaration to your app's AndroidManifest.xml file: + +```manifest + + ... + + + +``` + +## On-device Text Recognition + +To use the on-device text recognition model, run the text detector as described below: + +1. Create a FirebaseVisionImage object from your image. -For help getting started with Flutter, view our online -[documentation](https://flutter.io/). +To create a `FirebaseVisionImage` from an image `File` object: + +```dart +final File imageFile = getImageFile(); +final FirebaseVisionImage visionImage = FirebaseVisionImage.fromFile(imageFile); +``` + +2. Get an instance of `TextDetector` and pass `visionImage` to `detectInImage().` + +```dart +final TextDetector detector = FirebaseVision.instance.getTextDetector(); +final List blocks = await detector.detectInImage(visionImage); + +detector.close(); +``` + +3. Extract text and text locations from blocks of recognized text. + +```dart +for (TextBlock block in textLocations) { + final Rectangle boundingBox = block.boundingBox; + final List> cornerPoints = block.cornerPoints; + final String text = block.text; + + for (TextLine line in block.lines) { + // .... + + for (TextElement element in line.elements) { + //... + } + } +} +``` + +## Getting Started -For help on editing plugin code, view the [documentation](https://flutter.io/platform-plugins/#edit-code). \ No newline at end of file +See the `example` directory for a complete sample app using Google ML Kit for Firebase. diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java index bb71e8f41f04..33358aeb0b58 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java @@ -25,6 +25,7 @@ /** FirebaseMlVisionPlugin */ public class FirebaseMlVisionPlugin implements MethodCallHandler { private Registrar registrar; + private FirebaseVisionTextDetector textDetector; private FirebaseMlVisionPlugin(Registrar registrar) { this.registrar = registrar; @@ -39,10 +40,24 @@ public static void registerWith(Registrar registrar) { @Override public void onMethodCall(MethodCall call, Result result) { - if (call.method.equals("TextDetector#detectInImage")) { - handleTextDetectionResult(call, result); - } else { - result.notImplemented(); + switch (call.method) { + case "TextDetector#detectInImage": + handleTextDetectionResult(call, result); + break; + case "TextDetector#close": + if (textDetector != null) { + try { + textDetector.close(); + } catch (IOException exception) { + result.error("textDetectorError", exception.getLocalizedMessage(), null); + } finally { + textDetector = null; + } + } + result.success(null); + break; + default: + result.notImplemented(); } } @@ -57,8 +72,8 @@ private void handleTextDetectionResult(MethodCall call, final Result result) { return; } - FirebaseVisionTextDetector detector = FirebaseVision.getInstance().getVisionTextDetector(); - detector + if (textDetector == null) textDetector = FirebaseVision.getInstance().getVisionTextDetector(); + textDetector .detectInImage(image) .addOnSuccessListener( new OnSuccessListener() { @@ -98,8 +113,8 @@ public void onSuccess(FirebaseVisionText firebaseVisionText) { .addOnFailureListener( new OnFailureListener() { @Override - public void onFailure(@NonNull Exception e) { - result.error("textDetectorError", e.getLocalizedMessage(), null); + public void onFailure(@NonNull Exception exception) { + result.error("textDetectorError", exception.getLocalizedMessage(), null); } }); } @@ -108,14 +123,18 @@ private void addTextData( Map addTo, Rect boundingBox, Point[] cornerPoints, String text) { addTo.put("text", text); - addTo.put("left", boundingBox.left); - addTo.put("top", boundingBox.top); - addTo.put("width", boundingBox.width()); - addTo.put("height", boundingBox.height()); + if (boundingBox != null) { + addTo.put("left", boundingBox.left); + addTo.put("top", boundingBox.top); + addTo.put("width", boundingBox.width()); + addTo.put("height", boundingBox.height()); + } List points = new ArrayList<>(); - for (Point point : cornerPoints) { - points.add(new int[] {point.x, point.y}); + if (cornerPoints != null) { + for (Point point : cornerPoints) { + points.add(new int[] {point.x, point.y}); + } } addTo.put("points", points); } diff --git a/packages/firebase_ml_vision/example/README.md b/packages/firebase_ml_vision/example/README.md index fcb429d16af2..13f4934d76ff 100644 --- a/packages/firebase_ml_vision/example/README.md +++ b/packages/firebase_ml_vision/example/README.md @@ -2,7 +2,11 @@ Demonstrates how to use the firebase_ml_vision plugin. +## Usage + +This example uses the *image_picker* plugin to get images from the device gallery. If using an iOS device you will have to configure you project with the correct permissions seen under iOS configuration [here.](https://pub.dartlang.org/packages/image_picker) + ## Getting Started For help getting started with Flutter, view our online -[documentation](https://flutter.io/). +[documentation.](https://flutter.io/) diff --git a/packages/firebase_ml_vision/example/lib/main.dart b/packages/firebase_ml_vision/example/lib/main.dart index f734813bc2e1..f5c002851426 100644 --- a/packages/firebase_ml_vision/example/lib/main.dart +++ b/packages/firebase_ml_vision/example/lib/main.dart @@ -42,24 +42,28 @@ class _MyHomePageState extends State<_MyHomePage> { final TextDetector detector = FirebaseVision.instance.getTextDetector(); final List blocks = await detector.detectInImage(visionImage); - final Image image = Image.file(_imageFile); - final Size imageSize = await _getImageSize(image); - setState(() { _textLocations = blocks; - _imageSize = imageSize; }); + + detector.close(); } - Future _getImageSize(Image image) { + Future _getImageSize(Image image) async { final Completer completer = new Completer(); - image.image - .resolve(const ImageConfiguration()) - .addListener((ImageInfo info, bool _) => completer.complete(Size( - info.image.width.toDouble(), - info.image.height.toDouble(), - ))); - return completer.future; + image.image.resolve(const ImageConfiguration()).addListener( + (ImageInfo info, bool _) { + completer.complete(Size( + info.image.width.toDouble(), + info.image.height.toDouble(), + )); + }, + ); + + final Size imageSize = await completer.future; + setState(() { + _imageSize = imageSize; + }); } Widget _buildImage() { @@ -98,7 +102,10 @@ class _MyHomePageState extends State<_MyHomePage> { floatingActionButton: new FloatingActionButton( onPressed: () async { await _getImage(); - if (_imageFile != null) _scanImage(); + if (_imageFile != null) { + _getImageSize(Image.file(_imageFile)); + _scanImage(); + } }, tooltip: 'Pick Image', child: const Icon(Icons.add_a_photo), @@ -107,6 +114,7 @@ class _MyHomePageState extends State<_MyHomePage> { } } +// Paints rectangles around all the text in the image. class ScannedTextPainter extends CustomPainter { ScannedTextPainter(this.absoluteImageSize, this.textLocations); diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index cef55474ed07..8df4357d4262 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -38,23 +38,25 @@ - (instancetype)init { } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - NSString *filePath = call.arguments; - UIImage *image = [UIImage imageWithContentsOfFile:filePath]; - FIRVisionImage *visionImage = [[FIRVisionImage alloc] initWithImage:image]; - if ([@"TextDetector#detectInImage" isEqualToString:call.method]) { - [self handleTextDetectionResult:visionImage result:result]; + [self handleTextDetectionResult:call result:result]; + } else if ([@"TextDetector#close" isEqualToString:call.method]) { + result(_textDetector = nil); } else { result(FlutterMethodNotImplemented); } } -- (void)handleTextDetectionResult:(FIRVisionImage *)image result:(FlutterResult)result { +- (void)handleTextDetectionResult:(FlutterMethodCall *)call result:(FlutterResult)result { + NSString *filePath = call.arguments; + UIImage *image = [UIImage imageWithContentsOfFile:filePath]; + FIRVisionImage *visionImage = [[FIRVisionImage alloc] initWithImage:image]; + FIRVision *vision = [FIRVision vision]; if (_textDetector == nil) _textDetector = [vision textDetector]; [_textDetector - detectInImage:image + detectInImage:visionImage completion:^(NSArray> *_Nullable features, NSError *_Nullable error) { if (error) { result([error flutterError]); diff --git a/packages/firebase_ml_vision/lib/src/firebase_vision.dart b/packages/firebase_ml_vision/lib/src/firebase_vision.dart index b15d9c1a04bf..1e45d4f9c0f2 100644 --- a/packages/firebase_ml_vision/lib/src/firebase_vision.dart +++ b/packages/firebase_ml_vision/lib/src/firebase_vision.dart @@ -38,18 +38,25 @@ class FirebaseVision { class FirebaseVisionImage { FirebaseVisionImage._(this.imageFile); + /// Construct a [FirebaseVisionImage] from a file. factory FirebaseVisionImage.fromFile(File imageFile) { return FirebaseVisionImage._(imageFile); } + /// Construct a [FirebaseVisionImage] from a file path. factory FirebaseVisionImage.fromFilePath(String imagePath) { return FirebaseVisionImage._(new File(imagePath)); } + /// The file location of the image. final File imageFile; } /// Abstract class for detectors in [FirebaseVision] API. abstract class FirebaseVisionDetector { + /// Uses machine learning model to detect objects of interest in an image. Future detectInImage(FirebaseVisionImage visionImage); + + /// Release model resources for the detector. + Future close(); } diff --git a/packages/firebase_ml_vision/lib/src/text_detector.dart b/packages/firebase_ml_vision/lib/src/text_detector.dart index 4df383273e25..9f3068fa66fb 100644 --- a/packages/firebase_ml_vision/lib/src/text_detector.dart +++ b/packages/firebase_ml_vision/lib/src/text_detector.dart @@ -31,18 +31,26 @@ class TextDetector implements FirebaseVisionDetector { return blocks; } + + /// Closes the text detector and release its model resources. + @override + Future close() { + return FirebaseVision.channel.invokeMethod('TextDetector#close'); + } } /// Abstract class representing dimensions of recognized text in an image. abstract class TextContainer { TextContainer._(Map data) - : boundingBox = Rectangle( - data['left'], - data['top'], - data['width'], - data['height'], - ), - cornerPoints = data['points'] + : boundingBox = data['left'] != null + ? Rectangle( + data['left'], + data['top'], + data['width'], + data['height'], + ) + : null, + _cornerPoints = data['points'] .map>((dynamic item) => Point( item[0], item[1], @@ -50,20 +58,26 @@ abstract class TextContainer { .toList(), text = data['text']; - /// Axis-aligned bounding rectangle of the detected text. - final Rectangle boundingBox; + final List> _cornerPoints; - /// The four corner points in clockwise direction starting with top-left. + /// Axis-aligned bounding rectangle of the detected text. /// - /// Due to the possible perspective distortions, this is not necessarily a - /// rectangle. Parts of the region could be outside of the image. - final List> cornerPoints; + /// Could be null even if text is found. + final Rectangle boundingBox; /// The recognized text as a string. /// /// Returned in reading order for the language. For Latin, this is top to /// bottom within a Block, and left-to-right within a Line. final String text; + + /// The four corner points in clockwise direction starting with top-left. + /// + /// Due to the possible perspective distortions, this is not necessarily a + /// rectangle. Parts of the region could be outside of the image. + /// + /// Could be empty even if text is found. + List> get cornerPoints => List>.from(_cornerPoints); } /// A block of text (think of it as a paragraph) as deemed by the OCR engine. @@ -76,6 +90,7 @@ class TextBlock extends TextContainer { final List _lines; + /// The contents of the text block, broken down into individual lines. List get lines => List.from(_lines); } @@ -89,13 +104,14 @@ class TextLine extends TextContainer { final List _elements; + /// The contents of this line, broken down into individual elements. List get elements => List.from(_elements); } /// Roughly equivalent to a space-separated "word." /// -/// Separates elements into words in most Latin languages, but could separate -/// by characters in others. +/// The API separates elements into words in most Latin languages, but could +/// separate by characters in others. /// /// If a word is split between two lines by a hyphen, each part is encoded as a /// separate element. diff --git a/packages/firebase_ml_vision/pubspec.yaml b/packages/firebase_ml_vision/pubspec.yaml index d6613aaf62ce..66cadd06c2e4 100644 --- a/packages/firebase_ml_vision/pubspec.yaml +++ b/packages/firebase_ml_vision/pubspec.yaml @@ -1,8 +1,9 @@ name: firebase_ml_vision -description: A new Flutter plugin. +description: Flutter plugin for Google ML Vision for Firebase, an SDK that brings Google's machine + learning expertise to Android and iOS apps in a powerful yet easy-to-use package. version: 0.0.1 -author: -homepage: +author: Flutter Team +homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_ml_vision dependencies: flutter: @@ -17,3 +18,7 @@ flutter: androidPackage: io.flutter.plugins.firebasemlvision iosPrefix: FLT pluginClass: FirebaseMlVisionPlugin + +environment: + sdk: ">=2.0.0-dev.28.0 <3.0.0" + flutter: ">=0.2.4 <2.0.0" diff --git a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart index 486154a622a6..9e031cd225d3 100644 --- a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart +++ b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart @@ -114,6 +114,71 @@ void main() { const Point(7, 8), ]); }); + + test('detectInImage no blocks', () async { + returnValue = []; + + final TextDetector detector = FirebaseVision.instance.getTextDetector(); + final FirebaseVisionImage image = + new FirebaseVisionImage.fromFilePath('empty'); + + final List blocks = await detector.detectInImage(image); + + expect(log, [ + isMethodCall( + 'TextDetector#detectInImage', + arguments: 'empty', + ), + ]); + + expect(blocks, []); + }); + + test('close', () async { + final TextDetector detector = FirebaseVision.instance.getTextDetector(); + await detector.close(); + + expect(log, [ + isMethodCall( + 'TextDetector#close', + arguments: null, + ), + ]); + }); + + test('detectInImage no bounding box', () async { + returnValue = [ + { + 'text': 'potato', + 'points': [ + [17, 18], + [19, 20], + ], + 'lines': [], + }, + ]; + + final TextDetector detector = FirebaseVision.instance.getTextDetector(); + final FirebaseVisionImage image = + new FirebaseVisionImage.fromFilePath('empty'); + + final List blocks = await detector.detectInImage(image); + + expect(log, [ + isMethodCall( + 'TextDetector#detectInImage', + arguments: 'empty', + ), + ]); + + final TextBlock block = blocks[0]; + expect(block.boundingBox, null); + expect(block.text, 'potato'); + expect(block.cornerPoints, >[ + const Point(17, 18), + const Point(19, 20), + ]); + }); }); }); } From df5055e21483ed34987cde352faa4386d780cc38 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 26 Jun 2018 11:27:17 -0700 Subject: [PATCH 29/34] Alphabetize --- FlutterFire.md | 53 +++++++++++++++++++++++++------------------------- README.md | 10 +++++----- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/FlutterFire.md b/FlutterFire.md index 65b96c107b03..387ad5de0e27 100644 --- a/FlutterFire.md +++ b/FlutterFire.md @@ -14,19 +14,19 @@ The plugins are still under development, and some APIs might not be available ye | Plugin | Version | Firebase feature | Source code | |---|---|---|---| +| [cloud_firestore][firestore_pub] | ![pub package][firestore_badge] | [Cloud Firestore][firestore_product] | [`packages/cloud_firestore`][firestore_code] | +| [cloud_functions][functions_pub] | ![pub package][functions_badge] | [Cloud Functions][functions_product] | [`packages/cloud_functions`][functions_code] | | [firebase_admob][admob_pub] | ![pub package][admob_badge] | [Firebase AdMob][admob_product] | [`packages/firebase_admob`][admob_code] | | [firebase_analytics][analytics_pub] | ![pub package][analytics_badge] | [Firebase Analytics][analytics_product] | [`packages/firebase_analytics`][analytics_code] | | [firebase_auth][auth_pub] | ![pub package][auth_badge] | [Firebase Authentication][auth_product] | [`packages/firebase_auth`][auth_code] | | [firebase_core][core_pub] | ![pub package][core_badge] | [Firebase Core][core_product] | [`packages/firebase_core`][core_code] | | [firebase_database][database_pub] | ![pub package][database_badge] | [Firebase Realtime Database][database_product] | [`packages/firebase_database`][database_code] | | [firebase_dynamic_links][dynamic_links_pub] | ![pub package][dynamic_links_badge] | [Firebase Dynamic Links][dynamic_links_product] | [`packages/firebase_dynamic_links`][dynamic_links_code] | -| [cloud_firestore][firestore_pub] | ![pub package][firestore_badge] | [Cloud Firestore][firestore_product] | [`packages/cloud_firestore`][firestore_code] | | [firebase_messaging][messaging_pub] | ![pub package][messaging_badge] | [Firebase Cloud Messaging][messaging_product] | [`packages/firebase_messaging`][messaging_code] | -| [firebase_storage][storage_pub] | ![pub package][storage_badge] | [Firebase Cloud Storage][storage_product] | [`packages/firebase_storage`][storage_code] | +| [firebase_ml_vision][ml_vision_pub] | ![pub package][ml_vision_badge] | [Firebase ML Kit][ml_vision_product] | [`packages/firebase_ml_vision`][ml_vision_code] | | [firebase_performance][performance_pub] | ![pub package][performance_badge] | [Firebase Performance Monitoring][performance_product] | [`packages/firebase_performance`][performance_code] | | [firebase_remote_config][remote_config_pub] | ![pub package][remote_config_badge] | [Firebase Remote Config][remote_config_product] | [`packages/firebase_remote_config`][remote_config_code] | -| [cloud_functions][functions_pub] | ![pub package][functions_badge] | [Cloud Functions][functions_product] | [`packages/cloud_functions`][functions_code] | -| [firebase_ml_vision][ml_vision_pub] | ![pub package][ml_vision_badge] | [Firebase ML Kit][ml_vision_product] | [`packages/firebase_ml_vision`][ml_vision_code] | +| [firebase_storage][storage_pub] | ![pub package][storage_badge] | [Firebase Cloud Storage][storage_product] | [`packages/firebase_storage`][storage_code] | [admob_pub]: https://pub.dartlang.org/packages/firebase_admob [admob_product]: https://firebase.google.com/docs/admob/ @@ -43,11 +43,6 @@ The plugins are still under development, and some APIs might not be available ye [auth_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_auth [auth_badge]: https://img.shields.io/pub/v/firebase_auth.svg -[firestore_pub]: https://pub.dartlang.org/packages/cloud_firestore -[firestore_product]: https://firebase.google.com/products/firestore/ -[firestore_code]: https://github.com/flutter/plugins/tree/master/packages/cloud_firestore -[firestore_badge]: https://img.shields.io/pub/v/cloud_firestore.svg - [core_pub]: https://pub.dartlang.org/packages/firebase_core [core_product]: https://firebase.google.com/ [core_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_core @@ -58,15 +53,30 @@ The plugins are still under development, and some APIs might not be available ye [database_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_database [database_badge]: https://img.shields.io/pub/v/firebase_database.svg +[dynamic_links_pub]: https://pub.dartlang.org/packages/firebase_dynamic_links +[dynamic_links_product]: https://firebase.google.com/products/dynamic-links/ +[dynamic_links_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_dynamic_links +[dynamic_links_badge]: https://img.shields.io/pub/v/firebase_dynamic_links.svg + +[firestore_pub]: https://pub.dartlang.org/packages/cloud_firestore +[firestore_product]: https://firebase.google.com/products/firestore/ +[firestore_code]: https://github.com/flutter/plugins/tree/master/packages/cloud_firestore +[firestore_badge]: https://img.shields.io/pub/v/cloud_firestore.svg + +[functions_pub]: https://pub.dartlang.org/packages/cloud_functions +[functions_product]: https://firebase.google.com/products/functions/ +[functions_code]: https://github.com/flutter/plugins/tree/master/packages/cloud_functions +[functions_badge]: https://img.shields.io/pub/v/cloud_functions.svg + [messaging_pub]: https://pub.dartlang.org/packages/firebase_messaging [messaging_product]: https://firebase.google.com/products/cloud-messaging/ [messaging_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_messaging [messaging_badge]: https://img.shields.io/pub/v/firebase_messaging.svg -[storage_pub]: https://pub.dartlang.org/packages/firebase_storage -[storage_product]: https://firebase.google.com/products/storage/ -[storage_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_storage -[storage_badge]: https://img.shields.io/pub/v/firebase_storage.svg +[ml_vision_pub]: https://pub.dartlang.org/packages/firebase_ml_vision +[ml_vision_product]: https://firebase.google.com/products/ml-kit/ +[ml_vision_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_ml_vision +[ml_vision_badge]: https://img.shields.io/pub/v/firebase_ml_vision.svg [performance_pub]: https://pub.dartlang.org/packages/firebase_performance [performance_product]: https://firebase.google.com/products/performance/ @@ -78,17 +88,8 @@ The plugins are still under development, and some APIs might not be available ye [remote_config_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_remote_config [remote_config_badge]: https://img.shields.io/pub/v/firebase_remote_config.svg -[dynamic_links_pub]: https://pub.dartlang.org/packages/firebase_dynamic_links -[dynamic_links_product]: https://firebase.google.com/products/dynamic-links/ -[dynamic_links_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_dynamic_links -[dynamic_links_badge]: https://img.shields.io/pub/v/firebase_dynamic_links.svg - -[functions_pub]: https://pub.dartlang.org/packages/cloud_functions -[functions_product]: https://firebase.google.com/products/functions/ -[functions_code]: https://github.com/flutter/plugins/tree/master/packages/cloud_functions -[functions_badge]: https://img.shields.io/pub/v/cloud_functions.svg +[storage_pub]: https://pub.dartlang.org/packages/firebase_storage +[storage_product]: https://firebase.google.com/products/storage/ +[storage_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_storage +[storage_badge]: https://img.shields.io/pub/v/firebase_storage.svg -[ml_vision_pub]: https://pub.dartlang.org/packages/firebase_ml_vision -[ml_vision_product]: https://firebase.google.com/products/ml-kit/ -[ml_vision_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_ml_vision -[ml_vision_badge]: https://img.shields.io/pub/v/firebase_ml_vision.svg diff --git a/README.md b/README.md index 9ff6b9f1a97a..92d79c959759 100644 --- a/README.md +++ b/README.md @@ -58,18 +58,18 @@ These are the available plugins in this repository. | [video_player](./packages/video_player/) | [![pub package](https://img.shields.io/pub/v/video_player.svg)](https://pub.dartlang.org/packages/video_player) | | | | | **FlutterFire Plugins** | | +| [cloud_firestore](./packages/cloud_firestore/) | [![pub package](https://img.shields.io/pub/v/cloud_firestore.svg)](https://pub.dartlang.org/packages/cloud_firestore) +| [cloud_functions](./packages/cloud_functions/) | [![pub package](https://img.shields.io/pub/v/cloud_functions.svg)](https://pub.dartlang.org/packages/cloud_functions) | | [firebase_admob](./packages/firebase_admob/) | [![pub package](https://img.shields.io/pub/v/firebase_admob.svg)](https://pub.dartlang.org/packages/firebase_admob) | | [firebase_analytics](./packages/firebase_analytics/) | [![pub package](https://img.shields.io/pub/v/firebase_analytics.svg)](https://pub.dartlang.org/packages/firebase_analytics) | | [firebase_auth](./packages/firebase_auth/) | [![pub package](https://img.shields.io/pub/v/firebase_auth.svg)](https://pub.dartlang.org/packages/firebase_auth) | -| [cloud_firestore](./packages/cloud_firestore/) | [![pub package](https://img.shields.io/pub/v/cloud_firestore.svg)](https://pub.dartlang.org/packages/cloud_firestore) | [firebase_core](./packages/firebase_core/) | [![pub package](https://img.shields.io/pub/v/firebase_core.svg)](https://pub.dartlang.org/packages/firebase_core) | | [firebase_database](./packages/firebase_database/) | [![pub package](https://img.shields.io/pub/v/firebase_database.svg)](https://pub.dartlang.org/packages/firebase_database) | +| [firebase_dynamic_links](./packages/firebase_dynamic_links/) | [![pub package](https://img.shields.io/pub/v/firebase_dynamic_links.svg)](https://pub.dartlang.org/packages/firebase_dynamic_links) | | [firebase_messaging](./packages/firebase_messaging/) | [![pub package](https://img.shields.io/pub/v/firebase_messaging.svg)](https://pub.dartlang.org/packages/firebase_messaging) | -| [firebase_storage](./packages/firebase_storage/) | [![pub package](https://img.shields.io/pub/v/firebase_storage.svg)](https://pub.dartlang.org/packages/firebase_storage) | +| [firebase_ml_vision](./packages/firebase_ml_vision/) | [![pub package](https://img.shields.io/pub/v/firebase_ml_vision.svg)](https://pub.dartlang.org/packages/firebase_ml_vision) | | [firebase_performance](./packages/firebase_performance/) | [![pub package](https://img.shields.io/pub/v/firebase_performance.svg)](https://pub.dartlang.org/packages/firebase_performance) | | [firebase_remote_config](./packages/firebase_remote_config/) | [![pub package](https://img.shields.io/pub/v/firebase_remote_config.svg)](https://pub.dartlang.org/packages/firebase_remote_config) | -| [firebase_dynamic_links](./packages/firebase_dynamic_links/) | [![pub package](https://img.shields.io/pub/v/firebase_dynamic_links.svg)](https://pub.dartlang.org/packages/firebase_dynamic_links) | -| [cloud_functions](./packages/cloud_functions/) | [![pub package](https://img.shields.io/pub/v/cloud_functions.svg)](https://pub.dartlang.org/packages/cloud_functions) | -| [firebase_ml_vision](./packages/firebase_ml_vision/) | [![pub package](https://img.shields.io/pub/v/firebase_ml_vision.svg)](https://pub.dartlang.org/packages/firebase_ml_vision) | +| [firebase_storage](./packages/firebase_storage/) | [![pub package](https://img.shields.io/pub/v/firebase_storage.svg)](https://pub.dartlang.org/packages/firebase_storage) | Learn more about [FlutterFire](https://github.com/flutter/plugins/blob/master/FlutterFire.md). From 6427a5b2478594e2daac4eaaf5338c39065bc343 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 26 Jun 2018 12:36:34 -0700 Subject: [PATCH 30/34] Small code fixes and updated README --- packages/firebase_ml_vision/README.md | 8 ++++---- .../plugins/firebasemlvision/FirebaseMlVisionPlugin.java | 6 +++--- .../firebase_ml_vision/test/firebase_ml_vision_test.dart | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/firebase_ml_vision/README.md b/packages/firebase_ml_vision/README.md index 6f2c7375ab1f..be6b6f08c737 100644 --- a/packages/firebase_ml_vision/README.md +++ b/packages/firebase_ml_vision/README.md @@ -10,7 +10,7 @@ For Flutter plugins for other Firebase products, see [FlutterFire.md](https://gi ## Usage -To use this plugin, add `firebase_ml_vision` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/). You must also configure firebase for each platform project: Android and iOS (see the example folder or https://codelabs.developers.google.com/codelabs/flutter-firebase/#4 for step by step details). +To use this plugin, add `firebase_ml_vision` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/). You must also configure Firebase for each platform project: Android and iOS (see the example folder or https://codelabs.developers.google.com/codelabs/flutter-firebase/#4 for step by step details). ### Android Optional but recommended: If you use the on-device API, configure your app to automatically download the ML model to the device after your app is installed from the Play Store. To do so, add the following declaration to your app's AndroidManifest.xml file: @@ -29,7 +29,7 @@ Optional but recommended: If you use the on-device API, configure your app to au To use the on-device text recognition model, run the text detector as described below: -1. Create a FirebaseVisionImage object from your image. +1. Create a `FirebaseVisionImage` object from your image. To create a `FirebaseVisionImage` from an image `File` object: @@ -56,10 +56,10 @@ for (TextBlock block in textLocations) { final String text = block.text; for (TextLine line in block.lines) { - // .... + // ... for (TextElement element in line.elements) { - //... + // ... } } } diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java index 33358aeb0b58..5a58c7ba5a6c 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java @@ -48,13 +48,13 @@ public void onMethodCall(MethodCall call, Result result) { if (textDetector != null) { try { textDetector.close(); + result.success(null); } catch (IOException exception) { result.error("textDetectorError", exception.getLocalizedMessage(), null); - } finally { - textDetector = null; } + + textDetector = null; } - result.success(null); break; default: result.notImplemented(); diff --git a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart index 9e031cd225d3..bd26cb352829 100644 --- a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart +++ b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart @@ -131,7 +131,7 @@ void main() { ), ]); - expect(blocks, []); + expect(blocks, isEmpty); }); test('close', () async { From 822bc381af00aa986f16ae8a1c51ee17caa1b371 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 26 Jun 2018 13:33:51 -0700 Subject: [PATCH 31/34] Return only ints --- .../ios/Classes/FirebaseMlVisionPlugin.m | 8 ++++---- packages/firebase_ml_vision/lib/src/text_detector.dart | 10 +++++----- .../test/firebase_ml_vision_test.dart | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index d7a25be0efa3..4e4ee03a4998 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -123,10 +123,10 @@ - (NSDictionary *)getTextData:(CGRect)frame return @{ @"text" : text, - @"left" : @(frame.origin.x), - @"top" : @(frame.origin.y), - @"width" : @(frame.size.width), - @"height" : @(frame.size.height), + @"left" : [NSNumber numberWithInt:[@(frame.origin.x) intValue]], + @"top" : [NSNumber numberWithInt:[@(frame.origin.y) intValue]], + @"width" : [NSNumber numberWithInt:[@(frame.size.width) intValue]], + @"height" : [NSNumber numberWithInt:[@(frame.size.height) intValue]], @"points" : points, }; } diff --git a/packages/firebase_ml_vision/lib/src/text_detector.dart b/packages/firebase_ml_vision/lib/src/text_detector.dart index 9f3068fa66fb..c6b37d53dc23 100644 --- a/packages/firebase_ml_vision/lib/src/text_detector.dart +++ b/packages/firebase_ml_vision/lib/src/text_detector.dart @@ -43,7 +43,7 @@ class TextDetector implements FirebaseVisionDetector { abstract class TextContainer { TextContainer._(Map data) : boundingBox = data['left'] != null - ? Rectangle( + ? Rectangle( data['left'], data['top'], data['width'], @@ -51,19 +51,19 @@ abstract class TextContainer { ) : null, _cornerPoints = data['points'] - .map>((dynamic item) => Point( + .map>((dynamic item) => Point( item[0], item[1], )) .toList(), text = data['text']; - final List> _cornerPoints; + final List> _cornerPoints; /// Axis-aligned bounding rectangle of the detected text. /// /// Could be null even if text is found. - final Rectangle boundingBox; + final Rectangle boundingBox; /// The recognized text as a string. /// @@ -77,7 +77,7 @@ abstract class TextContainer { /// rectangle. Parts of the region could be outside of the image. /// /// Could be empty even if text is found. - List> get cornerPoints => List>.from(_cornerPoints); + List> get cornerPoints => List>.from(_cornerPoints); } /// A block of text (think of it as a paragraph) as deemed by the OCR engine. diff --git a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart index bd26cb352829..8a2acb12c643 100644 --- a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart +++ b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart @@ -50,8 +50,8 @@ void main() { 'width': 7, 'height': 8, 'points': [ - [9.0, 10.0], - [11.0, 12.0], + [9, 10], + [11, 12], ], 'elements': [ textElement, From ae3d8875d065770851f6314711ecdf9cdd25243e Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 26 Jun 2018 14:09:00 -0700 Subject: [PATCH 32/34] Formatting --- .../ios/Classes/FirebaseMlVisionPlugin.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index 4e4ee03a4998..81ae07334568 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -123,10 +123,10 @@ - (NSDictionary *)getTextData:(CGRect)frame return @{ @"text" : text, - @"left" : [NSNumber numberWithInt:[@(frame.origin.x) intValue]], - @"top" : [NSNumber numberWithInt:[@(frame.origin.y) intValue]], - @"width" : [NSNumber numberWithInt:[@(frame.size.width) intValue]], - @"height" : [NSNumber numberWithInt:[@(frame.size.height) intValue]], + @"left" : [NSNumber numberWithInt:[@(frame.origin.x) intValue]], + @"top" : [NSNumber numberWithInt:[@(frame.origin.y) intValue]], + @"width" : [NSNumber numberWithInt:[@(frame.size.width) intValue]], + @"height" : [NSNumber numberWithInt:[@(frame.size.height) intValue]], @"points" : points, }; } From c411458d279e2ae8627b36a4c68a386235b0cec8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 26 Jun 2018 14:18:40 -0700 Subject: [PATCH 33/34] Simplified conversion --- .../ios/Classes/FirebaseMlVisionPlugin.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index 81ae07334568..1037806ab178 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -123,10 +123,10 @@ - (NSDictionary *)getTextData:(CGRect)frame return @{ @"text" : text, - @"left" : [NSNumber numberWithInt:[@(frame.origin.x) intValue]], - @"top" : [NSNumber numberWithInt:[@(frame.origin.y) intValue]], - @"width" : [NSNumber numberWithInt:[@(frame.size.width) intValue]], - @"height" : [NSNumber numberWithInt:[@(frame.size.height) intValue]], + @"left" : @((int) frame.origin.x), + @"top" : @((int) frame.origin.y), + @"width" : @((int) frame.size.width), + @"height" : @((int) frame.size.height), @"points" : points, }; } From 00cf836a8d407e643f802a8b93b66856349554ba Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 27 Jun 2018 21:07:21 -0700 Subject: [PATCH 34/34] Formatting --- .../ios/Classes/FirebaseMlVisionPlugin.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m index 1037806ab178..e227aab5fd79 100644 --- a/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m +++ b/packages/firebase_ml_vision/ios/Classes/FirebaseMlVisionPlugin.m @@ -123,10 +123,10 @@ - (NSDictionary *)getTextData:(CGRect)frame return @{ @"text" : text, - @"left" : @((int) frame.origin.x), - @"top" : @((int) frame.origin.y), - @"width" : @((int) frame.size.width), - @"height" : @((int) frame.size.height), + @"left" : @((int)frame.origin.x), + @"top" : @((int)frame.origin.y), + @"width" : @((int)frame.size.width), + @"height" : @((int)frame.size.height), @"points" : points, }; }