diff --git a/.github/workflows/firebase_installations.yaml b/.github/workflows/firebase_installations.yaml
new file mode 100644
index 000000000000..59125449cffa
--- /dev/null
+++ b/.github/workflows/firebase_installations.yaml
@@ -0,0 +1,80 @@
+name: firebase_installations
+
+on:
+ pull_request:
+ paths:
+ - 'packages/firebase_installations/**'
+ - '.github/workflows/firebase_installations.yaml'
+ push:
+ branches:
+ - master
+ paths-ignore:
+ - 'docs/**'
+ - '**.md'
+
+env:
+ FLUTTERFIRE_PLUGIN_SCOPE: '*installations*'
+ FLUTTERFIRE_PLUGIN_SCOPE_EXAMPLE: '*installations_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
+ - name: 'Build Example'
+ run: ./.github/workflows/scripts/build-example.sh android
+ - name: 'Drive Example'
+ uses: reactivecircus/android-emulator-runner@v2
+ with:
+ api-level: 28
+ arch: x86_64
+ # Firebase Core 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: 35
+ 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
+ flutter config --enable-macos-desktop
+ - name: 'Build iOS Example'
+ run: ./.github/workflows/scripts/build-example.sh ios
+ - name: 'Drive iOS Example'
+ run: ./.github/workflows/scripts/drive-example.sh ios
+ - name: 'Build MacOS Example'
+ run: ./.github/workflows/scripts/build-example.sh macos
+ - name: 'Drive MacOS Example'
+ run: ./.github/workflows/scripts/drive-example.sh macos
+
+ web:
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+ 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
+ flutter config --enable-web
+ - name: 'Drive Example'
+ run: ./.github/workflows/scripts/drive-example.sh web
diff --git a/docs/installations/overview.mdx b/docs/installations/overview.mdx
new file mode 100644
index 000000000000..393e42f14e01
--- /dev/null
+++ b/docs/installations/overview.mdx
@@ -0,0 +1,70 @@
+---
+title: Firebase Installations
+sidebar_label: Overview
+---
+
+## What does it do?
+
+Firebase Installations is a service that allows you to manage the installation of your app on a user's device.
+The Firebase installations service (FIS) provides a Firebase installation ID (FID) for each installed instance of a Firebase app.
+
+Internally, the installation ID is used by the following Firebase Services:
+
+- Firebase Cloud Messaging (FCM)
+- Firebase In-App Messaging (FIAM)
+- Firebase Performance Monitoring
+- Firebase Predictions
+- Google Analytics for Firebase
+- Firebase Remote Config
+- Firebase ML
+
+Typically, Firebase services use the Firebase installations service without requiring developers to interact directly with the FIS API. However, there are cases where app developers might want to directly call the FIS API, such as:
+
+- Delete a Firebase installation and data tied to the installation.
+- Retrieve identifiers (Firebase installation IDs) in order to target specific app installations.
+- Retrieve installation auth tokens to authenticate Firebase installations.
+
+## Installation
+
+Add the `flutterfire_installations` dependency to your projects `pubspec.yaml` file:
+
+```yaml {5} title="pubspec.yaml"
+dependencies:
+ flutter:
+ sdk: flutter
+ firebase_core: "^{{ plugins.firebase_core_ns }}"
+ flutterfire_installations: "^{{ plugins.flutterfire_installations_ns }}"
+```
+
+### 2. Download dependency
+
+```
+$ flutter pub get
+```
+
+### 3. (Web Only) Add the SDK
+
+If using FlutterFire on the web, add the `firebase-installations` JavaScript SDK to your `index.html` file:
+
+```html {5} title="web/index.html"
+
+ ...
+
+
+
+
+
+```
+
+### 4. Rebuild your app
+
+Once complete, rebuild your Flutter application:
+
+```bash
+$ flutter run
+```
+
+## Next Steps
+
+Once installed, you're ready to start using Firebase Installations in your Flutter Project. View the
+[Usage documentation](./usage.mdx) to get started.
\ No newline at end of file
diff --git a/docs/installations/usage.mdx b/docs/installations/usage.mdx
new file mode 100644
index 000000000000..c5b40cf45ee3
--- /dev/null
+++ b/docs/installations/usage.mdx
@@ -0,0 +1,108 @@
+---
+title: Firebase Installations
+sidebar_label: Usage
+---
+
+To start using the Firebase Installations package within your project, import it at the top of your project files:
+
+```dart
+import 'package:flutterfire_installations/flutterfire_installations.dart';
+```
+
+Before using Firebase Installations, you must first have ensured you have [initialized FlutterFire](../overview.mdx#initializing-flutterfire).
+
+To create a new Installations instance, call the [`instance`](!firebase_installations.FirebaseInstallations.instance) getter on
+[`FirebaseInstallations`](!firebase_installations.FirebaseInstallations):
+
+```dart
+FirebaseInstallations installations = FirebaseInstallations.instance;
+```
+
+By default, this allows you to interact with Installations 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` method:
+
+```dart
+FirebaseApp secondaryApp = Firebase.app('SecondaryApp');
+FirebaseInstallations installations = FirebaseInstallations.instanceFor(app: secondaryApp);
+```
+
+## Delete a Firebase installation
+
+Data tied to a Firebase installation is generally not personally identifying. Still, it can be helpful to give users an option to manage and delete this data.
+
+Firebase installation IDs are different for every installation of every application; different applications on the same device have different Firebase installation IDs.
+Firebase installation IDs identify app installations and data tied to those app installations.
+
+When you delete an installation ID, the data tied to that installation ID is removed from live and backup systems of all Firebase services that use Firebase installation
+IDs to identify installations within 180 days. This process is described at a high level in Google’s [statement on deletion and retention](https://policies.google.com/technologies/retention).
+
+Unless you disable all FID-generating services in your app, FIS creates a new ID within a few days. Firebase considers the newly-created ID to be a new Firebase installation,
+and doesn't associate it with the previous ID or data in any way.
+
+To delete an FID, call the `delete` method on the [`FirebaseInstallations`](!firebase_installations.FirebaseInstallations) instance:
+
+```dart
+await FirebaseInstallations.instance.delete();
+```
+
+## Retrieve client identifiers
+
+If you have a requirement to identify particular installations of your app, you can do so by retrieving the Firebase installation ID.
+For example, to perform testing during Firebase In-App Messaging development, you can identify and target the correct test device using
+its Firebase installation ID.
+
+To get the Firebase installation ID, call the `getId` method on the [`FirebaseInstallations`](!firebase_installations.FirebaseInstallations) instance:
+
+```dart
+String id = await FirebaseInstallations.instance.getId();
+```
+
+## Retrieve installation auth tokens
+
+Firebase services can authenticate Firebase installations with auth tokens retrieved from FIS. For example, when designing A/B tests for Remote Config,
+you can authenticate a targeted test device using an installation auth token.
+
+An installation auth token is a short-lived bearer token in JSON web token (JWT) format containing the following information for an installation:
+
+- The Firebase installation ID
+- The associated project (`projectNumber`)
+- The associated Firebase application ID (`appId`)
+- The token's expiration date
+
+An installation auth token cannot be revoked, and remains valid until its expiration date. The default token lifetime is one week.
+
+To retrieve an installation auth token:
+
+```dart
+String token = await FirebaseInstallations.instance.getToken();
+```
+
+Optionally, you can force a token refresh when called:
+
+```dart
+String token = await FirebaseInstallations.instance.getToken(true);
+```
+
+## Monitor the Firebase Installation ID
+
+During the normal operation of an app, Firebase installation IDs (FIDs) don't require special monitoring. However, apps that explicitly retrieve and
+use FIDs should add logic to monitor the potential deletion or rotation of the FID. Here are some cases where FIDs could be deleted or rotated:
+
+- Uninstallation or re-installation of the app, for instance when an end user installs on a new device.
+- The end user clears the cache of the app or the device.
+- FID deletion is triggered in the backend due to app inactivity (currently the threshold for this is 270 days of inactivity).
+
+When apps experience a FID rotation or deletion in these kinds of cases, they are assigned a new FID. Also, the installation auth token associated with
+a deleted FID is deleted, regardless of its own maturity, and is replaced with a new installation auth token.
+
+Apps can monitor these changes and respond accordingly.
+
+To monitor the FID token, listen to the `Stream` returned from the `onIdChange` getter:
+
+```dart
+FirebaseInstallations.instance.onIdChange.listen((token) {
+ print('FID token: $token');
+});
+```
+
+
diff --git a/docs/sidebars.js b/docs/sidebars.js
index 35dbe61f38d0..00b01bb619cc 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -67,6 +67,10 @@ module.exports = {
toReferenceAPI("cloud_functions"),
toGithubExample("cloud_functions"),
],
+ Installations: [
+ "installations/overview",
+ "installations/usage",
+ ],
"Cloud Messaging": [
"messaging/overview",
"messaging/usage",
diff --git a/docs/versions.js b/docs/versions.js
index 6368194003d7..d56030f08f73 100644
--- a/docs/versions.js
+++ b/docs/versions.js
@@ -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,
+ flutterfire_installations: PUB_NS_FLUTTERFIRE_INSTALLATIONS,
firebase_ml_model_downloader_ns: PUB_NS_FIREBASE_ML_MODEL_DOWNLOADER,
google_sign_in: "^4.4.4",
},
diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart
index 649e4bd2e0c9..08b939f1d3fd 100644
--- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart
+++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart
@@ -157,6 +157,8 @@ class FirebaseCoreWeb extends FirebasePlatform {
'https://www.gstatic.com/firebasejs/$version/firebase-remote-config',
'@firebase/performance':
'https://www.gstatic.com/firebasejs/$version/firebase-performance',
+ '@firebase/installations':
+ 'https://www.gstatic.com/firebasejs/$version/firebase-installations',
},
})
]);
diff --git a/packages/firebase_installations/firebase_installations/.gitignore b/packages/firebase_installations/firebase_installations/.gitignore
new file mode 100644
index 000000000000..e9dc58d3d6e2
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/.gitignore
@@ -0,0 +1,7 @@
+.DS_Store
+.dart_tool/
+
+.packages
+.pub/
+
+build/
diff --git a/packages/firebase_installations/firebase_installations/.metadata b/packages/firebase_installations/firebase_installations/.metadata
new file mode 100644
index 000000000000..5bed5265e818
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/.metadata
@@ -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
diff --git a/packages/firebase_installations/firebase_installations/CHANGELOG.md b/packages/firebase_installations/firebase_installations/CHANGELOG.md
new file mode 100644
index 000000000000..c9e662fb6d43
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.1.0
+
+ - Initial release of the Firebase Installations plugin.
diff --git a/packages/firebase_installations/firebase_installations/LICENSE b/packages/firebase_installations/firebase_installations/LICENSE
new file mode 100644
index 000000000000..5b8717b87644
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/LICENSE
@@ -0,0 +1,27 @@
+// Copyright 2021 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.
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations/README.md b/packages/firebase_installations/firebase_installations/README.md
new file mode 100644
index 000000000000..f905a19cb839
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/README.md
@@ -0,0 +1,23 @@
+# Firebase Installations Plugin for Flutter
+
+A Flutter plugin to use the [Firebase Installations API](https://firebase.google.com/docs/projects/manage-installations).
+
+[![pub package](https://img.shields.io/pub/v/flutterfire_installations.svg)](https://pub.dev/packages/flutterfire_installations)
+
+## Getting Started
+
+To get started with Firebase Installations for Flutter, please [see the documentation](https://firebase.flutter.dev/docs/installations/overview).
+
+## Usage
+
+To use this plugin, please visit the [Installations Usage documentation](https://firebase.flutter.dev/docs/installations/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).
diff --git a/packages/firebase_installations/firebase_installations/android/.gitignore b/packages/firebase_installations/firebase_installations/android/.gitignore
new file mode 100644
index 000000000000..c6cbe562a427
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/android/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/packages/firebase_installations/firebase_installations/android/build.gradle b/packages/firebase_installations/firebase_installations/android/build.gradle
new file mode 100644
index 000000000000..aa39bb0c0c45
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/android/build.gradle
@@ -0,0 +1,60 @@
+group 'io.flutter.plugins.firebase.installations.firebase_installations'
+version '1.0'
+
+buildscript {
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.1.0'
+ }
+}
+
+rootProject.allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+apply plugin: 'com.android.library'
+
+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)
+}
+
+android {
+ compileSdkVersion 29
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ minSdkVersion 19
+ }
+
+ dependencies {
+ api firebaseCoreProject
+ implementation platform("com.google.firebase:firebase-bom:${getRootProjectExtOrCoreProperty("FirebaseSDKVersion", firebaseCoreProject)}")
+ implementation 'com.google.firebase:firebase-installations'
+ }
+}
+
+dependencies {
+ implementation 'androidx.annotation:annotation:1.1.0'
+}
+
+apply from: file("./user-agent.gradle")
diff --git a/packages/firebase_installations/firebase_installations/android/gradle.properties b/packages/firebase_installations/firebase_installations/android/gradle.properties
new file mode 100644
index 000000000000..94adc3a3f97a
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/packages/firebase_installations/firebase_installations/android/gradle/wrapper/gradle-wrapper.properties b/packages/firebase_installations/firebase_installations/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000000..3c9d0852bfa5
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
diff --git a/packages/firebase_installations/firebase_installations/android/settings.gradle b/packages/firebase_installations/firebase_installations/android/settings.gradle
new file mode 100644
index 000000000000..18b9c62dc781
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'firebase_installations'
diff --git a/packages/firebase_installations/firebase_installations/android/src/main/AndroidManifest.xml b/packages/firebase_installations/firebase_installations/android/src/main/AndroidManifest.xml
new file mode 100644
index 000000000000..279a00995d6a
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/android/src/main/AndroidManifest.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_installations/FirebaseInstallationsPlugin.java b/packages/firebase_installations/firebase_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_installations/FirebaseInstallationsPlugin.java
new file mode 100644
index 000000000000..8f2e65d7f000
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_installations/FirebaseInstallationsPlugin.java
@@ -0,0 +1,170 @@
+// Copyright 2021 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.
+
+package io.flutter.plugins.firebase.installations.firebase_installations;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.gms.tasks.Task;
+import com.google.android.gms.tasks.Tasks;
+import com.google.firebase.FirebaseApp;
+import com.google.firebase.installations.FirebaseInstallations;
+import com.google.firebase.installations.InstallationTokenResult;
+import io.flutter.embedding.engine.plugins.FlutterPlugin;
+import io.flutter.plugin.common.BinaryMessenger;
+import io.flutter.plugin.common.EventChannel;
+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.plugins.firebase.core.FlutterFirebasePlugin;
+import io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/** FirebaseInstallationsPlugin */
+public class FirebaseInstallationsPlugin
+ implements FlutterFirebasePlugin, FlutterPlugin, MethodCallHandler {
+ private MethodChannel channel;
+ private static final String METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_installations";
+ private final Map streamHandlers = new HashMap<>();
+
+ @Nullable private BinaryMessenger messenger;
+
+ private MethodChannel setup(BinaryMessenger binaryMessenger) {
+ final MethodChannel channel = new MethodChannel(binaryMessenger, METHOD_CHANNEL_NAME);
+ channel.setMethodCallHandler(this);
+ this.messenger = binaryMessenger;
+ return channel;
+ }
+
+ @Override
+ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
+ BinaryMessenger binaryMessenger = flutterPluginBinding.getBinaryMessenger();
+ channel = setup(binaryMessenger);
+
+ FlutterFirebasePluginRegistry.registerPlugin(METHOD_CHANNEL_NAME, this);
+ }
+
+ @Override
+ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
+ channel.setMethodCallHandler(null);
+ channel = null;
+ messenger = null;
+
+ removeEventListeners();
+ }
+
+ private FirebaseInstallations getInstallations(Map arguments) {
+ @NonNull String appName = (String) Objects.requireNonNull(arguments.get("appName"));
+ FirebaseApp app = FirebaseApp.getInstance(appName);
+ return FirebaseInstallations.getInstance(app);
+ }
+
+ private Task getId(Map arguments) {
+ return Tasks.call(cachedThreadPool, () -> Tasks.await(getInstallations(arguments).getId()));
+ }
+
+ private Task getToken(Map arguments) {
+ return Tasks.call(
+ cachedThreadPool,
+ () -> {
+ FirebaseInstallations firebaseInstallations = getInstallations(arguments);
+ Boolean forceRefresh = (Boolean) Objects.requireNonNull(arguments.get("forceRefresh"));
+ InstallationTokenResult tokenResult =
+ Tasks.await(firebaseInstallations.getToken(forceRefresh));
+ return tokenResult.getToken();
+ });
+ }
+
+ private Task registerIdChangeListener(Map arguments) {
+ return Tasks.call(
+ cachedThreadPool,
+ () -> {
+ String appName = (String) Objects.requireNonNull(arguments.get("appName"));
+ FirebaseInstallations firebaseInstallations = getInstallations(arguments);
+
+ TokenChannelStreamHandler handler = new TokenChannelStreamHandler(firebaseInstallations);
+
+ final String name = METHOD_CHANNEL_NAME + "/token/" + appName;
+ final EventChannel channel = new EventChannel(messenger, name);
+ channel.setStreamHandler(handler);
+ streamHandlers.put(channel, handler);
+
+ return name;
+ });
+ }
+
+ private Task deleteId(Map arguments) {
+ return Tasks.call(cachedThreadPool, () -> Tasks.await(getInstallations(arguments).delete()));
+ }
+
+ @Override
+ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
+ Task> methodCallTask;
+
+ switch (call.method) {
+ case "FirebaseInstallations#getId":
+ methodCallTask = getId(call.arguments());
+ break;
+ case "FirebaseInstallations#getToken":
+ methodCallTask = getToken(call.arguments());
+ break;
+ case "FirebaseInstallations#delete":
+ methodCallTask = deleteId(call.arguments());
+ break;
+ case "FirebaseInstallations#registerIdChangeListener":
+ methodCallTask = registerIdChangeListener(call.arguments());
+ break;
+
+ default:
+ result.notImplemented();
+ return;
+ }
+
+ methodCallTask.addOnCompleteListener(
+ task -> {
+ if (task.isSuccessful()) {
+ result.success(task.getResult());
+ } else {
+ Exception exception = task.getException();
+ result.error(
+ "firebase_installations",
+ exception != null ? exception.getMessage() : null,
+ getExceptionDetails(exception));
+ }
+ });
+ }
+
+ private Map getExceptionDetails(@Nullable Exception exception) {
+ Map details = new HashMap<>();
+ details.put("code", "unknown");
+ if (exception != null) {
+ details.put("message", exception.getMessage());
+ } else {
+ details.put("message", "An unknown error has occurred.");
+ }
+ return details;
+ }
+
+ @Override
+ public Task> getPluginConstantsForFirebaseApp(FirebaseApp firebaseApp) {
+ return Tasks.call(cachedThreadPool, () -> null);
+ }
+
+ @Override
+ public Task didReinitializeFirebaseCore() {
+ return Tasks.call(cachedThreadPool, () -> null);
+ }
+
+ private void removeEventListeners() {
+ for (EventChannel eventChannel : streamHandlers.keySet()) {
+ EventChannel.StreamHandler streamHandler = streamHandlers.get(eventChannel);
+ streamHandler.onCancel(null);
+ eventChannel.setStreamHandler(null);
+ }
+ streamHandlers.clear();
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_installations/FlutterFirebaseAppRegistrar.java b/packages/firebase_installations/firebase_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_installations/FlutterFirebaseAppRegistrar.java
new file mode 100644
index 000000000000..ff8becf25d7b
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_installations/FlutterFirebaseAppRegistrar.java
@@ -0,0 +1,21 @@
+// Copyright 2021 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.
+
+package io.flutter.plugins.firebase.installations.firebase_installations;
+
+import androidx.annotation.Keep;
+import com.google.firebase.components.Component;
+import com.google.firebase.components.ComponentRegistrar;
+import com.google.firebase.platforminfo.LibraryVersionComponent;
+import java.util.Collections;
+import java.util.List;
+
+@Keep
+public class FlutterFirebaseAppRegistrar implements ComponentRegistrar {
+ @Override
+ public List> getComponents() {
+ return Collections.>singletonList(
+ LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION));
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_installations/TokenChannelStreamHandler.java b/packages/firebase_installations/firebase_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_installations/TokenChannelStreamHandler.java
new file mode 100644
index 000000000000..690e6347c01f
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/android/src/main/java/io/flutter/plugins/firebase/installations/firebase_installations/TokenChannelStreamHandler.java
@@ -0,0 +1,46 @@
+// Copyright 2021 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.
+
+package io.flutter.plugins.firebase.installations.firebase_installations;
+
+import com.google.firebase.installations.FirebaseInstallations;
+import com.google.firebase.installations.internal.FidListener;
+import io.flutter.plugin.common.EventChannel;
+import java.util.HashMap;
+import java.util.Map;
+
+public class TokenChannelStreamHandler implements EventChannel.StreamHandler {
+
+ private final FirebaseInstallations firebaseInstallations;
+ private FidListener listener;
+
+ public TokenChannelStreamHandler(FirebaseInstallations firebaseInstallations) {
+ this.firebaseInstallations = firebaseInstallations;
+ }
+
+ @Override
+ public void onListen(Object arguments, EventChannel.EventSink events) {
+
+ listener = createTokenEventListener(events);
+
+ firebaseInstallations.registerFidListener(listener);
+ }
+
+ @Override
+ public void onCancel(Object arguments) {
+ if (listener != null) {
+ listener = null;
+ }
+ }
+
+ FidListener createTokenEventListener(final EventChannel.EventSink events) {
+ return token -> {
+ Map event = new HashMap<>();
+
+ event.put("token", token);
+
+ events.success(event);
+ };
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/android/user-agent.gradle b/packages/firebase_installations/firebase_installations/android/user-agent.gradle
new file mode 100644
index 000000000000..3454bf0b3a48
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/android/user-agent.gradle
@@ -0,0 +1,22 @@
+import java.util.regex.Matcher
+import java.util.regex.Pattern
+
+String libraryVersionName = "UNKNOWN"
+String libraryName = "flutter-fire-rc"
+File pubspec = new File(project.projectDir.parentFile, 'pubspec.yaml')
+
+if (pubspec.exists()) {
+ String yaml = pubspec.text
+ // Using \s*['|"]?([^\n|'|"]*)['|"]? to extract version number.
+ Matcher versionMatcher = Pattern.compile("^version:\\s*['|\"]?([^\\n|'|\"]*)['|\"]?\$", Pattern.MULTILINE).matcher(yaml)
+ if (versionMatcher.find()) libraryVersionName = versionMatcher.group(1).replaceAll("\\+", "-")
+}
+
+android {
+ defaultConfig {
+ // BuildConfig.VERSION_NAME
+ buildConfigField 'String', 'LIBRARY_VERSION', "\"${libraryVersionName}\""
+ // BuildConfig.LIBRARY_NAME
+ buildConfigField 'String', 'LIBRARY_NAME', "\"${libraryName}\""
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/example/.gitignore b/packages/firebase_installations/firebase_installations/example/.gitignore
new file mode 100644
index 000000000000..0fa6b675c0a5
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/.gitignore
@@ -0,0 +1,46 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/packages/firebase_installations/firebase_installations/example/.metadata b/packages/firebase_installations/firebase_installations/example/.metadata
new file mode 100644
index 000000000000..a5584fc372d9
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/.metadata
@@ -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: app
diff --git a/packages/firebase_installations/firebase_installations/example/README.md b/packages/firebase_installations/firebase_installations/example/README.md
new file mode 100644
index 000000000000..a13562602822
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/README.md
@@ -0,0 +1,16 @@
+# example
+
+A new Flutter project.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
+
+For help getting started with Flutter, view our
+[online documentation](https://flutter.dev/docs), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
diff --git a/packages/firebase_installations/firebase_installations/example/analysis_options.yaml b/packages/firebase_installations/firebase_installations/example/analysis_options.yaml
new file mode 100644
index 000000000000..61b6c4de17c9
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/packages/firebase_installations/firebase_installations/example/android/.gitignore b/packages/firebase_installations/firebase_installations/example/android/.gitignore
new file mode 100644
index 000000000000..6f568019d3c6
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/build.gradle b/packages/firebase_installations/firebase_installations/example/android/app/build.gradle
new file mode 100644
index 000000000000..a8941c290917
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/app/build.gradle
@@ -0,0 +1,69 @@
+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) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'com.google.gms.google-services'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion 30
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "io.flutter.plugins.firebase.installations.example"
+ minSdkVersion 19
+ targetSdkVersion 30
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ 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 {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/google-services.json b/packages/firebase_installations/firebase_installations/example/android/app/google-services.json
new file mode 100644
index 000000000000..4b6c0fccd142
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/app/google-services.json
@@ -0,0 +1,892 @@
+{
+ "project_info": {
+ "project_number": "448618578101",
+ "firebase_url": "https://react-native-firebase-testing.firebaseio.com",
+ "project_id": "react-native-firebase-testing",
+ "storage_bucket": "react-native-firebase-testing.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:8a26b64c4bb2bd1dac3efc",
+ "android_client_info": {
+ "package_name": "com.example.firebase_in_app_messaging_example"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:cc6c1dc7a65cc83c",
+ "android_client_info": {
+ "package_name": "com.invertase.testing"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-a9p7bj5jlakabp22fo3cbkj7nsmag24e.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.invertase.testing",
+ "certificate_hash": "889b4292c735f371168a372cc7778992cd8a5052"
+ }
+ },
+ {
+ "client_id": "448618578101-f50e0ln93159r9nlhr1ktmf125nf64g1.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.invertase.testing",
+ "certificate_hash": "a094b2938a1d0cdcbb9b7a6611d1731cbdb641d8"
+ }
+ },
+ {
+ "client_id": "448618578101-gva3jv7cr8qquj04k0o7cni674j65kha.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.invertase.testing",
+ "certificate_hash": "5e8f16062ea3cd2c4a0d547876baa6f38cabf625"
+ }
+ },
+ {
+ "client_id": "448618578101-h0o9b94jnhcoal2qgjn7s7ckkc2n7okq.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.invertase.testing",
+ "certificate_hash": "909ca1482ef022bbae45a2db6b6d05d807a4c4aa"
+ }
+ },
+ {
+ "client_id": "448618578101-pdjje2lkv3p941e03hkrhfa7459cr2v8.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.invertase.testing",
+ "certificate_hash": "992e468b990cc418f306d0131be61ecfad800ac1"
+ }
+ },
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:cc5ce91648e65dbeac3efc",
+ "android_client_info": {
+ "package_name": "com.notifeetestapp"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-j9nluebtat700ua550esfvaf64gbo5l5.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "com.notifeetestapp",
+ "certificate_hash": "5e8f16062ea3cd2c4a0d547876baa6f38cabf625"
+ }
+ },
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:6aa085e64d694703ac3efc",
+ "android_client_info": {
+ "package_name": "com.rnfbdemo"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:6bf0706c1f27114dac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebase.cloudfunctions.cloudfunctionsexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:5cc04a661d27c405ac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebase.crashlytics.firebasecrashlyticsexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:1be54ee660fd87d2ac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebase.dynamiclinksexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-b5v53gfm2pgtblp8iu352ett69jssghb.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "io.flutter.plugins.firebase.dynamiclinksexample",
+ "certificate_hash": "909ca1482ef022bbae45a2db6b6d05d807a4c4aa"
+ }
+ },
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:e005c2b7f723853fac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebase.firebaseremoteconfigexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:3ad281c0067ccf97ac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebase.firestoreexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-npu5ll2fj4emgvtietpb685fvdm7fg3s.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "io.flutter.plugins.firebase.firestoreexample",
+ "certificate_hash": "909ca1482ef022bbae45a2db6b6d05d807a4c4aa"
+ }
+ },
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:a723be2eb2bf60d9ac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebase.installations.example"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:0568e76dc62e89bcac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebase.messaging.example"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:507d24bc5fc4d20eac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebaseanalyticsexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:9d44a7b85d1ab0baac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebaseauthexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-qd7qb4i251kmq2ju79bl7sif96si0ve3.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "io.flutter.plugins.firebaseauthexample",
+ "certificate_hash": "909ca1482ef022bbae45a2db6b6d05d807a4c4aa"
+ }
+ },
+ {
+ "client_id": "448618578101-velutq65ok2dr5ohh0oi1q62irr920ss.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "io.flutter.plugins.firebaseauthexample",
+ "certificate_hash": "29142b8612b4b6a0ba0fefd1dbf65ab565fb2cbd"
+ }
+ },
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:0446912d5f1476b6ac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebasecoreexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:29bf96f913c195f5ac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebasecrashlyticsexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:a7b3b683e70a7a17ac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebasedatabaseexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:d767a536227718bcac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebasemessagingexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-rthm8sh42ifgn9vp60914nol7u8h7mgq.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "io.flutter.plugins.firebasemessagingexample",
+ "certificate_hash": "29142b8612b4b6a0ba0fefd1dbf65ab565fb2cbd"
+ }
+ },
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:56e2f97d61c5da38ac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebasemlcustomexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:f2548276e02d9ddbac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebaseperformanceexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sn6oicnu6cmq0lfa84hit4t5vs0e6676.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "io.flutter.plugins.firebaseperformanceexample",
+ "certificate_hash": "909ca1482ef022bbae45a2db6b6d05d807a4c4aa"
+ }
+ },
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:553625b1be8cf2efac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.firebasestorageexample"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:448618578101:android:5180baaa9cc2b8fcac3efc",
+ "android_client_info": {
+ "package_name": "io.flutter.plugins.flutterfire_ui.flutterfire_ui_example"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "448618578101-ld5ohh347f6fkfggetdn3qnda99n813a.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "io.flutter.plugins.flutterfire_ui.flutterfire_ui_example",
+ "certificate_hash": "b365a398dd6441427be2a9783ef98bc4fb39a2e8"
+ }
+ },
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "448618578101-sg12d2qin42cpr00f8b0gehs5s7inm0v.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "448618578101-28tsenal97nceuij1msj7iuqinv48t02.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "com.invertase.testing",
+ "app_store_id": "123456789"
+ }
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/debug/AndroidManifest.xml b/packages/firebase_installations/firebase_installations/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 000000000000..2da223860fd7
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/AndroidManifest.xml b/packages/firebase_installations/firebase_installations/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 000000000000..b3d025d66152
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/packages/firebase_installations/firebase_installations/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt
new file mode 100644
index 000000000000..0e2f85cd7aee
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt
@@ -0,0 +1,6 @@
+package io.flutter.plugins.firebase.installations.example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 000000000000..f74085f3f6a2
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/drawable/launch_background.xml b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 000000000000..304732f88420
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000000..db77bb4b7b09
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000000..17987b79bb8a
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000000..09d4391482be
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000000..d5f1c8d34e7a
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000000..4d6372eebdb2
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/values-night/styles.xml b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 000000000000..449a9f930826
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/values/styles.xml b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 000000000000..d74aa35c2826
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/android/app/src/profile/AndroidManifest.xml b/packages/firebase_installations/firebase_installations/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 000000000000..2da223860fd7
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/android/build.gradle b/packages/firebase_installations/firebase_installations/example/android/build.gradle
new file mode 100644
index 000000000000..fd01d85a8223
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/build.gradle
@@ -0,0 +1,30 @@
+buildscript {
+ ext.kotlin_version = '1.3.50'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.1.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.google.gms:google-services:4.3.8'
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+ project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/packages/firebase_installations/firebase_installations/example/android/gradle.properties b/packages/firebase_installations/firebase_installations/example/android/gradle.properties
new file mode 100644
index 000000000000..94adc3a3f97a
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/packages/firebase_installations/firebase_installations/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/firebase_installations/firebase_installations/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000000..bc6a58afdda2
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/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-6.7-all.zip
diff --git a/packages/firebase_installations/firebase_installations/example/android/settings.gradle b/packages/firebase_installations/firebase_installations/example/android/settings.gradle
new file mode 100644
index 000000000000..44e62bcf06ae
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/packages/firebase_installations/firebase_installations/example/ios/.gitignore b/packages/firebase_installations/firebase_installations/example/ios/.gitignore
new file mode 100644
index 000000000000..7a7f9873ad7d
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/.gitignore
@@ -0,0 +1,34 @@
+**/dgph
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/ephemeral/
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Flutter/AppFrameworkInfo.plist b/packages/firebase_installations/firebase_installations/example/ios/Flutter/AppFrameworkInfo.plist
new file mode 100644
index 000000000000..8d4492f977ad
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/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
+ 9.0
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Flutter/Debug.xcconfig b/packages/firebase_installations/firebase_installations/example/ios/Flutter/Debug.xcconfig
new file mode 100644
index 000000000000..ec97fc6f3021
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/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_installations/firebase_installations/example/ios/Flutter/Release.xcconfig b/packages/firebase_installations/firebase_installations/example/ios/Flutter/Release.xcconfig
new file mode 100644
index 000000000000..c4855bfe2000
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/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_installations/firebase_installations/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 000000000000..ca310f2b4e1e
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,552 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 51;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+ 25D8824F2757C5A50032AD7D /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 25D8824E2757C5A40032AD7D /* GoogleService-Info.plist */; };
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
+ 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 */; };
+ D31746244E2F2FE1872744CA /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69B8F88D9874F0301253207A /* Pods_Runner.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 0047649AA80D5E08710B83FC /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
+ 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 = ""; };
+ 25D8824E2757C5A40032AD7D /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 46C9450C09DECE161F8D2B0E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
+ 69B8F88D9874F0301253207A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 70BA4B84FBF4F8F98882ECE8 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; 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 = ""; };
+ 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 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 = (
+ D31746244E2F2FE1872744CA /* Pods_Runner.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 9740EEB11CF90186004384FC /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */,
+ );
+ name = Flutter;
+ sourceTree = "";
+ };
+ 97C146E51CF9000F007C117D = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB11CF90186004384FC /* Flutter */,
+ 97C146F01CF9000F007C117D /* Runner */,
+ 97C146EF1CF9000F007C117D /* Products */,
+ B73D1DC58D055FB68C9A8078 /* Pods */,
+ C9AFE18D56A992DC82EEDD72 /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ 97C146EF1CF9000F007C117D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146EE1CF9000F007C117D /* Runner.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 97C146F01CF9000F007C117D /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146FA1CF9000F007C117D /* Main.storyboard */,
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */,
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
+ 25D8824E2757C5A40032AD7D /* GoogleService-Info.plist */,
+ 97C147021CF9000F007C117D /* Info.plist */,
+ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
+ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ B73D1DC58D055FB68C9A8078 /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ 0047649AA80D5E08710B83FC /* Pods-Runner.debug.xcconfig */,
+ 70BA4B84FBF4F8F98882ECE8 /* Pods-Runner.release.xcconfig */,
+ 46C9450C09DECE161F8D2B0E /* Pods-Runner.profile.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
+ C9AFE18D56A992DC82EEDD72 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 69B8F88D9874F0301253207A /* Pods_Runner.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 97C146ED1CF9000F007C117D /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 86AB341DFEACCFD6CBE9739D /* [CP] Check Pods Manifest.lock */,
+ 9740EEB61CF901F6004384FC /* Run Script */,
+ 97C146EA1CF9000F007C117D /* Sources */,
+ 97C146EB1CF9000F007C117D /* Frameworks */,
+ 97C146EC1CF9000F007C117D /* Resources */,
+ 9705A1C41CF9048500538489 /* Embed Frameworks */,
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ ECA47BD16D6FC415D9110B06 /* [CP] Embed Pods Frameworks */,
+ );
+ 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 = 1020;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 97C146ED1CF9000F007C117D = {
+ CreatedOnToolsVersion = 7.3.1;
+ LastSwiftMigration = 1100;
+ };
+ };
+ };
+ buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ 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 */,
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
+ 25D8824F2757C5A50032AD7D /* GoogleService-Info.plist in Resources */,
+ 97C146FE1CF9000F007C117D /* Assets.xcassets 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\" embed_and_thin";
+ };
+ 86AB341DFEACCFD6CBE9739D /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ 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;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Run Script";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
+ };
+ ECA47BD16D6FC415D9110B06 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 97C146EA1CF9000F007C117D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift 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 */
+ 249021D3217E4FDB00AE95B9 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ 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_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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 = 10.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Profile;
+ };
+ 249021D4217E4FDB00AE95B9 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.installations.example;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Profile;
+ };
+ 97C147031CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ 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_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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 = 10.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 97C147041CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ 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_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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 = 10.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 97C147061CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.installations.example;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 97C147071CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.installations.example;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ 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 */,
+ 249021D3217E4FDB00AE95B9 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147061CF9000F007C117D /* Debug */,
+ 97C147071CF9000F007C117D /* Release */,
+ 249021D4217E4FDB00AE95B9 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 97C146E61CF9000F007C117D /* Project object */;
+}
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 000000000000..919434a6254f
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000000..18d981003d68
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 000000000000..f9b0d7c5ea15
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 000000000000..a28140cfdb3f
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 000000000000..21a3cc14c74e
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000000..18d981003d68
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 000000000000..f9b0d7c5ea15
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/AppDelegate.swift b/packages/firebase_installations/firebase_installations/example/ios/Runner/AppDelegate.swift
new file mode 100644
index 000000000000..70693e4a8c12
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner/AppDelegate.swift
@@ -0,0 +1,13 @@
+import UIKit
+import Flutter
+
+@UIApplicationMain
+@objc class AppDelegate: FlutterAppDelegate {
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ GeneratedPluginRegistrant.register(with: self)
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 000000000000..d36b1fab2d9d
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/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_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
new file mode 100644
index 000000000000..dc9ada4725e9
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
new file mode 100644
index 000000000000..28c6bf03016f
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
new file mode 100644
index 000000000000..2ccbfd967d96
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
new file mode 100644
index 000000000000..f091b6b0bca8
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
new file mode 100644
index 000000000000..4cde12118dda
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
new file mode 100644
index 000000000000..d0ef06e7edb8
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
new file mode 100644
index 000000000000..dcdc2306c285
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
new file mode 100644
index 000000000000..2ccbfd967d96
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
new file mode 100644
index 000000000000..c8f9ed8f5cee
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
new file mode 100644
index 000000000000..a6d6b8609df0
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
new file mode 100644
index 000000000000..a6d6b8609df0
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
new file mode 100644
index 000000000000..75b2d164a5a9
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
new file mode 100644
index 000000000000..c4df70d39da7
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
new file mode 100644
index 000000000000..6a84f41e14e2
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
new file mode 100644
index 000000000000..d0e1f5853602
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
new file mode 100644
index 000000000000..0bedcf2fd467
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage@3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
new file mode 100644
index 000000000000..9da19eacad3b
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
new file mode 100644
index 000000000000..9da19eacad3b
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
new file mode 100644
index 000000000000..9da19eacad3b
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/firebase_installations/firebase_installations/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
new file mode 100644
index 000000000000..89c2725b70f1
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/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_installations/firebase_installations/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/firebase_installations/firebase_installations/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 000000000000..f2e259c7c939
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Base.lproj/Main.storyboard b/packages/firebase_installations/firebase_installations/example/ios/Runner/Base.lproj/Main.storyboard
new file mode 100644
index 000000000000..f3c28516fb38
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner/Base.lproj/Main.storyboard
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/GoogleService-Info.plist b/packages/firebase_installations/firebase_installations/example/ios/Runner/GoogleService-Info.plist
new file mode 100644
index 000000000000..2bcf5ca4629d
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner/GoogleService-Info.plist
@@ -0,0 +1,38 @@
+
+
+
+
+ CLIENT_ID
+ 448618578101-ff6olegpc8901mthfv42r97oo0gbqebc.apps.googleusercontent.com
+ REVERSED_CLIENT_ID
+ com.googleusercontent.apps.448618578101-ff6olegpc8901mthfv42r97oo0gbqebc
+ ANDROID_CLIENT_ID
+ 448618578101-a9p7bj5jlakabp22fo3cbkj7nsmag24e.apps.googleusercontent.com
+ API_KEY
+ AIzaSyAHAsf51D0A407EklG1bs-5wA7EbyfNFg0
+ GCM_SENDER_ID
+ 448618578101
+ PLIST_VERSION
+ 1
+ BUNDLE_ID
+ io.flutter.plugins.firebase.installations.example
+ PROJECT_ID
+ react-native-firebase-testing
+ STORAGE_BUCKET
+ react-native-firebase-testing.appspot.com
+ IS_ADS_ENABLED
+
+ IS_ANALYTICS_ENABLED
+
+ IS_APPINVITE_ENABLED
+
+ IS_GCM_ENABLED
+
+ IS_SIGNIN_ENABLED
+
+ GOOGLE_APP_ID
+ 1:448618578101:ios:1135057e92910ad9ac3efc
+ DATABASE_URL
+ https://react-native-firebase-testing.firebaseio.com
+
+
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations/example/ios/Runner/Info.plist b/packages/firebase_installations/firebase_installations/example/ios/Runner/Info.plist
new file mode 100644
index 000000000000..67c34806c987
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner/Info.plist
@@ -0,0 +1,47 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ Firebase Installations Example
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ firebase_installations_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_installations/firebase_installations/example/ios/Runner/Runner-Bridging-Header.h b/packages/firebase_installations/firebase_installations/example/ios/Runner/Runner-Bridging-Header.h
new file mode 100644
index 000000000000..308a2a560b42
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/ios/Runner/Runner-Bridging-Header.h
@@ -0,0 +1 @@
+#import "GeneratedPluginRegistrant.h"
diff --git a/packages/firebase_installations/firebase_installations/example/lib/firebase_config.dart b/packages/firebase_installations/firebase_installations/example/lib/firebase_config.dart
new file mode 100644
index 000000000000..9eaaa126e8d2
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/lib/firebase_config.dart
@@ -0,0 +1,47 @@
+import 'dart:io';
+
+import 'package:firebase_core/firebase_core.dart';
+import 'package:flutter/foundation.dart';
+
+class DefaultFirebaseConfig {
+ static FirebaseOptions get platformOptions {
+ if (kIsWeb) {
+ // Web
+ return const FirebaseOptions(
+ apiKey: 'AIzaSyAgUhHU8wSJgO5MVNy95tMT07NEjzMOfz0',
+ authDomain: 'react-native-firebase-testing.firebaseapp.com',
+ databaseURL: 'https://react-native-firebase-testing.firebaseio.com',
+ projectId: 'react-native-firebase-testing',
+ storageBucket: 'react-native-firebase-testing.appspot.com',
+ messagingSenderId: '448618578101',
+ appId: '1:448618578101:web:0b650370bb29e29cac3efc',
+ measurementId: 'G-F79DJ0VFGS',
+ );
+ } else if (Platform.isIOS || Platform.isMacOS) {
+ // iOS and MacOS
+ return const FirebaseOptions(
+ appId: '1:448618578101:ios:f7208957983eeee4ac3efc',
+ apiKey: 'AIzaSyAHAsf51D0A407EklG1bs-5wA7EbyfNFg0',
+ projectId: 'react-native-firebase-testing',
+ messagingSenderId: '448618578101',
+ iosBundleId: 'io.flutter.plugins.firebase.installations.example',
+ iosClientId:
+ '448618578101-ff6olegpc8901mthfv42r97oo0gbqebc.apps.googleusercontent.com',
+ androidClientId:
+ '448618578101-a9p7bj5jlakabp22fo3cbkj7nsmag24e.apps.googleusercontent.com',
+ databaseURL: 'https://react-native-firebase-testing.firebaseio.com',
+ storageBucket: 'react-native-firebase-testing.appspot.com',
+ );
+ } else {
+ // Android
+ return const FirebaseOptions(
+ appId: '1:448618578101:android:a723be2eb2bf60d9ac3efc',
+ apiKey: 'AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA',
+ projectId: 'react-native-firebase-testing',
+ messagingSenderId: '448618578101',
+ databaseURL: 'https://react-native-firebase-testing.firebaseio.com',
+ storageBucket: 'react-native-firebase-testing.appspot.com',
+ );
+ }
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/example/lib/main.dart b/packages/firebase_installations/firebase_installations/example/lib/main.dart
new file mode 100644
index 000000000000..8c8e1dd62e9a
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/lib/main.dart
@@ -0,0 +1,188 @@
+import 'dart:developer';
+
+import 'package:firebase_installations_example/firebase_config.dart';
+import 'package:flutter/material.dart';
+
+import 'package:firebase_core/firebase_core.dart';
+import 'package:flutterfire_installations/flutterfire_installations.dart';
+
+void main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+
+ await Firebase.initializeApp(options: DefaultFirebaseConfig.platformOptions);
+
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ theme: ThemeData(primarySwatch: Colors.amber),
+ home: Scaffold(
+ appBar: AppBar(
+ title: const Text('Firebase Installations'),
+ ),
+ body: const InstallationsCard(),
+ ),
+ );
+ }
+}
+
+class InstallationsCard extends StatefulWidget {
+ const InstallationsCard({Key? key}) : super(key: key);
+
+ @override
+ _InstallationsCardState createState() => _InstallationsCardState();
+}
+
+class _InstallationsCardState extends State {
+ @override
+ void initState() {
+ super.initState();
+ init();
+
+ // Listen to changes
+ FirebaseInstallations.instance.onIdChange.listen((event) {
+ setState(() {
+ id = event;
+ });
+
+ // Make sure that the Auth Token is updated once the Installation Id is updated
+ getAuthToken();
+
+ ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
+ content: Text('New Firebase Installations Id generated 🎉'),
+ backgroundColor: Colors.green,
+ ));
+ }).onError((error) {
+ log("$error");
+ });
+ }
+
+ String id = 'None';
+ String authToken = 'None';
+
+ init() async {
+ await getId();
+ await getAuthToken();
+ }
+
+ Future deleteId() async {
+ try {
+ await FirebaseInstallations.instance.delete();
+
+ setState(() {
+ id = 'None';
+ });
+ } catch (e) {
+ log('$e');
+ }
+ }
+
+ Future getId() async {
+ try {
+ final _newid = await FirebaseInstallations.instance.getId();
+
+ setState(() {
+ id = _newid;
+ });
+ } catch (e) {
+ log('$e');
+ }
+ }
+
+ Future getAuthToken([forceRefresh = false]) async {
+ try {
+ final token = await FirebaseInstallations.instance.getToken(forceRefresh);
+ setState(() {
+ authToken = token;
+ });
+ } catch (e) {
+ log('$e');
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Center(
+ child: ConstrainedBox(
+ constraints: const BoxConstraints(maxWidth: 500),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ SizedBox(
+ width: double.infinity,
+ child: Card(
+ margin: EdgeInsets.zero,
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Column(
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const Expanded(
+ child: Text("Installation Id: "),
+ ),
+ Expanded(
+ flex: 2,
+ child: Text(id),
+ ),
+ ],
+ ),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const Expanded(
+ child: Text("Auth Token: "),
+ ),
+ Expanded(
+ flex: 2,
+ child: Text(authToken),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ const SizedBox(height: 20),
+ SizedBox(
+ width: double.infinity,
+ child: ElevatedButton(
+ onPressed: () => getAuthToken(true),
+ child: const Text("Force update token"),
+ ),
+ ),
+ const SizedBox(height: 20),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ Expanded(
+ child: ElevatedButton(
+ onPressed: deleteId,
+ child: const Text("Delete ID"),
+ ),
+ ),
+ const SizedBox(width: 20),
+ Expanded(
+ child: ElevatedButton(
+ onPressed: getId,
+ child: const Text("Get ID"),
+ ),
+ )
+ ],
+ )
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/example/macos/.gitignore b/packages/firebase_installations/firebase_installations/example/macos/.gitignore
new file mode 100644
index 000000000000..746adbb6b9e1
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/.gitignore
@@ -0,0 +1,7 @@
+# Flutter-related
+**/Flutter/ephemeral/
+**/Pods/
+
+# Xcode-related
+**/dgph
+**/xcuserdata/
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/firebase_installations/firebase_installations/example/macos/Flutter/Flutter-Debug.xcconfig
new file mode 100644
index 000000000000..4b81f9b2d200
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Flutter/Flutter-Debug.xcconfig
@@ -0,0 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Flutter/Flutter-Release.xcconfig b/packages/firebase_installations/firebase_installations/example/macos/Flutter/Flutter-Release.xcconfig
new file mode 100644
index 000000000000..5caa9d1579e4
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Flutter/Flutter-Release.xcconfig
@@ -0,0 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Podfile b/packages/firebase_installations/firebase_installations/example/macos/Podfile
new file mode 100644
index 000000000000..22d9caad2e9d
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Podfile
@@ -0,0 +1,40 @@
+platform :osx, '10.12'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_macos_podfile_setup
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_macos_build_settings(target)
+ end
+end
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_installations/firebase_installations/example/macos/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 000000000000..09bd291b065e
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,631 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 51;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
+ buildPhases = (
+ 33CC111E2044C6BF0003C045 /* ShellScript */,
+ );
+ dependencies = (
+ );
+ name = "Flutter Assemble";
+ productName = FLX;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
+ CECC36D088977FEA6F4C1003 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8B6589603437F8EF35345E /* Pods_Runner.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 33CC111A2044C6BA0003C045;
+ remoteInfo = FLX;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 33CC110E2044A8840003C045 /* Bundle Framework */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Bundle Framework";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 1779DABB40E431F6140D7937 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; };
+ 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; };
+ 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
+ 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; };
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; };
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; };
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; };
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; };
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; };
+ 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; };
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; };
+ 6D913916A8D84C1FDC8F7B4C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
+ 7234BB708D5460BA64D90E26 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; };
+ BE8B6589603437F8EF35345E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 33CC10EA2044A3C60003C045 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CECC36D088977FEA6F4C1003 /* Pods_Runner.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 1C79AB84644B94FC4355DDDB /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ 6D913916A8D84C1FDC8F7B4C /* Pods-Runner.debug.xcconfig */,
+ 7234BB708D5460BA64D90E26 /* Pods-Runner.release.xcconfig */,
+ 1779DABB40E431F6140D7937 /* Pods-Runner.profile.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
+ 33BA886A226E78AF003329D5 /* Configs */ = {
+ isa = PBXGroup;
+ children = (
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
+ );
+ path = Configs;
+ sourceTree = "";
+ };
+ 33CC10E42044A3C60003C045 = {
+ isa = PBXGroup;
+ children = (
+ 33FAB671232836740065AC1E /* Runner */,
+ 33CEB47122A05771004F2AC0 /* Flutter */,
+ 33CC10EE2044A3C60003C045 /* Products */,
+ D73912EC22F37F3D000D13A0 /* Frameworks */,
+ 1C79AB84644B94FC4355DDDB /* Pods */,
+ );
+ sourceTree = "";
+ };
+ 33CC10EE2044A3C60003C045 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10ED2044A3C60003C045 /* example.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 33CC11242044D66E0003C045 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */,
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */,
+ 33CC10F72044A3C60003C045 /* Info.plist */,
+ );
+ name = Resources;
+ path = ..;
+ sourceTree = "";
+ };
+ 33CEB47122A05771004F2AC0 /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
+ );
+ path = Flutter;
+ sourceTree = "";
+ };
+ 33FAB671232836740065AC1E /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */,
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */,
+ 33E51914231749380026EE4D /* Release.entitlements */,
+ 33CC11242044D66E0003C045 /* Resources */,
+ 33BA886A226E78AF003329D5 /* Configs */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ D73912EC22F37F3D000D13A0 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ BE8B6589603437F8EF35345E /* Pods_Runner.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 33CC10EC2044A3C60003C045 /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ A2B5BA26A8ECD333A76C446C /* [CP] Check Pods Manifest.lock */,
+ 33CC10E92044A3C60003C045 /* Sources */,
+ 33CC10EA2044A3C60003C045 /* Frameworks */,
+ 33CC10EB2044A3C60003C045 /* Resources */,
+ 33CC110E2044A8840003C045 /* Bundle Framework */,
+ 3399D490228B24CF009A79C7 /* ShellScript */,
+ 9B0D0C0196D50B117C72597B /* [CP] Embed Pods Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */,
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 33CC10ED2044A3C60003C045 /* example.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 33CC10E52044A3C60003C045 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0920;
+ LastUpgradeCheck = 0930;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 33CC10EC2044A3C60003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ LastSwiftMigration = 1100;
+ ProvisioningStyle = Automatic;
+ SystemCapabilities = {
+ com.apple.Sandbox = {
+ enabled = 1;
+ };
+ };
+ };
+ 33CC111A2044C6BA0003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Manual;
+ };
+ };
+ };
+ buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 33CC10E42044A3C60003C045;
+ productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 33CC10EC2044A3C60003C045 /* Runner */,
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 33CC10EB2044A3C60003C045 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3399D490228B24CF009A79C7 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
+ };
+ 33CC111E2044C6BF0003C045 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ Flutter/ephemeral/FlutterInputs.xcfilelist,
+ );
+ inputPaths = (
+ Flutter/ephemeral/tripwire,
+ );
+ outputFileListPaths = (
+ Flutter/ephemeral/FlutterOutputs.xcfilelist,
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
+ };
+ 9B0D0C0196D50B117C72597B /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ A2B5BA26A8ECD333A76C446C /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ 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;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 33CC10E92044A3C60003C045 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
+ targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 33CC10F52044A3C60003C045 /* Base */,
+ );
+ name = MainMenu.xib;
+ path = Runner;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 338D0CE9231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ 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_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ 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_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Profile;
+ };
+ 338D0CEA231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Profile;
+ };
+ 338D0CEB231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Profile;
+ };
+ 33CC10F92044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ 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_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ 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_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ 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_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 33CC10FA2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ 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_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ 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_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Release;
+ };
+ 33CC10FC2044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ 33CC10FD2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+ 33CC111C2044C6BA0003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 33CC111D2044C6BA0003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10F92044A3C60003C045 /* Debug */,
+ 33CC10FA2044A3C60003C045 /* Release */,
+ 338D0CE9231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10FC2044A3C60003C045 /* Debug */,
+ 33CC10FD2044A3C60003C045 /* Release */,
+ 338D0CEA231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC111C2044C6BA0003C045 /* Debug */,
+ 33CC111D2044C6BA0003C045 /* Release */,
+ 338D0CEB231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 33CC10E52044A3C60003C045 /* Project object */;
+}
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/firebase_installations/firebase_installations/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000000..18d981003d68
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_installations/firebase_installations/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 000000000000..ae8ff59d97b3
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/firebase_installations/firebase_installations/example/macos/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 000000000000..21a3cc14c74e
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/firebase_installations/firebase_installations/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000000..18d981003d68
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/AppDelegate.swift b/packages/firebase_installations/firebase_installations/example/macos/Runner/AppDelegate.swift
new file mode 100644
index 000000000000..d53ef6437726
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/AppDelegate.swift
@@ -0,0 +1,9 @@
+import Cocoa
+import FlutterMacOS
+
+@NSApplicationMain
+class AppDelegate: FlutterAppDelegate {
+ override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
+ return true
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 000000000000..a2ec33f19f11
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+ "images" : [
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_16.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_64.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_128.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_1024.png",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
new file mode 100644
index 000000000000..3c4935a7ca84
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
new file mode 100644
index 000000000000..ed4cc1642168
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
new file mode 100644
index 000000000000..483be6138973
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
new file mode 100644
index 000000000000..bcbf36df2f2a
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
new file mode 100644
index 000000000000..9c0a65286476
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
new file mode 100644
index 000000000000..e71a726136a4
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
new file mode 100644
index 000000000000..8a31fe2dd3f9
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Base.lproj/MainMenu.xib b/packages/firebase_installations/firebase_installations/example/macos/Runner/Base.lproj/MainMenu.xib
new file mode 100644
index 000000000000..537341abf994
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/Base.lproj/MainMenu.xib
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/AppInfo.xcconfig b/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/AppInfo.xcconfig
new file mode 100644
index 000000000000..cf9be60ca471
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/AppInfo.xcconfig
@@ -0,0 +1,14 @@
+// Application-level settings for the Runner target.
+//
+// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
+// future. If not, the values below would default to using the project name when this becomes a
+// 'flutter create' template.
+
+// The application's name. By default this is also the title of the Flutter window.
+PRODUCT_NAME = example
+
+// The application's bundle identifier
+PRODUCT_BUNDLE_IDENTIFIER = com.example.example
+
+// The copyright displayed in application information
+PRODUCT_COPYRIGHT = Copyright © 2021 com.example. All rights reserved.
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/Debug.xcconfig b/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/Debug.xcconfig
new file mode 100644
index 000000000000..36b0fd9464f4
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Debug.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/Release.xcconfig b/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/Release.xcconfig
new file mode 100644
index 000000000000..dff4f49561c8
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/Release.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Release.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/Warnings.xcconfig b/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/Warnings.xcconfig
new file mode 100644
index 000000000000..42bcbf4780b1
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/Configs/Warnings.xcconfig
@@ -0,0 +1,13 @@
+WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
+GCC_WARN_UNDECLARED_SELECTOR = YES
+CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
+CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
+CLANG_WARN_PRAGMA_PACK = YES
+CLANG_WARN_STRICT_PROTOTYPES = YES
+CLANG_WARN_COMMA = YES
+GCC_WARN_STRICT_SELECTOR_MATCH = YES
+CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
+CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
+GCC_WARN_SHADOW = YES
+CLANG_WARN_UNREACHABLE_CODE = YES
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/DebugProfile.entitlements b/packages/firebase_installations/firebase_installations/example/macos/Runner/DebugProfile.entitlements
new file mode 100644
index 000000000000..3ba6c1266f21
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/DebugProfile.entitlements
@@ -0,0 +1,14 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.network.client
+
+ com.apple.security.network.server
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Info.plist b/packages/firebase_installations/firebase_installations/example/macos/Runner/Info.plist
new file mode 100644
index 000000000000..4789daa6a443
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ $(PRODUCT_COPYRIGHT)
+ NSMainNibFile
+ MainMenu
+ NSPrincipalClass
+ NSApplication
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/MainFlutterWindow.swift b/packages/firebase_installations/firebase_installations/example/macos/Runner/MainFlutterWindow.swift
new file mode 100644
index 000000000000..2722837ec918
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/MainFlutterWindow.swift
@@ -0,0 +1,15 @@
+import Cocoa
+import FlutterMacOS
+
+class MainFlutterWindow: NSWindow {
+ override func awakeFromNib() {
+ let flutterViewController = FlutterViewController.init()
+ let windowFrame = self.frame
+ self.contentViewController = flutterViewController
+ self.setFrame(windowFrame, display: true)
+
+ RegisterGeneratedPlugins(registry: flutterViewController)
+
+ super.awakeFromNib()
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/example/macos/Runner/Release.entitlements b/packages/firebase_installations/firebase_installations/example/macos/Runner/Release.entitlements
new file mode 100644
index 000000000000..852fa1a4728a
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/macos/Runner/Release.entitlements
@@ -0,0 +1,8 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+
+
diff --git a/packages/firebase_installations/firebase_installations/example/pubspec.yaml b/packages/firebase_installations/firebase_installations/example/pubspec.yaml
new file mode 100644
index 000000000000..805605bea706
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/pubspec.yaml
@@ -0,0 +1,91 @@
+name: firebase_installations_example
+description: A new Flutter project.
+
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+# 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.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# Read more about iOS versioning at
+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+version: 1.0.0+1
+
+environment:
+ sdk: '>=2.12.0 <3.0.0'
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+ firebase_core: ^1.10.0
+ flutterfire_installations:
+ path: ../
+ flutter:
+ sdk: flutter
+
+dependency_overrides:
+ firebase_core:
+ path: ../../../firebase_core/firebase_core
+ firebase_installations_web:
+ path: ../../firebase_installations_web
+ firebase_installations_platform_interface:
+ path: ../../firebase_installations_platform_interface
+
+dev_dependencies:
+ drive: ^1.0.0-1.0.nullsafety.1
+ flutter_driver:
+ sdk: flutter
+
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^1.0.0
+ test: any
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/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.dev/assets-and-images/#resolution-aware.
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/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.dev/custom-fonts/#from-packages
diff --git a/packages/firebase_installations/firebase_installations/example/test_driver/firebase_config.dart b/packages/firebase_installations/firebase_installations/example/test_driver/firebase_config.dart
new file mode 100644
index 000000000000..79c0f4c5147c
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/test_driver/firebase_config.dart
@@ -0,0 +1,47 @@
+import 'dart:io';
+
+import 'package:firebase_core/firebase_core.dart';
+import 'package:flutter/foundation.dart';
+
+class TestFirebaseConfig {
+ static FirebaseOptions get platformOptions {
+ if (kIsWeb) {
+ // Web
+ return const FirebaseOptions(
+ apiKey: 'AIzaSyAgUhHU8wSJgO5MVNy95tMT07NEjzMOfz0',
+ authDomain: 'react-native-firebase-testing.firebaseapp.com',
+ databaseURL: 'https://react-native-firebase-testing.firebaseio.com',
+ projectId: 'react-native-firebase-testing',
+ storageBucket: 'react-native-firebase-testing.appspot.com',
+ messagingSenderId: '448618578101',
+ appId: '1:448618578101:web:0b650370bb29e29cac3efc',
+ measurementId: 'G-F79DJ0VFGS',
+ );
+ } else if (Platform.isIOS || Platform.isMacOS) {
+ // iOS and MacOS
+ return const FirebaseOptions(
+ appId: '1:448618578101:ios:f7208957983eeee4ac3efc',
+ apiKey: 'AIzaSyAHAsf51D0A407EklG1bs-5wA7EbyfNFg0',
+ projectId: 'react-native-firebase-testing',
+ messagingSenderId: '448618578101',
+ iosBundleId: 'io.flutter.plugins.firebase.installations.example',
+ iosClientId:
+ '448618578101-ff6olegpc8901mthfv42r97oo0gbqebc.apps.googleusercontent.com',
+ androidClientId:
+ '448618578101-a9p7bj5jlakabp22fo3cbkj7nsmag24e.apps.googleusercontent.com',
+ databaseURL: 'https://react-native-firebase-testing.firebaseio.com',
+ storageBucket: 'react-native-firebase-testing.appspot.com',
+ );
+ } else {
+ // Android
+ return const FirebaseOptions(
+ appId: '1:448618578101:android:a723be2eb2bf60d9ac3efc',
+ apiKey: 'AIzaSyCuu4tbv9CwwTudNOweMNstzZHIDBhgJxA',
+ projectId: 'react-native-firebase-testing',
+ messagingSenderId: '448618578101',
+ databaseURL: 'https://react-native-firebase-testing.firebaseio.com',
+ storageBucket: 'react-native-firebase-testing.appspot.com',
+ );
+ }
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/example/test_driver/flutterfire_installations_e2e.dart b/packages/firebase_installations/firebase_installations/example/test_driver/flutterfire_installations_e2e.dart
new file mode 100644
index 000000000000..bb98192407b1
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/test_driver/flutterfire_installations_e2e.dart
@@ -0,0 +1,46 @@
+// Copyright 2020, the Chromium project authors. Please see the AUTHORS file
+// for details. 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:drive/drive.dart' as drive;
+import 'package:firebase_core/firebase_core.dart';
+import 'package:flutterfire_installations/flutterfire_installations.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'firebase_config.dart';
+
+void testsMain() {
+ late FirebaseInstallations installations;
+
+ setUpAll(() async {
+ await Firebase.initializeApp(options: TestFirebaseConfig.platformOptions);
+ installations = FirebaseInstallations.instance;
+ });
+
+ group('Installations ', () {
+ test('.getId', () async {
+ final id = await installations.getId();
+ expect(id, isNotEmpty);
+ });
+ test('.delete', () async {
+ final id = await installations.getId();
+
+ // Wait a little so we don't get a delete-pending exception
+ await Future.delayed(const Duration(seconds: 8));
+
+ await installations.delete();
+
+ // Wait a little so we don't get a delete-pending exception
+ await Future.delayed(const Duration(seconds: 8));
+
+ final newId = await installations.getId();
+ expect(newId, isNot(equals(id)));
+ });
+ test('.getToken', () async {
+ final token = await installations.getId();
+ expect(token, isNotEmpty);
+ });
+ });
+}
+
+void main() => drive.main(testsMain);
diff --git a/packages/firebase_installations/firebase_installations/example/test_driver/flutterfire_installations_e2e_test.dart b/packages/firebase_installations/firebase_installations/example/test_driver/flutterfire_installations_e2e_test.dart
new file mode 100644
index 000000000000..9940272d4af6
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/test_driver/flutterfire_installations_e2e_test.dart
@@ -0,0 +1,3 @@
+import 'package:drive/drive_driver.dart' as drive;
+
+void main() => drive.main();
diff --git a/packages/firebase_installations/firebase_installations/example/web/favicon.png b/packages/firebase_installations/firebase_installations/example/web/favicon.png
new file mode 100644
index 000000000000..8aaa46ac1ae2
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/web/favicon.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/web/icons/Icon-192.png b/packages/firebase_installations/firebase_installations/example/web/icons/Icon-192.png
new file mode 100644
index 000000000000..b749bfef0747
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/web/icons/Icon-192.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/web/icons/Icon-512.png b/packages/firebase_installations/firebase_installations/example/web/icons/Icon-512.png
new file mode 100644
index 000000000000..88cfd48dff11
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/web/icons/Icon-512.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/web/icons/Icon-maskable-192.png b/packages/firebase_installations/firebase_installations/example/web/icons/Icon-maskable-192.png
new file mode 100644
index 000000000000..eb9b4d76e525
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/web/icons/Icon-maskable-192.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/web/icons/Icon-maskable-512.png b/packages/firebase_installations/firebase_installations/example/web/icons/Icon-maskable-512.png
new file mode 100644
index 000000000000..d69c56691fbd
Binary files /dev/null and b/packages/firebase_installations/firebase_installations/example/web/icons/Icon-maskable-512.png differ
diff --git a/packages/firebase_installations/firebase_installations/example/web/index.html b/packages/firebase_installations/firebase_installations/example/web/index.html
new file mode 100644
index 000000000000..27adaa918413
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/web/index.html
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ example
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations/example/web/manifest.json b/packages/firebase_installations/firebase_installations/example/web/manifest.json
new file mode 100644
index 000000000000..096edf8fe4cd
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/example/web/manifest.json
@@ -0,0 +1,35 @@
+{
+ "name": "example",
+ "short_name": "example",
+ "start_url": ".",
+ "display": "standalone",
+ "background_color": "#0175C2",
+ "theme_color": "#0175C2",
+ "description": "A new Flutter project.",
+ "orientation": "portrait-primary",
+ "prefer_related_applications": false,
+ "icons": [
+ {
+ "src": "icons/Icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-maskable-192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "maskable"
+ },
+ {
+ "src": "icons/Icon-maskable-512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "maskable"
+ }
+ ]
+}
diff --git a/packages/firebase_installations/firebase_installations/ios/.gitignore b/packages/firebase_installations/firebase_installations/ios/.gitignore
new file mode 100644
index 000000000000..0c885071e36b
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/ios/.gitignore
@@ -0,0 +1,38 @@
+.idea/
+.vagrant/
+.sconsign.dblite
+.svn/
+
+.DS_Store
+*.swp
+profile
+
+DerivedData/
+build/
+GeneratedPluginRegistrant.h
+GeneratedPluginRegistrant.m
+
+.generated/
+
+*.pbxuser
+*.mode1v3
+*.mode2v3
+*.perspectivev3
+
+!default.pbxuser
+!default.mode1v3
+!default.mode2v3
+!default.perspectivev3
+
+xcuserdata
+
+*.moved-aside
+
+*.pyc
+*sync/
+Icon?
+.tags*
+
+/Flutter/Generated.xcconfig
+/Flutter/ephemeral/
+/Flutter/flutter_export_environment.sh
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations/ios/Assets/.gitkeep b/packages/firebase_installations/firebase_installations/ios/Assets/.gitkeep
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/packages/firebase_installations/firebase_installations/ios/Classes/FirebaseInstallationsPlugin.h b/packages/firebase_installations/firebase_installations/ios/Classes/FirebaseInstallationsPlugin.h
new file mode 100644
index 000000000000..a907f47bee53
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/ios/Classes/FirebaseInstallationsPlugin.h
@@ -0,0 +1,16 @@
+// Copyright 2021 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
+
+#if TARGET_OS_OSX
+#import
+#else
+#import
+#endif
+
+#import
+
+@interface FirebaseInstallationsPlugin : FLTFirebasePlugin
+@end
diff --git a/packages/firebase_installations/firebase_installations/ios/Classes/FirebaseInstallationsPlugin.m b/packages/firebase_installations/firebase_installations/ios/Classes/FirebaseInstallationsPlugin.m
new file mode 100644
index 000000000000..a701b6acbc50
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/ios/Classes/FirebaseInstallationsPlugin.m
@@ -0,0 +1,40 @@
+// Copyright 2021 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 "FirebaseInstallationsPlugin.h"
+#if __has_include()
+#import
+#else
+// Support project import fallback if the generated compatibility header
+// is not copied when this plugin is created as a library.
+// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
+#import "flutterfire_installations-Swift.h"
+#endif
+
+@implementation FirebaseInstallationsPlugin
++ (void)registerWithRegistrar:(NSObject*)registrar {
+ [FirebaseInstallationsPluginSwift registerWithRegistrar:registrar];
+}
+
+- (void)didReinitializeFirebaseCore:(void (^_Nonnull)(void))completion {
+ completion();
+}
+
+- (NSString* _Nonnull)firebaseLibraryName {
+ return LIBRARY_NAME;
+}
+
+- (NSString* _Nonnull)firebaseLibraryVersion {
+ return LIBRARY_VERSION;
+}
+
+- (NSString* _Nonnull)flutterChannelName {
+ return @"plugins.flutter.io/firebase_installations";
+}
+
+- (NSDictionary* _Nonnull)pluginConstantsForFIRApp:(FIRApp* _Nonnull)firebaseApp {
+ return @{};
+}
+
+@end
diff --git a/packages/firebase_installations/firebase_installations/ios/Classes/FirebaseInstallationsPlugin.swift b/packages/firebase_installations/firebase_installations/ios/Classes/FirebaseInstallationsPlugin.swift
new file mode 100644
index 000000000000..a4338e4ba9a7
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/ios/Classes/FirebaseInstallationsPlugin.swift
@@ -0,0 +1,161 @@
+// Copyright 2021 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.
+
+#if canImport(FlutterMacOS)
+ import FlutterMacOS
+#else
+ import Flutter
+#endif
+
+import firebase_core
+import FirebaseInstallations
+
+let kFLTFirebaseInstallationsChannelName = "plugins.flutter.io/firebase_installations"
+
+public class FirebaseInstallationsPluginSwift: FLTFirebasePlugin, FlutterPlugin {
+ private var eventSink: FlutterEventSink?
+ private var messenger: FlutterBinaryMessenger
+
+ var result: FLTFirebaseMethodCallResult?
+ var streamHandler = [String: IdChangedStreamHandler?]()
+
+ var args = NSDictionary()
+
+ init(messenger: FlutterBinaryMessenger) {
+ self.messenger = messenger
+ }
+
+ public static func register(with registrar: FlutterPluginRegistrar) {
+ let binaryMessenger: FlutterBinaryMessenger
+
+ #if os(macOS)
+ binaryMessenger = registrar.messenger
+ #elseif os(iOS)
+ binaryMessenger = registrar.messenger()
+ #endif
+
+ let channel = FlutterMethodChannel(name: kFLTFirebaseInstallationsChannelName, binaryMessenger: binaryMessenger)
+ let instance = FirebaseInstallationsPluginSwift(messenger: binaryMessenger)
+ registrar.addMethodCallDelegate(instance, channel: channel)
+ }
+
+ /// Gets Installations instance for a Firebase App.
+ /// - Returns: a Firebase Installations instance for the passed app from Dart
+ internal func getInstallations() -> Installations {
+ let app: FirebaseApp = FLTFirebasePlugin.firebaseAppNamed(args["appName"] as! String)!
+ return Installations.installations(app: app)
+ }
+
+ /// Gets Installations Id for an instance.
+ /// - Parameter arguments: the arguments passed by the Dart calling method
+ /// - Parameter result: the result instance used to send the result to Dart.
+ internal func getId() {
+ let instance: Installations = getInstallations()
+ instance.installationID { (id: String?, error: Error?) in
+ if error != nil {
+ self.result!.error(nil, nil, nil, error)
+ } else {
+ self.result!.success(id)
+ }
+ }
+ }
+
+ /// Deletes Installations Id for an instance.
+ internal func deleteId() {
+ let instance: Installations = getInstallations()
+ instance.delete { (error: Error?) in
+ if error != nil {
+ self.result!.error(nil, nil, nil, error)
+ } else {
+ self.result!.success(nil)
+ }
+ }
+ }
+
+ /// Gets the token Id for an instance.
+ internal func getToken() {
+ let instance: Installations = getInstallations()
+ let forceRefresh: Bool = (args["forceRefresh"] as? Bool) ?? false
+
+ instance.authTokenForcingRefresh(forceRefresh, completion: { (tokenResult: InstallationsAuthTokenResult?, error: Error?) in
+ if error != nil {
+ self.result!.error(nil, nil, nil, error)
+ } else {
+ self.result!.success(tokenResult?.authToken)
+ }
+ })
+ }
+
+ /// Starts listening to Installation ID events for an instance.
+ internal func registerIdChangeListener() {
+ let instance: Installations = getInstallations()
+
+ let appName = (args["appName"] as! String)
+ let eventChannelName: String = kFLTFirebaseInstallationsChannelName + "/token/" + appName
+
+ let eventChannel = FlutterEventChannel(name: eventChannelName, binaryMessenger: messenger)
+
+ if streamHandler[eventChannelName] == nil {
+ streamHandler[eventChannelName] = IdChangedStreamHandler(instance: instance)
+ }
+
+ eventChannel.setStreamHandler(streamHandler[eventChannelName]!)
+
+ result?.success(eventChannelName)
+ }
+
+ internal func mapInstallationsErrorCodes(code: UInt) -> NSString {
+ let error = InstallationsErrorCode(rawValue: code) ?? InstallationsErrorCode.unknown
+
+ switch error {
+ case InstallationsErrorCode.invalidConfiguration:
+ return "invalid-configuration"
+ case InstallationsErrorCode.keychain:
+ return "invalid-keychain"
+ case InstallationsErrorCode.serverUnreachable:
+ return "server-unreachable"
+ case InstallationsErrorCode.unknown:
+ return "unknown"
+ default:
+ return "unknown"
+ }
+ }
+
+ public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
+ let args = call.arguments as! NSDictionary
+
+ let errorBlock: FLTFirebaseMethodCallErrorBlock = { (code, message, details, error: Error?) in
+ var errorDetails = [String: Any?]()
+
+ errorDetails["code"] = code ?? self.mapInstallationsErrorCodes(code: UInt((error! as NSError).code))
+ errorDetails["message"] = message ?? error?.localizedDescription ?? "An unknown error has occurred."
+ errorDetails["additionalData"] = details
+
+ if code == "unknown" {
+ NSLog("FLTFirebaseInstallations: An error occurred while calling method %@", call.method)
+ }
+
+ result(FLTFirebasePlugin.createFlutterError(fromCode: errorDetails["code"] as! String,
+ message: errorDetails["message"] as! String,
+ optionalDetails: errorDetails["additionalData"] as? [AnyHashable: Any],
+ andOptionalNSError: error))
+ }
+
+ self.result = .create(success: result, andErrorBlock: errorBlock)
+ self.args = args
+
+ switch call.method {
+ case "FirebaseInstallations#getId":
+ getId()
+ case "FirebaseInstallations#delete":
+ deleteId()
+ case "FirebaseInstallations#getToken":
+ getToken()
+ case "FirebaseInstallations#registerIdChangeListener":
+ registerIdChangeListener()
+ default:
+ result(FlutterMethodNotImplemented)
+ }
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/ios/Classes/IdChangedStreamHandler.swift b/packages/firebase_installations/firebase_installations/ios/Classes/IdChangedStreamHandler.swift
new file mode 100644
index 000000000000..e20f95685d86
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/ios/Classes/IdChangedStreamHandler.swift
@@ -0,0 +1,53 @@
+// Copyright 2021 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.
+
+#if canImport(FlutterMacOS)
+ import FlutterMacOS
+#else
+ import Flutter
+#endif
+
+import FirebaseInstallations
+import Foundation
+
+class IdChangedStreamHandler: NSObject, FlutterStreamHandler {
+ var eventSink: FlutterEventSink?
+ var installationIDObserver: NSObjectProtocol?
+ var instance: Installations
+ var installationsId: String = ""
+
+ init(instance: Installations) {
+ self.instance = instance
+ }
+
+ internal func handleIdChange() {
+ var events = [String: String]()
+ instance.installationID { (newId: String?, error: Error?) in
+ if error != nil {
+ self.eventSink!(FlutterError.init(code: "unknown", message: error?.localizedDescription, details: ["code": "unknown", "message": error?.localizedDescription]))
+ } else if newId != self.installationsId {
+ self.installationsId = newId!
+ events["token"] = self.installationsId
+ self.eventSink!(events)
+ }
+ }
+ }
+
+ public func onListen(withArguments _: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
+ eventSink = events
+ installationIDObserver = NotificationCenter.default.addObserver(
+ forName: .InstallationIDDidChange,
+ object: nil,
+ queue: nil
+ ) { _ in
+ self.handleIdChange()
+ }
+ return nil
+ }
+
+ public func onCancel(withArguments _: Any?) -> FlutterError? {
+ eventSink = nil
+ return nil
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/ios/flutterfire_installations.podspec b/packages/firebase_installations/firebase_installations/ios/flutterfire_installations.podspec
new file mode 100644
index 000000000000..6df0a00e1e1b
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/ios/flutterfire_installations.podspec
@@ -0,0 +1,43 @@
+require 'yaml'
+
+pubspec = YAML.load_file(File.join('..', 'pubspec.yaml'))
+library_version = pubspec['version'].gsub('+', '-')
+
+if defined?($FirebaseSDKVersion)
+ Pod::UI.puts "#{pubspec['name']}: Using user specified Firebase SDK version '#{$FirebaseSDKVersion}'"
+ firebase_sdk_version = $FirebaseSDKVersion
+else
+ firebase_core_script = File.join(File.expand_path('..', File.expand_path('..', File.dirname(__FILE__))), 'firebase_core/ios/firebase_sdk_version.rb')
+ if File.exist?(firebase_core_script)
+ require firebase_core_script
+ firebase_sdk_version = firebase_sdk_version!
+ Pod::UI.puts "#{pubspec['name']}: Using Firebase SDK version '#{firebase_sdk_version}' defined in 'firebase_core'"
+ end
+end
+
+Pod::Spec.new do |s|
+ s.name = pubspec['name']
+ s.version = library_version
+ s.summary = pubspec['description']
+ s.description = pubspec['description']
+ s.homepage = pubspec['homepage']
+ s.license = { :file => '../LICENSE' }
+ s.authors = 'The Chromium Authors'
+ s.source = { :path => '.' }
+ s.source_files = 'Classes/**/*'
+ s.public_header_files = 'Classes/**/*.h'
+
+ s.ios.deployment_target = '10.0'
+
+ s.swift_version = '5.5'
+
+ s.dependency 'Flutter'
+ s.dependency 'firebase_core'
+ s.dependency 'Firebase/Installations', firebase_sdk_version
+
+ s.static_framework = true
+ s.pod_target_xcconfig = {
+ 'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\@\\\"#{library_version}\\\" LIBRARY_NAME=\\@\\\"flutter-fire-installations\\\"",
+ 'DEFINES_MODULE' => 'YES'
+ }
+end
diff --git a/packages/firebase_installations/firebase_installations/lib/flutterfire_installations.dart b/packages/firebase_installations/firebase_installations/lib/flutterfire_installations.dart
new file mode 100644
index 000000000000..456ea64ec417
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/lib/flutterfire_installations.dart
@@ -0,0 +1,12 @@
+// Copyright 2021, the Chromium project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library flutterfire_installations;
+
+import 'package:firebase_core/firebase_core.dart';
+import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'
+ show FirebasePluginPlatform;
+import 'package:firebase_installations_platform_interface/firebase_installations_platform_interface.dart';
+
+part 'src/flutterfire_installations.dart';
diff --git a/packages/firebase_installations/firebase_installations/lib/src/flutterfire_installations.dart b/packages/firebase_installations/firebase_installations/lib/src/flutterfire_installations.dart
new file mode 100644
index 000000000000..3fbc142f23a4
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/lib/src/flutterfire_installations.dart
@@ -0,0 +1,62 @@
+// Copyright 2021 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 flutterfire_installations;
+
+class FirebaseInstallations extends FirebasePluginPlatform {
+ FirebaseInstallations._({required this.app})
+ : super(app.name, 'plugins.flutter.io/firebase_installations');
+
+ // Cached and lazily loaded instance of [FirebaseInstallationsPlatform] to avoid
+ // creating a [MethodChannelFirebaseInstallations] when not needed or creating an
+ // instance with the default app before a user specifies an app.
+ FirebaseInstallationsPlatform? _delegatePackingProperty;
+
+ /// Returns the underlying [FirebaseFunctionsPlatform] delegate for this
+ /// [FirebaseFunctions] instance. This is useful for testing purposes only.
+ FirebaseInstallationsPlatform get _delegate {
+ return _delegatePackingProperty ??=
+ FirebaseInstallationsPlatform.instanceFor(app: app);
+ }
+
+ /// The [FirebaseApp] for this current [FirebaseInstallations] instance.
+ final FirebaseApp app;
+
+ static final Map _cachedInstances = {};
+
+ /// Returns an instance using the default [FirebaseApp] and region.
+ static FirebaseInstallations get instance {
+ return FirebaseInstallations.instanceFor(
+ app: Firebase.app(),
+ );
+ }
+
+ /// Returns an instance using a specified [FirebaseApp].
+ static FirebaseInstallations instanceFor({required FirebaseApp app}) {
+ return _cachedInstances.putIfAbsent(app.name, () {
+ return FirebaseInstallations._(app: app);
+ });
+ }
+
+ /// Deletes the Firebase Installation and all associated data.
+ Future delete() {
+ return _delegate.delete();
+ }
+
+ /// Creates a Firebase Installation if there isn't one for the app and
+ /// returns the Installation ID.
+ Future getId() {
+ return _delegate.getId();
+ }
+
+ /// Returns an Authentication Token for the current Firebase Installation.
+ Future getToken([bool forceRefresh = false]) {
+ return _delegate.getToken(forceRefresh);
+ }
+
+ /// Sends a new event via a [Stream] whenever the Installation ID changes.
+ Stream get onIdChange {
+ return _delegate.onIdChange;
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations/macos/Classes/FirebaseInstallationsPlugin.h b/packages/firebase_installations/firebase_installations/macos/Classes/FirebaseInstallationsPlugin.h
new file mode 120000
index 000000000000..cf1e960c6ebf
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/macos/Classes/FirebaseInstallationsPlugin.h
@@ -0,0 +1 @@
+../../ios/Classes/FirebaseInstallationsPlugin.h
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations/macos/Classes/FirebaseInstallationsPlugin.m b/packages/firebase_installations/firebase_installations/macos/Classes/FirebaseInstallationsPlugin.m
new file mode 120000
index 000000000000..f671f2938a28
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/macos/Classes/FirebaseInstallationsPlugin.m
@@ -0,0 +1 @@
+../../ios/Classes/FirebaseInstallationsPlugin.m
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations/macos/Classes/FirebaseInstallationsPlugin.swift b/packages/firebase_installations/firebase_installations/macos/Classes/FirebaseInstallationsPlugin.swift
new file mode 120000
index 000000000000..c65783793f21
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/macos/Classes/FirebaseInstallationsPlugin.swift
@@ -0,0 +1 @@
+../../ios/Classes/FirebaseInstallationsPlugin.swift
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations/macos/Classes/IdChangedStreamHandler.swift b/packages/firebase_installations/firebase_installations/macos/Classes/IdChangedStreamHandler.swift
new file mode 120000
index 000000000000..b9d22007e609
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/macos/Classes/IdChangedStreamHandler.swift
@@ -0,0 +1 @@
+../../ios/Classes/IdChangedStreamHandler.swift
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations/macos/flutterfire_installations.podspec b/packages/firebase_installations/firebase_installations/macos/flutterfire_installations.podspec
new file mode 100644
index 000000000000..bd7272bb3211
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/macos/flutterfire_installations.podspec
@@ -0,0 +1,62 @@
+require 'yaml'
+
+pubspec = YAML.load_file(File.join('..', 'pubspec.yaml'))
+library_version = pubspec['version'].gsub('+', '-')
+
+if defined?($FirebaseSDKVersion)
+ Pod::UI.puts "#{pubspec['name']}: Using user specified Firebase SDK version '#{$FirebaseSDKVersion}'"
+ firebase_sdk_version = $FirebaseSDKVersion
+else
+ firebase_core_script = File.join(File.expand_path('..', File.expand_path('..', File.dirname(__FILE__))), 'firebase_core/ios/firebase_sdk_version.rb')
+ if File.exist?(firebase_core_script)
+ require firebase_core_script
+ firebase_sdk_version = firebase_sdk_version!
+ Pod::UI.puts "#{pubspec['name']}: Using Firebase SDK version '#{firebase_sdk_version}' defined in 'firebase_core'"
+ end
+end
+
+begin
+ required_macos_version = "10.12"
+ current_target_definition = Pod::Config.instance.podfile.send(:current_target_definition)
+ user_osx_target = current_target_definition.to_hash["platform"]["osx"]
+ if (Gem::Version.new(user_osx_target) < Gem::Version.new(required_macos_version))
+ error_message = "The FlutterFire plugin #{pubspec['name']} for macOS requires a macOS deployment target of #{required_macos_version} or later."
+ Pod::UI.warn error_message, [
+ "Update the `platform :osx, '#{user_osx_target}'` line in your macOS/Podfile to version `#{required_macos_version}` and ensure you commit this file.",
+ "Open your `macos/Runner.xcodeproj` Xcode project and under the 'Runner' target General tab set your Deployment Target to #{required_macos_version} or later."
+ ]
+ raise Pod::Informative, error_message
+ end
+rescue Pod::Informative
+ raise
+rescue
+ # Do nothing for all other errors and let `pod install` deal with any issues.
+end
+
+Pod::Spec.new do |s|
+ s.name = pubspec['name']
+ s.version = library_version
+ s.summary = pubspec['description']
+ s.description = pubspec['description']
+ s.homepage = pubspec['homepage']
+ s.license = { :file => '../LICENSE' }
+ s.authors = 'The Chromium Authors'
+ s.source = { :path => '.' }
+ s.source_files = 'Classes/**/*'
+
+ s.platform = :osx, '10.12'
+
+ # Flutter dependencies
+ s.dependency 'FlutterMacOS'
+ s.dependency 'firebase_core'
+
+ # Firebase dependencies
+ s.dependency 'Firebase/CoreOnly', "~> #{firebase_sdk_version}"
+ s.dependency 'Firebase/Installations', "~> #{firebase_sdk_version}"
+
+ s.static_framework = true
+ s.pod_target_xcconfig = {
+ 'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\@\\\"#{library_version}\\\" LIBRARY_NAME=\\@\\\"flutter-fire-installations\\\"",
+ 'DEFINES_MODULE' => 'YES'
+ }
+end
diff --git a/packages/firebase_installations/firebase_installations/pubspec.yaml b/packages/firebase_installations/firebase_installations/pubspec.yaml
new file mode 100644
index 000000000000..1af5fc2f994e
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/pubspec.yaml
@@ -0,0 +1,38 @@
+# FlutterFire_X naming due to package being take already on Pub.dev.
+name: flutterfire_installations
+description: A Flutter plugin allowing you to use Firebase Installations.
+version: 0.1.0
+homepage: https://firebase.flutter.dev/docs/installations/overview
+repository: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_installations/firebase_installations
+
+environment:
+ sdk: ">=2.12.0 <3.0.0"
+ flutter: ">=1.20.0"
+
+dependencies:
+ firebase_core: ^1.10.0
+ firebase_core_platform_interface: ^4.1.0
+ firebase_installations_platform_interface: ^0.1.0
+ firebase_installations_web: ^0.1.0
+ flutter:
+ sdk: flutter
+
+dev_dependencies:
+ flutter_driver:
+ sdk: flutter
+ flutter_test:
+ sdk: flutter
+ mockito: ^5.0.16
+ plugin_platform_interface: ^2.0.0
+ test: any
+
+flutter:
+ plugin:
+ platforms:
+ android:
+ package: io.flutter.plugins.firebase.installations.firebase_installations
+ pluginClass: FirebaseInstallationsPlugin
+ ios:
+ pluginClass: FirebaseInstallationsPlugin
+ macos:
+ pluginClass: FirebaseInstallationsPlugin
diff --git a/packages/firebase_installations/firebase_installations/test/firebase_installations_test.dart b/packages/firebase_installations/firebase_installations/test/firebase_installations_test.dart
new file mode 100644
index 000000000000..6893112283e5
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations/test/firebase_installations_test.dart
@@ -0,0 +1,136 @@
+// ignore_for_file: require_trailing_commas
+// Copyright 2019 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_core/firebase_core.dart';
+import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart';
+import 'package:flutterfire_installations/flutterfire_installations.dart';
+import 'package:firebase_installations_platform_interface/firebase_installations_platform_interface.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mockito/mockito.dart';
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
+
+typedef Callback = Function(MethodCall call);
+final mockInstallations = MockFirebaseInstallations();
+
+void main() {
+ setupFirebaseInstallationsMocks();
+
+ late FirebaseInstallations installations;
+ FirebaseInstallationsPlatform.instance = mockInstallations;
+ group('$FirebaseInstallations', () {
+ setUpAll(() async {
+ await Firebase.initializeApp();
+ installations = FirebaseInstallations.instance;
+ when(mockInstallations.delegateFor(
+ app: anyNamed('app'),
+ )).thenAnswer((_) => mockInstallations);
+ when(mockInstallations.getId()).thenAnswer(
+ (_) => Future.value('some-id'),
+ );
+ });
+
+ test('getId', () async {
+ await installations.getId();
+ verify(mockInstallations.getId());
+ });
+ test('getAuthToken', () async {
+ await installations.getToken();
+ verify(mockInstallations.getToken());
+ });
+ test('delete', () async {
+ await installations.delete();
+ verify(mockInstallations.delete());
+ });
+ });
+}
+
+void setupFirebaseInstallationsMocks([Callback? customHandlers]) {
+ TestWidgetsFlutterBinding.ensureInitialized();
+
+ MethodChannelFirebase.channel.setMockMethodCallHandler((call) async {
+ if (call.method == 'Firebase#initializeCore') {
+ return [
+ {
+ 'name': defaultFirebaseAppName,
+ 'options': {
+ 'apiKey': '123',
+ 'appId': '123',
+ 'messagingSenderId': '123',
+ 'projectId': '123',
+ },
+ 'pluginConstants': {},
+ }
+ ];
+ }
+
+ if (call.method == 'Firebase#initializeApp') {
+ return {
+ 'name': call.arguments['appName'],
+ 'options': call.arguments['options'],
+ 'pluginConstants': {},
+ };
+ }
+
+ if (customHandlers != null) {
+ customHandlers(call);
+ }
+
+ return null;
+ });
+}
+
+class MockFirebaseInstallations extends Mock
+ with
+ // ignore: prefer_mixin
+ MockPlatformInterfaceMixin
+ implements
+ TestFirebaseInstallationsPlatform {
+ @override
+ TestFirebaseInstallationsPlatform delegateFor({FirebaseApp? app}) {
+ return super.noSuchMethod(
+ Invocation.method(#delegateFor, [], {#app: app}),
+ returnValue: TestFirebaseInstallationsPlatform(app),
+ returnValueForMissingStub: TestFirebaseInstallationsPlatform(app),
+ );
+ }
+
+ @override
+ Future getId() {
+ return super.noSuchMethod(
+ Invocation.method(#getId, []),
+ returnValue: Future.value(''),
+ returnValueForMissingStub: Future.value(''),
+ );
+ }
+
+ @override
+ // ignore: type_annotate_public_apis
+ Future getToken([forceRefresh = false]) {
+ return super.noSuchMethod(
+ Invocation.method(#getToken, [forceRefresh]),
+ returnValue: Future.value(''),
+ returnValueForMissingStub: Future.value(''),
+ );
+ }
+
+ @override
+ Future delete() {
+ return super.noSuchMethod(
+ Invocation.method(#getId, []),
+ returnValue: Future.value(),
+ returnValueForMissingStub: Future.value(),
+ );
+ }
+}
+
+class TestFirebaseInstallationsPlatform extends FirebaseInstallationsPlatform {
+ TestFirebaseInstallationsPlatform(FirebaseApp? app) : super(app);
+
+ @override
+ TestFirebaseInstallationsPlatform delegateFor({FirebaseApp? app}) {
+ return this;
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/.gitignore b/packages/firebase_installations/firebase_installations_platform_interface/.gitignore
new file mode 100644
index 000000000000..a247422ef7c3
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/.gitignore
@@ -0,0 +1,75 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+build/
+
+# Android related
+**/android/**/gradle-wrapper.jar
+**/android/.gradle
+**/android/captures/
+**/android/gradlew
+**/android/gradlew.bat
+**/android/local.properties
+**/android/**/GeneratedPluginRegistrant.java
+
+# iOS/XCode related
+**/ios/**/*.mode1v3
+**/ios/**/*.mode2v3
+**/ios/**/*.moved-aside
+**/ios/**/*.pbxuser
+**/ios/**/*.perspectivev3
+**/ios/**/*sync/
+**/ios/**/.sconsign.dblite
+**/ios/**/.tags*
+**/ios/**/.vagrant/
+**/ios/**/DerivedData/
+**/ios/**/Icon?
+**/ios/**/Pods/
+**/ios/**/.symlinks/
+**/ios/**/profile
+**/ios/**/xcuserdata
+**/ios/.generated/
+**/ios/Flutter/App.framework
+**/ios/Flutter/Flutter.framework
+**/ios/Flutter/Flutter.podspec
+**/ios/Flutter/Generated.xcconfig
+**/ios/Flutter/ephemeral
+**/ios/Flutter/app.flx
+**/ios/Flutter/app.zip
+**/ios/Flutter/flutter_assets/
+**/ios/Flutter/flutter_export_environment.sh
+**/ios/ServiceDefinitions.json
+**/ios/Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!**/ios/**/default.mode1v3
+!**/ios/**/default.mode2v3
+!**/ios/**/default.pbxuser
+!**/ios/**/default.perspectivev3
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/.metadata b/packages/firebase_installations/firebase_installations_platform_interface/.metadata
new file mode 100644
index 000000000000..db56104b21ff
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/.metadata
@@ -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: package
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/CHANGELOG.md b/packages/firebase_installations/firebase_installations_platform_interface/CHANGELOG.md
new file mode 100644
index 000000000000..c9e662fb6d43
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.1.0
+
+ - Initial release of the Firebase Installations plugin.
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/LICENSE b/packages/firebase_installations/firebase_installations_platform_interface/LICENSE
new file mode 100644
index 000000000000..5b8717b87644
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/LICENSE
@@ -0,0 +1,27 @@
+// Copyright 2021 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.
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/README.md b/packages/firebase_installations/firebase_installations_platform_interface/README.md
new file mode 100644
index 000000000000..00f6dfe07c3c
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/README.md
@@ -0,0 +1,26 @@
+# firebase_installations_platform_interface
+
+A common platform interface for the [`firebase_installations`][1] plugin.
+
+This interface allows platform-specific implementations of the `flutterfire_installations`
+plugin, as well as the plugin itself, to ensure they are supporting the
+same interface.
+
+## Usage
+
+To implement a new platform-specific implementation of `flutterfire_installations`, extend
+[`FirebaseInstallationsPlatform`][2] with an implementation that performs the
+platform-specific behavior, and when you register your plugin, set the default
+`FirebaseInstallationsPlatform` by calling
+`FirebaseInstallationsPlatform.instance = MyFirebaseInstallations()`.
+
+## Note on breaking changes
+
+Strongly prefer non-breaking changes (such as adding a method to the interface)
+over breaking changes for this package.
+
+See https://flutter.dev/go/platform-interface-breaking-changes for a discussion
+on why a less-clean interface is preferable to a breaking change.
+
+[1]: ../firebase_installations
+[2]: lib/firebase_installations_platform_interface.dart
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/analysis_options.yaml b/packages/firebase_installations/firebase_installations_platform_interface/analysis_options.yaml
new file mode 100644
index 000000000000..a5744c1cfbe7
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/analysis_options.yaml
@@ -0,0 +1,4 @@
+include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/lib/firebase_installations_platform_interface.dart b/packages/firebase_installations/firebase_installations_platform_interface/lib/firebase_installations_platform_interface.dart
new file mode 100644
index 000000000000..2e753ccbb432
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/lib/firebase_installations_platform_interface.dart
@@ -0,0 +1,7 @@
+// Copyright 2021 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_installations_platform_interface;
+
+export 'src/platform_interface/firebase_installations_platform_interface.dart';
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/lib/src/method_channel/method_channel_firebase_installations.dart b/packages/firebase_installations/firebase_installations_platform_interface/lib/src/method_channel/method_channel_firebase_installations.dart
new file mode 100644
index 000000000000..6a095a68808e
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/lib/src/method_channel/method_channel_firebase_installations.dart
@@ -0,0 +1,112 @@
+// Copyright 2021 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:async';
+
+import 'package:firebase_core/firebase_core.dart';
+import 'package:firebase_installations_platform_interface/firebase_installations_platform_interface.dart';
+import 'package:flutter/services.dart';
+
+import 'utils/exception.dart';
+
+class MethodChannelFirebaseInstallations extends FirebaseInstallationsPlatform {
+ /// Returns a stub instance to allow the platform interface to access
+ /// the class instance statically.
+ static MethodChannelFirebaseInstallations get instance {
+ return MethodChannelFirebaseInstallations._();
+ }
+
+ /// The [MethodChannelFirebaseFunctions] method channel.
+ static const MethodChannel channel = MethodChannel(
+ 'plugins.flutter.io/firebase_installations',
+ );
+
+ static final Map> _idTokenChangesListeners =
+ >{};
+
+ /// Creates a new [MethodChannelFirebaseInstallations] instance with an [app].
+ MethodChannelFirebaseInstallations({required FirebaseApp app}) : super(app) {
+ _idTokenChangesListeners[app.name] = StreamController.broadcast();
+
+ channel.invokeMethod(
+ 'FirebaseInstallations#registerIdChangeListener', {
+ 'appName': app.name,
+ }).then((channelName) {
+ final events = EventChannel(channelName!, channel.codec);
+ events.receiveBroadcastStream().listen((arguments) {
+ _handleIdChangedListener(app.name, arguments);
+ }, onError: (error, stackTrace) {
+ _handleIdChangedError(app.name, error, stackTrace);
+ });
+ });
+ }
+ void _handleIdChangedError(String appName, Object error,
+ [StackTrace? stackTrace]) {
+ final StreamController controller =
+ _idTokenChangesListeners[appName]!;
+ controller.addError(convertPlatformException(error), stackTrace);
+ }
+
+ /// Handle any incoming events from Event Channel and forward on to the user.
+ void _handleIdChangedListener(
+ String appName, Map arguments) {
+ final StreamController controller =
+ _idTokenChangesListeners[appName]!;
+ controller.add(arguments['token']);
+ }
+
+ /// Internal stub class initializer.
+ ///
+ /// When the user code calls a functions method, the real instance is
+ /// then initialized via the [delegateFor] method.
+ MethodChannelFirebaseInstallations._() : super(null);
+
+ @override
+ FirebaseInstallationsPlatform delegateFor({required FirebaseApp app}) {
+ return MethodChannelFirebaseInstallations(app: app);
+ }
+
+ @override
+ Future delete() async {
+ try {
+ await channel.invokeMethod('FirebaseInstallations#delete', {
+ 'appName': app!.name,
+ });
+ } catch (e, s) {
+ throw convertPlatformException(e, s);
+ }
+ }
+
+ @override
+ Future getId() async {
+ try {
+ String? id =
+ await channel.invokeMethod('FirebaseInstallations#getId', {
+ 'appName': app!.name,
+ });
+
+ return id!;
+ } catch (e, s) {
+ throw convertPlatformException(e, s);
+ }
+ }
+
+ @override
+ Future getToken(bool forceRefresh) async {
+ try {
+ String? id = await channel.invokeMethod(
+ 'FirebaseInstallations#getToken',
+ {'appName': app!.name, 'forceRefresh': forceRefresh});
+
+ return id!;
+ } catch (e, s) {
+ throw convertPlatformException(e, s);
+ }
+ }
+
+ @override
+ Stream get onIdChange {
+ return _idTokenChangesListeners[app!.name]!.stream;
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/lib/src/method_channel/utils/exception.dart b/packages/firebase_installations/firebase_installations_platform_interface/lib/src/method_channel/utils/exception.dart
new file mode 100644
index 000000000000..87aa836d8e24
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/lib/src/method_channel/utils/exception.dart
@@ -0,0 +1,44 @@
+// Copyright 2021 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_core/firebase_core.dart';
+import 'package:flutter/services.dart';
+
+/// Catches a [PlatformException] and returns an [Exception].
+///
+/// If the [Exception] is a [PlatformException], a [FirebaseException] is returned.
+Exception convertPlatformException(Object exception, [StackTrace? stackTrace]) {
+ if (exception is! Exception || exception is! PlatformException) {
+ throw exception;
+ }
+
+ return platformExceptionToFirebaseException(exception, stackTrace);
+}
+
+/// Converts a [PlatformException] into a [FirebaseException].
+///
+/// A [PlatformException] can only be converted to a [FirebaseException] if the
+/// `details` of the exception exist. Firebase returns specific codes and messages
+/// which can be converted into user friendly exceptions.
+FirebaseException platformExceptionToFirebaseException(
+ PlatformException platformException,
+ [StackTrace? stackTrace]) {
+ Map? details = platformException.details != null
+ ? Map.from(platformException.details)
+ : null;
+
+ String code = 'unknown';
+ String message = platformException.message ?? '';
+
+ if (details != null) {
+ code = details['code'] ?? code;
+ message = details['message'] ?? message;
+ }
+
+ return FirebaseException(
+ plugin: 'firebase_installations',
+ code: code,
+ message: message,
+ stackTrace: stackTrace);
+}
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/lib/src/platform_interface/firebase_installations_platform_interface.dart b/packages/firebase_installations/firebase_installations_platform_interface/lib/src/platform_interface/firebase_installations_platform_interface.dart
new file mode 100644
index 000000000000..14ee6412ea35
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/lib/src/platform_interface/firebase_installations_platform_interface.dart
@@ -0,0 +1,69 @@
+// Copyright 2021 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_core/firebase_core.dart';
+import 'package:meta/meta.dart';
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
+
+import '../method_channel/method_channel_firebase_installations.dart';
+
+abstract class FirebaseInstallationsPlatform extends PlatformInterface {
+ /// Create an instance using [app].
+ FirebaseInstallationsPlatform(this.app) : super(token: _token);
+
+ static final Object _token = Object();
+
+ static FirebaseInstallationsPlatform? _instance;
+
+ /// The [FirebaseApp] this instance was initialized with
+ final FirebaseApp? app;
+
+ /// Create an instance using [app] using the existing implementation
+ factory FirebaseInstallationsPlatform.instanceFor(
+ {required FirebaseApp app}) {
+ return FirebaseInstallationsPlatform.instance.delegateFor(app: app);
+ }
+
+ /// The current default [FirebaseInstallationsPlatform] instance.
+ ///
+ /// It will always default to [MethodChannelFirebaseInstallations]
+ /// if no other implementation was provided.
+ static FirebaseInstallationsPlatform get instance {
+ return _instance ??= MethodChannelFirebaseInstallations.instance;
+ }
+
+ /// Sets the [FirebaseInstallationsPlatform.instance]
+ static set instance(FirebaseInstallationsPlatform instance) {
+ PlatformInterface.verifyToken(instance, _token);
+ _instance = instance;
+ }
+
+ /// Enables delegates to create new instances of themselves if a none default
+ /// [FirebaseApp] instance or region is required by the user.
+ @protected
+ FirebaseInstallationsPlatform delegateFor({required FirebaseApp app}) {
+ throw UnimplementedError('delegateFor() is not implemented');
+ }
+
+ /// Deletes the Firebase Installation and all associated data.
+ Future delete() {
+ throw UnimplementedError('delete() is not implemented');
+ }
+
+ /// Creates a Firebase Installation if there isn't one for the app and
+ /// returns the Installation ID.
+ Future getId() {
+ throw UnimplementedError('getId() is not implemented');
+ }
+
+ /// Returns an Authentication Token for the current Firebase Installation.
+ Future getToken(bool forceRefresh) {
+ throw UnimplementedError('getToken() is not implemented');
+ }
+
+ /// Sends a new event via a [Stream] whenever the Installation ID changes.
+ Stream get onIdChange {
+ throw UnimplementedError('get onIdChange is not implemented');
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations_platform_interface/pubspec.yaml b/packages/firebase_installations/firebase_installations_platform_interface/pubspec.yaml
new file mode 100644
index 000000000000..d2787862cdd7
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_platform_interface/pubspec.yaml
@@ -0,0 +1,22 @@
+name: firebase_installations_platform_interface
+description: A common platform interface for the firebase_installations plugin.
+version: 0.1.0
+homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_installations/firebase_installations_platform_interface
+repository: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_installations/firebase_installations_platform_interface
+
+environment:
+ sdk: ">=2.12.0 <3.0.0"
+ flutter: ">=1.17.0"
+
+dependencies:
+ firebase_core: ^1.10.0
+ flutter:
+ sdk: flutter
+ meta: ^1.3.0
+ plugin_platform_interface: ^2.0.0
+
+dev_dependencies:
+ firebase_core_platform_interface: ^4.1.0
+ flutter_test:
+ sdk: flutter
+ flutter_lints: ^1.0.0
diff --git a/packages/firebase_installations/firebase_installations_web/.gitignore b/packages/firebase_installations/firebase_installations_web/.gitignore
new file mode 100644
index 000000000000..a247422ef7c3
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/.gitignore
@@ -0,0 +1,75 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+build/
+
+# Android related
+**/android/**/gradle-wrapper.jar
+**/android/.gradle
+**/android/captures/
+**/android/gradlew
+**/android/gradlew.bat
+**/android/local.properties
+**/android/**/GeneratedPluginRegistrant.java
+
+# iOS/XCode related
+**/ios/**/*.mode1v3
+**/ios/**/*.mode2v3
+**/ios/**/*.moved-aside
+**/ios/**/*.pbxuser
+**/ios/**/*.perspectivev3
+**/ios/**/*sync/
+**/ios/**/.sconsign.dblite
+**/ios/**/.tags*
+**/ios/**/.vagrant/
+**/ios/**/DerivedData/
+**/ios/**/Icon?
+**/ios/**/Pods/
+**/ios/**/.symlinks/
+**/ios/**/profile
+**/ios/**/xcuserdata
+**/ios/.generated/
+**/ios/Flutter/App.framework
+**/ios/Flutter/Flutter.framework
+**/ios/Flutter/Flutter.podspec
+**/ios/Flutter/Generated.xcconfig
+**/ios/Flutter/ephemeral
+**/ios/Flutter/app.flx
+**/ios/Flutter/app.zip
+**/ios/Flutter/flutter_assets/
+**/ios/Flutter/flutter_export_environment.sh
+**/ios/ServiceDefinitions.json
+**/ios/Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!**/ios/**/default.mode1v3
+!**/ios/**/default.mode2v3
+!**/ios/**/default.pbxuser
+!**/ios/**/default.perspectivev3
diff --git a/packages/firebase_installations/firebase_installations_web/.metadata b/packages/firebase_installations/firebase_installations_web/.metadata
new file mode 100644
index 000000000000..db56104b21ff
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/.metadata
@@ -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: package
diff --git a/packages/firebase_installations/firebase_installations_web/CHANGELOG.md b/packages/firebase_installations/firebase_installations_web/CHANGELOG.md
new file mode 100644
index 000000000000..c9e662fb6d43
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.1.0
+
+ - Initial release of the Firebase Installations plugin.
diff --git a/packages/firebase_installations/firebase_installations_web/LICENSE b/packages/firebase_installations/firebase_installations_web/LICENSE
new file mode 100644
index 000000000000..5b8717b87644
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/LICENSE
@@ -0,0 +1,27 @@
+// Copyright 2021 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.
\ No newline at end of file
diff --git a/packages/firebase_installations/firebase_installations_web/README.md b/packages/firebase_installations/firebase_installations_web/README.md
new file mode 100644
index 000000000000..001155ac60ea
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/README.md
@@ -0,0 +1,12 @@
+# firebase_installations_web
+
+The web implementation of `flutterfire_installations`.
+
+## Getting Started
+
+To get started with Firebase Installations Web, please [see the documentation](https://firebase.flutter.dev/docs/installations/overview)
+available at [https://firebase.flutter.dev](https://firebase.flutter.dev)
+
+Once installed, Firebase Installations needs to be configured for Web Installation. Please [see the documentation](https://firebase.flutter.dev/docs/installations/overview#3-web-only-add-the-sdk) on Web Installation
+
+To learn more about managing Firebase Installations for you project, please visit the [Firebase website](https://firebase.google.com/docs/projects/manage-installations)
diff --git a/packages/firebase_installations/firebase_installations_web/analysis_options.yaml b/packages/firebase_installations/firebase_installations_web/analysis_options.yaml
new file mode 100644
index 000000000000..a5744c1cfbe7
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/analysis_options.yaml
@@ -0,0 +1,4 @@
+include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/packages/firebase_installations/firebase_installations_web/lib/firebase_installations_web.dart b/packages/firebase_installations/firebase_installations_web/lib/firebase_installations_web.dart
new file mode 100644
index 000000000000..f2f63fbef3df
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/lib/firebase_installations_web.dart
@@ -0,0 +1,71 @@
+// Copyright 2021 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_installations_web;
+
+import 'package:firebase_core/firebase_core.dart';
+import 'package:firebase_core_web/firebase_core_web.dart';
+import 'package:firebase_core_web/firebase_core_web_interop.dart'
+ as core_interop;
+import 'package:firebase_installations_platform_interface/firebase_installations_platform_interface.dart';
+import 'package:flutter_web_plugins/flutter_web_plugins.dart';
+
+import 'src/guard.dart';
+import 'src/interop/installations.dart' as installations_interop;
+
+class FirebaseInstallationsWeb extends FirebaseInstallationsPlatform {
+ /// The entry point for the [FirebaseInstallationsWeb] class.
+ FirebaseInstallationsWeb({FirebaseApp? app}) : super(app);
+
+ /// Stub initializer to allow the [registerWith] to create an instance without
+ /// registering the web delegates or listeners.
+ FirebaseInstallationsWeb._()
+ : _webInstallations = null,
+ super(null);
+
+ /// Instance of installations from the web plugin.
+ installations_interop.Installations? _webInstallations;
+
+ /// Lazily initialize [_webFunctions] on first method call
+ installations_interop.Installations get _delegate {
+ return _webInstallations ??= installations_interop
+ .getInstallationsInstance(core_interop.app(app?.name));
+ }
+
+ /// Create the default instance of the [FirebaseInstallationsPlatform] as a [FirebaseInstallationsWeb]
+ static void registerWith(Registrar registrar) {
+ FirebaseCoreWeb.registerService('installations');
+ FirebaseInstallationsPlatform.instance = FirebaseInstallationsWeb.instance;
+ }
+
+ /// Returns an instance of [FirebaseInstallationsWeb].
+ static FirebaseInstallationsWeb get instance {
+ return FirebaseInstallationsWeb._();
+ }
+
+ @override
+ FirebaseInstallationsPlatform delegateFor({required FirebaseApp app}) {
+ return FirebaseInstallationsWeb(app: app);
+ }
+
+ @override
+ Future delete() async {
+ return guard(() => _delegate.delete());
+ }
+
+ @override
+ Future getId() async {
+ return guard(() => _delegate.getId());
+ }
+
+ @override
+ Future getToken(bool forceRefresh) async {
+ return guard(() => _delegate.getToken(forceRefresh));
+ }
+
+ @override
+ Stream get onIdChange {
+ return guard(() => _delegate.onIdChange);
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations_web/lib/src/guard.dart b/packages/firebase_installations/firebase_installations_web/lib/src/guard.dart
new file mode 100644
index 000000000000..a57cfab0ef81
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/lib/src/guard.dart
@@ -0,0 +1,20 @@
+// Copyright 2021 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_core/firebase_core.dart';
+
+// ignore: implementation_imports
+import 'package:firebase_core/src/internals.dart' as internals;
+
+export 'package:firebase_core/src/internals.dart' hide guard;
+
+/// Will return a [FirebaseException] from a thrown web error.
+/// Any other errors will be propagated as normal.
+R guard(R Function() cb) {
+ return internals.guard(
+ cb,
+ plugin: 'firebase_installations',
+ codeParser: (code) => code.replaceFirst('installations/', ''),
+ );
+}
diff --git a/packages/firebase_installations/firebase_installations_web/lib/src/interop/firebase_interop.dart b/packages/firebase_installations/firebase_installations_web/lib/src/interop/firebase_interop.dart
new file mode 100644
index 000000000000..b7960feb5c86
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/lib/src/interop/firebase_interop.dart
@@ -0,0 +1,16 @@
+// Copyright 2021 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.
+
+// ignore_for_file: public_member_api_docs
+
+@JS('firebase')
+library firebase_interop.firebase;
+
+import 'package:firebase_core_web/firebase_core_web_interop.dart';
+import 'package:js/js.dart';
+
+import 'installations_interop.dart';
+
+@JS()
+external InstallationsJsImpl installations([AppJsImpl? app]);
diff --git a/packages/firebase_installations/firebase_installations_web/lib/src/interop/installations.dart b/packages/firebase_installations/firebase_installations_web/lib/src/interop/installations.dart
new file mode 100644
index 000000000000..a4a313829914
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/lib/src/interop/installations.dart
@@ -0,0 +1,71 @@
+// Copyright 2021 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:async';
+
+import 'package:firebase_core_web/firebase_core_web_interop.dart';
+import 'package:js/js.dart';
+
+import 'firebase_interop.dart' as firebase_interop;
+import 'installations_interop.dart' as installations_interop;
+
+export 'installations_interop.dart';
+
+Installations getInstallationsInstance([App? app]) {
+ return Installations.getInstance(app != null
+ ? firebase_interop.installations(app.jsObject)
+ : firebase_interop.installations());
+}
+
+class Installations
+ extends JsObjectWrapper {
+ static final _expando = Expando();
+
+ /// Creates a new Installations from a [jsObject].
+ static Installations getInstance(
+ installations_interop.InstallationsJsImpl jsObject) {
+ return _expando[jsObject] ??= Installations._fromJsObject(jsObject);
+ }
+
+ Installations._fromJsObject(
+ installations_interop.InstallationsJsImpl jsObject)
+ : super.fromJsObject(jsObject);
+
+ Future delete() => handleThenable(jsObject.delete());
+
+ Future getId() => handleThenable(jsObject.getId());
+
+ Future getToken([bool forceRefresh = false]) =>
+ handleThenable(jsObject.getToken(forceRefresh));
+
+ Func0? _onIdChangedUnsubscribe;
+
+ StreamController? _idChangeController;
+
+ Stream get onIdChange {
+ if (_idChangeController == null) {
+ final wrapper = allowInterop((String id) {
+ _idChangeController!.add(id);
+ });
+
+ void startListen() {
+ assert(_onIdChangedUnsubscribe == null);
+ _onIdChangedUnsubscribe = jsObject.onIdChange(wrapper);
+ }
+
+ void stopListen() {
+ _onIdChangedUnsubscribe!();
+ _onIdChangedUnsubscribe = null;
+ }
+
+ _idChangeController = StreamController.broadcast(
+ onListen: startListen,
+ onCancel: stopListen,
+ sync: true,
+ );
+ }
+
+ return _idChangeController!.stream;
+ }
+}
diff --git a/packages/firebase_installations/firebase_installations_web/lib/src/interop/installations_interop.dart b/packages/firebase_installations/firebase_installations_web/lib/src/interop/installations_interop.dart
new file mode 100644
index 000000000000..187e2b02cfbd
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/lib/src/interop/installations_interop.dart
@@ -0,0 +1,22 @@
+// Copyright 2021 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.
+
+@JS('firebase.installations')
+library firebase_interop.installations;
+
+import 'package:firebase_core_web/firebase_core_web_interop.dart';
+import 'package:js/js.dart';
+
+@JS('Installations')
+abstract class InstallationsJsImpl {
+ external AppJsImpl get app;
+
+ external PromiseJsImpl delete();
+
+ external PromiseJsImpl getId();
+
+ external PromiseJsImpl getToken([bool? forceRefresh]);
+
+ external Func0 onIdChange(Func1 observer);
+}
diff --git a/packages/firebase_installations/firebase_installations_web/pubspec.yaml b/packages/firebase_installations/firebase_installations_web/pubspec.yaml
new file mode 100644
index 000000000000..f6b882390934
--- /dev/null
+++ b/packages/firebase_installations/firebase_installations_web/pubspec.yaml
@@ -0,0 +1,32 @@
+name: firebase_installations_web
+description: The web implementation of firebase_installations.
+version: 0.1.0
+homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_installations/firebase_installations_web
+repository: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_installations/firebase_installations_web
+
+environment:
+ sdk: '>=2.12.0 <3.0.0'
+ flutter: '>=1.17.0'
+
+dependencies:
+ firebase_installations_platform_interface: ^0.1.0
+ firebase_core: ^1.10.0
+ firebase_core_web: ^1.2.0
+ flutter:
+ sdk: flutter
+ flutter_web_plugins:
+ sdk: flutter
+ js: ^0.6.3
+
+dev_dependencies:
+ firebase_core_platform_interface: ^4.1.0
+ flutter_test:
+ sdk: flutter
+ flutter_lints: ^1.0.0
+
+flutter:
+ plugin:
+ platforms:
+ web:
+ pluginClass: FirebaseInstallationsWeb
+ fileName: firebase_installations_web.dart
diff --git a/website/plugins.js b/website/plugins.js
index 5ad27e5951f9..2060dff00278 100644
--- a/website/plugins.js
+++ b/website/plugins.js
@@ -71,6 +71,18 @@ module.exports = [
macos: true,
},
},
+ {
+ name: 'Installations',
+ pub: 'flutterfire_installations',
+ firebase: 'https://firebase.google.com/docs/projects/manage-installations',
+ status: 'Stable',
+ documentation: 'https://firebase.flutter.dev/docs/installations/overview',
+ support: {
+ web: true,
+ mobile: true,
+ macos: true,
+ },
+ },
{
name: 'Cloud Messaging',
pub: 'firebase_messaging',