diff --git a/packages/firebase_analytics/.gitignore b/packages/firebase_analytics/.gitignore
new file mode 100755
index 000000000000..14c7d4c3f73e
--- /dev/null
+++ b/packages/firebase_analytics/.gitignore
@@ -0,0 +1,9 @@
+.DS_Store
+.atom/
+.idea
+.packages
+.pub/
+build/
+ios/.generated/
+packages
+pubspec.lock
diff --git a/packages/firebase_analytics/LICENSE b/packages/firebase_analytics/LICENSE
new file mode 100755
index 000000000000..282a0f51aa4a
--- /dev/null
+++ b/packages/firebase_analytics/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2017, the Flutter project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of Google Inc. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/packages/firebase_analytics/README.md b/packages/firebase_analytics/README.md
new file mode 100755
index 000000000000..5e757d5e8c2e
--- /dev/null
+++ b/packages/firebase_analytics/README.md
@@ -0,0 +1,13 @@
+# Firebase Analytics for Flutter
+
+**WARNING: this is incomplete and highly experimental**
+
+This plugin allows Flutter apps use the Firebase Analytics API from their Dart
+code.
+
+## Getting Started
+
+The the `example` directory for a sample app using Firebase Analytics.
+
+To learn more about Flutter plugins, view our online
+[documentation](https://flutter.io/platform-plugins).
diff --git a/packages/firebase_analytics/android/.gitignore b/packages/firebase_analytics/android/.gitignore
new file mode 100755
index 000000000000..5c4ef82869b5
--- /dev/null
+++ b/packages/firebase_analytics/android/.gitignore
@@ -0,0 +1,12 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+
+/gradle
+/gradlew
+/gradlew.bat
diff --git a/packages/firebase_analytics/android/build.gradle b/packages/firebase_analytics/android/build.gradle
new file mode 100755
index 000000000000..cf7ace763e2e
--- /dev/null
+++ b/packages/firebase_analytics/android/build.gradle
@@ -0,0 +1,36 @@
+group 'io.flutter.firebase_analytics'
+version '1.0-SNAPSHOT'
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.3.0'
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion '25.0.2'
+
+ defaultConfig {
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ lintOptions {
+ disable 'InvalidPackage'
+ }
+ dependencies {
+ compile 'com.google.firebase:firebase-auth:10.2.1'
+ compile 'com.google.firebase:firebase-analytics:10.2.1'
+ }
+}
diff --git a/packages/firebase_analytics/android/gradle.properties b/packages/firebase_analytics/android/gradle.properties
new file mode 100755
index 000000000000..8bd86f680510
--- /dev/null
+++ b/packages/firebase_analytics/android/gradle.properties
@@ -0,0 +1 @@
+org.gradle.jvmargs=-Xmx1536M
diff --git a/packages/firebase_analytics/android/settings.gradle b/packages/firebase_analytics/android/settings.gradle
new file mode 100755
index 000000000000..4b80dda8afc7
--- /dev/null
+++ b/packages/firebase_analytics/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'firebase_analytics'
diff --git a/packages/firebase_analytics/android/src/main/AndroidManifest.xml b/packages/firebase_analytics/android/src/main/AndroidManifest.xml
new file mode 100755
index 000000000000..fe60fa496e73
--- /dev/null
+++ b/packages/firebase_analytics/android/src/main/AndroidManifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_analytics/android/src/main/java/io/flutter/firebase_analytics/FirebaseAnalyticsPlugin.java b/packages/firebase_analytics/android/src/main/java/io/flutter/firebase_analytics/FirebaseAnalyticsPlugin.java
new file mode 100755
index 000000000000..c4fe7b7cff52
--- /dev/null
+++ b/packages/firebase_analytics/android/src/main/java/io/flutter/firebase_analytics/FirebaseAnalyticsPlugin.java
@@ -0,0 +1,147 @@
+// Copyright 2017 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.firebase_analytics;
+
+import java.util.Map;
+
+import com.google.firebase.FirebaseApp;
+import com.google.firebase.analytics.FirebaseAnalytics;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import io.flutter.plugin.common.MethodChannel;
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
+import io.flutter.plugin.common.MethodChannel.Result;
+import io.flutter.plugin.common.MethodCall;
+import io.flutter.plugin.common.PluginRegistry;
+
+/**
+ * Flutter plugin for Firebase Analytics.
+ */
+public class FirebaseAnalyticsPlugin implements MethodCallHandler {
+ private final Activity activity;
+ private final FirebaseAnalytics firebaseAnalytics;
+
+ public static void registerWith(PluginRegistry.Registrar registrar) {
+ final MethodChannel channel = new MethodChannel(registrar.messenger(), "firebase_analytics");
+ channel.setMethodCallHandler(new FirebaseAnalyticsPlugin(registrar.activity()));
+ }
+
+ private FirebaseAnalyticsPlugin(Activity activity) {
+ this.activity = activity;
+ FirebaseApp.initializeApp(activity);
+ this.firebaseAnalytics = FirebaseAnalytics.getInstance(activity);
+ }
+
+ @Override
+ public void onMethodCall(MethodCall call, Result result) {
+ switch (call.method) {
+ case "logEvent":
+ handleLogEvent(call, result);
+ break;
+ case "setUserId":
+ handleSetUserId(call, result);
+ break;
+ case "setCurrentScreen":
+ handleSetCurrentScreen(call, result);
+ break;
+ case "setAnalyticsCollectionEnabled":
+ handleSetAnalyticsCollectionEnabled(call, result);
+ break;
+ case "setMinimumSessionDuration":
+ handleSetMinimumSessionDuration(call, result);
+ break;
+ case "setSessionTimeoutDuration":
+ handleSetSessionTimeoutDuration(call, result);
+ break;
+ case "setUserProperty":
+ handleSetUserProperty(call, result);
+ break;
+ default:
+ result.notImplemented();
+ break;
+ }
+ }
+
+ private void handleLogEvent(MethodCall call, Result result) {
+ @SuppressWarnings("unchecked")
+ Map arguments = (Map) call.arguments;
+ final String eventName = (String) arguments.get("name");
+
+ @SuppressWarnings("unchecked")
+ final Bundle parameterBundle = createBundleFromMap((Map) arguments.get("parameters"));
+ firebaseAnalytics.logEvent(eventName, parameterBundle);
+ result.success(null);
+ }
+
+ private void handleSetUserId(MethodCall call, Result result) {
+ final String id = (String) call.arguments;
+ firebaseAnalytics.setUserId(id);
+ result.success(null);
+ }
+
+ private void handleSetCurrentScreen(MethodCall call, Result result) {
+ @SuppressWarnings("unchecked")
+ Map arguments = (Map) call.arguments;
+ final String screenName = (String) arguments.get("screenName");
+ final String screenClassOverride = (String) arguments.get("screenClassOverride");
+
+ firebaseAnalytics.setCurrentScreen(activity, screenName, screenClassOverride);
+ result.success(null);
+ }
+
+ private void handleSetAnalyticsCollectionEnabled(MethodCall call, Result result) {
+ final Boolean enabled = (Boolean) call.arguments;
+ firebaseAnalytics.setAnalyticsCollectionEnabled(enabled);
+ result.success(null);
+ }
+
+ private void handleSetMinimumSessionDuration(MethodCall call, Result result) {
+ final Integer milliseconds = (Integer) call.arguments;
+ firebaseAnalytics.setMinimumSessionDuration(milliseconds);
+ result.success(null);
+ }
+
+ private void handleSetSessionTimeoutDuration(MethodCall call, Result result) {
+ final Integer milliseconds = (Integer) call.arguments;
+ firebaseAnalytics.setSessionTimeoutDuration(milliseconds);
+ result.success(null);
+ }
+
+ private void handleSetUserProperty(MethodCall call, Result result) {
+ @SuppressWarnings("unchecked")
+ Map arguments = (Map) call.arguments;
+ final String name = (String) arguments.get("name");
+ final String value = (String) arguments.get("value");
+
+ firebaseAnalytics.setUserProperty(name, value);
+ result.success(null);
+ }
+
+ private static Bundle createBundleFromMap(Map map) {
+ if (map == null) {
+ return null;
+ }
+
+ Bundle bundle = new Bundle();
+ for (Map.Entry jsonParam : map.entrySet()) {
+ final Object value = jsonParam.getValue();
+ final String key = jsonParam.getKey();
+ if (value instanceof String) {
+ bundle.putString(key, (String) value);
+ } else if (value instanceof Integer) {
+ bundle.putInt(key, (Integer) value);
+ } else if (value instanceof Double) {
+ bundle.putDouble(key, (Double) value);
+ } else if (value instanceof Boolean) {
+ bundle.putBoolean(key, (Boolean) value);
+ } else {
+ throw new IllegalArgumentException("Unsupported value type: " + value.getClass().getCanonicalName());
+ }
+ }
+ return bundle;
+ }
+}
diff --git a/packages/firebase_analytics/example/.gitignore b/packages/firebase_analytics/example/.gitignore
new file mode 100755
index 000000000000..eb15c3d27cab
--- /dev/null
+++ b/packages/firebase_analytics/example/.gitignore
@@ -0,0 +1,10 @@
+.DS_Store
+.atom/
+.idea
+.packages
+.pub/
+build/
+ios/.generated/
+packages
+pubspec.lock
+.flutter-plugins
diff --git a/packages/firebase_analytics/example/README.md b/packages/firebase_analytics/example/README.md
new file mode 100755
index 000000000000..101d033eea86
--- /dev/null
+++ b/packages/firebase_analytics/example/README.md
@@ -0,0 +1,8 @@
+# firebase_analytics_example
+
+Demonstrates how to use the firebase_analytics plugin.
+
+## Getting Started
+
+For help getting started with Flutter, view our online
+[documentation](http://flutter.io/).
diff --git a/packages/firebase_analytics/example/android.iml b/packages/firebase_analytics/example/android.iml
new file mode 100755
index 000000000000..462b903e05b6
--- /dev/null
+++ b/packages/firebase_analytics/example/android.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_analytics/example/android/.gitignore b/packages/firebase_analytics/example/android/.gitignore
new file mode 100755
index 000000000000..5c4ef82869b5
--- /dev/null
+++ b/packages/firebase_analytics/example/android/.gitignore
@@ -0,0 +1,12 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+
+/gradle
+/gradlew
+/gradlew.bat
diff --git a/packages/firebase_analytics/example/android/app/build.gradle b/packages/firebase_analytics/example/android/app/build.gradle
new file mode 100755
index 000000000000..c4d9481743ec
--- /dev/null
+++ b/packages/firebase_analytics/example/android/app/build.gradle
@@ -0,0 +1,46 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withInputStream { stream ->
+ localProperties.load(stream)
+ }
+}
+
+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.")
+}
+
+apply plugin: 'com.android.application'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion '25.0.2'
+
+ lintOptions {
+ disable 'InvalidPackage'
+ }
+
+ defaultConfig {
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ compile 'com.google.firebase:firebase-core:10.0.1'
+}
+
+apply plugin: 'com.google.gms.google-services'
diff --git a/packages/firebase_analytics/example/android/app/google-services.json b/packages/firebase_analytics/example/android/app/google-services.json
new file mode 100755
index 000000000000..20259483c372
--- /dev/null
+++ b/packages/firebase_analytics/example/android/app/google-services.json
@@ -0,0 +1,62 @@
+{
+ "project_info": {
+ "project_number": "389050544128",
+ "firebase_url": "https://flutterfire-analytics-test.firebaseio.com",
+ "project_id": "flutterfire-analytics-test",
+ "storage_bucket": "flutterfire-analytics-test.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:389050544128:android:2a61bf3bd685ab07",
+ "android_client_info": {
+ "package_name": "io.flutter.firebase_analytics_example"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "389050544128-7uac6td8i05t4bph5tndb87fn3tsj270.apps.googleusercontent.com",
+ "client_type": 1,
+ "android_info": {
+ "package_name": "io.flutter.firebase_analytics_example",
+ "certificate_hash": "329274e93660a35697463bd44f4e7deaf54f6cd4"
+ }
+ },
+ {
+ "client_id": "389050544128-ia9mchg12k1nla2je9untm2tv0fv6cv2.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyBDV1YB19hn6lyF_Ie9AcChrlgA9k8W0WI"
+ }
+ ],
+ "services": {
+ "analytics_service": {
+ "status": 1
+ },
+ "appinvite_service": {
+ "status": 2,
+ "other_platform_oauth_client": [
+ {
+ "client_id": "389050544128-ia9mchg12k1nla2je9untm2tv0fv6cv2.apps.googleusercontent.com",
+ "client_type": 3
+ },
+ {
+ "client_id": "389050544128-8b1peb2i3ai7o7gpdoemu044m61db209.apps.googleusercontent.com",
+ "client_type": 2,
+ "ios_info": {
+ "bundle_id": "io.flutter.firebaseanalytics"
+ }
+ }
+ ]
+ },
+ "ads_service": {
+ "status": 2
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/packages/firebase_analytics/example/android/app/src/main/AndroidManifest.xml b/packages/firebase_analytics/example/android/app/src/main/AndroidManifest.xml
new file mode 100755
index 000000000000..4fd8e239c262
--- /dev/null
+++ b/packages/firebase_analytics/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_analytics/example/android/app/src/main/java/io/flutter/firebase_analytics_example/MainActivity.java b/packages/firebase_analytics/example/android/app/src/main/java/io/flutter/firebase_analytics_example/MainActivity.java
new file mode 100755
index 000000000000..472f6a42850f
--- /dev/null
+++ b/packages/firebase_analytics/example/android/app/src/main/java/io/flutter/firebase_analytics_example/MainActivity.java
@@ -0,0 +1,13 @@
+package io.flutter.firebase_analytics_example;
+
+import android.os.Bundle;
+import io.flutter.app.FlutterActivity;
+import io.flutter.plugins.GeneratedPluginRegistrant;
+
+public class MainActivity extends FlutterActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ GeneratedPluginRegistrant.registerWith(this);
+ }
+}
diff --git a/packages/firebase_analytics/example/android/app/src/main/java/io/flutter/plugins/.gitignore b/packages/firebase_analytics/example/android/app/src/main/java/io/flutter/plugins/.gitignore
new file mode 100755
index 000000000000..0f2aeaa1dc2c
--- /dev/null
+++ b/packages/firebase_analytics/example/android/app/src/main/java/io/flutter/plugins/.gitignore
@@ -0,0 +1,3 @@
+GeneratedPluginRegistrant.java
+
+
diff --git a/packages/firebase_analytics/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/firebase_analytics/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100755
index 000000000000..db77bb4b7b09
Binary files /dev/null and b/packages/firebase_analytics/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/packages/firebase_analytics/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/firebase_analytics/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100755
index 000000000000..17987b79bb8a
Binary files /dev/null and b/packages/firebase_analytics/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/packages/firebase_analytics/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/firebase_analytics/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100755
index 000000000000..09d4391482be
Binary files /dev/null and b/packages/firebase_analytics/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/packages/firebase_analytics/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/firebase_analytics/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100755
index 000000000000..d5f1c8d34e7a
Binary files /dev/null and b/packages/firebase_analytics/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/packages/firebase_analytics/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/firebase_analytics/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100755
index 000000000000..4d6372eebdb2
Binary files /dev/null and b/packages/firebase_analytics/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/packages/firebase_analytics/example/android/build.gradle b/packages/firebase_analytics/example/android/build.gradle
new file mode 100755
index 000000000000..eabb32cea02a
--- /dev/null
+++ b/packages/firebase_analytics/example/android/build.gradle
@@ -0,0 +1,30 @@
+buildscript {
+ repositories {
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.3.1'
+ classpath 'com.google.gms:google-services:3.0.0'
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+ project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
+
+task wrapper(type: Wrapper) {
+ gradleVersion = '2.14.1'
+}
diff --git a/packages/firebase_analytics/example/android/gradle.properties b/packages/firebase_analytics/example/android/gradle.properties
new file mode 100755
index 000000000000..8bd86f680510
--- /dev/null
+++ b/packages/firebase_analytics/example/android/gradle.properties
@@ -0,0 +1 @@
+org.gradle.jvmargs=-Xmx1536M
diff --git a/packages/firebase_analytics/example/android/settings.gradle b/packages/firebase_analytics/example/android/settings.gradle
new file mode 100755
index 000000000000..115da6cb4f4d
--- /dev/null
+++ b/packages/firebase_analytics/example/android/settings.gradle
@@ -0,0 +1,15 @@
+include ':app'
+
+def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
+
+def plugins = new Properties()
+def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
+if (pluginsFile.exists()) {
+ pluginsFile.withInputStream { stream -> plugins.load(stream) }
+}
+
+plugins.each { name, path ->
+ def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
+ include ":$name"
+ project(":$name").projectDir = pluginDirectory
+}
diff --git a/packages/firebase_analytics/example/firebase_analytics_example.iml b/packages/firebase_analytics/example/firebase_analytics_example.iml
new file mode 100755
index 000000000000..1ae40a0f7f54
--- /dev/null
+++ b/packages/firebase_analytics/example/firebase_analytics_example.iml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/firebase_analytics/example/ios/.gitignore b/packages/firebase_analytics/example/ios/.gitignore
new file mode 100755
index 000000000000..664e66b11f16
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/.gitignore
@@ -0,0 +1,42 @@
+.idea/
+.vagrant/
+.sconsign.dblite
+.svn/
+
+.DS_Store
+*.swp
+profile
+
+DerivedData/
+build/
+
+*.pbxuser
+*.mode1v3
+*.mode2v3
+*.perspectivev3
+
+!default.pbxuser
+!default.mode1v3
+!default.mode2v3
+!default.perspectivev3
+
+xcuserdata
+
+*.moved-aside
+
+*.pyc
+*sync/
+Icon?
+.tags*
+
+/Flutter/app.flx
+/Flutter/app.zip
+/Flutter/App.framework
+/Flutter/Flutter.framework
+/Flutter/Generated.xcconfig
+/ServiceDefinitions.json
+
+Podfile.lock
+Pods
+/Runner/GeneratedPluginRegistrant.h
+/Runner/GeneratedPluginRegistrant.m
diff --git a/packages/firebase_analytics/example/ios/Flutter/AppFrameworkInfo.plist b/packages/firebase_analytics/example/ios/Flutter/AppFrameworkInfo.plist
new file mode 100755
index 000000000000..6c2de8086bcd
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Flutter/AppFrameworkInfo.plist
@@ -0,0 +1,30 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ App
+ CFBundleIdentifier
+ io.flutter.flutter.app
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ App
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ MinimumOSVersion
+ 8.0
+
+
diff --git a/packages/firebase_analytics/example/ios/Flutter/Debug.xcconfig b/packages/firebase_analytics/example/ios/Flutter/Debug.xcconfig
new file mode 100755
index 000000000000..9803018ca79d
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Flutter/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include "Generated.xcconfig"
+#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
diff --git a/packages/firebase_analytics/example/ios/Flutter/Release.xcconfig b/packages/firebase_analytics/example/ios/Flutter/Release.xcconfig
new file mode 100755
index 000000000000..a4a8c604e13d
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Flutter/Release.xcconfig
@@ -0,0 +1,2 @@
+#include "Generated.xcconfig"
+#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
diff --git a/packages/firebase_analytics/example/ios/Podfile b/packages/firebase_analytics/example/ios/Podfile
new file mode 100755
index 000000000000..90b5f651fb63
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Podfile
@@ -0,0 +1,36 @@
+# Uncomment this line to define a global platform for your project
+# platform :ios, '9.0'
+
+if ENV['FLUTTER_FRAMEWORK_DIR'] == nil
+ abort('Please set FLUTTER_FRAMEWORK_DIR to the directory containing Flutter.framework')
+end
+
+target 'Runner' do
+ # Pods for Runner
+
+ # Flutter Pods
+ pod 'Flutter', :path => ENV['FLUTTER_FRAMEWORK_DIR']
+
+ if File.exists? '../.flutter-plugins'
+ flutter_root = File.expand_path('..')
+ File.foreach('../.flutter-plugins') { |line|
+ plugin = line.split(pattern='=')
+ if plugin.length == 2
+ name = plugin[0].strip()
+ path = plugin[1].strip()
+ resolved_path = File.expand_path("#{path}/ios", flutter_root)
+ pod name, :path => resolved_path
+ else
+ puts "Invalid plugin specification: #{line}"
+ end
+ }
+ end
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ target.build_configurations.each do |config|
+ config.build_settings['ENABLE_BITCODE'] = 'NO'
+ end
+ end
+end
diff --git a/packages/firebase_analytics/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_analytics/example/ios/Runner.xcodeproj/project.pbxproj
new file mode 100755
index 000000000000..cef65a5b036c
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,499 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
+ 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
+ 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 5C6F5A6B1EC3AF0E008D64B5 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C6F5A6A1EC3AF0E008D64B5 /* GeneratedPluginRegistrant.m */; };
+ 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
+ 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 9740EEBB1CF902C7004384FC /* app.flx in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB71CF902C7004384FC /* app.flx */; };
+ 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
+ 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
+ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
+ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
+ B1F3D14E8117A6C9F65810E0 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D558BB7489B1C82B42A9097 /* libPods-Runner.a */; };
+ B43DDBB51EA0304000A48ABE /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B43DDBB41EA0304000A48ABE /* GoogleService-Info.plist */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
+ 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
+ 4D558BB7489B1C82B42A9097 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 5C6F5A691EC3AF0E008D64B5 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
+ 5C6F5A6A1EC3AF0E008D64B5 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
+ 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
+ 9740EEB71CF902C7004384FC /* app.flx */ = {isa = PBXFileReference; lastKnownFileType = file; name = app.flx; path = Flutter/app.flx; sourceTree = ""; };
+ 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
+ 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ B43DDBB41EA0304000A48ABE /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 97C146EB1CF9000F007C117D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
+ 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
+ B1F3D14E8117A6C9F65810E0 /* libPods-Runner.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 840012C8B5EDBCF56B0E4AC1 /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Pods;
+ sourceTree = "";
+ };
+ 9740EEB11CF90186004384FC /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB71CF902C7004384FC /* app.flx */,
+ 3B80C3931E831B6300D905FE /* App.framework */,
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
+ 9740EEBA1CF902C7004384FC /* Flutter.framework */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */,
+ );
+ name = Flutter;
+ sourceTree = "";
+ };
+ 97C146E51CF9000F007C117D = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB11CF90186004384FC /* Flutter */,
+ 97C146F01CF9000F007C117D /* Runner */,
+ 97C146EF1CF9000F007C117D /* Products */,
+ 840012C8B5EDBCF56B0E4AC1 /* Pods */,
+ CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ 97C146EF1CF9000F007C117D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146EE1CF9000F007C117D /* Runner.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 97C146F01CF9000F007C117D /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 5C6F5A691EC3AF0E008D64B5 /* GeneratedPluginRegistrant.h */,
+ 5C6F5A6A1EC3AF0E008D64B5 /* GeneratedPluginRegistrant.m */,
+ 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
+ 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
+ 97C146FA1CF9000F007C117D /* Main.storyboard */,
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */,
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
+ 97C147021CF9000F007C117D /* Info.plist */,
+ B43DDBB41EA0304000A48ABE /* GoogleService-Info.plist */,
+ 97C146F11CF9000F007C117D /* Supporting Files */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ 97C146F11CF9000F007C117D /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146F21CF9000F007C117D /* main.m */,
+ );
+ name = "Supporting Files";
+ sourceTree = "";
+ };
+ CF3B75C9A7D2FA2A4C99F110 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 4D558BB7489B1C82B42A9097 /* libPods-Runner.a */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 97C146ED1CF9000F007C117D /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ AB1344B0443C71CD721E1BB7 /* [CP] Check Pods Manifest.lock */,
+ 9740EEB61CF901F6004384FC /* Run Script */,
+ 97C146EA1CF9000F007C117D /* Sources */,
+ 97C146EB1CF9000F007C117D /* Frameworks */,
+ 97C146EC1CF9000F007C117D /* Resources */,
+ 9705A1C41CF9048500538489 /* Embed Frameworks */,
+ 95BB15E9E1769C0D146AA592 /* [CP] Embed Pods Frameworks */,
+ 532EA9D341340B1DCD08293D /* [CP] Copy Pods Resources */,
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 97C146E61CF9000F007C117D /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0830;
+ ORGANIZATIONNAME = "The Chromium Authors";
+ TargetAttributes = {
+ 97C146ED1CF9000F007C117D = {
+ CreatedOnToolsVersion = 7.3.1;
+ DevelopmentTeam = 3GRKCVVJ22;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 97C146E51CF9000F007C117D;
+ productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 97C146ED1CF9000F007C117D /* Runner */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 97C146EC1CF9000F007C117D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9740EEBB1CF902C7004384FC /* app.flx in Resources */,
+ B43DDBB51EA0304000A48ABE /* GoogleService-Info.plist in Resources */,
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.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\" thin";
+ };
+ 532EA9D341340B1DCD08293D /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Copy Pods Resources";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 95BB15E9E1769C0D146AA592 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\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";
+ };
+ AB1344B0443C71CD721E1BB7 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_ROOT}/../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";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 97C146EA1CF9000F007C117D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
+ 97C146F31CF9000F007C117D /* main.m in Sources */,
+ 5C6F5A6B1EC3AF0E008D64B5 /* GeneratedPluginRegistrant.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 97C146FB1CF9000F007C117D /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 97C147001CF9000F007C117D /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 97C147031CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 97C147041CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 97C147061CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ DEVELOPMENT_TEAM = 3GRKCVVJ22;
+ ENABLE_BITCODE = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = io.flutter.firebaseAnalyticsExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE = "";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ };
+ name = Debug;
+ };
+ 97C147071CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ DEVELOPMENT_TEAM = 3GRKCVVJ22;
+ ENABLE_BITCODE = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = io.flutter.firebaseAnalyticsExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE = "";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147031CF9000F007C117D /* Debug */,
+ 97C147041CF9000F007C117D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147061CF9000F007C117D /* Debug */,
+ 97C147071CF9000F007C117D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 97C146E61CF9000F007C117D /* Project object */;
+}
diff --git a/packages/firebase_analytics/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/firebase_analytics/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100755
index 000000000000..21a3cc14c74e
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/packages/firebase_analytics/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_analytics/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100755
index 000000000000..1c9580788197
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_analytics/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/firebase_analytics/example/ios/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100755
index 000000000000..21a3cc14c74e
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/packages/firebase_analytics/example/ios/Runner/AppDelegate.h b/packages/firebase_analytics/example/ios/Runner/AppDelegate.h
new file mode 100755
index 000000000000..cf210d213f27
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner/AppDelegate.h
@@ -0,0 +1,6 @@
+#import
+#import
+
+@interface AppDelegate : FlutterAppDelegate
+
+@end
diff --git a/packages/firebase_analytics/example/ios/Runner/AppDelegate.m b/packages/firebase_analytics/example/ios/Runner/AppDelegate.m
new file mode 100755
index 000000000000..0e94ecd7e4e8
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner/AppDelegate.m
@@ -0,0 +1,12 @@
+#include "AppDelegate.h"
+#include "GeneratedPluginRegistrant.h"
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ [GeneratedPluginRegistrant registerWithRegistry:self];
+ return [super application:application didFinishLaunchingWithOptions:launchOptions];
+}
+
+@end
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100755
index 000000000000..d22f10b2ab63
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,116 @@
+{
+ "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"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
new file mode 100755
index 000000000000..28c6bf03016f
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
new file mode 100755
index 000000000000..2ccbfd967d96
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
new file mode 100755
index 000000000000..f091b6b0bca8
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
new file mode 100755
index 000000000000..4cde12118dda
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
new file mode 100755
index 000000000000..d0ef06e7edb8
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
new file mode 100755
index 000000000000..dcdc2306c285
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
new file mode 100755
index 000000000000..2ccbfd967d96
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
new file mode 100755
index 000000000000..c8f9ed8f5cee
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
new file mode 100755
index 000000000000..a6d6b8609df0
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
new file mode 100755
index 000000000000..a6d6b8609df0
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
new file mode 100755
index 000000000000..75b2d164a5a9
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
new file mode 100755
index 000000000000..c4df70d39da7
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
new file mode 100755
index 000000000000..6a84f41e14e2
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
new file mode 100755
index 000000000000..d0e1f5853602
Binary files /dev/null and b/packages/firebase_analytics/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
diff --git a/packages/firebase_analytics/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/firebase_analytics/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
new file mode 100755
index 000000000000..ebf48f603974
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_analytics/example/ios/Runner/Base.lproj/Main.storyboard b/packages/firebase_analytics/example/ios/Runner/Base.lproj/Main.storyboard
new file mode 100755
index 000000000000..f3c28516fb38
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner/Base.lproj/Main.storyboard
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_analytics/example/ios/Runner/GoogleService-Info.plist b/packages/firebase_analytics/example/ios/Runner/GoogleService-Info.plist
new file mode 100755
index 000000000000..515c84c63cdf
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner/GoogleService-Info.plist
@@ -0,0 +1,40 @@
+
+
+
+
+ AD_UNIT_ID_FOR_BANNER_TEST
+ ca-app-pub-3940256099942544/2934735716
+ AD_UNIT_ID_FOR_INTERSTITIAL_TEST
+ ca-app-pub-3940256099942544/4411468910
+ CLIENT_ID
+ 389050544128-8b1peb2i3ai7o7gpdoemu044m61db209.apps.googleusercontent.com
+ REVERSED_CLIENT_ID
+ com.googleusercontent.apps.389050544128-8b1peb2i3ai7o7gpdoemu044m61db209
+ API_KEY
+ AIzaSyCKms_Et6CUgO9xu2RxwM6z5qFWXMdbMNc
+ GCM_SENDER_ID
+ 389050544128
+ PLIST_VERSION
+ 1
+ BUNDLE_ID
+ io.flutter.firebaseanalytics
+ PROJECT_ID
+ flutterfire-analytics-test
+ STORAGE_BUCKET
+ flutterfire-analytics-test.appspot.com
+ IS_ADS_ENABLED
+
+ IS_ANALYTICS_ENABLED
+
+ IS_APPINVITE_ENABLED
+
+ IS_GCM_ENABLED
+
+ IS_SIGNIN_ENABLED
+
+ GOOGLE_APP_ID
+ 1:389050544128:ios:d6252587c74a8055
+ DATABASE_URL
+ https://flutterfire-analytics-test.firebaseio.com
+
+
\ No newline at end of file
diff --git a/packages/firebase_analytics/example/ios/Runner/Info.plist b/packages/firebase_analytics/example/ios/Runner/Info.plist
new file mode 100755
index 000000000000..50d501fd1f7f
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner/Info.plist
@@ -0,0 +1,49 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ firebase_analytics_example
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIViewControllerBasedStatusBarAppearance
+
+
+
diff --git a/packages/firebase_analytics/example/ios/Runner/main.m b/packages/firebase_analytics/example/ios/Runner/main.m
new file mode 100755
index 000000000000..1bdb8e28d1db
--- /dev/null
+++ b/packages/firebase_analytics/example/ios/Runner/main.m
@@ -0,0 +1,10 @@
+#import
+#import
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil,
+ NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/packages/firebase_analytics/example/lib/main.dart b/packages/firebase_analytics/example/lib/main.dart
new file mode 100755
index 000000000000..ec15812ced98
--- /dev/null
+++ b/packages/firebase_analytics/example/lib/main.dart
@@ -0,0 +1,291 @@
+// Copyright 2017 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:flutter/material.dart';
+import 'package:firebase_analytics/firebase_analytics.dart';
+
+void main() {
+ runApp(new MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new MaterialApp(
+ title: 'Firebase Analytics Demo',
+ theme: new ThemeData(
+ primarySwatch: Colors.blue,
+ ),
+ home: new MyHomePage(title: 'Firebase Analytics Demo'),
+ );
+ }
+}
+
+class MyHomePage extends StatefulWidget {
+ MyHomePage({Key key, this.title}) : super(key: key);
+
+ final String title;
+
+ @override
+ _MyHomePageState createState() => new _MyHomePageState();
+}
+
+class _MyHomePageState extends State {
+ String _message = '';
+ final FirebaseAnalytics analytics = new FirebaseAnalytics();
+
+ void setMessage(String message) {
+ setState(() {
+ _message = message;
+ });
+ }
+
+ Future _sendAnalyticsEvent() async {
+ await analytics.logEvent(name: 'test_event');
+ setMessage('logEvent succeeded');
+ }
+
+ Future _testSetUserId() async {
+ await analytics.setUserId('some-user');
+ setMessage('setUserId succeeded');
+ }
+
+ Future _testSetCurrentScreen() async {
+ await analytics.setCurrentScreen(
+ screenName: 'Analytics Demo',
+ screenClassOverride: 'AnalyticsDemo',
+ );
+ setMessage('setCurrentScreen succeeded');
+ }
+
+ Future _testSetAnalyticsCollectionEnabled() async {
+ await analytics.android?.setAnalyticsCollectionEnabled(false);
+ await analytics.android?.setAnalyticsCollectionEnabled(true);
+ setMessage('setAnalyticsCollectionEnabled succeeded');
+ }
+
+ Future _testSetMinimumSessionDuration() async {
+ await analytics.android?.setMinimumSessionDuration(20000);
+ setMessage('setMinimumSessionDuration succeeded');
+ }
+
+ Future _testSetSessionTimeoutDuration() async {
+ await analytics.android?.setSessionTimeoutDuration(2000000);
+ setMessage('setSessionTimeoutDuration succeeded');
+ }
+
+ Future _testSetUserProperty() async {
+ await analytics.setUserProperty(name: 'regular', value: 'indeed');
+ setMessage('setUserProperty succeeded');
+ }
+
+ Future _testAllEventTypes() async {
+ await analytics.logAddPaymentInfo();
+ await analytics.logAddToCart(
+ currency: 'USD',
+ value: 123.0,
+ itemId: 'test item id',
+ itemName: 'test item name',
+ itemCategory: 'test item category',
+ quantity: 5,
+ price: 24.0,
+ origin: 'test origin',
+ itemLocationId: 'test location id',
+ destination: 'test destination',
+ startDate: '2015-09-14',
+ endDate: '2015-09-17',
+ );
+ await analytics.logAddToWishlist(
+ itemId: 'test item id',
+ itemName: 'test item name',
+ itemCategory: 'test item category',
+ quantity: 5,
+ price: 24.0,
+ value: 123.0,
+ currency: 'USD',
+ itemLocationId: 'test location id',
+ );
+ await analytics.logAppOpen();
+ await analytics.logBeginCheckout(
+ value: 123.0,
+ currency: 'USD',
+ transactionId: 'test tx id',
+ numberOfNights: 2,
+ numberOfRooms: 3,
+ numberOfPassengers: 4,
+ origin: 'test origin',
+ destination: 'test destination',
+ startDate: '2015-09-14',
+ endDate: '2015-09-17',
+ travelClass: 'test travel class',
+ );
+ await analytics.logCampaignDetails(
+ source: 'test source',
+ medium: 'test medium',
+ campaign: 'test campaign',
+ term: 'test term',
+ content: 'test content',
+ aclid: 'test aclid',
+ cp1: 'test cp1',
+ );
+ await analytics.logEarnVirtualCurrency(
+ virtualCurrencyName: 'bitcoin',
+ value: 345.66,
+ );
+ await analytics.logEcommercePurchase(
+ currency: 'USD',
+ value: 432.45,
+ transactionId: 'test tx id',
+ tax: 3.45,
+ shipping: 5.67,
+ coupon: 'test coupon',
+ location: 'test location',
+ numberOfNights: 3,
+ numberOfRooms: 4,
+ numberOfPassengers: 5,
+ origin: 'test origin',
+ destination: 'test destination',
+ startDate: '2015-09-13',
+ endDate: '2015-09-14',
+ travelClass: 'test travel class',
+ );
+ await analytics.logGenerateLead(
+ currency: 'USD',
+ value: 123.45,
+ );
+ await analytics.logJoinGroup(
+ groupId: 'test group id',
+ );
+ await analytics.logLevelUp(
+ level: 5,
+ character: 'witch doctor',
+ );
+ await analytics.logLogin();
+ await analytics.logPostScore(
+ score: 1000000,
+ level: 70,
+ character: 'tiefling cleric',
+ );
+ await analytics.logPresentOffer(
+ itemId: 'test item id',
+ itemName: 'test item name',
+ itemCategory: 'test item category',
+ quantity: 6,
+ price: 3.45,
+ value: 67.8,
+ currency: 'USD',
+ itemLocationId: 'test item location id',
+ );
+ await analytics.logPurchaseRefund(
+ currency: 'USD',
+ value: 45.67,
+ transactionId: 'test tx id',
+ );
+ await analytics.logSearch(
+ searchTerm: 'hotel',
+ numberOfNights: 2,
+ numberOfRooms: 1,
+ numberOfPassengers: 3,
+ origin: 'test origin',
+ destination: 'test destination',
+ startDate: '2015-09-14',
+ endDate: '2015-09-16',
+ travelClass: 'test travel class',
+ );
+ await analytics.logSelectContent(
+ contentType: 'test content type',
+ itemId: 'test item id',
+ );
+ await analytics.logShare(
+ contentType: 'test content type',
+ itemId: 'test item id',
+ );
+ await analytics.logSignUp(
+ signUpMethod: 'test sign up method',
+ );
+ await analytics.logSpendVirtualCurrency(
+ itemName: 'test item name',
+ virtualCurrencyName: 'bitcoin',
+ value: 34,
+ );
+ await analytics.logTutorialBegin();
+ await analytics.logTutorialComplete();
+ await analytics.logUnlockAchievement(id: 'all Firebase API covered');
+ await analytics.logViewItem(
+ itemId: 'test item id',
+ itemName: 'test item name',
+ itemCategory: 'test item category',
+ itemLocationId: 'test item location id',
+ price: 3.45,
+ quantity: 6,
+ currency: 'USD',
+ value: 67.8,
+ flightNumber: 'test flight number',
+ numberOfPassengers: 3,
+ numberOfRooms: 1,
+ numberOfNights: 2,
+ origin: 'test origin',
+ destination: 'test destination',
+ startDate: '2015-09-14',
+ endDate: '2015-09-15',
+ searchTerm: 'test search term',
+ travelClass: 'test travel class',
+ );
+ await analytics.logViewItemList(
+ itemCategory: 'test item category',
+ );
+ await analytics.logViewSearchResults(
+ searchTerm: 'test search term',
+ );
+ setMessage('All standard events logged successfully');
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return new Scaffold(
+ appBar: new AppBar(
+ title: new Text(widget.title),
+ ),
+ body: new Column(
+ children: [
+ new MaterialButton(
+ child: const Text('Test logEvent'),
+ onPressed: _sendAnalyticsEvent,
+ ),
+ new MaterialButton(
+ child: const Text('Test standard event types'),
+ onPressed: _testAllEventTypes,
+ ),
+ new MaterialButton(
+ child: const Text('Test setUserId'),
+ onPressed: _testSetUserId,
+ ),
+ new MaterialButton(
+ child: const Text('Test setCurrentScreen'),
+ onPressed: _testSetCurrentScreen,
+ ),
+ new MaterialButton(
+ child: const Text('Test setAnalyticsCollectionEnabled'),
+ onPressed: _testSetAnalyticsCollectionEnabled,
+ ),
+ new MaterialButton(
+ child: const Text('Test setMinimumSessionDuration'),
+ onPressed: _testSetMinimumSessionDuration,
+ ),
+ new MaterialButton(
+ child: const Text('Test setSessionTimeoutDuration'),
+ onPressed: _testSetSessionTimeoutDuration,
+ ),
+ new MaterialButton(
+ child: const Text('Test setUserProperty'),
+ onPressed: _testSetUserProperty,
+ ),
+ new Text(_message, style: const TextStyle(color: const Color.fromARGB(255, 0, 155, 0))),
+ ],
+ ),
+ );
+ }
+}
diff --git a/packages/firebase_analytics/example/pubspec.yaml b/packages/firebase_analytics/example/pubspec.yaml
new file mode 100755
index 000000000000..c4cb03a3242f
--- /dev/null
+++ b/packages/firebase_analytics/example/pubspec.yaml
@@ -0,0 +1,53 @@
+name: firebase_analytics_example
+description: Demonstrates how to use the firebase_analytics plugin.
+
+dependencies:
+ flutter:
+ sdk: flutter
+ firebase_analytics:
+ path: ../
+
+# For information on the generic Dart part of this file, see the
+# following page: https://www.dartlang.org/tools/pub/pubspec
+
+# The following section is specific to Flutter.
+flutter:
+
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section here, in
+ # this "flutter" section, as in:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # To add assets from package dependencies, first ensure the asset
+ # is in the lib/ directory of the dependency. Then,
+ # refer to the asset with a path prefixed with
+ # `packages/PACKAGE_NAME/`. Note: the `lib/` is implied, do not
+ # include `lib/` in the asset path.
+ #
+ # Here is an example:
+ #
+ # assets:
+ # - packages/PACKAGE_NAME/path/to/asset
+
+ # 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
diff --git a/packages/firebase_analytics/ios/.gitignore b/packages/firebase_analytics/ios/.gitignore
new file mode 100755
index 000000000000..956c87f3aa28
--- /dev/null
+++ b/packages/firebase_analytics/ios/.gitignore
@@ -0,0 +1,31 @@
+.idea/
+.vagrant/
+.sconsign.dblite
+.svn/
+
+.DS_Store
+*.swp
+profile
+
+DerivedData/
+build/
+
+*.pbxuser
+*.mode1v3
+*.mode2v3
+*.perspectivev3
+
+!default.pbxuser
+!default.mode1v3
+!default.mode2v3
+!default.perspectivev3
+
+xcuserdata
+
+*.moved-aside
+
+*.pyc
+*sync/
+Icon?
+.tags*
+
diff --git a/packages/firebase_analytics/ios/Assets/.gitkeep b/packages/firebase_analytics/ios/Assets/.gitkeep
new file mode 100755
index 000000000000..e69de29bb2d1
diff --git a/packages/firebase_analytics/ios/Classes/FirebaseAnalyticsPlugin.h b/packages/firebase_analytics/ios/Classes/FirebaseAnalyticsPlugin.h
new file mode 100755
index 000000000000..93f8d43c3cf7
--- /dev/null
+++ b/packages/firebase_analytics/ios/Classes/FirebaseAnalyticsPlugin.h
@@ -0,0 +1,8 @@
+// Copyright 2017 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
+
+@interface FirebaseAnalyticsPlugin : NSObject
+@end
diff --git a/packages/firebase_analytics/ios/Classes/FirebaseAnalyticsPlugin.m b/packages/firebase_analytics/ios/Classes/FirebaseAnalyticsPlugin.m
new file mode 100755
index 000000000000..60d44966c174
--- /dev/null
+++ b/packages/firebase_analytics/ios/Classes/FirebaseAnalyticsPlugin.m
@@ -0,0 +1,63 @@
+// Copyright 2017 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 "FirebaseAnalyticsPlugin.h"
+
+#import "Firebase/Firebase.h"
+
+@implementation FirebaseAnalyticsPlugin {
+}
+
++ (void)registerWithRegistrar:(NSObject *)registrar {
+ FlutterMethodChannel *channel =
+ [FlutterMethodChannel methodChannelWithName:@"firebase_analytics"
+ binaryMessenger:[registrar messenger]];
+ FirebaseAnalyticsPlugin *instance = [[FirebaseAnalyticsPlugin alloc] init];
+ [registrar addMethodCallDelegate:instance channel:channel];
+}
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ if (![FIRApp defaultApp]) {
+ [FIRApp configure];
+ }
+ }
+ return self;
+}
+
+- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
+ if ([@"logEvent" isEqualToString:call.method]) {
+ NSString *eventName = call.arguments[@"name"];
+ id parameterMap = call.arguments[@"parameters"];
+
+ if (parameterMap != [NSNull null]) {
+ [FIRAnalytics logEventWithName:eventName
+ parameters:parameterMap];
+ } else {
+ [FIRAnalytics logEventWithName:eventName
+ parameters:nil];
+ }
+
+ result(nil);
+ } else if ([@"setUserId" isEqualToString:call.method]) {
+ NSString *userId = call.arguments;
+ [FIRAnalytics setUserID:userId];
+ result(nil);
+ } else if ([@"setCurrentScreen" isEqualToString:call.method]) {
+ NSString *screenName = call.arguments[@"screenName"];
+ NSString *screenClassOverride = call.arguments[@"screenClassOverride"];
+ [FIRAnalytics setScreenName:screenName screenClass:screenClassOverride];
+ result(nil);
+ } else if ([@"setUserProperty" isEqualToString:call.method]) {
+ NSString *name = call.arguments[@"name"];
+ NSString *value = call.arguments[@"value"];
+ [FIRAnalytics setUserPropertyString:value forName:name];
+ result(nil);
+ } else {
+ result(FlutterMethodNotImplemented);
+ }
+}
+
+@end
diff --git a/packages/firebase_analytics/ios/firebase_analytics.podspec b/packages/firebase_analytics/ios/firebase_analytics.podspec
new file mode 100755
index 000000000000..5ab1bbb86f46
--- /dev/null
+++ b/packages/firebase_analytics/ios/firebase_analytics.podspec
@@ -0,0 +1,20 @@
+#
+# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
+#
+Pod::Spec.new do |s|
+ s.name = 'firebase_analytics'
+ s.version = '0.0.1'
+ s.summary = 'Firebase Analytics plugin for Flutter.'
+ s.description = <<-DESC
+Firebase Analytics plugin for Flutter.
+ DESC
+ s.homepage = 'https://github.com/flutter/plugins/tree/master/packages/firebase_analytics'
+ s.license = { :file => '../LICENSE' }
+ s.author = { 'Flutter Team' => 'flutter-dev@googlegroups.com' }
+ s.source = { :path => '.' }
+ s.source_files = 'Classes/**/*'
+ s.public_header_files = 'Classes/**/*.h'
+ s.ios.deployment_target = '6.0'
+ s.dependency 'Flutter'
+ s.dependency 'Firebase/Core'
+end
diff --git a/packages/firebase_analytics/lib/firebase_analytics.dart b/packages/firebase_analytics/lib/firebase_analytics.dart
new file mode 100755
index 000000000000..62b2a0800abd
--- /dev/null
+++ b/packages/firebase_analytics/lib/firebase_analytics.dart
@@ -0,0 +1,968 @@
+// Copyright 2017 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:meta/meta.dart';
+
+import 'package:flutter/services.dart';
+import 'package:flutter/foundation.dart';
+
+/// Firebase Analytics API.
+class FirebaseAnalytics {
+ static final FirebaseAnalytics _instance = new FirebaseAnalytics.private(const MethodChannel('firebase_analytics'));
+
+ /// Provides an instance of this class.
+ factory FirebaseAnalytics() => _instance;
+
+ /// We don't want people to extend this class, but implementing its interface,
+ /// e.g. in tests, is OK.
+ @visibleForTesting
+ FirebaseAnalytics.private(MethodChannel platformChannel)
+ : _channel = platformChannel,
+ android = defaultTargetPlatform == TargetPlatform.android
+ ? new FirebaseAnalyticsAndroid.private(platformChannel)
+ : null;
+
+ final MethodChannel _channel;
+
+ /// Namespace for analytics API available on Android only.
+ ///
+ /// The value of this field is `null` on non-Android platforms. If you are
+ /// writing cross-platform code, consider using null-aware operator when
+ /// accessing it.
+ ///
+ /// Example:
+ ///
+ /// FirebaseAnalytics analytics = new FirebaseAnalytics();
+ /// analytics.android?.setMinimumSessionDuration(200000);
+ final FirebaseAnalyticsAndroid android;
+
+ /// Logs a custom Flutter Analytics event with the given [name] and event [parameters].
+ Future logEvent({@required String name, Map parameters}) async {
+ if (_reservedEventNames.contains(name)) {
+ throw new ArgumentError.value(name, 'name',
+ 'Event name is reserved and cannot be used');
+ }
+
+ const String kReservedPrefix = 'firebase_';
+
+ if (name.startsWith(kReservedPrefix)) {
+ throw new ArgumentError.value(name, 'name',
+ 'Prefix "$kReservedPrefix" is reserved and cannot be used.');
+ }
+
+ await _channel.invokeMethod('logEvent', {
+ 'name': name,
+ 'parameters': parameters,
+ });
+ }
+
+ /// Sets the user ID property.
+ ///
+ /// This feature must be used in accordance with [Google's Privacy Policy][1].
+ ///
+ /// [1]: https://www.google.com/policies/privacy/
+ Future setUserId(String id) async {
+ if (id == null)
+ throw new ArgumentError.notNull('id');
+
+ await _channel.invokeMethod('setUserId', id);
+ }
+
+ /// Sets the current [screenName], which specifies the current visual context
+ /// in your app.
+ ///
+ /// This helps identify the areas in your app where users spend their time
+ /// and how they interact with your app.
+ ///
+ /// The class name can optionally be overridden by the [screenClassOverride]
+ /// parameter.
+ ///
+ /// The [screenName] and [screenClassOverride] remain in effect until the
+ /// current `Activity` (in Android) or `UIViewController` (in iOS) changes or
+ /// a new call to [setCurrentScreen] is made.
+ ///
+ /// See also:
+ ///
+ /// https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.html#setCurrentScreen(android.app.Activity, java.lang.String, java.lang.String)
+ /// https://firebase.google.com/docs/reference/ios/firebaseanalytics/api/reference/Classes/FIRAnalytics#setscreennamescreenclass
+ Future setCurrentScreen({@required String screenName, String screenClassOverride}) async {
+ if (screenName == null)
+ throw new ArgumentError.notNull('screenName');
+
+ await _channel.invokeMethod('setCurrentScreen', {
+ 'screenName': screenName,
+ 'screenClassOverride': screenClassOverride,
+ });
+ }
+
+ static final RegExp _nonAlphaNumeric = new RegExp(r'[^a-zA-Z0-9_]');
+ static final RegExp _alpha = new RegExp(r'[a-zA-Z]');
+
+ /// Sets a user property to a given value.
+ ///
+ /// Up to 25 user property names are supported. Once set, user property
+ /// values persist throughout the app lifecycle and across sessions.
+ ///
+ /// [name] is the name of the user property to set. Should contain 1 to 24
+ /// alphanumeric characters or underscores and must start with an alphabetic
+ /// character. The "firebase_" prefix is reserved and should not be used for
+ /// user property names.
+ Future setUserProperty({@required String name, @required String value}) async {
+ if (name == null)
+ throw new ArgumentError.notNull('name');
+
+ if (name.isEmpty || name.length > 24 || name.indexOf(_alpha) != 0 || name.contains(_nonAlphaNumeric))
+ throw new ArgumentError.value(name, 'name', 'must contain 1 to 24 alphanumeric characters.');
+
+ if (name.startsWith('firebase_'))
+ throw new ArgumentError.value(name, 'name', '"firebase_" prefix is reserved');
+
+ await _channel.invokeMethod('setUserProperty', {
+ 'name': name,
+ 'value': value,
+ });
+ }
+
+ /// Logs the standard `add_payment_info` event.
+ ///
+ /// This event signifies that a user has submitted their payment information
+ /// to your app.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#ADD_PAYMENT_INFO
+ Future logAddPaymentInfo() {
+ return logEvent(name: 'add_payment_info');
+ }
+
+ /// Logs the standard `add_to_cart` event.
+ ///
+ /// This event signifies that an item was added to a cart for purchase. Add
+ /// this event to a funnel with [logEcommercePurchase] to gauge the
+ /// effectiveness of your checkout process. Note: If you supply the
+ /// [value] parameter, you must also supply the [currency] parameter so that
+ /// revenue metrics can be computed accurately.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#ADD_TO_CART
+ Future logAddToCart({
+ @required String itemId,
+ @required String itemName,
+ @required String itemCategory,
+ @required int quantity,
+ double price,
+ double value,
+ String currency,
+ String origin,
+ String itemLocationId,
+ String destination,
+ String startDate,
+ String endDate,
+ }) {
+ _requireValueAndCurrencyTogether(value, currency);
+
+ return logEvent(
+ name: 'add_to_cart',
+ parameters: filterOutNulls({
+ _ITEM_ID: itemId,
+ _ITEM_NAME: itemName,
+ _ITEM_CATEGORY: itemCategory,
+ _QUANTITY: quantity,
+ _PRICE: price,
+ _VALUE: value,
+ _CURRENCY: currency,
+ _ORIGIN: origin,
+ _ITEM_LOCATION_ID: itemLocationId,
+ _DESTINATION: destination,
+ _START_DATE: startDate,
+ _END_DATE: endDate,
+ }),
+ );
+ }
+
+ /// Logs the standard `add_to_wishlist` event.
+ ///
+ /// This event signifies that an item was added to a wishlist. Use this event
+ /// to identify popular gift items in your app. Note: If you supply the
+ /// [value] parameter, you must also supply the [currency] parameter so that
+ /// revenue metrics can be computed accurately.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#ADD_TO_WISHLIST
+ Future logAddToWishlist({
+ @required String itemId,
+ @required String itemName,
+ @required String itemCategory,
+ @required int quantity,
+ double price,
+ double value,
+ String currency,
+ String itemLocationId,
+ }) {
+ _requireValueAndCurrencyTogether(value, currency);
+
+ return logEvent(
+ name: 'add_to_wishlist',
+ parameters: filterOutNulls({
+ _ITEM_ID: itemId,
+ _ITEM_NAME: itemName,
+ _ITEM_CATEGORY: itemCategory,
+ _QUANTITY: quantity,
+ _PRICE: price,
+ _VALUE: value,
+ _CURRENCY: currency,
+ _ITEM_LOCATION_ID: itemLocationId,
+ }),
+ );
+ }
+
+ /// Logs the standard `app_open` event.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#APP_OPEN
+ Future logAppOpen() {
+ return logEvent(name: 'app_open');
+ }
+
+ /// Logs the standard `begin_checkout` event.
+ ///
+ /// This event signifies that a user has begun the process of checking out.
+ /// Add this event to a funnel with your [logEcommercePurchase] event to
+ /// gauge the effectiveness of your checkout process. Note: If you supply the
+ /// [value] parameter, you must also supply the [currency] parameter so that
+ /// revenue metrics can be computed accurately.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#BEGIN_CHECKOUT
+ Future logBeginCheckout({
+ double value,
+ String currency,
+ String transactionId,
+ int numberOfNights,
+ int numberOfRooms,
+ int numberOfPassengers,
+ String origin,
+ String destination,
+ String startDate,
+ String endDate,
+ String travelClass,
+ }) {
+ _requireValueAndCurrencyTogether(value, currency);
+
+ return logEvent(
+ name: 'begin_checkout',
+ parameters: filterOutNulls({
+ _VALUE: value,
+ _CURRENCY: currency,
+ _TRANSACTION_ID: transactionId,
+ _NUMBER_OF_NIGHTS: numberOfNights,
+ _NUMBER_OF_ROOMS: numberOfRooms,
+ _NUMBER_OF_PASSENGERS: numberOfPassengers,
+ _ORIGIN: origin,
+ _DESTINATION: destination,
+ _START_DATE: startDate,
+ _END_DATE: endDate,
+ _TRAVEL_CLASS: travelClass,
+ }),
+ );
+ }
+
+ /// Logs the standard `campaign_details` event.
+ ///
+ /// Log this event to supply the referral details of a re-engagement campaign.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#CAMPAIGN_DETAILS
+ Future logCampaignDetails({
+ @required String source,
+ @required String medium,
+ @required String campaign,
+ String term,
+ String content,
+ String aclid,
+ String cp1,
+ }) {
+ return logEvent(
+ name: 'campaign_details',
+ parameters: filterOutNulls({
+ _SOURCE: source,
+ _MEDIUM: medium,
+ _CAMPAIGN: campaign,
+ _TERM: term,
+ _CONTENT: content,
+ _ACLID: aclid,
+ _CP1: cp1,
+ }),
+ );
+ }
+
+ /// Logs the standard `earn_virtual_currency` event.
+ ///
+ /// This event tracks the awarding of virtual currency in your app. Log this
+ /// along with [logSpendVirtualCurrency] to better understand your virtual
+ /// economy.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#EARN_VIRTUAL_CURRENCY
+ Future logEarnVirtualCurrency({
+ @required String virtualCurrencyName,
+ @required num value,
+ }) {
+ return logEvent(
+ name: 'earn_virtual_currency',
+ parameters: filterOutNulls({
+ _VIRTUAL_CURRENCY_NAME: virtualCurrencyName,
+ _VALUE: value,
+ }),
+ );
+ }
+
+ /// Logs the standard `ecommerce_purchase` event.
+ ///
+ /// This event signifies that an item was purchased by a user. Note: This is
+ /// different from the in-app purchase event, which is reported automatically
+ /// for Google Play-based apps. Note: If you supply the [value] parameter,
+ /// you must also supply the [currency] parameter so that revenue metrics can
+ /// be computed accurately.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#ECOMMERCE_PURCHASE
+ Future logEcommercePurchase({
+ String currency,
+ double value,
+ String transactionId,
+ double tax,
+ double shipping,
+ String coupon,
+ String location,
+ int numberOfNights,
+ int numberOfRooms,
+ int numberOfPassengers,
+ String origin,
+ String destination,
+ String startDate,
+ String endDate,
+ String travelClass,
+ }) {
+ _requireValueAndCurrencyTogether(value, currency);
+
+ return logEvent(
+ name: 'ecommerce_purchase',
+ parameters: filterOutNulls({
+ _CURRENCY: currency,
+ _VALUE: value,
+ _TRANSACTION_ID: transactionId,
+ _TAX: tax,
+ _SHIPPING: shipping,
+ _COUPON: coupon,
+ _LOCATION: location,
+ _NUMBER_OF_NIGHTS: numberOfNights,
+ _NUMBER_OF_ROOMS: numberOfRooms,
+ _NUMBER_OF_PASSENGERS: numberOfPassengers,
+ _ORIGIN: origin,
+ _DESTINATION: destination,
+ _START_DATE: startDate,
+ _END_DATE: endDate,
+ _TRAVEL_CLASS: travelClass,
+ }),
+ );
+ }
+
+ /// Logs the standard `generate_lead` event.
+ ///
+ /// Log this event when a lead has been generated in the app to understand
+ /// the efficacy of your install and re-engagement campaigns. Note: If you
+ /// supply the [value] parameter, you must also supply the [currency]
+ /// parameter so that revenue metrics can be computed accurately.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#GENERATE_LEAD
+ Future logGenerateLead({
+ String currency,
+ double value,
+ }) {
+ _requireValueAndCurrencyTogether(value, currency);
+
+ return logEvent(
+ name: 'generate_lead',
+ parameters: filterOutNulls({
+ _CURRENCY: currency,
+ _VALUE: value,
+ }),
+ );
+ }
+
+ /// Logs the standard `join_group` event.
+ ///
+ /// Log this event when a user joins a group such as a guild, team or family.
+ /// Use this event to analyze how popular certain groups or social features
+ /// are in your app.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#JOIN_GROUP
+ Future logJoinGroup({
+ @required String groupId,
+ }) {
+ return logEvent(
+ name: 'join_group',
+ parameters: filterOutNulls({
+ _GROUP_ID: groupId,
+ }),
+ );
+ }
+
+ /// Logs the standard `level_up` event.
+ ///
+ /// This event signifies that a player has leveled up in your gaming app. It
+ /// can help you gauge the level distribution of your userbase and help you
+ /// identify certain levels that are difficult to pass.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#LEVEL_UP
+ Future logLevelUp({
+ @required int level,
+ String character,
+ }) {
+ return logEvent(
+ name: 'level_up',
+ parameters: filterOutNulls({
+ _LEVEL: level,
+ _CHARACTER: character,
+ }),
+ );
+ }
+
+ /// Logs the standard `login` event.
+ ///
+ /// Apps with a login feature can report this event to signify that a user
+ /// has logged in.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#LOGIN
+ Future logLogin() {
+ return logEvent(name: 'login');
+ }
+
+ /// Logs the standard `post_score` event.
+ ///
+ /// Log this event when the user posts a score in your gaming app. This event
+ /// can help you understand how users are actually performing in your game
+ /// and it can help you correlate high scores with certain audiences or
+ /// behaviors.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#POST_SCORE
+ Future logPostScore({
+ @required int score,
+ int level,
+ String character,
+ }) {
+ return logEvent(
+ name: 'post_score',
+ parameters: filterOutNulls({
+ _SCORE: score,
+ _LEVEL: level,
+ _CHARACTER: character,
+ }),
+ );
+ }
+
+ /// Logs the standard `present_offer` event.
+ ///
+ /// This event signifies that the app has presented a purchase offer to a
+ /// user. Add this event to a funnel with the [logAddToCart] and
+ /// [logEcommercePurchase] to gauge your conversion process. Note: If you
+ /// supply the [value] parameter, you must also supply the [currency]
+ /// parameter so that revenue metrics can be computed accurately.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#PRESENT_OFFER
+ Future logPresentOffer({
+ @required String itemId,
+ @required String itemName,
+ @required String itemCategory,
+ @required int quantity,
+ double price,
+ double value,
+ String currency,
+ String itemLocationId,
+ }) {
+ _requireValueAndCurrencyTogether(value, currency);
+
+ return logEvent(
+ name: 'present_offer',
+ parameters: filterOutNulls({
+ _ITEM_ID: itemId,
+ _ITEM_NAME: itemName,
+ _ITEM_CATEGORY: itemCategory,
+ _QUANTITY: quantity,
+ _PRICE: price,
+ _VALUE: value,
+ _CURRENCY: currency,
+ _ITEM_LOCATION_ID: itemLocationId,
+ }),
+ );
+ }
+
+ /// Logs the standard `purchase_refund` event.
+ ///
+ /// This event signifies that an item purchase was refunded. Note: If you
+ /// supply the [value] parameter, you must also supply the [currency]
+ /// parameter so that revenue metrics can be computed accurately.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#PURCHASE_REFUND
+ Future logPurchaseRefund({
+ String currency,
+ double value,
+ String transactionId,
+ }) {
+ _requireValueAndCurrencyTogether(value, currency);
+
+ return logEvent(
+ name: 'purchase_refund',
+ parameters: filterOutNulls({
+ _CURRENCY: currency,
+ _VALUE: value,
+ _TRANSACTION_ID: transactionId,
+ }),
+ );
+ }
+
+ /// Logs the standard `search` event.
+ ///
+ /// Apps that support search features can use this event to contextualize
+ /// search operations by supplying the appropriate, corresponding parameters.
+ /// This event can help you identify the most popular content in your app.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#SEARCH
+ Future logSearch({
+ @required String searchTerm,
+ int numberOfNights,
+ int numberOfRooms,
+ int numberOfPassengers,
+ String origin,
+ String destination,
+ String startDate,
+ String endDate,
+ String travelClass,
+ }) {
+ return logEvent(
+ name: 'search',
+ parameters: filterOutNulls({
+ _SEARCH_TERM: searchTerm,
+ _NUMBER_OF_NIGHTS: numberOfNights,
+ _NUMBER_OF_ROOMS: numberOfRooms,
+ _NUMBER_OF_PASSENGERS: numberOfPassengers,
+ _ORIGIN: origin,
+ _DESTINATION: destination,
+ _START_DATE: startDate,
+ _END_DATE: endDate,
+ _TRAVEL_CLASS: travelClass,
+ }),
+ );
+ }
+
+ /// Logs the standard `select_content` event.
+ ///
+ /// This general purpose event signifies that a user has selected some
+ /// content of a certain type in an app. The content can be any object in
+ /// your app. This event can help you identify popular content and categories
+ /// of content in your app.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#SELECT_CONTENT
+ Future logSelectContent({
+ @required String contentType,
+ @required String itemId,
+ }) {
+ return logEvent(
+ name: 'select_content',
+ parameters: filterOutNulls({
+ _CONTENT_TYPE: contentType,
+ _ITEM_ID: itemId,
+ }),
+ );
+ }
+
+ /// Logs the standard `share` event.
+ ///
+ /// Apps with social features can log the Share event to identify the most
+ /// viral content.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#SHARE
+ Future logShare({
+ @required String contentType,
+ @required String itemId,
+ }) {
+ return logEvent(
+ name: 'share',
+ parameters: filterOutNulls({
+ _CONTENT_TYPE: contentType,
+ _ITEM_ID: itemId,
+ }),
+ );
+ }
+
+ /// Logs the standard `sign_up` event.
+ ///
+ /// This event indicates that a user has signed up for an account in your
+ /// app. The parameter signifies the method by which the user signed up. Use
+ /// this event to understand the different behaviors between logged in and
+ /// logged out users.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#SIGN_UP
+ Future logSignUp({
+ @required String signUpMethod,
+ }) {
+ return logEvent(
+ name: 'sign_up',
+ parameters: filterOutNulls({
+ _SIGN_UP_METHOD: signUpMethod,
+ }),
+ );
+ }
+
+ /// Logs the standard `spend_virtual_currency` event.
+ ///
+ /// This event tracks the sale of virtual goods in your app and can help you
+ /// identify which virtual goods are the most popular objects of purchase.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#SPEND_VIRTUAL_CURRENCY
+ Future logSpendVirtualCurrency({
+ @required String itemName,
+ @required String virtualCurrencyName,
+ @required num value,
+ }) {
+ return logEvent(
+ name: 'spend_virtual_currency',
+ parameters: filterOutNulls({
+ _ITEM_NAME: itemName,
+ _VIRTUAL_CURRENCY_NAME: virtualCurrencyName,
+ _VALUE: value,
+ }),
+ );
+ }
+
+ /// Logs the standard `tutorial_begin` event.
+ ///
+ /// This event signifies the start of the on-boarding process in your app.
+ /// Use this in a funnel with [logTutorialComplete] to understand how many
+ /// users complete this process and move on to the full app experience.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#TUTORIAL_BEGIN
+ Future logTutorialBegin() {
+ return logEvent(name: 'tutorial_begin');
+ }
+
+ /// Logs the standard `tutorial_complete` event.
+ ///
+ /// Use this event to signify the user's completion of your app's on-boarding
+ /// process. Add this to a funnel with [logTutorialBegin] to gauge the
+ /// completion rate of your on-boarding process.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#TUTORIAL_COMPLETE
+ Future logTutorialComplete() {
+ return logEvent(name: 'tutorial_complete');
+ }
+
+ /// Logs the standard `unlock_achievement` event with a given achievement
+ /// [id].
+ ///
+ /// Log this event when the user has unlocked an achievement in your game.
+ /// Since achievements generally represent the breadth of a gaming
+ /// experience, this event can help you understand how many users are
+ /// experiencing all that your game has to offer.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#UNLOCK_ACHIEVEMENT
+ Future logUnlockAchievement({
+ @required String id,
+ }) {
+ return logEvent(
+ name: 'unlock_achievement',
+ parameters: filterOutNulls({
+ _ACHIEVEMENT_ID: id,
+ }),
+ );
+ }
+
+ /// Logs the standard `view_item` event.
+ ///
+ /// This event signifies that some content was shown to the user. This
+ /// content may be a product, a webpage or just a simple image or text. Use
+ /// the appropriate parameters to contextualize the event. Use this event to
+ /// discover the most popular items viewed in your app. Note: If you supply
+ /// the [value] parameter, you must also supply the [currency] parameter so
+ /// that revenue metrics can be computed accurately.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#VIEW_ITEM
+ Future logViewItem({
+ @required String itemId,
+ @required String itemName,
+ @required String itemCategory,
+ String itemLocationId,
+ double price,
+ int quantity,
+ String currency,
+ double value,
+ String flightNumber,
+ int numberOfPassengers,
+ int numberOfNights,
+ int numberOfRooms,
+ String origin,
+ String destination,
+ String startDate,
+ String endDate,
+ String searchTerm,
+ String travelClass,
+ }) {
+ _requireValueAndCurrencyTogether(value, currency);
+
+ return logEvent(
+ name: 'view_item',
+ parameters: filterOutNulls({
+ _ITEM_ID: itemId,
+ _ITEM_NAME: itemName,
+ _ITEM_CATEGORY: itemCategory,
+ _ITEM_LOCATION_ID: itemLocationId,
+ _PRICE: price,
+ _QUANTITY: quantity,
+ _CURRENCY: currency,
+ _VALUE: value,
+ _FLIGHT_NUMBER: flightNumber,
+ _NUMBER_OF_PASSENGERS: numberOfPassengers,
+ _NUMBER_OF_NIGHTS: numberOfNights,
+ _NUMBER_OF_ROOMS: numberOfRooms,
+ _ORIGIN: origin,
+ _DESTINATION: destination,
+ _START_DATE: startDate,
+ _END_DATE: endDate,
+ _SEARCH_TERM: searchTerm,
+ _TRAVEL_CLASS: travelClass,
+ }),
+ );
+ }
+
+ /// Logs the standard `view_item_list` event.
+ ///
+ /// Log this event when the user has been presented with a list of items of a
+ /// certain category.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#VIEW_ITEM_LIST
+ Future logViewItemList({
+ @required String itemCategory,
+ }) {
+ return logEvent(
+ name: 'view_item_list',
+ parameters: filterOutNulls({
+ _ITEM_CATEGORY: itemCategory,
+ }),
+ );
+ }
+
+ /// Logs the standard `view_search_results` event.
+ ///
+ /// Log this event when the user has been presented with the results of a
+ /// search.
+ ///
+ /// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html#VIEW_SEARCH_RESULTS
+ Future logViewSearchResults({
+ @required String searchTerm,
+ }) {
+ return logEvent(
+ name: 'view_search_results',
+ parameters: filterOutNulls({
+ _SEARCH_TERM: searchTerm,
+ }),
+ );
+ }
+}
+
+/// Android-specific analytics API.
+class FirebaseAnalyticsAndroid {
+ final MethodChannel _channel;
+
+ @visibleForTesting
+ const FirebaseAnalyticsAndroid.private(this._channel);
+
+ /// Sets whether analytics collection is enabled for this app on this device.
+ ///
+ /// This setting is persisted across app sessions. By default it is enabled.
+ Future setAnalyticsCollectionEnabled(bool enabled) async {
+ if (enabled == null)
+ throw new ArgumentError.notNull('enabled');
+
+ await _channel.invokeMethod('setAnalyticsCollectionEnabled', enabled);
+ }
+
+ /// Sets the minimum engagement time required before starting a session.
+ ///
+ /// The default value is 10000 (10 seconds).
+ Future setMinimumSessionDuration(int milliseconds) async {
+ if (milliseconds == null)
+ throw new ArgumentError.notNull('milliseconds');
+
+ await _channel.invokeMethod('setMinimumSessionDuration', milliseconds);
+ }
+
+ /// Sets the duration of inactivity that terminates the current session.
+ ///
+ /// The default value is 1800000 (30 minutes).
+ Future setSessionTimeoutDuration(int milliseconds) async {
+ if (milliseconds == null)
+ throw new ArgumentError.notNull('milliseconds');
+
+ await _channel.invokeMethod('setSessionTimeoutDuration', milliseconds);
+ }
+}
+
+/// Creates a new map containing all of the key/value pairs from [parameters]
+/// except those whose value is `null`.
+@visibleForTesting
+Map filterOutNulls(Map parameters) {
+ final Map filtered = {};
+ parameters.forEach((String key, dynamic value) {
+ if (value != null)
+ filtered[key] = value;
+ });
+ return filtered;
+}
+
+@visibleForTesting
+const String valueAndCurrencyMustBeTogetherError = 'If you supply the "value" '
+ 'parameter, you must also supply the "currency" parameter.';
+
+void _requireValueAndCurrencyTogether(double value, String currency) {
+ if (value != null && currency == null) {
+ throw new ArgumentError(valueAndCurrencyMustBeTogetherError);
+ }
+}
+
+/// Reserved event names that cannot be used.
+///
+/// See: https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event.html
+const List _reservedEventNames = const [
+ 'app_clear_data',
+ 'app_uninstall',
+ 'app_update',
+ 'error',
+ 'first_open',
+ 'in_app_purchase',
+ 'notification_dismiss',
+ 'notification_foreground',
+ 'notification_open',
+ 'notification_receive',
+ 'os_update',
+ 'session_start',
+ 'user_engagement',
+];
+
+// The following constants are defined in:
+//
+// https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Param.html
+
+/// Game achievement ID.
+const String _ACHIEVEMENT_ID = 'achievement_id';
+
+/// `CAMPAIGN_DETAILS` click ID.
+const String _ACLID = 'aclid';
+
+/// `CAMPAIGN_DETAILS` name; used for keyword analysis to identify a specific
+/// product promotion or strategic campaign.
+const String _CAMPAIGN = 'campaign';
+
+/// Character used in game.
+const String _CHARACTER = 'character';
+
+/// `CAMPAIGN_DETAILS` content; used for A/B testing and content-targeted ads to
+/// differentiate ads or links that point to the same URL.
+const String _CONTENT = 'content';
+
+/// Type of content selected.
+const String _CONTENT_TYPE = 'content_type';
+
+/// Coupon code for a purchasable item.
+const String _COUPON = 'coupon';
+
+/// `CAMPAIGN_DETAILS` custom parameter.
+const String _CP1 = 'cp1';
+
+/// Purchase currency in 3 letter ISO_4217 format.
+const String _CURRENCY = 'currency';
+
+/// Flight or Travel destination.
+const String _DESTINATION = 'destination';
+
+/// The arrival date, check-out date, or rental end date for the item.
+const String _END_DATE = 'end_date';
+
+/// Flight number for travel events.
+const String _FLIGHT_NUMBER = 'flight_number';
+
+/// Group/clan/guild id.
+const String _GROUP_ID = 'group_id';
+
+/// Item category.
+const String _ITEM_CATEGORY = 'item_category';
+
+/// Item ID.
+const String _ITEM_ID = 'item_id';
+
+/// The Google Place ID that corresponds to the associated item.
+const String _ITEM_LOCATION_ID = 'item_location_id';
+
+/// Item name.
+const String _ITEM_NAME = 'item_name';
+
+/// Level in game (long).
+const String _LEVEL = 'level';
+
+/// Location.
+const String _LOCATION = 'location';
+
+/// `CAMPAIGN_DETAILS` medium; used to identify a medium such as email or
+/// cost-per-click (cpc).
+const String _MEDIUM = 'medium';
+
+/// Number of nights staying at hotel (long).
+const String _NUMBER_OF_NIGHTS = 'number_of_nights';
+
+/// Number of passengers traveling (long).
+const String _NUMBER_OF_PASSENGERS = 'number_of_passengers';
+
+/// Number of rooms for travel events (long).
+const String _NUMBER_OF_ROOMS = 'number_of_rooms';
+
+/// Flight or Travel origin.
+const String _ORIGIN = 'origin';
+
+/// Purchase price (double).
+const String _PRICE = 'price';
+
+/// Purchase quantity (long).
+const String _QUANTITY = 'quantity';
+
+/// Score in game (long).
+const String _SCORE = 'score';
+
+/// The search string/keywords used.
+const String _SEARCH_TERM = 'search_term';
+
+/// Shipping cost (double).
+const String _SHIPPING = 'shipping';
+
+/// Signup method.
+const String _SIGN_UP_METHOD = 'sign_up_method';
+
+/// `CAMPAIGN_DETAILS` source; used to identify a search engine, newsletter, or
+/// other source.
+const String _SOURCE = 'source';
+
+/// The departure date, check-in date, or rental start date for the item.
+const String _START_DATE = 'start_date';
+
+/// Tax amount (double).
+const String _TAX = 'tax';
+
+/// `CAMPAIGN_DETAILS` term; used with paid search to supply the keywords for
+/// ads.
+const String _TERM = 'term';
+
+/// A single ID for a ecommerce group transaction.
+const String _TRANSACTION_ID = 'transaction_id';
+
+/// Travel class.
+const String _TRAVEL_CLASS = 'travel_class';
+
+/// A context-specific numeric value which is accumulated automatically for
+/// each event type.
+const String _VALUE = 'value';
+
+/// Name of virtual currency type.
+const String _VIRTUAL_CURRENCY_NAME = 'virtual_currency_name';
diff --git a/packages/firebase_analytics/pubspec.yaml b/packages/firebase_analytics/pubspec.yaml
new file mode 100755
index 000000000000..d91b8efd361d
--- /dev/null
+++ b/packages/firebase_analytics/pubspec.yaml
@@ -0,0 +1,16 @@
+name: firebase_analytics
+description: Firebase Analytics plugin for Flutter.
+
+flutter:
+ plugin:
+ androidPackage: io.flutter.firebase_analytics
+ pluginClass: FirebaseAnalyticsPlugin
+
+dependencies:
+ meta: ^1.0.4
+ flutter:
+ sdk: flutter
+
+dev_dependencies:
+ mockito: ^2.0.2
+ test: ^0.12.20
diff --git a/packages/firebase_analytics/test/firebase_analytics_test.dart b/packages/firebase_analytics/test/firebase_analytics_test.dart
new file mode 100755
index 000000000000..afadcbe8dd4b
--- /dev/null
+++ b/packages/firebase_analytics/test/firebase_analytics_test.dart
@@ -0,0 +1,328 @@
+// Copyright 2017 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:mockito/mockito.dart';
+import 'package:test/test.dart';
+
+import 'package:flutter/services.dart';
+
+import 'package:firebase_analytics/firebase_analytics.dart';
+
+void main() {
+ group('filterOutNulls', () {
+ test('filters out null values', () {
+ final Map original = {'a': 1, 'b': null, 'c': 'd'};
+ final Map filtered = filterOutNulls(original);
+
+ expect(filtered, isNot(same(original)));
+ expect(original, {'a': 1, 'b': null, 'c': 'd'});
+ expect(filtered, {'a': 1, 'c': 'd'});
+ });
+ });
+
+ group('$FirebaseAnalytics', () {
+ FirebaseAnalytics analytics;
+
+ String invokedMethod;
+ dynamic arguments;
+
+ setUp(() {
+ MockPlatformChannel mockChannel = new MockPlatformChannel();
+
+ invokedMethod = null;
+ arguments = null;
+
+ when(mockChannel.invokeMethod(any, any)).thenAnswer((Invocation invocation) {
+ invokedMethod = invocation.positionalArguments[0];
+ arguments = invocation.positionalArguments[1];
+ });
+
+ analytics = new FirebaseAnalytics.private(mockChannel);
+ });
+
+ test('setUserId', () async {
+ await analytics.setUserId('test-user-id');
+ expect(invokedMethod, 'setUserId');
+ expect(arguments, 'test-user-id');
+ });
+
+ test('setCurrentScreen', () async {
+ await analytics.setCurrentScreen(screenName: 'test-screen-name', screenClassOverride: 'test-class-override');
+ expect(invokedMethod, 'setCurrentScreen');
+ expect(arguments, {
+ 'screenName': 'test-screen-name',
+ 'screenClassOverride': 'test-class-override',
+ });
+ });
+
+ test('setUserProperty', () async {
+ await analytics.setUserProperty(name: 'test_name', value: 'test-value');
+ expect(invokedMethod, 'setUserProperty');
+ expect(arguments, {
+ 'name': 'test_name',
+ 'value': 'test-value',
+ });
+ });
+
+ test('setUserProperty rejects invalid names', () async {
+ // invalid character
+ expect(analytics.setUserProperty(name: 'test-name', value: 'test-value'), throwsArgumentError);
+ // non-alpha first character
+ expect(analytics.setUserProperty(name: '0test', value: 'test-value'), throwsArgumentError);
+ // null
+ expect(analytics.setUserProperty(name: null, value: 'test-value'), throwsArgumentError);
+ // blank
+ expect(analytics.setUserProperty(name: '', value: 'test-value'), throwsArgumentError);
+ // reserved prefix
+ expect(analytics.setUserProperty(name: 'firebase_test', value: 'test-value'), throwsArgumentError);
+ });
+
+ test('setAnalyticsCollectionEnabled', () async {
+ await analytics.android.setAnalyticsCollectionEnabled(false);
+ expect(invokedMethod, 'setAnalyticsCollectionEnabled');
+ expect(arguments, false);
+ });
+
+ test('setMinimumSessionDuration', () async {
+ await analytics.android.setMinimumSessionDuration(123);
+ expect(invokedMethod, 'setMinimumSessionDuration');
+ expect(arguments, 123);
+ });
+
+ test('setSessionTimeoutDuration', () async {
+ await analytics.android.setSessionTimeoutDuration(234);
+ expect(invokedMethod, 'setSessionTimeoutDuration');
+ expect(arguments, 234);
+ });
+ });
+
+ group('$FirebaseAnalytics analytics events', () {
+ FirebaseAnalytics analytics;
+
+ String name;
+ Map parameters;
+
+ setUp(() {
+ MockPlatformChannel mockChannel = new MockPlatformChannel();
+
+ name = null;
+ parameters = null;
+
+ when(mockChannel.invokeMethod('logEvent', any)).thenAnswer((Invocation invocation) {
+ Map args = invocation.positionalArguments[1];
+ name = args['name'];
+ parameters = args['parameters'];
+ expect(args.keys, unorderedEquals(['name', 'parameters']));
+ });
+
+ when(mockChannel.invokeMethod(isNot('logEvent') as dynamic, any))
+ .thenThrow(new ArgumentError('Only logEvent invocations expected'));
+
+ analytics = new FirebaseAnalytics.private(mockChannel);
+ });
+
+ test('logEvent log events', () async {
+ await analytics.logEvent(name: 'test-event', parameters: {'a': 'b'});
+ expect(name, 'test-event');
+ expect(parameters, {'a': 'b'});
+ });
+
+ test('logEvent rejects events with reserved names', () async {
+ expect(analytics.logEvent(name: 'app_clear_data'), throwsArgumentError);
+ });
+
+ test('logEvent rejects events with reserved prefix', () async {
+ expect(analytics.logEvent(name: 'firebase_foo'), throwsArgumentError);
+ });
+
+ void smokeTest(String testFunctionName, Future testFunction()) {
+ test('$testFunctionName works', () async {
+ await testFunction();
+ expect(name, testFunctionName);
+ });
+ }
+
+ smokeTest('add_payment_info', () => analytics.logAddPaymentInfo());
+
+ smokeTest('add_to_cart', () => analytics.logAddToCart(
+ itemId: 'test-id',
+ itemName: 'test-name',
+ itemCategory: 'test-category',
+ quantity: 5,
+ ));
+
+ smokeTest('add_to_wishlist', () => analytics.logAddToWishlist(
+ itemId: 'test-id',
+ itemName: 'test-name',
+ itemCategory: 'test-category',
+ quantity: 5,
+ ));
+
+ smokeTest('app_open', () => analytics.logAppOpen());
+
+ smokeTest('begin_checkout', () => analytics.logBeginCheckout());
+
+ smokeTest('campaign_details', () => analytics.logCampaignDetails(
+ source: 'test-source',
+ medium: 'test-medium',
+ campaign: 'test-campaign',
+ ));
+
+ smokeTest('earn_virtual_currency', () => analytics.logEarnVirtualCurrency(
+ virtualCurrencyName: 'bitcoin',
+ value: 34,
+ ));
+
+ smokeTest('ecommerce_purchase', () => analytics.logEcommercePurchase());
+
+ smokeTest('generate_lead', () => analytics.logGenerateLead());
+
+ smokeTest('join_group', () => analytics.logJoinGroup(
+ groupId: 'test-group-id',
+ ));
+
+ smokeTest('level_up', () => analytics.logLevelUp(
+ level: 56,
+ ));
+
+ smokeTest('login', () => analytics.logLogin());
+
+ smokeTest('post_score', () => analytics.logPostScore(
+ score: 34,
+ ));
+
+ smokeTest('present_offer', () => analytics.logPresentOffer(
+ itemId: 'test-id',
+ itemName: 'test-name',
+ itemCategory: 'test-category',
+ quantity: 5,
+ ));
+
+ smokeTest('purchase_refund', () => analytics.logPurchaseRefund());
+
+ smokeTest('search', () => analytics.logSearch(
+ searchTerm: 'test search term',
+ ));
+
+ smokeTest('select_content', () => analytics.logSelectContent(
+ contentType: 'test content type',
+ itemId: 'test item id',
+ ));
+
+ smokeTest('share', () => analytics.logShare(
+ contentType: 'test content type',
+ itemId: 'test item id',
+ ));
+
+ smokeTest('sign_up', () => analytics.logSignUp(
+ signUpMethod: 'test sign-up method',
+ ));
+
+ smokeTest('spend_virtual_currency', () => analytics.logSpendVirtualCurrency(
+ itemName: 'test-item-name',
+ virtualCurrencyName: 'bitcoin',
+ value: 345,
+ ));
+
+ smokeTest('tutorial_begin', () => analytics.logTutorialBegin());
+
+ smokeTest('tutorial_complete', () => analytics.logTutorialComplete());
+
+ smokeTest('unlock_achievement', () => analytics.logUnlockAchievement(
+ id: 'firebase analytics api coverage',
+ ));
+
+ smokeTest('view_item', () => analytics.logViewItem(
+ itemId: 'test-id',
+ itemName: 'test-name',
+ itemCategory: 'test-category',
+ ));
+
+ smokeTest('view_item_list', () => analytics.logViewItemList(
+ itemCategory: 'test-category',
+ ));
+
+ smokeTest('view_search_results', () => analytics.logViewSearchResults(
+ searchTerm: 'test search term',
+ ));
+
+ void testRequiresValueAndCurrencyTogether(String methodName, Future testFn()) {
+ test('$methodName requires value and currency together', () async {
+ try {
+ testFn();
+ fail('Expected ArgumentError');
+ } on ArgumentError catch(error) {
+ expect(error.message, valueAndCurrencyMustBeTogetherError);
+ }
+ });
+ }
+
+ testRequiresValueAndCurrencyTogether('logAddToCart', () {
+ return analytics.logAddToCart(
+ itemId: 'test-id',
+ itemName: 'test-name',
+ itemCategory: 'test-category',
+ quantity: 5,
+ value: 123.90,
+ );
+ });
+
+ testRequiresValueAndCurrencyTogether('logAddToWishlist', () {
+ return analytics.logAddToWishlist(
+ itemId: 'test-id',
+ itemName: 'test-name',
+ itemCategory: 'test-category',
+ quantity: 5,
+ value: 123.90,
+ );
+ });
+
+ testRequiresValueAndCurrencyTogether('logBeginCheckout', () {
+ return analytics.logBeginCheckout(
+ value: 123.90,
+ );
+ });
+
+ testRequiresValueAndCurrencyTogether('logEcommercePurchase', () {
+ return analytics.logEcommercePurchase(
+ value: 123.90,
+ );
+ });
+
+ testRequiresValueAndCurrencyTogether('logGenerateLead', () {
+ return analytics.logGenerateLead(
+ value: 123.90,
+ );
+ });
+
+ testRequiresValueAndCurrencyTogether('logPresentOffer', () {
+ return analytics.logPresentOffer(
+ itemId: 'test-id',
+ itemName: 'test-name',
+ itemCategory: 'test-category',
+ quantity: 5,
+ value: 123.90,
+ );
+ });
+
+ testRequiresValueAndCurrencyTogether('logPurchaseRefund', () {
+ return analytics.logPurchaseRefund(
+ value: 123.90,
+ );
+ });
+
+ testRequiresValueAndCurrencyTogether('logViewItem', () {
+ return analytics.logViewItem(
+ itemId: 'test-id',
+ itemName: 'test-name',
+ itemCategory: 'test-category',
+ value: 123.90,
+ );
+ });
+ });
+}
+
+class MockPlatformChannel extends Mock implements MethodChannel { }
diff --git a/packages/firebase_auth/.gitignore b/packages/firebase_auth/.gitignore
new file mode 100755
index 000000000000..14c7d4c3f73e
--- /dev/null
+++ b/packages/firebase_auth/.gitignore
@@ -0,0 +1,9 @@
+.DS_Store
+.atom/
+.idea
+.packages
+.pub/
+build/
+ios/.generated/
+packages
+pubspec.lock
diff --git a/packages/firebase_auth/LICENSE b/packages/firebase_auth/LICENSE
new file mode 100755
index 000000000000..86928f657555
--- /dev/null
+++ b/packages/firebase_auth/LICENSE
@@ -0,0 +1,27 @@
+// Copyright 2017 Your Company. 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 Your Company nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/packages/firebase_auth/README.md b/packages/firebase_auth/README.md
new file mode 100755
index 000000000000..aac93dbcaf71
--- /dev/null
+++ b/packages/firebase_auth/README.md
@@ -0,0 +1,8 @@
+# firebase_auth
+
+A new flutter plugin project.
+
+## Getting Started
+
+For help getting started with Flutter, view our online
+[documentation](http://flutter.io/).
diff --git a/packages/firebase_auth/android/.gitignore b/packages/firebase_auth/android/.gitignore
new file mode 100755
index 000000000000..5c4ef82869b5
--- /dev/null
+++ b/packages/firebase_auth/android/.gitignore
@@ -0,0 +1,12 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+
+/gradle
+/gradlew
+/gradlew.bat
diff --git a/packages/firebase_auth/android/build.gradle b/packages/firebase_auth/android/build.gradle
new file mode 100755
index 000000000000..aa9bc67f3667
--- /dev/null
+++ b/packages/firebase_auth/android/build.gradle
@@ -0,0 +1,37 @@
+group 'com.yourcompany.firebase_auth'
+version '1.0-SNAPSHOT'
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.3.0'
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion '25.0.0'
+
+ defaultConfig {
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ lintOptions {
+ disable 'InvalidPackage'
+ }
+ dependencies {
+ compile 'com.google.guava:guava:20.0'
+ compile 'com.google.firebase:firebase-core:10.2.1'
+ compile 'com.google.firebase:firebase-auth:10.2.1'
+ }
+}
diff --git a/packages/firebase_auth/android/gradle.properties b/packages/firebase_auth/android/gradle.properties
new file mode 100755
index 000000000000..8bd86f680510
--- /dev/null
+++ b/packages/firebase_auth/android/gradle.properties
@@ -0,0 +1 @@
+org.gradle.jvmargs=-Xmx1536M
diff --git a/packages/firebase_auth/android/settings.gradle b/packages/firebase_auth/android/settings.gradle
new file mode 100755
index 000000000000..acfe1855910f
--- /dev/null
+++ b/packages/firebase_auth/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'firebase_auth'
diff --git a/packages/firebase_auth/android/src/main/AndroidManifest.xml b/packages/firebase_auth/android/src/main/AndroidManifest.xml
new file mode 100755
index 000000000000..13d1ce1b00e9
--- /dev/null
+++ b/packages/firebase_auth/android/src/main/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/packages/firebase_auth/android/src/main/java/io/flutter/firebase_auth/FirebaseAuthPlugin.java b/packages/firebase_auth/android/src/main/java/io/flutter/firebase_auth/FirebaseAuthPlugin.java
new file mode 100755
index 000000000000..cb460b2ed229
--- /dev/null
+++ b/packages/firebase_auth/android/src/main/java/io/flutter/firebase_auth/FirebaseAuthPlugin.java
@@ -0,0 +1,132 @@
+// Copyright 2017 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.firebase_auth;
+
+import android.app.Activity;
+import android.support.annotation.NonNull;
+
+import com.google.android.gms.tasks.Task;
+import com.google.android.gms.tasks.OnCompleteListener;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.firebase.FirebaseApp;
+import com.google.firebase.auth.AuthResult;
+import com.google.firebase.auth.FirebaseAuth;
+import com.google.firebase.auth.AuthCredential;
+import com.google.firebase.auth.GoogleAuthProvider;
+import com.google.firebase.auth.FirebaseUser;
+import com.google.firebase.auth.UserInfo;
+
+import io.flutter.plugin.common.MethodChannel;
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
+import io.flutter.plugin.common.MethodChannel.Result;
+import io.flutter.plugin.common.MethodCall;
+import io.flutter.plugin.common.PluginRegistry;
+
+import java.util.Map;
+
+/**
+ * Flutter plugin for Firebase Auth.
+ */
+public class FirebaseAuthPlugin implements MethodCallHandler {
+ private final Activity activity;
+ private final FirebaseAuth firebaseAuth;
+
+ private static final String ERROR_REASON_EXCEPTION = "exception";
+
+
+ public static void registerWith(PluginRegistry.Registrar registrar) {
+ final MethodChannel channel =
+ new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_auth");
+ channel.setMethodCallHandler(new FirebaseAuthPlugin(registrar.activity()));
+ }
+
+ private FirebaseAuthPlugin(Activity activity) {
+ this.activity = activity;
+ FirebaseApp.initializeApp(activity);
+ this.firebaseAuth = FirebaseAuth.getInstance();
+ }
+
+ @Override
+ public void onMethodCall(MethodCall call, Result result) {
+ switch (call.method) {
+ case "signInAnonymously":
+ handleSignInAnonymously(call, result);
+ break;
+ case "signInWithGoogle":
+ handleSignInWithGoogle(call, result);
+ break;
+ default:
+ result.notImplemented();
+ break;
+ }
+ }
+
+ private void handleSignInAnonymously(MethodCall call, final Result result) {
+ firebaseAuth
+ .signInAnonymously()
+ .addOnCompleteListener(activity, new SignInCompleteListener(result));
+ }
+
+ private void handleSignInWithGoogle(MethodCall call, final Result result) {
+ @SuppressWarnings("unchecked")
+ Map arguments = (Map) call.arguments;
+ String idToken = arguments.get("idToken");
+ String accessToken = arguments.get("accessToken");
+ AuthCredential credential = GoogleAuthProvider.getCredential(idToken, accessToken);
+ firebaseAuth.signInWithCredential(credential)
+ .addOnCompleteListener(activity, new SignInCompleteListener(result));
+ }
+
+ private class SignInCompleteListener implements OnCompleteListener {
+ private final Result result;
+
+ SignInCompleteListener(Result result) {
+ this.result = result;
+ }
+
+ private ImmutableMap.Builder userInfoToMap(UserInfo userInfo) {
+ ImmutableMap.Builder builder =
+ ImmutableMap.builder()
+ .put("providerId", userInfo.getProviderId())
+ .put("uid", userInfo.getUid());
+ if (userInfo.getDisplayName() != null) {
+ builder.put("displayName", userInfo.getDisplayName());
+ }
+ if (userInfo.getPhotoUrl() != null) {
+ builder.put("photoUrl", userInfo.getPhotoUrl().toString());
+ }
+ if (userInfo.getEmail() != null) {
+ builder.put("email", userInfo.getEmail());
+ }
+ return builder;
+ }
+
+ @Override
+ public void onComplete(@NonNull Task task) {
+ if (!task.isSuccessful()) {
+ Exception e = task.getException();
+ result.error(ERROR_REASON_EXCEPTION, e.getMessage(), null);
+ } else {
+ FirebaseUser user = task.getResult().getUser();
+ if (user != null) {
+ ImmutableList.Builder> providerDataBuilder =
+ ImmutableList.>builder();
+ for (UserInfo userInfo : user.getProviderData()) {
+ providerDataBuilder.add(userInfoToMap(userInfo).build());
+ }
+ ImmutableMap userMap = userInfoToMap(user)
+ .put("isAnonymous", user.isAnonymous())
+ .put("isEmailVerified", user.isEmailVerified())
+ .put("providerData", providerDataBuilder.build())
+ .build();
+ result.success(userMap);
+ } else {
+ result.success(null);
+ }
+ }
+ }
+ }
+}
diff --git a/packages/firebase_auth/example/.gitignore b/packages/firebase_auth/example/.gitignore
new file mode 100755
index 000000000000..eb15c3d27cab
--- /dev/null
+++ b/packages/firebase_auth/example/.gitignore
@@ -0,0 +1,10 @@
+.DS_Store
+.atom/
+.idea
+.packages
+.pub/
+build/
+ios/.generated/
+packages
+pubspec.lock
+.flutter-plugins
diff --git a/packages/firebase_auth/example/README.md b/packages/firebase_auth/example/README.md
new file mode 100755
index 000000000000..228dede4b027
--- /dev/null
+++ b/packages/firebase_auth/example/README.md
@@ -0,0 +1,8 @@
+# firebase_auth_example
+
+Demonstrates how to use the firebase_auth plugin.
+
+## Getting Started
+
+For help getting started with Flutter, view our online
+[documentation](http://flutter.io/).
diff --git a/packages/firebase_auth/example/android.iml b/packages/firebase_auth/example/android.iml
new file mode 100755
index 000000000000..462b903e05b6
--- /dev/null
+++ b/packages/firebase_auth/example/android.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_auth/example/android/.gitignore b/packages/firebase_auth/example/android/.gitignore
new file mode 100755
index 000000000000..5c4ef82869b5
--- /dev/null
+++ b/packages/firebase_auth/example/android/.gitignore
@@ -0,0 +1,12 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+
+/gradle
+/gradlew
+/gradlew.bat
diff --git a/packages/firebase_auth/example/android/app/build.gradle b/packages/firebase_auth/example/android/app/build.gradle
new file mode 100755
index 000000000000..50474b6ac11d
--- /dev/null
+++ b/packages/firebase_auth/example/android/app/build.gradle
@@ -0,0 +1,49 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withInputStream { stream ->
+ localProperties.load(stream)
+ }
+}
+
+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.")
+}
+
+apply plugin: 'com.android.application'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion '25.0.2'
+
+ lintOptions {
+ disable 'InvalidPackage'
+ }
+
+ defaultConfig {
+ applicationId 'com.yourcompany.firebaseauth.example'
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ androidTestCompile 'com.android.support:support-annotations:24.0.0'
+ androidTestCompile 'com.android.support.test:runner:0.5'
+ androidTestCompile 'com.android.support.test:rules:0.5'
+}
+
+apply plugin: 'com.google.gms.google-services'
diff --git a/packages/firebase_auth/example/android/app/google-services.json b/packages/firebase_auth/example/android/app/google-services.json
new file mode 100755
index 000000000000..11dc3ae0bf4d
--- /dev/null
+++ b/packages/firebase_auth/example/android/app/google-services.json
@@ -0,0 +1,42 @@
+{
+ "project_info": {
+ "project_number": "297855924061",
+ "firebase_url": "https://flutterfire-cd2f7.firebaseio.com",
+ "project_id": "flutterfire-cd2f7",
+ "storage_bucket": "flutterfire-cd2f7.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:297855924061:android:669871c998cc21bd",
+ "android_client_info": {
+ "package_name": "com.yourcompany.firebaseauth.example"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "297855924061-f68m5v860ms5faiotn5mv9f50cmpacdq.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyD_shO5mfO9lhy2TVWhfo1VUmARKlG4suk"
+ }
+ ],
+ "services": {
+ "analytics_service": {
+ "status": 1
+ },
+ "appinvite_service": {
+ "status": 1,
+ "other_platform_oauth_client": []
+ },
+ "ads_service": {
+ "status": 2
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/packages/firebase_auth/example/android/app/src/main/AndroidManifest.xml b/packages/firebase_auth/example/android/app/src/main/AndroidManifest.xml
new file mode 100755
index 000000000000..b9cf7689b923
--- /dev/null
+++ b/packages/firebase_auth/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_auth/example/android/app/src/main/java/io/flutter/plugins/.gitignore b/packages/firebase_auth/example/android/app/src/main/java/io/flutter/plugins/.gitignore
new file mode 100755
index 000000000000..9eb4563d2ae1
--- /dev/null
+++ b/packages/firebase_auth/example/android/app/src/main/java/io/flutter/plugins/.gitignore
@@ -0,0 +1 @@
+GeneratedPluginRegistrant.java
diff --git a/packages/firebase_auth/example/android/app/src/main/java/io/flutter/plugins/firebase_auth_example/MainActivity.java b/packages/firebase_auth/example/android/app/src/main/java/io/flutter/plugins/firebase_auth_example/MainActivity.java
new file mode 100755
index 000000000000..fe418a9d1d1a
--- /dev/null
+++ b/packages/firebase_auth/example/android/app/src/main/java/io/flutter/plugins/firebase_auth_example/MainActivity.java
@@ -0,0 +1,13 @@
+package io.flutter.plugins.firebase_auth_example;
+
+import android.os.Bundle;
+import io.flutter.app.FlutterActivity;
+import io.flutter.plugins.GeneratedPluginRegistrant;
+
+public class MainActivity extends FlutterActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ GeneratedPluginRegistrant.registerWith(this);
+ }
+}
diff --git a/packages/firebase_auth/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/firebase_auth/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100755
index 000000000000..db77bb4b7b09
Binary files /dev/null and b/packages/firebase_auth/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/packages/firebase_auth/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/firebase_auth/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100755
index 000000000000..17987b79bb8a
Binary files /dev/null and b/packages/firebase_auth/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/packages/firebase_auth/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/firebase_auth/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100755
index 000000000000..09d4391482be
Binary files /dev/null and b/packages/firebase_auth/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/packages/firebase_auth/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/firebase_auth/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100755
index 000000000000..d5f1c8d34e7a
Binary files /dev/null and b/packages/firebase_auth/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/packages/firebase_auth/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/firebase_auth/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100755
index 000000000000..4d6372eebdb2
Binary files /dev/null and b/packages/firebase_auth/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/packages/firebase_auth/example/android/build.gradle b/packages/firebase_auth/example/android/build.gradle
new file mode 100755
index 000000000000..2023b0f5725e
--- /dev/null
+++ b/packages/firebase_auth/example/android/build.gradle
@@ -0,0 +1,30 @@
+buildscript {
+ repositories {
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.2.3'
+ classpath 'com.google.gms:google-services:3.0.0'
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+ project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
+
+task wrapper(type: Wrapper) {
+ gradleVersion = '2.14.1'
+}
diff --git a/packages/firebase_auth/example/android/gradle.properties b/packages/firebase_auth/example/android/gradle.properties
new file mode 100755
index 000000000000..8bd86f680510
--- /dev/null
+++ b/packages/firebase_auth/example/android/gradle.properties
@@ -0,0 +1 @@
+org.gradle.jvmargs=-Xmx1536M
diff --git a/packages/firebase_auth/example/android/settings.gradle b/packages/firebase_auth/example/android/settings.gradle
new file mode 100755
index 000000000000..115da6cb4f4d
--- /dev/null
+++ b/packages/firebase_auth/example/android/settings.gradle
@@ -0,0 +1,15 @@
+include ':app'
+
+def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
+
+def plugins = new Properties()
+def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
+if (pluginsFile.exists()) {
+ pluginsFile.withInputStream { stream -> plugins.load(stream) }
+}
+
+plugins.each { name, path ->
+ def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
+ include ":$name"
+ project(":$name").projectDir = pluginDirectory
+}
diff --git a/packages/firebase_auth/example/firebase_auth_example.iml b/packages/firebase_auth/example/firebase_auth_example.iml
new file mode 100755
index 000000000000..1ae40a0f7f54
--- /dev/null
+++ b/packages/firebase_auth/example/firebase_auth_example.iml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/firebase_auth/example/ios/.gitignore b/packages/firebase_auth/example/ios/.gitignore
new file mode 100755
index 000000000000..0c4c14679cff
--- /dev/null
+++ b/packages/firebase_auth/example/ios/.gitignore
@@ -0,0 +1,41 @@
+.idea/
+.vagrant/
+.sconsign.dblite
+.svn/
+
+.DS_Store
+*.swp
+profile
+
+DerivedData/
+build/
+
+*.pbxuser
+*.mode1v3
+*.mode2v3
+*.perspectivev3
+
+!default.pbxuser
+!default.mode1v3
+!default.mode2v3
+!default.perspectivev3
+
+xcuserdata
+
+*.moved-aside
+
+*.pyc
+*sync/
+Icon?
+.tags*
+
+/Flutter/app.flx
+/Flutter/app.zip
+/Flutter/App.framework
+/Flutter/Flutter.framework
+/Flutter/Generated.xcconfig
+/ServiceDefinitions.json
+/Runner/GeneratedPluginRegistrant.h
+/Runner/GeneratedPluginRegistrant.m
+Podfile.lock
+Pods/
diff --git a/packages/firebase_auth/example/ios/Flutter/AppFrameworkInfo.plist b/packages/firebase_auth/example/ios/Flutter/AppFrameworkInfo.plist
new file mode 100755
index 000000000000..6c2de8086bcd
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Flutter/AppFrameworkInfo.plist
@@ -0,0 +1,30 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ App
+ CFBundleIdentifier
+ io.flutter.flutter.app
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ App
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ MinimumOSVersion
+ 8.0
+
+
diff --git a/packages/firebase_auth/example/ios/Flutter/Debug.xcconfig b/packages/firebase_auth/example/ios/Flutter/Debug.xcconfig
new file mode 100755
index 000000000000..9803018ca79d
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Flutter/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include "Generated.xcconfig"
+#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
diff --git a/packages/firebase_auth/example/ios/Flutter/Release.xcconfig b/packages/firebase_auth/example/ios/Flutter/Release.xcconfig
new file mode 100755
index 000000000000..a4a8c604e13d
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Flutter/Release.xcconfig
@@ -0,0 +1,2 @@
+#include "Generated.xcconfig"
+#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
diff --git a/packages/firebase_auth/example/ios/Podfile b/packages/firebase_auth/example/ios/Podfile
new file mode 100755
index 000000000000..90b5f651fb63
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Podfile
@@ -0,0 +1,36 @@
+# Uncomment this line to define a global platform for your project
+# platform :ios, '9.0'
+
+if ENV['FLUTTER_FRAMEWORK_DIR'] == nil
+ abort('Please set FLUTTER_FRAMEWORK_DIR to the directory containing Flutter.framework')
+end
+
+target 'Runner' do
+ # Pods for Runner
+
+ # Flutter Pods
+ pod 'Flutter', :path => ENV['FLUTTER_FRAMEWORK_DIR']
+
+ if File.exists? '../.flutter-plugins'
+ flutter_root = File.expand_path('..')
+ File.foreach('../.flutter-plugins') { |line|
+ plugin = line.split(pattern='=')
+ if plugin.length == 2
+ name = plugin[0].strip()
+ path = plugin[1].strip()
+ resolved_path = File.expand_path("#{path}/ios", flutter_root)
+ pod name, :path => resolved_path
+ else
+ puts "Invalid plugin specification: #{line}"
+ end
+ }
+ end
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ target.build_configurations.each do |config|
+ config.build_settings['ENABLE_BITCODE'] = 'NO'
+ end
+ end
+end
diff --git a/packages/firebase_auth/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_auth/example/ios/Runner.xcodeproj/project.pbxproj
new file mode 100755
index 000000000000..0bee7281e1ac
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,498 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 0690AA46E879ED4CF7B7AEB4 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A6A0D603F1BEC33B95572EC3 /* libPods-Runner.a */; };
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
+ 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
+ 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 5C97AA501EC3F2C300D441D1 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C97AA4F1EC3F2C300D441D1 /* GeneratedPluginRegistrant.m */; };
+ 7ABDE8F71EA727FA0074FEFB /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7ABDE8F61EA727FA0074FEFB /* GoogleService-Info.plist */; };
+ 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
+ 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
+ 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; };
+ 9740EEBB1CF902C7004384FC /* app.flx in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB71CF902C7004384FC /* app.flx */; };
+ 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
+ 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
+ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
+ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
+ 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
+ 5C97AA4E1EC3F2C300D441D1 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
+ 5C97AA4F1EC3F2C300D441D1 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
+ 7ABDE8F61EA727FA0074FEFB /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
+ 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
+ 9740EEB71CF902C7004384FC /* app.flx */ = {isa = PBXFileReference; lastKnownFileType = file; name = app.flx; path = Flutter/app.flx; sourceTree = ""; };
+ 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
+ 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ A6A0D603F1BEC33B95572EC3 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 97C146EB1CF9000F007C117D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
+ 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
+ 0690AA46E879ED4CF7B7AEB4 /* libPods-Runner.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 840012C8B5EDBCF56B0E4AC1 /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Pods;
+ sourceTree = "";
+ };
+ 9740EEB11CF90186004384FC /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB71CF902C7004384FC /* app.flx */,
+ 3B80C3931E831B6300D905FE /* App.framework */,
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
+ 9740EEBA1CF902C7004384FC /* Flutter.framework */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */,
+ );
+ name = Flutter;
+ sourceTree = "";
+ };
+ 97C146E51CF9000F007C117D = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB11CF90186004384FC /* Flutter */,
+ 97C146F01CF9000F007C117D /* Runner */,
+ 97C146EF1CF9000F007C117D /* Products */,
+ 840012C8B5EDBCF56B0E4AC1 /* Pods */,
+ CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ 97C146EF1CF9000F007C117D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146EE1CF9000F007C117D /* Runner.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 97C146F01CF9000F007C117D /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 5C97AA4E1EC3F2C300D441D1 /* GeneratedPluginRegistrant.h */,
+ 5C97AA4F1EC3F2C300D441D1 /* GeneratedPluginRegistrant.m */,
+ 7ABDE8F61EA727FA0074FEFB /* GoogleService-Info.plist */,
+ 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
+ 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
+ 97C146FA1CF9000F007C117D /* Main.storyboard */,
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */,
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
+ 97C147021CF9000F007C117D /* Info.plist */,
+ 97C146F11CF9000F007C117D /* Supporting Files */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ 97C146F11CF9000F007C117D /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146F21CF9000F007C117D /* main.m */,
+ );
+ name = "Supporting Files";
+ sourceTree = "";
+ };
+ CF3B75C9A7D2FA2A4C99F110 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ A6A0D603F1BEC33B95572EC3 /* libPods-Runner.a */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 97C146ED1CF9000F007C117D /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ AB1344B0443C71CD721E1BB7 /* [CP] Check Pods Manifest.lock */,
+ 9740EEB61CF901F6004384FC /* Run Script */,
+ 97C146EA1CF9000F007C117D /* Sources */,
+ 97C146EB1CF9000F007C117D /* Frameworks */,
+ 97C146EC1CF9000F007C117D /* Resources */,
+ 9705A1C41CF9048500538489 /* Embed Frameworks */,
+ 95BB15E9E1769C0D146AA592 /* [CP] Embed Pods Frameworks */,
+ 532EA9D341340B1DCD08293D /* [CP] Copy Pods Resources */,
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 97C146E61CF9000F007C117D /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0830;
+ ORGANIZATIONNAME = "The Chromium Authors";
+ TargetAttributes = {
+ 97C146ED1CF9000F007C117D = {
+ CreatedOnToolsVersion = 7.3.1;
+ DevelopmentTeam = 3GRKCVVJ22;
+ };
+ };
+ };
+ buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 97C146E51CF9000F007C117D;
+ productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 97C146ED1CF9000F007C117D /* Runner */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 97C146EC1CF9000F007C117D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9740EEBB1CF902C7004384FC /* app.flx in Resources */,
+ 7ABDE8F71EA727FA0074FEFB /* GoogleService-Info.plist in Resources */,
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
+ 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
+ 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
+ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
+ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Thin Binary";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
+ };
+ 532EA9D341340B1DCD08293D /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Copy Pods Resources";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 95BB15E9E1769C0D146AA592 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\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";
+ };
+ AB1344B0443C71CD721E1BB7 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_ROOT}/../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";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 97C146EA1CF9000F007C117D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
+ 97C146F31CF9000F007C117D /* main.m in Sources */,
+ 5C97AA501EC3F2C300D441D1 /* GeneratedPluginRegistrant.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 97C146FB1CF9000F007C117D /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 97C147001CF9000F007C117D /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 97C147031CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 97C147041CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 97C147061CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ARCHS = arm64;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ DEVELOPMENT_TEAM = 3GRKCVVJ22;
+ ENABLE_BITCODE = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.firebaseAuthExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 97C147071CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ARCHS = arm64;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ DEVELOPMENT_TEAM = 3GRKCVVJ22;
+ ENABLE_BITCODE = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.firebaseAuthExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147031CF9000F007C117D /* Debug */,
+ 97C147041CF9000F007C117D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147061CF9000F007C117D /* Debug */,
+ 97C147071CF9000F007C117D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 97C146E61CF9000F007C117D /* Project object */;
+}
diff --git a/packages/firebase_auth/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/firebase_auth/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100755
index 000000000000..21a3cc14c74e
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/packages/firebase_auth/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_auth/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100755
index 000000000000..1c9580788197
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_auth/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/firebase_auth/example/ios/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100755
index 000000000000..21a3cc14c74e
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/packages/firebase_auth/example/ios/Runner/AppDelegate.h b/packages/firebase_auth/example/ios/Runner/AppDelegate.h
new file mode 100755
index 000000000000..cf210d213f27
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner/AppDelegate.h
@@ -0,0 +1,6 @@
+#import
+#import
+
+@interface AppDelegate : FlutterAppDelegate
+
+@end
diff --git a/packages/firebase_auth/example/ios/Runner/AppDelegate.m b/packages/firebase_auth/example/ios/Runner/AppDelegate.m
new file mode 100755
index 000000000000..ce9c30f9f812
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner/AppDelegate.m
@@ -0,0 +1,12 @@
+#include "AppDelegate.h"
+#include "GeneratedPluginRegistrant.h"
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application
+didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ [GeneratedPluginRegistrant registerWithRegistry:self];
+ return [super application:application didFinishLaunchingWithOptions:launchOptions];
+}
+
+@end
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100755
index 000000000000..d22f10b2ab63
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,116 @@
+{
+ "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"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
new file mode 100755
index 000000000000..28c6bf03016f
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
new file mode 100755
index 000000000000..2ccbfd967d96
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
new file mode 100755
index 000000000000..f091b6b0bca8
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
new file mode 100755
index 000000000000..4cde12118dda
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
new file mode 100755
index 000000000000..d0ef06e7edb8
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
new file mode 100755
index 000000000000..dcdc2306c285
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
new file mode 100755
index 000000000000..2ccbfd967d96
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
new file mode 100755
index 000000000000..c8f9ed8f5cee
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
new file mode 100755
index 000000000000..a6d6b8609df0
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
new file mode 100755
index 000000000000..a6d6b8609df0
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
new file mode 100755
index 000000000000..75b2d164a5a9
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
new file mode 100755
index 000000000000..c4df70d39da7
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
new file mode 100755
index 000000000000..6a84f41e14e2
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
new file mode 100755
index 000000000000..d0e1f5853602
Binary files /dev/null and b/packages/firebase_auth/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
diff --git a/packages/firebase_auth/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/firebase_auth/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
new file mode 100755
index 000000000000..ebf48f603974
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_auth/example/ios/Runner/Base.lproj/Main.storyboard b/packages/firebase_auth/example/ios/Runner/Base.lproj/Main.storyboard
new file mode 100755
index 000000000000..f3c28516fb38
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner/Base.lproj/Main.storyboard
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/firebase_auth/example/ios/Runner/GoogleService-Info.plist b/packages/firebase_auth/example/ios/Runner/GoogleService-Info.plist
new file mode 100755
index 000000000000..dd1067c0166c
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner/GoogleService-Info.plist
@@ -0,0 +1,40 @@
+
+
+
+
+ AD_UNIT_ID_FOR_BANNER_TEST
+ ca-app-pub-3940256099942544/2934735716
+ AD_UNIT_ID_FOR_INTERSTITIAL_TEST
+ ca-app-pub-3940256099942544/4411468910
+ CLIENT_ID
+ 297855924061-48k2m6hl6pa4q9hukijjd0c20ev4qans.apps.googleusercontent.com
+ REVERSED_CLIENT_ID
+ com.googleusercontent.apps.297855924061-48k2m6hl6pa4q9hukijjd0c20ev4qans
+ API_KEY
+ AIzaSyBq6mcufFXfyqr79uELCiqM_O_1-G72PVU
+ GCM_SENDER_ID
+ 297855924061
+ PLIST_VERSION
+ 1
+ BUNDLE_ID
+ com.yourcompany.firebaseAuthExample
+ PROJECT_ID
+ flutterfire-cd2f7
+ STORAGE_BUCKET
+ flutterfire-cd2f7.appspot.com
+ IS_ADS_ENABLED
+
+ IS_ANALYTICS_ENABLED
+
+ IS_APPINVITE_ENABLED
+
+ IS_GCM_ENABLED
+
+ IS_SIGNIN_ENABLED
+
+ GOOGLE_APP_ID
+ 1:297855924061:ios:9441bad932d26629
+ DATABASE_URL
+ https://flutterfire-cd2f7.firebaseio.com
+
+
\ No newline at end of file
diff --git a/packages/firebase_auth/example/ios/Runner/Info.plist b/packages/firebase_auth/example/ios/Runner/Info.plist
new file mode 100755
index 000000000000..0d20e1c5f477
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner/Info.plist
@@ -0,0 +1,60 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ firebase_auth_example
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLSchemes
+
+ com.googleusercontent.apps.297855924061-48k2m6hl6pa4q9hukijjd0c20ev4qans
+
+
+
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIViewControllerBasedStatusBarAppearance
+
+
+
diff --git a/packages/firebase_auth/example/ios/Runner/main.m b/packages/firebase_auth/example/ios/Runner/main.m
new file mode 100755
index 000000000000..1bdb8e28d1db
--- /dev/null
+++ b/packages/firebase_auth/example/ios/Runner/main.m
@@ -0,0 +1,10 @@
+#import
+#import
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil,
+ NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/packages/firebase_auth/example/lib/main.dart b/packages/firebase_auth/example/lib/main.dart
new file mode 100755
index 000000000000..b84f45c7151b
--- /dev/null
+++ b/packages/firebase_auth/example/lib/main.dart
@@ -0,0 +1,112 @@
+// Copyright 2017 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 'dart:io';
+
+import 'package:flutter/material.dart';
+import 'package:firebase_auth/firebase_auth.dart';
+import 'package:google_sign_in/google_sign_in.dart';
+
+final FirebaseAuth auth = FirebaseAuth.instance;
+final GoogleSignIn googleSignIn = new GoogleSignIn();
+
+void main() {
+ runApp(new MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new MaterialApp(
+ title: 'Firebase Auth Demo',
+ home: new MyHomePage(title: 'Firebase Auth Demo'),
+ );
+ }
+}
+
+class MyHomePage extends StatefulWidget {
+ MyHomePage({Key key, this.title}) : super(key: key);
+
+ final String title;
+
+ @override
+ _MyHomePageState createState() => new _MyHomePageState();
+}
+
+class _MyHomePageState extends State {
+ Future _message = new Future.value('');
+
+ Future _testSignInAnonymously() async {
+ FirebaseUser user = await auth.signInAnonymously();
+ assert(user != null);
+ assert(user == auth.currentUser);
+ assert(user.isAnonymous);
+ assert(!user.isEmailVerified);
+ if (Platform.isIOS) {
+ // Anonymous auth doesn't show up as a provider on iOS
+ assert(user.providerData.length == 0);
+ } else if (Platform.isAndroid) {
+ // Anonymous auth does show up as a provider on Android
+ assert(user.providerData.length == 1);
+ assert(user.providerData[0].providerId == 'firebase');
+ assert(user.providerData[0].uid != null);
+ assert(user.providerData[0].displayName == null);
+ assert(user.providerData[0].photoUrl == null);
+ assert(user.providerData[0].email == null);
+ }
+ return 'signInAnonymously succeeded: $user';
+ }
+
+ Future _testSignInWithGoogle() async {
+ GoogleSignInAccount googleUser = await googleSignIn.signIn();
+ GoogleSignInAuthentication googleAuth = await googleUser.authentication;
+ FirebaseUser user = await auth.signInWithGoogle(
+ accessToken: googleAuth.accessToken,
+ idToken: googleAuth.idToken,
+ );
+ assert(user.email != null);
+ assert(user.displayName != null);
+ return 'signInWithGoogle succeeded: $user';
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return new Scaffold(
+ appBar: new AppBar(
+ title: new Text(widget.title),
+ ),
+ body: new Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ new MaterialButton(
+ child: const Text('Test signInAnonymously'),
+ onPressed: () {
+ setState(() {
+ _message = _testSignInAnonymously();
+ });
+ }
+ ),
+ new MaterialButton(
+ child: const Text('Test signInWithGoogle'),
+ onPressed: () {
+ setState(() {
+ _message = _testSignInWithGoogle();
+ });
+ }
+ ),
+ new FutureBuilder(
+ future: _message,
+ builder: (_, AsyncSnapshot snapshot) {
+ return new Text(
+ snapshot.data ?? '',
+ style: const TextStyle(color: const Color.fromARGB(255, 0, 155, 0))
+ );
+ }
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/packages/firebase_auth/example/pubspec.yaml b/packages/firebase_auth/example/pubspec.yaml
new file mode 100755
index 000000000000..db9fc539f8f3
--- /dev/null
+++ b/packages/firebase_auth/example/pubspec.yaml
@@ -0,0 +1,14 @@
+name: firebase_auth_example
+description: Demonstrates how to use the firebase_auth plugin.
+
+dependencies:
+ flutter:
+ sdk: flutter
+ firebase_auth:
+ path: ../
+ # TODO(jackson): Point this at pub once a stable version is published
+ google_sign_in:
+ git: git://github.com/flutter/google_sign_in
+
+flutter:
+ uses-material-design: true
diff --git a/packages/firebase_auth/ios/.gitignore b/packages/firebase_auth/ios/.gitignore
new file mode 100755
index 000000000000..fc95c100cffd
--- /dev/null
+++ b/packages/firebase_auth/ios/.gitignore
@@ -0,0 +1,32 @@
+.idea/
+.vagrant/
+.sconsign.dblite
+.svn/
+
+.DS_Store
+*.swp
+profile
+
+DerivedData/
+build/
+
+*.pbxuser
+*.mode1v3
+*.mode2v3
+*.perspectivev3
+
+!default.pbxuser
+!default.mode1v3
+!default.mode2v3
+!default.perspectivev3
+
+xcuserdata
+
+*.moved-aside
+
+*.pyc
+*sync/
+Icon?
+.tags*
+
+Pods/
diff --git a/packages/firebase_auth/ios/Assets/.gitkeep b/packages/firebase_auth/ios/Assets/.gitkeep
new file mode 100755
index 000000000000..e69de29bb2d1
diff --git a/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.h b/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.h
new file mode 100755
index 000000000000..429a2015f6ac
--- /dev/null
+++ b/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.h
@@ -0,0 +1,4 @@
+#import
+
+@interface FirebaseAuthPlugin : NSObject
+@end
diff --git a/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m b/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m
new file mode 100755
index 000000000000..019520a999cf
--- /dev/null
+++ b/packages/firebase_auth/ios/Classes/FirebaseAuthPlugin.m
@@ -0,0 +1,96 @@
+#import "FirebaseAuthPlugin.h"
+
+#import "Firebase/Firebase.h"
+
+@interface NSError (FlutterError)
+@property(readonly, nonatomic) FlutterError *flutterError;
+@end
+
+@implementation NSError (FlutterError)
+- (FlutterError *)flutterError {
+ return [FlutterError
+ errorWithCode:[NSString stringWithFormat:@"Error %d", (int)self.code]
+ message:self.domain
+ details:self.localizedDescription];
+}
+@end
+
+NSDictionary *toDictionary(id userInfo) {
+ return @{
+ @"providerId" : userInfo.providerID,
+ @"displayName" : userInfo.displayName ?: [NSNull null],
+ @"uid" : userInfo.uid,
+ @"photoUrl" : userInfo.photoURL.absoluteString ?: [NSNull null],
+ @"email" : userInfo.email ?: [NSNull null],
+ };
+}
+
+@implementation FirebaseAuthPlugin {
+}
+
++ (void)registerWithRegistrar:(NSObject *)registrar {
+ FlutterMethodChannel *channel =
+ [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_auth"
+ binaryMessenger:[registrar messenger]];
+ FirebaseAuthPlugin *instance = [[FirebaseAuthPlugin alloc] init];
+ [registrar addMethodCallDelegate:instance channel:channel];
+}
+
+
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ if (![FIRApp defaultApp]) {
+ [FIRApp configure];
+ }
+ }
+ return self;
+}
+
+
+- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
+ if ([@"signInAnonymously" isEqualToString:call.method]) {
+ [[FIRAuth auth] signInAnonymouslyWithCompletion:^(FIRUser *user,
+ NSError *error) {
+ [self sendResult:result forUser:user error:error];
+ }];
+ } else if ([@"signInWithGoogle" isEqualToString:call.method]) {
+ NSString *idToken = call.arguments[@"idToken"];
+ NSString *accessToken = call.arguments[@"accessToken"];
+ FIRAuthCredential *credential =
+ [FIRGoogleAuthProvider credentialWithIDToken:idToken
+ accessToken:accessToken];
+ [[FIRAuth auth]
+ signInWithCredential:credential
+ completion:^(FIRUser *user, NSError *error) {
+ [self sendResult:result forUser:user error:error];
+ }];
+ } else {
+ result(FlutterMethodNotImplemented);
+ }
+}
+
+- (void)sendResult:(FlutterResult)result
+ forUser:(FIRUser *)user
+ error:(NSError *)error {
+ if (error != nil) {
+ result(error.flutterError);
+ } else if (user == nil) {
+ result(nil);
+ } else {
+ NSMutableArray *> *providerData =
+ [NSMutableArray arrayWithCapacity:user.providerData.count];
+ for (id userInfo in user.providerData) {
+ [providerData addObject:toDictionary(userInfo)];
+ }
+ NSMutableDictionary *userData = [toDictionary(user) mutableCopy];
+ userData[@"isAnonymous"] = [NSNumber numberWithBool:user.isAnonymous];
+ userData[@"isEmailVerified"] =
+ [NSNumber numberWithBool:user.isEmailVerified];
+ userData[@"providerData"] = providerData;
+ result(userData);
+ }
+}
+
+@end
diff --git a/packages/firebase_auth/ios/firebase_auth.podspec b/packages/firebase_auth/ios/firebase_auth.podspec
new file mode 100755
index 000000000000..5d9041f106c8
--- /dev/null
+++ b/packages/firebase_auth/ios/firebase_auth.podspec
@@ -0,0 +1,24 @@
+#
+# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
+#
+Pod::Spec.new do |s|
+ s.name = 'firebase_auth'
+ s.version = '0.0.1'
+ s.summary = 'Firebase Auth plugin for Flutter.'
+ s.description = <<-DESC
+Firebase Auth plugin for Flutter.
+ DESC
+ s.homepage = 'https://github.com/flutter/plugins/tree/master/packages/firebase_auth'
+ s.license = { :file => '../LICENSE' }
+ s.author = { 'Flutter Team' => 'flutter-dev@googlegroups.com' }
+ s.source = { :path => '.' }
+ s.source_files = 'Classes/**/*'
+ s.public_header_files = 'Classes/**/*.h'
+ s.ios.deployment_target = '6.0'
+ s.dependency 'Flutter'
+ s.dependency 'Firebase/Auth'
+ s.dependency 'Firebase/Core'
+ s.dependency 'FirebaseUI/Auth', '~> 3.0'
+ s.dependency 'FirebaseUI/Google'
+ s.dependency 'Google/SignIn'
+end
diff --git a/packages/firebase_auth/lib/firebase_auth.dart b/packages/firebase_auth/lib/firebase_auth.dart
new file mode 100755
index 000000000000..20ce2d19690a
--- /dev/null
+++ b/packages/firebase_auth/lib/firebase_auth.dart
@@ -0,0 +1,110 @@
+// Copyright 2017 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:meta/meta.dart';
+import 'package:flutter/services.dart';
+
+/// Represents user data returned from an identity provider.
+class UserInfo {
+ final Map _data;
+ UserInfo._(this._data);
+
+ /// The provider identifier.
+ String get providerId => _data['providerId'];
+
+ /// The provider’s user ID for the user.
+ String get uid => _data['uid'];
+
+ /// The name of the user.
+ String get displayName => _data['displayName'];
+
+ /// The URL of the user’s profile photo.
+ String get photoUrl => _data['photoUrl'];
+
+ /// The user’s email address.
+ String get email => _data['email'];
+
+ @override
+ String toString() {
+ return '$runtimeType($_data)';
+ }
+}
+
+/// Represents a user.
+class FirebaseUser extends UserInfo {
+ final Map _data;
+ final List providerData;
+ FirebaseUser._(this._data)
+ : providerData = (_data['providerData'] as List