Skip to content

Commit 974d634

Browse files
authored
[firebase_ml_custom] New firebase_ml_custom plugin to download custom models from Firebase (#3122)
* [firebase_ml_custom] Add support for using custom ML models.
1 parent eae1373 commit 974d634

File tree

98 files changed

+4294
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+4294
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.DS_Store
2+
.dart_tool/
3+
4+
.packages
5+
.pub/
6+
7+
build/

packages/firebase_ml_custom/.metadata

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: b041144f833e05cf463b8887fa12efdec9493488
8+
channel: stable
9+
10+
project_type: plugin
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 0.0.1
2+
3+
* TODO: Describe initial release.

packages/firebase_ml_custom/LICENSE

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2020 The Chromium Authors. All rights reserved.
2+
//
3+
// Redistribution and use in source and binary forms, with or without
4+
// modification, are permitted provided that the following conditions are
5+
// met:
6+
//
7+
// * Redistributions of source code must retain the above copyright
8+
// notice, this list of conditions and the following disclaimer.
9+
// * Redistributions in binary form must reproduce the above
10+
// copyright notice, this list of conditions and the following disclaimer
11+
// in the documentation and/or other materials provided with the
12+
// distribution.
13+
// * Neither the name of Google Inc. nor the names of its
14+
// contributors may be used to endorse or promote products derived from
15+
// this software without specific prior written permission.
16+
//
17+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

packages/firebase_ml_custom/README.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Firebase Machine Learning Custom
2+
3+
[![pub package](https://img.shields.io/pub/v/firebase_ml_custom.svg)](https://pub.dartlang.org/packages/firebase_ml_custom)
4+
5+
A Flutter plugin to use the [Firebase ML Custom Models API](https://firebase.google.com/docs/ml/use-custom-models).
6+
7+
For Flutter plugins for other Firebase products, see [README.md](https://github.com/FirebaseExtended/flutterfire/blob/master/README.md).
8+
9+
## Usage
10+
11+
To use this plugin, add `firebase_ml_custom` 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).
12+
13+
### Android
14+
15+
In order to use methods referencing those of [Firebase Model Manager](https://firebase.google.com/docs/reference/android/com/google/firebase/ml/common/modeldownload/FirebaseModelManager) minimum SDK version required is 24.
16+
Otherwise minimum SDK version is 21.
17+
This can be specified in your app-level `build.gradle` file.
18+
19+
### iOS
20+
21+
A minimum deployment target of 9.0 is required. You can add the line `platform :ios, '9.0'` in your iOS project `Podfile`.
22+
23+
You may also need to update your app's deployment target to 9.0 using Xcode. Otherwise, you may see
24+
compilation errors.
25+
26+
## Using Firebase Model Manager
27+
28+
### 1. Create a `FirebaseCustomRemoteModel`.
29+
30+
Create a `FirebaseCustomRemoteModel` object.
31+
You should already have a model in your Firebase console available for download. Use the name that you gave your model in the Firebase console.
32+
33+
```dart
34+
FirebaseCustomRemoteModel remoteModel = FirebaseCustomRemoteModel('myModelName');
35+
```
36+
37+
### 2. Create a `FirebaseModelDownloadConditions`.
38+
39+
Create a `FirebaseModelDownloadConditions` object.
40+
Specify optional platform-specific conditions for the model download.
41+
42+
```dart
43+
FirebaseModelDownloadConditions conditions =
44+
FirebaseModelDownloadConditions(
45+
androidRequireWifi: true,
46+
androidRequireDeviceIdle: true,
47+
androidRequiredCharging: true,
48+
iosAllowCellularAccess: false,
49+
iosAllowBackgroundDownloading: true);
50+
```
51+
All of these parameters except `iosAllowCellularAccess` default to `false` if not specified. `iosAllowCellularAccess` defaults to `true`.
52+
Each platform looks only at its platform-specific parameters and ignores the rest.
53+
54+
### 3. Create an instance of `FirebaseModelManager`.
55+
56+
Create a `FirebaseModelManager` object corresponding to the default `FirebaseApp` instance.
57+
```dart
58+
FirebaseModelManager modelManager = FirebaseModelManager.instance;
59+
```
60+
61+
### 4. Call `download()` with `FirebaseCustomRemoteModel` and `FirebaseModelDownloadConditions`.
62+
63+
Initiate the download of a remote model if the download hasn't begun.
64+
If the model's download is already in progress, the current download task will continue executing.
65+
If the model is already downloaded to the device, and there is no update, the call will immediately succeed.
66+
If the model is already downloaded to the device, and there is update, a download for the updated version will be attempted.
67+
```dart
68+
await modelManager.download(remoteModel, conditions);
69+
```
70+
71+
### 5. Call `isModelDownloaded()` with `FirebaseCustomRemoteModel`.
72+
73+
Return whether the given remote model is currently downloaded.
74+
```dart
75+
if (await modelManager.isModelDownloaded(model) == true) ) {
76+
// do something with this model
77+
} else {
78+
// fall back on a locally-bundled model or do something else
79+
}
80+
```
81+
82+
You can also check if download was successfully completed by surrounding download method with `try` and `catch`.
83+
84+
### 5. Call `getLatestModelFile()` with `FirebaseCustomRemoteModel`.
85+
86+
Return the `File` containing the latest model for the remote model name. This will fail if the model is not yet downloaded on the device or valid custom remote model is not provided.
87+
88+
```dart
89+
File modelFile = await modelManager.getLatestModelFile(model);
90+
```
91+
92+
You can feed this file directly into an interpreter or preprocess it, depending on the interpreter of your choice.
93+
94+
Possible Flutter TF Lite interpreters:
95+
- [tflite](https://pub.dev/packages/tflite)
96+
- [tflite_flutter](https://pub.dev/packages/tflite_flutter)
97+
98+
Google does not recommend usage of any specific interpreter and leaves it up to the user to decide.
99+
100+
## Getting Started
101+
102+
See the `example` directory for a complete sample app using Firebase Machine Learning Custom.
103+
104+
## Issues and feedback
105+
106+
Please file Flutterfire specific issues, bugs, or feature requests in our [issue tracker](https://github.com/FirebaseExtended/flutterfire/issues/new).
107+
108+
Plugin issues that are not specific to Flutterfire can be filed in the [Flutter issue tracker](https://github.com/flutter/flutter/issues/new).
109+
110+
To contribute a change to this plugin,
111+
please review our [contribution guide](https://github.com/FirebaseExtended/flutterfire/blob/master/CONTRIBUTING.md),
112+
and send a [pull request](https://github.com/FirebaseExtended/flutterfire/pulls).
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
*.iml
2+
.gradle
3+
/local.properties
4+
/.idea/workspace.xml
5+
/.idea/libraries
6+
.DS_Store
7+
/build
8+
/captures
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
group 'io.flutter.plugins.firebasemlcustom'
2+
version '1.0'
3+
4+
buildscript {
5+
repositories {
6+
google()
7+
jcenter()
8+
}
9+
10+
dependencies {
11+
classpath 'com.android.tools.build:gradle:3.5.0'
12+
}
13+
}
14+
15+
rootProject.allprojects {
16+
repositories {
17+
google()
18+
jcenter()
19+
}
20+
}
21+
22+
apply plugin: 'com.android.library'
23+
24+
android {
25+
compileSdkVersion 28
26+
27+
defaultConfig {
28+
minSdkVersion 16
29+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
30+
}
31+
lintOptions {
32+
disable 'InvalidPackage'
33+
}
34+
dependencies {
35+
api 'com.google.firebase:firebase-ml-model-interpreter:22.0.3'
36+
implementation 'androidx.annotation:annotation:1.0.0'
37+
implementation 'androidx.exifinterface:exifinterface:1.0.0'
38+
}
39+
}
40+
41+
// TODO: Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348
42+
afterEvaluate {
43+
def containsEmbeddingDependencies = false
44+
for (def configuration : configurations.all) {
45+
for (def dependency : configuration.dependencies) {
46+
if (dependency.group == 'io.flutter' &&
47+
dependency.name.startsWith('flutter_embedding') &&
48+
dependency.isTransitive())
49+
{
50+
containsEmbeddingDependencies = true
51+
break
52+
}
53+
}
54+
}
55+
if (!containsEmbeddingDependencies) {
56+
android {
57+
dependencies {
58+
def lifecycle_version = "1.1.1"
59+
implementation "android.arch.lifecycle:runtime:$lifecycle_version"
60+
implementation "android.arch.lifecycle:common:$lifecycle_version"
61+
implementation "android.arch.lifecycle:common-java8:$lifecycle_version"
62+
}
63+
}
64+
}
65+
}
66+
67+
apply from: file("./user-agent.gradle")
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
org.gradle.jvmargs=-Xmx1536M
2+
android.enableR8=true
3+
android.useAndroidX=true
4+
android.enableJetifier=true
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
zipStoreBase=GRADLE_USER_HOME
4+
zipStorePath=wrapper/dists
5+
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rootProject.name = 'firebase_ml_custom'
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
package="io.flutter.plugins.firebasemlcustom">
3+
<application>
4+
<service android:name="com.google.firebase.components.ComponentDiscoveryService">
5+
<meta-data android:name="com.google.firebase.components:io.flutter.plugins.firebasemlcustom.FlutterFirebaseAppRegistrar"
6+
android:value="com.google.firebase.components.ComponentRegistrar" />
7+
</service>
8+
</application>
9+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2020 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.package io.flutter.plugins.firebaseml;
4+
5+
package io.flutter.plugins.firebasemlcustom;
6+
7+
import android.os.Build;
8+
import androidx.annotation.NonNull;
9+
import androidx.annotation.RequiresApi;
10+
import io.flutter.embedding.engine.plugins.FlutterPlugin;
11+
import io.flutter.plugin.common.MethodCall;
12+
import io.flutter.plugin.common.MethodChannel;
13+
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
14+
import io.flutter.plugin.common.MethodChannel.Result;
15+
import io.flutter.plugin.common.PluginRegistry.Registrar;
16+
17+
/** A flutter plugin for accessing the FirebaseML API for custom models. */
18+
public class FirebaseMLCustomPlugin implements FlutterPlugin, MethodCallHandler {
19+
20+
private static final String CHANNEL_NAME = "plugins.flutter.io/firebase_ml_custom";
21+
22+
private MethodChannel channel;
23+
24+
/**
25+
* Registers a plugin with the v1 embedding api {@code io.flutter.plugin.common}.
26+
*
27+
* <p>Calling this will register the plugin with the passed registrar. However, plugins
28+
* initialized this way won't react to changes in activity or context.
29+
*
30+
* @param registrar connects this plugin's {@link
31+
* io.flutter.plugin.common.MethodChannel.MethodCallHandler} to its {@link
32+
* io.flutter.plugin.common.BinaryMessenger}.
33+
*/
34+
public static void registerWith(Registrar registrar) {
35+
final MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL_NAME);
36+
channel.setMethodCallHandler(new FirebaseMLCustomPlugin());
37+
}
38+
39+
@Override
40+
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
41+
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), CHANNEL_NAME);
42+
channel.setMethodCallHandler(this);
43+
}
44+
45+
@RequiresApi(api = Build.VERSION_CODES.N)
46+
@Override
47+
public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) {
48+
if (call.method.split("#")[0].equals("FirebaseModelManager")) {
49+
ModelManager.handleModelManager(call, result);
50+
} else {
51+
result.notImplemented();
52+
}
53+
}
54+
55+
@Override
56+
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
57+
channel.setMethodCallHandler(null);
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2020 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.firebasemlcustom;
6+
7+
import androidx.annotation.Keep;
8+
import com.google.firebase.components.Component;
9+
import com.google.firebase.components.ComponentRegistrar;
10+
import com.google.firebase.platforminfo.LibraryVersionComponent;
11+
import java.util.Collections;
12+
import java.util.List;
13+
14+
@Keep
15+
public class FlutterFirebaseAppRegistrar implements ComponentRegistrar {
16+
@Override
17+
public List<Component<?>> getComponents() {
18+
return Collections.<Component<?>>singletonList(
19+
LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION));
20+
}
21+
}

0 commit comments

Comments
 (0)