Skip to content

Commit

Permalink
feat(firebase_ml_model_downloader): initial release of ML Downloader …
Browse files Browse the repository at this point in the history
…plugin for Firebase (#7432)

Co-authored-by: russellwheatley <russellwheatley85@gmail.com>
Co-authored-by: pr_Mais <hiimechi@gmail.com>
  • Loading branch information
3 people authored and Salakar committed Dec 7, 2021
1 parent 1afba21 commit a788f89
Show file tree
Hide file tree
Showing 117 changed files with 4,014 additions and 0 deletions.
66 changes: 66 additions & 0 deletions .github/workflows/firebase_ml_model_downloader.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: firebase_ml_model_downloader

on:
pull_request:
paths:
- 'packages/firebase_ml_model_downloader/**'
- '.github/workflows/firebase_ml_model_downloader.yaml'
# Ensure this workflow runs if the Firebase Android SDK version gets bumped.
- 'packages/firebase_core/firebase_core/android/gradle.properties'
# Ensure this workflow runs if the Firebase iOS SDK version gets bumped.
- 'packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb'
push:
branches:
- master
paths-ignore:
- 'docs/**'
- '**.md'

env:
FLUTTERFIRE_PLUGIN_SCOPE: '*firebase_ml_model_downloader*'
FLUTTERFIRE_PLUGIN_SCOPE_EXAMPLE: '*firebase_ml_model_downloader_example*'

jobs:
android:
runs-on: macos-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v2.3.4
with:
fetch-depth: 0
- name: 'Install Flutter'
run: ./.github/workflows/scripts/install-flutter.sh stable
- name: 'Install Tools'
run: |
./.github/workflows/scripts/install-tools.sh
sudo npm i -g firebase-tools
- name: 'Build Example'
run: ./.github/workflows/scripts/build-example.sh android
- name: Start Firebase Emulator
run: cd ./.github/workflows/scripts && ./start-firebase-emulator.sh
- name: 'Drive Example'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 28
arch: x86_64
# Firebase ML Downloader works without Google Play Services, so we don't use the `googleapis`
# emulator target as it's considerably slower on CI.
target: default
profile: Nexus 5X
script: ./.github/workflows/scripts/drive-example.sh android

apple:
runs-on: macos-latest
timeout-minutes: 40
steps:
- uses: actions/checkout@v2.3.4
with:
fetch-depth: 0
- name: 'Install Flutter'
run: ./.github/workflows/scripts/install-flutter.sh stable
- name: 'Install Tools'
run: ./.github/workflows/scripts/install-tools.sh
- name: 'Build iOS Example'
run: ./.github/workflows/scripts/build-example.sh ios
- name: 'Drive iOS Example'
run: ./.github/workflows/scripts/drive-example.sh ios
50 changes: 50 additions & 0 deletions docs/ml-model-downloader/overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: Firebase ML Model Downloader
sidebar_label: Overview
---

## What does it do?

If you use custom [TensorFlow Lite models](https://www.tensorflow.org/lite/), Firebase ML can help you ensure your users are always using the best-available version of
your custom model. When you deploy your model with Firebase, Firebase ML only downloads the model when it's needed and automatically
updates your users with the latest version.

Once downloaded, you can use packages such as [tflite](https://pub.dev/packages/tflite) and [tfline_flutter](https://pub.dev/packages/tflite_flutter)
to interpret your model.

> Google does not recommend usage of any specific interpreter and leaves it up to the user to decide.
## Installation

### 1. Add dependency

Add the `firebase_ml_model_downloader` dependency to your projects `pubspec.yaml` file:

```yaml {5} title="pubspec.yaml"
dependencies:
flutter:
sdk: flutter
firebase_core: "^{{ plugins.firebase_core_ns }}"
firebase_ml_model_downloader: "^{{ plugins.firebase_ml_model_downloader_ns }}"
```
### 2. Download dependency
Download the dependency by running the following command in your project:
```bash
$ flutter pub get
```

### 3. Rebuild your app

Once complete, rebuild your Flutter application:

```bash
$ flutter run
```

## Next Steps

Once installed, you're ready to start using Firebase ML Model Downloader in your Flutter Project. View the
[Usage documentation](./usage.mdx) to get started.
112 changes: 112 additions & 0 deletions docs/ml-model-downloader/usage.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
---
title: Firebase ML Model Downloader
sidebar_label: Usage
---

Once installed, you can access the [`firebase_ml_model_downloader`](!firebase_ml_model_downloader) plugin by importing it in your Dart code:

```dart
import 'package:firebase_ml_model_downloader/firebase_ml_model_downloader.dart';
```

Before using the package, you must first have ensured you have [initialized FlutterFire](../overview.mdx#initializing-flutterfire).

To create a new downloader instance, call the [`instance`](!firebase_ml_model_downloader.FirebaseMlModelDownloader.instance) getter on [`FirebaseMlModelDownloader`](!firebase_ml_model_downloader.FirebaseMlModelDownloader):

```dart
FirebaseMlModelDownloader downloader = FirebaseMlModelDownloader.instance;
```

By default, this allows you to interact with the downloader using the default Firebase App used whilst installing FlutterFire on your
platform. If however you'd like to use a secondary Firebase App, use the [`instanceFor`](!firebase_ml_model_downloader.FirebaseMlModelDownloader.instanceFor) method:

```dart
FirebaseApp secondaryApp = Firebase.app('SecondaryApp');
FirebaseMlModelDownloader downloader = FirebaseMlModelDownloader.instanceFor(app: secondaryApp);
```

## List downloaded models

To access any locally downloaded models on the device, call the `listDownloadedModels` method. The response contains a list of any locally
downloaded custom models:

```dart
List<CustomModel> models = await FirebaseMlModelDownloader.instance.listDownloadedModels();
```

## Custom model

A custom model contains information such as the name, size and unique hash of the model. It also contains access to the local `File` on the device,
allowing you to provide it to an interpreter plugin.

Once a custom model has been downloaded, you can access it using the [`CustomModel`](!firebase_ml_model_downloader.CustomModel) class:

```dart
List<CustomModel> models = await FirebaseMlModelDownloader.instance.listDownloadedModels();
models.forEach((model) {
print('Name: ${model.name}');
print('Size: ${model.size}');
print('Hash: ${model.hash}');
});
```

If you're working with a 3rd party interpreter such as [`tflite_flutter`](https://pub.dev/packages/tflite_flutter),
use the returned file to access the model:

```dart
final interpreter = await tfl.Interpreter.fromAsset(
model.absolute
);
```

## Downloading a model

Once you have [deployed a TensorFlow model](https://firebase.google.com/docs/ml/manage-hosted-models), you can download them to your
device using the `getModel` method, specifying the model name and download options.

```dart
CustomModel model = await FirebaseMlModelDownloader.instance.getModel('myModel', DownloadType.latestModel);
```

The above code will download the latest available `myModel` model to the device, since the `DownloadType.latestModel` has been specified.
The method accepts 3 download types for differing behavior:

| Type | Description |
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DownloadType.localModel` | Returns the current model if present, otherwise triggers new download (or finds one in progress) and only completes when download is finished. |
| `DownloadType.localModelUpdateInBackground` | Returns the current model if present and triggers an update to fetch a new version in the background. If no local model is present triggers a new download (or finds one in progress) and only completes when download is finished. |
| `DownloadType.latestModel` | Returns the latest model. Checks if latest model is different from local model. If the models are the same, returns the current model. Otherwise, triggers a new model download and returns when this download finishes. |

You can also provide specific conditions for the download, such as whether the model should be downloaded whilst the device has access to
cellular data, or if the device is charging.

To provide conditions, provide a `DownloadConditions` instance to the `getModel` method:

```dart
// The following are the default conditions:
DownloadConditions conditions = DownloadConditions(
// Download whilst connected to cellular data
iOSAllowsCellularAccess: true,
// Allow downloading in the background
iOSAllowsBackgroundDownloading: false,
// Only download whilst charging
androidChargingRequired: false,
// Only download whilst on Wifi
androidWifiRequired: false,
// Only download whilst the device is idle
androidDeviceIdleRequired: false,
);
CustomModel model = await FirebaseMlModelDownloader.instance.getModel('myModel', DownloadType.latestModel, conditions);
```

## Deleting a download model

To delete a model from the device, call the `deleteDownloadedModel` method:

```dart
await FirebaseMlModelDownloader.instance.deleteDownloadedModel('myModel');
```

Note; this does not delete the model from your Firebase project, only the local copy on the device. You can download it again at any time.
4 changes: 4 additions & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ module.exports = {
toReferenceAPI("firebase_in_app_messaging"),
toGithubExample("firebase_in_app_messaging"),
],
"ML Model Downloader": [
"ml-model-downloader/overview",
"ml-model-downloader/usage",
],
// "ML Kit Natural Language": ["ml-language/usage"],
// "ML Kit Vision": ["ml-vision/usage", toReferenceAPI("firebase_ml_vision")],
"Remote Config": [
Expand Down
1 change: 1 addition & 0 deletions docs/versions.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default {
firebase_performance_ns: PUB_NS_FIREBASE_PERFORMANCE,
firebase_remote_config: PUB_FIREBASE_REMOTE_CONFIG,
firebase_remote_config_ns: PUB_NS_FIREBASE_REMOTE_CONFIG,
firebase_ml_model_downloader_ns: PUB_NS_FIREBASE_ML_MODEL_DOWNLOADER,
google_sign_in: "^4.4.4",
},
android: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
.dart_tool/

.packages
.pub/

build/
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 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: 18116933e77adc82f80866c928266a5b4f1ed645
channel: stable

project_type: plugin
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.1.0

- Initial Firebase ML Downloader release.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Copyright 2021, the Chromium project 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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Firebase ML Model Downloader for Flutter
[![pub package](https://img.shields.io/pub/v/firebase_ml_model_downloader.svg)](https://pub.dev/packages/firebase_ml_model_downloader)

A Flutter plugin to use the [Firebase ML Model Downloader API](https://firebase.google.com/docs/ml/).

## Getting Started

To get started with Firebase ML Model Downloader, please [see the documentation](https://firebase.flutter.dev/docs/ml/overview).

## Usage

To use this plugin, please visit the [Firebase ML Model Downloader Usage documentation](https://firebase.flutter.dev/docs/ml/usage)

## Issues and feedback

Please file FlutterFire specific issues, bugs, or feature requests in our [issue tracker](https://github.com/FirebaseExtended/flutterfire/issues/new).

Plugin issues that are not specific to Flutterfire can be filed in the [Flutter issue tracker](https://github.com/flutter/flutter/issues/new).

To contribute a change to this plugin,
please review our [contribution guide](https://github.com/FirebaseExtended/flutterfire/blob/master/CONTRIBUTING.md)
and open a [pull request](https://github.com/FirebaseExtended/flutterfire/pulls).
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
group 'io.flutter.plugins.firebase.firebase_ml_model_downloader'
version '1.0'

buildscript {
repositories {
google()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:7.0.3'
}
}

rootProject.allprojects {
repositories {
google()
mavenCentral()
}
}

def firebaseCoreProject = findProject(':firebase_core')
if (firebaseCoreProject == null) {
throw new GradleException('Could not find the firebase_core FlutterFire plugin, have you added it as a dependency in your pubspec?')
} else if (!firebaseCoreProject.properties['FirebaseSDKVersion']) {
throw new GradleException('A newer version of the firebase_core FlutterFire plugin is required, please update your firebase_core pubspec dependency.')
}

def getRootProjectExtOrCoreProperty(name, firebaseCoreProject) {
if (!rootProject.ext.has('FlutterFire')) return firebaseCoreProject.properties[name]
if (!rootProject.ext.get('FlutterFire')[name]) return firebaseCoreProject.properties[name]
return rootProject.ext.get('FlutterFire').get(name)
}

apply plugin: 'com.android.library'

android {
compileSdkVersion 31
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion 19
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
dependencies {
api firebaseCoreProject
implementation platform("com.google.firebase:firebase-bom:${getRootProjectExtOrCoreProperty("FirebaseSDKVersion", firebaseCoreProject)}")
implementation 'com.google.firebase:firebase-ml-modeldownloader'
implementation 'androidx.annotation:annotation:1.3.0'
}
}

apply from: file("./user-agent.gradle")
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
Loading

0 comments on commit a788f89

Please sign in to comment.