From 51976cfb8b4a77e55231302d8d06ab610380c21f Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Sun, 7 Jul 2019 18:25:20 -0700 Subject: [PATCH 01/94] [android_intent] [battery] [shared_preferences] Fix Gradle version (#1797) --- packages/android_intent/CHANGELOG.md | 4 ++++ .../android/gradle/wrapper/gradle-wrapper.properties | 2 +- packages/android_intent/pubspec.yaml | 2 +- packages/battery/CHANGELOG.md | 4 ++++ .../battery/android/gradle/wrapper/gradle-wrapper.properties | 2 +- packages/battery/pubspec.yaml | 2 +- packages/shared_preferences/CHANGELOG.md | 4 ++++ .../android/gradle/wrapper/gradle-wrapper.properties | 5 +++++ packages/shared_preferences/pubspec.yaml | 2 +- 9 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 packages/shared_preferences/android/gradle/wrapper/gradle-wrapper.properties diff --git a/packages/android_intent/CHANGELOG.md b/packages/android_intent/CHANGELOG.md index 5b757c80697b..3622c65a0130 100644 --- a/packages/android_intent/CHANGELOG.md +++ b/packages/android_intent/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.1+1 + +* Fix Gradle version. + ## 0.3.1 * Add a new componentName parameter to help the intent resolution. diff --git a/packages/android_intent/android/gradle/wrapper/gradle-wrapper.properties b/packages/android_intent/android/gradle/wrapper/gradle-wrapper.properties index 9a4163a4f5ee..4e974715fd7b 100644 --- a/packages/android_intent/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/android_intent/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/android_intent/pubspec.yaml b/packages/android_intent/pubspec.yaml index 872e851e2a5e..a1d00c4ca970 100644 --- a/packages/android_intent/pubspec.yaml +++ b/packages/android_intent/pubspec.yaml @@ -2,7 +2,7 @@ name: android_intent description: Flutter plugin for launching Android Intents. Not supported on iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/android_intent -version: 0.3.1 +version: 0.3.1+1 flutter: plugin: diff --git a/packages/battery/CHANGELOG.md b/packages/battery/CHANGELOG.md index d4741b9faaa5..6777b98c4ab5 100644 --- a/packages/battery/CHANGELOG.md +++ b/packages/battery/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.0+5 + +* Fix Gradle version. + ## 0.3.0+4 * Update Dart code to conform to current Dart formatter. diff --git a/packages/battery/android/gradle/wrapper/gradle-wrapper.properties b/packages/battery/android/gradle/wrapper/gradle-wrapper.properties index 9a4163a4f5ee..4e974715fd7b 100644 --- a/packages/battery/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/battery/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/battery/pubspec.yaml b/packages/battery/pubspec.yaml index 9ab5b592bc0d..56a70b18f552 100644 --- a/packages/battery/pubspec.yaml +++ b/packages/battery/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for accessing information about the battery state (full, charging, discharging) on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/battery -version: 0.3.0+4 +version: 0.3.0+5 flutter: plugin: diff --git a/packages/shared_preferences/CHANGELOG.md b/packages/shared_preferences/CHANGELOG.md index 299c6857857b..5908c5ed6dc7 100644 --- a/packages/shared_preferences/CHANGELOG.md +++ b/packages/shared_preferences/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.3+2 + +* Fix Gradle version. + ## 0.5.3+1 * Add missing template type parameter to `invokeMethod` calls. diff --git a/packages/shared_preferences/android/gradle/wrapper/gradle-wrapper.properties b/packages/shared_preferences/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..caf54fa2801c --- /dev/null +++ b/packages/shared_preferences/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip diff --git a/packages/shared_preferences/pubspec.yaml b/packages/shared_preferences/pubspec.yaml index dd36cf91729a..5aaed2fba243 100644 --- a/packages/shared_preferences/pubspec.yaml +++ b/packages/shared_preferences/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for reading and writing simple key-value pairs. Wraps NSUserDefaults on iOS and SharedPreferences on Android. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/shared_preferences -version: 0.5.3+1 +version: 0.5.3+2 flutter: plugin: From 15558f2c211faae050742f38623dcec741115404 Mon Sep 17 00:00:00 2001 From: Harry ten Berge Date: Mon, 8 Jul 2019 16:20:45 +0200 Subject: [PATCH 02/94] [firebase_crashlytics] make sure the keys are actually added to the returned map (#1799) * make sure the keys are actually added to the returned map * Add testing, removed a print --- packages/firebase_crashlytics/CHANGELOG.md | 6 ++++++ .../example/test_driver/crashlytics.dart | 11 ++++++++--- .../lib/src/firebase_crashlytics.dart | 4 ++-- packages/firebase_crashlytics/pubspec.yaml | 2 +- .../test/firebase_crashlytics_test.dart | 17 ++++++++++++++++- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index 75afe030f843..65bb0a398ba4 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.0.4+9 + +* Fixed custom keys implementation. +* Added tests for custom keys implementation. +* Removed a print statement. + ## 0.0.4+8 * Automatically use version from pubspec.yaml when reporting usage to Firebase. diff --git a/packages/firebase_crashlytics/example/test_driver/crashlytics.dart b/packages/firebase_crashlytics/example/test_driver/crashlytics.dart index b40b396f59c8..c1a6c1d3df9e 100644 --- a/packages/firebase_crashlytics/example/test_driver/crashlytics.dart +++ b/packages/firebase_crashlytics/example/test_driver/crashlytics.dart @@ -16,10 +16,15 @@ void main() { test('onError', () async { // This is currently only testing that we can log errors without crashing. - await Crashlytics.instance.setUserName('testing'); - await Crashlytics.instance.setUserIdentifier('hello'); + final Crashlytics crashlytics = Crashlytics.instance; + await crashlytics.setUserName('testing'); + await crashlytics.setUserIdentifier('hello'); + crashlytics.setBool('testBool', true); + crashlytics.setInt('testInt', 42); + crashlytics.setDouble('testDouble', 42.0); + crashlytics.setString('testString', 'bar'); Crashlytics.instance.log('testing'); - await Crashlytics.instance.onError( + await crashlytics.onError( FlutterErrorDetails( exception: 'testing', stack: StackTrace.fromString(''), diff --git a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart index 9bb95238262d..dd43f7fd02f7 100644 --- a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart +++ b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart @@ -41,7 +41,7 @@ class Crashlytics { Trace.format(details.stack).trimRight().split('\n'); final List> stackTraceElements = getStackTraceElements(stackTraceLines); - final dynamic result = await channel + await channel .invokeMethod('Crashlytics#onError', { 'exception': details.exceptionAsString(), // FlutterErrorDetails.context has been migrated from a String to a @@ -52,7 +52,6 @@ class Crashlytics { 'logs': _logs.toList(), 'keys': _prepareKeys(), }); - print(result); } } @@ -156,6 +155,7 @@ class Crashlytics { } else if (value is bool) { crashlyticsKey['type'] = 'boolean'; } + crashlyticsKeys.add(crashlyticsKey); } return crashlyticsKeys; diff --git a/packages/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/pubspec.yaml index 326d8693fb27..dadc332573cc 100644 --- a/packages/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_crashlytics description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. -version: 0.0.4+8 +version: 0.0.4+9 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_crashlytics diff --git a/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart b/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart index 83a6530c8d1c..8eb771ee2707 100644 --- a/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart +++ b/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart @@ -42,13 +42,28 @@ void main() { ); crashlytics.enableInDevMode = true; crashlytics.log('foo'); + crashlytics.setBool('testBool', true); + crashlytics.setInt('testInt', 42); + crashlytics.setDouble('testDouble', 42.0); + crashlytics.setString('testString', 'bar'); await crashlytics.onError(details); expect(log[0].method, 'Crashlytics#onError'); expect(log[0].arguments['exception'], 'foo exception'); expect(log[0].arguments['context'], 'foo context'); expect(log[0].arguments['logs'], isNotEmpty); expect(log[0].arguments['logs'], contains('foo')); - expect(log[0].arguments['keys'], isEmpty); + expect(log[0].arguments['keys'][0]['key'], 'testBool'); + expect(log[0].arguments['keys'][0]['value'], isTrue); + expect(log[0].arguments['keys'][0]['type'], 'boolean'); + expect(log[0].arguments['keys'][1]['key'], 'testInt'); + expect(log[0].arguments['keys'][1]['value'], 42); + expect(log[0].arguments['keys'][1]['type'], 'int'); + expect(log[0].arguments['keys'][2]['key'], 'testDouble'); + expect(log[0].arguments['keys'][2]['value'], 42.0); + expect(log[0].arguments['keys'][2]['type'], 'double'); + expect(log[0].arguments['keys'][3]['key'], 'testString'); + expect(log[0].arguments['keys'][3]['value'], 'bar'); + expect(log[0].arguments['keys'][3]['type'], 'string'); }); test('isDebuggable', () async { From 51a0fecc919d0d7137d35cff5a1b286e495b74ff Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 8 Jul 2019 08:37:36 -0700 Subject: [PATCH 03/94] [cloud_firestore] Transactions improvements (#1780) * Add a test for rapidly updating in quick succession * Teach Transaction how to await automatically --- packages/cloud_firestore/CHANGELOG.md | 7 +++ .../cloudfirestore/CloudFirestorePlugin.java | 3 +- .../example/test_driver/cloud_firestore.dart | 13 ++++- .../cloud_firestore/lib/src/firestore.dart | 8 ++-- .../cloud_firestore/lib/src/transaction.dart | 48 ++++++++++++++++++- packages/cloud_firestore/pubspec.yaml | 2 +- packages/firebase_database/CHANGELOG.md | 4 ++ 7 files changed, 76 insertions(+), 9 deletions(-) diff --git a/packages/cloud_firestore/CHANGELOG.md b/packages/cloud_firestore/CHANGELOG.md index 0dd48a7d10c7..b078cfd0a41d 100644 --- a/packages/cloud_firestore/CHANGELOG.md +++ b/packages/cloud_firestore/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.12.7 + +* Methods of `Transaction` no longer require `await`. +* Added documentation to methods of `Transaction`. +* Removed an unnecessary log on Android. +* Added an integration test for rapidly incrementing field value. + ## 0.12.6 * Support for `orderBy` on map fields (e.g. `orderBy('cake.flavor')`) for diff --git a/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java b/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java index d0606a262ec3..5254b8b1493d 100644 --- a/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java +++ b/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java @@ -398,7 +398,7 @@ public void error( String errorMessage, Object errorDetails) { transactionTCS.trySetException( - new Exception("Do transaction failed.")); + new Exception("DoTransaction failed: " + errorMessage)); } @Override @@ -528,7 +528,6 @@ protected Void doInBackground(Void... voids) { new Runnable() { @Override public void run() { - Log.d(TAG, "sending set success"); result.success(null); } }); diff --git a/packages/cloud_firestore/example/test_driver/cloud_firestore.dart b/packages/cloud_firestore/example/test_driver/cloud_firestore.dart index 8926dcd0dcc4..d7d85db5b000 100644 --- a/packages/cloud_firestore/example/test_driver/cloud_firestore.dart +++ b/packages/cloud_firestore/example/test_driver/cloud_firestore.dart @@ -90,6 +90,16 @@ void main() { }); snapshot = await ref.get(); expect(snapshot.data['message'], 42.1); + + // Call several times without awaiting the result + await Future.wait(List>.generate( + 3, + (int i) => ref.updateData({ + 'message': FieldValue.increment(i), + }), + )); + snapshot = await ref.get(); + expect(snapshot.data['message'], 45.1); await ref.delete(); }); @@ -107,11 +117,12 @@ void main() { final Map updatedData = Map.from(snapshot.data); updatedData['message'] = 'testing2'; - await tx.update(ref, updatedData); + tx.update(ref, updatedData); // calling await here is optional return updatedData; }, ); expect(result['message'], 'testing2'); + await ref.delete(); final DocumentSnapshot nonexistentSnapshot = await ref.get(); expect(nonexistentSnapshot.data, null); diff --git a/packages/cloud_firestore/lib/src/firestore.dart b/packages/cloud_firestore/lib/src/firestore.dart index e91bc47261ef..c2fa17720995 100644 --- a/packages/cloud_firestore/lib/src/firestore.dart +++ b/packages/cloud_firestore/lib/src/firestore.dart @@ -25,9 +25,11 @@ class Firestore { _documentObservers[call.arguments['handle']].add(snapshot); } else if (call.method == 'DoTransaction') { final int transactionId = call.arguments['transactionId']; - return _transactionHandlers[transactionId]( - Transaction(transactionId, this), - ); + final Transaction transaction = Transaction(transactionId, this); + final dynamic result = + await _transactionHandlers[transactionId](transaction); + await transaction._finish(); + return result; } }); _initialized = true; diff --git a/packages/cloud_firestore/lib/src/transaction.dart b/packages/cloud_firestore/lib/src/transaction.dart index d42c89d9d59e..d13e3f19f9b2 100644 --- a/packages/cloud_firestore/lib/src/transaction.dart +++ b/packages/cloud_firestore/lib/src/transaction.dart @@ -12,8 +12,17 @@ class Transaction { int _transactionId; Firestore _firestore; + List> _pendingResults = >[]; + Future _finish() => Future.wait(_pendingResults); - Future get(DocumentReference documentReference) async { + /// Reads the document referenced by the provided DocumentReference. + Future get(DocumentReference documentReference) { + final Future result = _get(documentReference); + _pendingResults.add(result); + return result; + } + + Future _get(DocumentReference documentReference) async { final Map result = await Firestore.channel .invokeMapMethod('Transaction#get', { 'app': _firestore.app.name, @@ -32,7 +41,17 @@ class Transaction { } } - Future delete(DocumentReference documentReference) async { + /// Deletes the document referred to by the provided [documentReference]. + /// + /// Awaiting the returned [Future] is optional and will be done automatically + /// when the transaction handler completes. + Future delete(DocumentReference documentReference) { + final Future result = _delete(documentReference); + _pendingResults.add(result); + return result; + } + + Future _delete(DocumentReference documentReference) async { return Firestore.channel .invokeMethod('Transaction#delete', { 'app': _firestore.app.name, @@ -41,8 +60,20 @@ class Transaction { }); } + /// Updates fields in the document referred to by [documentReference]. + /// The update will fail if applied to a document that does not exist. + /// + /// Awaiting the returned [Future] is optional and will be done automatically + /// when the transaction handler completes. Future update( DocumentReference documentReference, Map data) async { + final Future result = _update(documentReference, data); + _pendingResults.add(result); + return result; + } + + Future _update( + DocumentReference documentReference, Map data) async { return Firestore.channel .invokeMethod('Transaction#update', { 'app': _firestore.app.name, @@ -52,7 +83,20 @@ class Transaction { }); } + /// Writes to the document referred to by the provided [DocumentReference]. + /// If the document does not exist yet, it will be created. If you pass + /// SetOptions, the provided data can be merged into the existing document. + /// + /// Awaiting the returned [Future] is optional and will be done automatically + /// when the transaction handler completes. Future set( + DocumentReference documentReference, Map data) { + final Future result = _set(documentReference, data); + _pendingResults.add(result); + return result; + } + + Future _set( DocumentReference documentReference, Map data) async { return Firestore.channel .invokeMethod('Transaction#set', { diff --git a/packages/cloud_firestore/pubspec.yaml b/packages/cloud_firestore/pubspec.yaml index 9c70101f356f..b488e30ccff8 100755 --- a/packages/cloud_firestore/pubspec.yaml +++ b/packages/cloud_firestore/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Cloud Firestore, a cloud-hosted, noSQL database live synchronization and offline support on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/cloud_firestore -version: 0.12.6 +version: 0.12.7 flutter: plugin: diff --git a/packages/firebase_database/CHANGELOG.md b/packages/firebase_database/CHANGELOG.md index c08e59b44483..3f8772587402 100644 --- a/packages/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.4 + +* Fix transactions on + ## 3.0.3 * Automatically use version from pubspec.yaml when reporting usage to Firebase. From 1850be00950e067b509fb44e6a43e463994493ee Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 8 Jul 2019 08:41:54 -0700 Subject: [PATCH 04/94] [path_provider] Update to use getExternalFilesDir (#1811) --- packages/path_provider/CHANGELOG.md | 4 ++++ .../flutter/plugins/pathprovider/PathProviderPlugin.java | 3 +-- .../path_provider/example/test_driver/path_provider.dart | 9 ++++++--- packages/path_provider/lib/path_provider.dart | 2 +- packages/path_provider/pubspec.yaml | 2 +- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/path_provider/CHANGELOG.md b/packages/path_provider/CHANGELOG.md index 0693af3e5153..ea956fcc766f 100644 --- a/packages/path_provider/CHANGELOG.md +++ b/packages/path_provider/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.2 + +* `getExternalStorageDirectory` now uses `getExternalFilesDir` on Android. + ## 1.1.1 * Cast error codes as longs in iOS error strings to ensure compatibility diff --git a/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java b/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java index d56cb2b60ca1..ae432639f75a 100644 --- a/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java +++ b/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java @@ -4,7 +4,6 @@ package io.flutter.plugins.pathprovider; -import android.os.Environment; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; @@ -52,6 +51,6 @@ private String getPathProviderApplicationDocumentsDirectory() { } private String getPathProviderStorageDirectory() { - return Environment.getExternalStorageDirectory().getAbsolutePath(); + return mRegistrar.context().getExternalFilesDir(null).getAbsolutePath(); } } diff --git a/packages/path_provider/example/test_driver/path_provider.dart b/packages/path_provider/example/test_driver/path_provider.dart index 2f225a7034d8..219d6660df7e 100644 --- a/packages/path_provider/example/test_driver/path_provider.dart +++ b/packages/path_provider/example/test_driver/path_provider.dart @@ -56,9 +56,12 @@ void main() { expect(result, throwsA(isInstanceOf())); } else if (Platform.isAndroid) { final Directory result = await getExternalStorageDirectory(); - // This directory is not accessible in Android emulators. - // However, it should at least have a fake path returned. - expect(result.path.length, isNonZero); + final String uuid = Uuid().v1(); + final File file = File('${result.path}/$uuid.txt'); + file.writeAsStringSync('Hello world!'); + expect(file.readAsStringSync(), 'Hello world!'); + expect(result.listSync(), isNotEmpty); + file.deleteSync(); } }); } diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 08e35d68dd63..10755873c321 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -76,7 +76,7 @@ Future getApplicationDocumentsDirectory() async { /// On iOS, this function throws an [UnsupportedError] as it is not possible /// to access outside the app's sandbox. /// -/// On Android this uses the `getExternalStorageDirectory` API. +/// On Android this uses the `getExternalFilesDir(null)`. Future getExternalStorageDirectory() async { if (Platform.isIOS) throw UnsupportedError("Functionality not available on iOS"); diff --git a/packages/path_provider/pubspec.yaml b/packages/path_provider/pubspec.yaml index 62bab1030fac..96f248625b8a 100644 --- a/packages/path_provider/pubspec.yaml +++ b/packages/path_provider/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for getting commonly used locations on the Android & iOS file systems, such as the temp and app data directories. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider -version: 1.1.1 +version: 1.1.2 flutter: plugin: From debf9cf1df25371cbad5272e28113a6c860f582e Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 8 Jul 2019 09:38:32 -0700 Subject: [PATCH 05/94] [firebase_database] Move firebase_database transaction calls to UI thread on Android (#1812) * Move calls to UI thread * Update packages/firebase_database/CHANGELOG.md Co-Authored-By: Chris Yang --- packages/firebase_database/CHANGELOG.md | 4 +- .../database/FirebaseDatabasePlugin.java | 79 +++++++++++-------- packages/firebase_database/pubspec.yaml | 2 +- 3 files changed, 51 insertions(+), 34 deletions(-) diff --git a/packages/firebase_database/CHANGELOG.md b/packages/firebase_database/CHANGELOG.md index 3f8772587402..0e032e4dc2d3 100644 --- a/packages/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/CHANGELOG.md @@ -1,6 +1,8 @@ ## 3.0.4 -* Fix transactions on +* Updated transactions implementation on Android for compatibility with + newer versions of Flutter engine that require channel calls be made + on the UI thread. ## 3.0.3 diff --git a/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java b/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java index 2f1f7145b9d9..c3fb751e5070 100644 --- a/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java +++ b/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java @@ -4,6 +4,7 @@ package io.flutter.plugins.firebase.database; +import android.app.Activity; import android.util.Log; import android.util.SparseArray; import com.google.android.gms.tasks.Task; @@ -37,6 +38,7 @@ public class FirebaseDatabasePlugin implements MethodCallHandler { private static final String TAG = "FirebaseDatabasePlugin"; private final MethodChannel channel; + private final Activity activity; private static final String EVENT_TYPE_CHILD_ADDED = "_EventType.childAdded"; private static final String EVENT_TYPE_CHILD_REMOVED = "_EventType.childRemoved"; private static final String EVENT_TYPE_CHILD_CHANGED = "_EventType.childChanged"; @@ -50,11 +52,12 @@ public class FirebaseDatabasePlugin implements MethodCallHandler { public static void registerWith(PluginRegistry.Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_database"); - channel.setMethodCallHandler(new FirebaseDatabasePlugin(channel)); + channel.setMethodCallHandler(new FirebaseDatabasePlugin(channel, registrar.activity())); } - private FirebaseDatabasePlugin(MethodChannel channel) { + private FirebaseDatabasePlugin(MethodChannel channel, Activity activity) { this.channel = channel; + this.activity = activity; } private DatabaseReference getReference(FirebaseDatabase database, Map arguments) { @@ -333,7 +336,7 @@ public Transaction.Result doTransaction(MutableData mutableData) { final Task> updateMutableDataTCSTask = updateMutableDataTCS.getTask(); - Map doTransactionMap = new HashMap<>(); + final Map doTransactionMap = new HashMap<>(); doTransactionMap.put("transactionKey", arguments.get("transactionKey")); final Map snapshotMap = new HashMap<>(); @@ -342,39 +345,46 @@ public Transaction.Result doTransaction(MutableData mutableData) { doTransactionMap.put("snapshot", snapshotMap); // Return snapshot to Dart side for update. - channel.invokeMethod( - "DoTransaction", - doTransactionMap, - new MethodChannel.Result() { + activity.runOnUiThread( + new Runnable() { @Override - @SuppressWarnings("unchecked") - public void success(Object result) { - updateMutableDataTCS.setResult((Map) result); - } - - @Override - public void error( - String errorCode, String errorMessage, Object errorDetails) { - String exceptionMessage = - "Error code: " - + errorCode - + "\nError message: " - + errorMessage - + "\nError details: " - + errorDetails; - updateMutableDataTCS.setException(new Exception(exceptionMessage)); - } - - @Override - public void notImplemented() { - updateMutableDataTCS.setException( - new Exception("DoTransaction not implemented on Dart side.")); + public void run() { + channel.invokeMethod( + "DoTransaction", + doTransactionMap, + new MethodChannel.Result() { + @Override + @SuppressWarnings("unchecked") + public void success(Object result) { + updateMutableDataTCS.setResult((Map) result); + } + + @Override + public void error( + String errorCode, String errorMessage, Object errorDetails) { + String exceptionMessage = + "Error code: " + + errorCode + + "\nError message: " + + errorMessage + + "\nError details: " + + errorDetails; + updateMutableDataTCS.setException( + new Exception(exceptionMessage)); + } + + @Override + public void notImplemented() { + updateMutableDataTCS.setException( + new Exception("DoTransaction not implemented on Dart side.")); + } + }); } }); try { // Wait for updated snapshot from the Dart side. - Map updatedSnapshotMap = + final Map updatedSnapshotMap = Tasks.await( updateMutableDataTCSTask, (int) arguments.get("transactionTimeout"), @@ -394,7 +404,7 @@ public void notImplemented() { @Override public void onComplete( DatabaseError databaseError, boolean committed, DataSnapshot dataSnapshot) { - Map completionMap = new HashMap<>(); + final Map completionMap = new HashMap<>(); completionMap.put("transactionKey", arguments.get("transactionKey")); if (databaseError != null) { completionMap.put("error", asMap(databaseError)); @@ -408,7 +418,12 @@ public void onComplete( } // Invoke transaction completion on the Dart side. - result.success(completionMap); + activity.runOnUiThread( + new Runnable() { + public void run() { + result.success(completionMap); + } + }); } }); break; diff --git a/packages/firebase_database/pubspec.yaml b/packages/firebase_database/pubspec.yaml index 59f8aa06ce4f..d91420632811 100755 --- a/packages/firebase_database/pubspec.yaml +++ b/packages/firebase_database/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database with realtime data syncing across Android and iOS clients, and offline access. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_database -version: 3.0.3 +version: 3.0.4 flutter: plugin: From c0e7a428a69e0488def0e8c5bef84af4b402cdaa Mon Sep 17 00:00:00 2001 From: Amir Hardon Date: Mon, 8 Jul 2019 09:43:13 -0700 Subject: [PATCH 06/94] Add a PR triage policy to the contributing guide. (#1779) --- CONTRIBUTING.md | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fa8438866b48..936b5b921ebf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,19 +1,19 @@ -Contributing to Flutter Plugins -=============================== +# Contributing to Flutter Plugins + [![Build Status](https://api.cirrus-ci.com/github/flutter/plugins.svg)](https://cirrus-ci.com/github/flutter/plugins/master) _See also: [Flutter's code of conduct](https://flutter.io/design-principles/#code-of-conduct)_ -Things you will need --------------------- +## Things you will need + * Linux, Mac OS X, or Windows. * git (used for source version control). * An ssh client (used to authenticate with GitHub). -Getting the code and configuring your environment -------------------------------------------------- +## Getting the code and configuring your environment + * Ensure all the dependencies described in the previous section are installed. * Fork `https://github.com/flutter/plugins` into your own GitHub account. If @@ -29,8 +29,8 @@ Getting the code and configuring your environment fetch from the master repository, not your clone, when running `git fetch` et al.) -Running the examples --------------------- +## Running the examples + To run an example with a prebuilt binary from the cloud, switch to that example's directory, run `pub get` to make sure its dependencies have been @@ -40,8 +40,7 @@ USB and debugging enabled on that device. * `cd packages/battery/example` * `flutter run` -Running the tests ------------------ +## Running the tests Flutter plugins have both unit tests of their Dart API and integration tests that run on a virtual or actual device. @@ -58,8 +57,7 @@ cd example flutter drive test/.dart ``` -Contributing code ------------------ +## Contributing code We gladly accept contributions via GitHub pull requests. @@ -112,3 +110,20 @@ You must complete the You can do this online, and it only takes a minute. If you've never submitted code before, you must add your (or your organization's) name and contact info to the [AUTHORS](AUTHORS) file. + +### The review process + +* This is a new process we are currently experimenting with, feedback on the process is welcomed at the Gitter contributors channel. * + +Reviewing PRs often requires a non trivial amount of time. We prioritize issues, not PRs, so that we use our maintainers' time in the most impactful way. Issues pertaining to this repository are managed in the [flutter/flutter issue tracker and are labeled with "plugin"](https://github.com/flutter/flutter/issues?q=is%3Aopen+is%3Aissue+label%3Aplugin+sort%3Areactions-%2B1-desc). Non trivial PRs should have an associated issue that will be used for prioritization. See the [prioritization section](https://github.com/flutter/flutter/wiki/Issue-hygiene#prioritization) in the Flutter wiki to understand how issues are prioritized. + +Newly opened PRs first go through initial triage which results in one of: + * **Merging the PR** - if the PR can be quickly reviewed and looks good. + * **Closing the PR** - if the PR maintainer decides that the PR should not be merged. + * **Moving the PR to the backlog** - if the review requires non trivial effort and the issue isn't a priority; in this case the maintainer will: + * Make sure that the PR has an associated issue labeled with "plugin". + * Add the "backlog" label to the issue. + * Leave a comment on the PR explaining that the review is not trivial and that the issue will be looked at according to priority order. + * **Starting a non trivial review** - if the review requires non trivial effort and the issue is a priority; in this case the maintainer will: + * Add the "in review" label to the issue. + * Self assign the PR. From c34a7be5b2764093d6ea4d7b6e831da3605de78a Mon Sep 17 00:00:00 2001 From: Dat Nguyen Date: Mon, 8 Jul 2019 23:50:06 +0700 Subject: [PATCH 07/94] [firebase_messaging] fix crash when func deleteInstanceID return result in incorrect thread (#1756) * [firebase_messaging] fix crash when calling func deleteInstanceID (#1756) --- packages/firebase_messaging/CHANGELOG.md | 4 ++++ .../FirebaseMessagingPlugin.java | 24 +++++++++++++++++-- packages/firebase_messaging/pubspec.yaml | 2 +- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/CHANGELOG.md index 8d5fb83365e3..206ce3796ffa 100644 --- a/packages/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.0.5 + +* On Android, fix crash when calling `deleteInstanceID` with latest Flutter engine. + ## 5.0.4 * Automatically use version from pubspec.yaml when reporting usage to Firebase. diff --git a/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java b/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java index 7c01c516c843..11befeba8642 100644 --- a/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java +++ b/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java @@ -148,10 +148,30 @@ public void onComplete(@NonNull Task task) { public void run() { try { FirebaseInstanceId.getInstance().deleteInstanceId(); - result.success(true); + if (registrar.activity() != null) { + registrar + .activity() + .runOnUiThread( + new Runnable() { + @Override + public void run() { + result.success(true); + } + }); + } } catch (IOException ex) { Log.e(TAG, "deleteInstanceID, error:", ex); - result.success(false); + if (registrar.activity() != null) { + registrar + .activity() + .runOnUiThread( + new Runnable() { + @Override + public void run() { + result.success(false); + } + }); + } } } }) diff --git a/packages/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/pubspec.yaml index 10d2f8e2eae5..f7fdb5b7223a 100644 --- a/packages/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_messaging -version: 5.0.4 +version: 5.0.5 flutter: plugin: From 9591d3c4f01034f3e2c84ddd67bb9e1daa0b8383 Mon Sep 17 00:00:00 2001 From: Stefano Saitta Date: Mon, 8 Jul 2019 19:23:18 +0200 Subject: [PATCH 08/94] [firebase_crashlytics] Update README with advice on testing installation (#1815) * Add the result section for successfully installations This section will give feedback on when the installation goes fine, plus informing user that `firebase` takes a while to display the collected crashes into the Firebase Console, since the time is quite long (almost a day) i think it's better to give a feedback here. --- packages/firebase_crashlytics/CHANGELOG.md | 4 ++++ packages/firebase_crashlytics/README.md | 11 +++++++++++ packages/firebase_crashlytics/pubspec.yaml | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index 65bb0a398ba4..124b410f9881 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.4+10 + +* Update README. + ## 0.0.4+9 * Fixed custom keys implementation. diff --git a/packages/firebase_crashlytics/README.md b/packages/firebase_crashlytics/README.md index 71161efa99db..784a4330e003 100644 --- a/packages/firebase_crashlytics/README.md +++ b/packages/firebase_crashlytics/README.md @@ -93,6 +93,17 @@ void main() { } ``` +## Result + +If an error is caught, you should see the following messages in your logs: +``` +flutter: Error caught by Crashlytics plugin: +... +flutter: Error reported to Crashlytics. +``` + +*Note:* It may take awhile (up to 24 hours) before you will be able to see the logs appear in your Firebase console. + ## Example See the [example application](https://github.com/flutter/plugins/tree/master/packages/firebase_crashlytics/example) source diff --git a/packages/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/pubspec.yaml index dadc332573cc..7510f37b167a 100644 --- a/packages/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_crashlytics description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. -version: 0.0.4+9 +version: 0.0.4+10 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_crashlytics From 5e48cd811d22629ec4c85c734b51eb68a50c296f Mon Sep 17 00:00:00 2001 From: Moritz Morgenroth <35544088+moritzmorgenroth@users.noreply.github.com> Date: Mon, 8 Jul 2019 19:30:59 +0200 Subject: [PATCH 09/94] [in_app_purchase] Readme updates (#1798) * Documentation updates CHANGELOG * Remove explicit typing in `_subscription` callback * Remove `const` modifier for `_kIds` list * Fix not found ids check typos * Migrate loop iterator from `:` to `in` * Fix typo from #1798 --- packages/in_app_purchase/CHANGELOG.md | 4 ++++ packages/in_app_purchase/README.md | 8 ++++---- packages/in_app_purchase/pubspec.yaml | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/in_app_purchase/CHANGELOG.md b/packages/in_app_purchase/CHANGELOG.md index be8d4d5c9cf4..32f56899826e 100644 --- a/packages/in_app_purchase/CHANGELOG.md +++ b/packages/in_app_purchase/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0+3 + +* Update the `README.md` so that the code samples compile with the latest Flutter/Dart version. + ## 0.2.0+2 * Fix a google_play_connection purchase update listener regression introduced in 0.2.0+1. diff --git a/packages/in_app_purchase/README.md b/packages/in_app_purchase/README.md index 24584850474c..3b8d1a4df04c 100644 --- a/packages/in_app_purchase/README.md +++ b/packages/in_app_purchase/README.md @@ -62,7 +62,7 @@ class _MyAppState extends State { void initState() { final Stream purchaseUpdates = InAppPurchaseConnection.instance.purchaseUpdatedStream; - _subscription = purchaseUpdates.listen((List purchases) { + _subscription = purchaseUpdates.listen((purchases) { _handlePurchaseUpdates(purchases); }); super.initState(); @@ -87,9 +87,9 @@ if (!available) { ### Loading products for sale ```dart -const Set _kIds = ['product1', 'product2'].toSet(); +Set _kIds = ['product1', 'product2'].toSet(); final ProductDetailsResponse response = await InAppPurchaseConnection.instance.queryProductDetails(_kIds); -if (!response.notFoundIds.isEmpty()) { +if (!response.notFoundIDs.isEmpty) { // Handle the error. } List products = response.productDetails; @@ -102,7 +102,7 @@ final QueryPurchaseDetailsResponse response = await InAppPurchaseConnection.inst if (response.error != null) { // Handle the error. } -for (PurchaseDetails purchase : repsonse.pastPurchases) { +for (PurchaseDetails purchase in response.pastPurchases) { _verifyPurchase(purchase); // Verify the purchase following the best practices for each storefront. _deliverPurchase(purchase); // Deliver the purchase to the user in your app. if (Platform.isIOS) { diff --git a/packages/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/pubspec.yaml index 75d187389ea5..3987990e1c77 100644 --- a/packages/in_app_purchase/pubspec.yaml +++ b/packages/in_app_purchase/pubspec.yaml @@ -2,7 +2,7 @@ name: in_app_purchase description: A Flutter plugin for in-app purchases. Exposes APIs for making in-app purchases through the App Store and Google Play. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase -version: 0.2.0+2 +version: 0.2.0+3 dependencies: async: ^2.0.8 From 80318be69aa81b6b3b089285a6d52cb588c8f98e Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 8 Jul 2019 11:02:17 -0700 Subject: [PATCH 10/94] [image_picker] use objc class instead of struct for GIFInfo on iOS (#1817) --- packages/image_picker/CHANGELOG.md | 4 +++ .../ImageUtilTests.m | 2 +- .../ios/Classes/FLTImagePickerImageUtil.h | 19 +++++++----- .../ios/Classes/FLTImagePickerImageUtil.m | 31 +++++++++++++++---- .../Classes/FLTImagePickerPhotoAssetUtil.m | 12 +++---- packages/image_picker/pubspec.yaml | 2 +- 6 files changed, 48 insertions(+), 22 deletions(-) diff --git a/packages/image_picker/CHANGELOG.md b/packages/image_picker/CHANGELOG.md index 7814f393927d..145fd4995a8e 100644 --- a/packages/image_picker/CHANGELOG.md +++ b/packages/image_picker/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.0+12 + +* Use class instead of struct for `GIFInfo` in iOS implementation. + ## 0.6.0+11 * Don't use module imports. diff --git a/packages/image_picker/example/ios/image_picker_exampleTests/ImageUtilTests.m b/packages/image_picker/example/ios/image_picker_exampleTests/ImageUtilTests.m index b554f4d02e05..f59c942ea7cb 100644 --- a/packages/image_picker/example/ios/image_picker_exampleTests/ImageUtilTests.m +++ b/packages/image_picker/example/ios/image_picker_exampleTests/ImageUtilTests.m @@ -31,7 +31,7 @@ - (void)testScaledGIFImage_ShouldBeScaled { // gif image that frame size is 3 and the duration is 1 second. NSData *data = [NSData dataWithContentsOfFile:[self.testBundle pathForResource:@"gifImage" ofType:@"gif"]]; - GIFInfo info = [FLTImagePickerImageUtil scaledGIFImage:data maxWidth:@3 maxHeight:@2]; + GIFInfo *info = [FLTImagePickerImageUtil scaledGIFImage:data maxWidth:@3 maxHeight:@2]; NSArray *images = info.images; NSTimeInterval duration = info.interval; diff --git a/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.h b/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.h index d9abec84bf52..0983f1fad6b8 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.h +++ b/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.h @@ -7,11 +7,14 @@ NS_ASSUME_NONNULL_BEGIN -typedef struct GIFInfo { - // frames of animation - NSArray *images; - NSTimeInterval interval; -} GIFInfo; +@interface GIFInfo : NSObject + +@property(strong, nonatomic, readonly) NSArray *images; +@property(assign, nonatomic, readonly) NSTimeInterval interval; + +- (instancetype)initWithImages:(NSArray *)images interval:(NSTimeInterval)interval; + +@end @interface FLTImagePickerImageUtil : NSObject @@ -20,9 +23,9 @@ typedef struct GIFInfo { maxHeight:(NSNumber *)maxHeight; // Resize all gif animation frames. -+ (GIFInfo)scaledGIFImage:(NSData *)data - maxWidth:(NSNumber *)maxWidth - maxHeight:(NSNumber *)maxHeight; ++ (GIFInfo *)scaledGIFImage:(NSData *)data + maxWidth:(NSNumber *)maxWidth + maxHeight:(NSNumber *)maxHeight; @end diff --git a/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.m index cd4d1ad489b8..2e57caf4b54f 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerImageUtil.m @@ -5,6 +5,27 @@ #import "FLTImagePickerImageUtil.h" #import +@interface GIFInfo () + +@property(strong, nonatomic, readwrite) NSArray *images; +@property(assign, nonatomic, readwrite) NSTimeInterval interval; + +@end + +@implementation GIFInfo + +- (instancetype)initWithImages:(NSArray *)images interval:(NSTimeInterval)interval; +{ + self = [super init]; + if (self) { + self.images = images; + self.interval = interval; + } + return self; +} + +@end + @implementation FLTImagePickerImageUtil : NSObject + (UIImage *)scaledImage:(UIImage *)image @@ -57,9 +78,9 @@ + (UIImage *)scaledImage:(UIImage *)image return scaledImage; } -+ (GIFInfo)scaledGIFImage:(NSData *)data - maxWidth:(NSNumber *)maxWidth - maxHeight:(NSNumber *)maxHeight { ++ (GIFInfo *)scaledGIFImage:(NSData *)data + maxWidth:(NSNumber *)maxWidth + maxHeight:(NSNumber *)maxHeight { NSMutableDictionary *options = [NSMutableDictionary dictionary]; options[(NSString *)kCGImageSourceShouldCache] = @(YES); options[(NSString *)kCGImageSourceTypeIdentifierHint] = (NSString *)kUTTypeGIF; @@ -98,9 +119,7 @@ + (GIFInfo)scaledGIFImage:(NSData *)data CFRelease(imageSource); - GIFInfo info; - info.images = images; - info.interval = interval; + GIFInfo *info = [[GIFInfo alloc] initWithImages:images interval:interval]; return info; } diff --git a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m index 80563e292943..c73bc11a53c2 100644 --- a/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m +++ b/packages/image_picker/ios/Classes/FLTImagePickerPhotoAssetUtil.m @@ -6,7 +6,7 @@ #import "FLTImagePickerImageUtil.h" #import "FLTImagePickerMetaDataUtil.h" -#import ; +#import @implementation FLTImagePickerPhotoAssetUtil @@ -35,9 +35,9 @@ + (NSString *)saveImageWithOriginalImageData:(NSData *)originalImageData metaData = [FLTImagePickerMetaDataUtil getMetaDataFromImageData:originalImageData]; } if (type == FLTImagePickerMIMETypeGIF) { - GIFInfo gifInfo = [FLTImagePickerImageUtil scaledGIFImage:originalImageData - maxWidth:maxWidth - maxHeight:maxHeight]; + GIFInfo *gifInfo = [FLTImagePickerImageUtil scaledGIFImage:originalImageData + maxWidth:maxWidth + maxHeight:maxHeight]; return [self saveImageWithMetaData:metaData gifInfo:gifInfo suffix:suffix]; } else { @@ -54,7 +54,7 @@ + (NSString *)saveImageWithPickerInfo:(nullable NSDictionary *)info image:(UIIma } + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData - gifInfo:(GIFInfo)gifInfo + gifInfo:(GIFInfo *)gifInfo suffix:(NSString *)suffix { NSString *path = [self temporaryFilePath:suffix]; return [self saveImageWithMetaData:metaData gifInfo:gifInfo path:path]; @@ -82,7 +82,7 @@ + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData } + (NSString *)saveImageWithMetaData:(NSDictionary *)metaData - gifInfo:(GIFInfo)gifInfo + gifInfo:(GIFInfo *)gifInfo path:(NSString *)path { CGImageDestinationRef destination = CGImageDestinationCreateWithURL( (CFURLRef)[NSURL fileURLWithPath:path], kUTTypeGIF, gifInfo.images.count, NULL); diff --git a/packages/image_picker/pubspec.yaml b/packages/image_picker/pubspec.yaml index f97340972639..4d4027156d91 100755 --- a/packages/image_picker/pubspec.yaml +++ b/packages/image_picker/pubspec.yaml @@ -5,7 +5,7 @@ authors: - Flutter Team - Rhodes Davis Jr. homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker -version: 0.6.0+11 +version: 0.6.0+12 flutter: plugin: From 8f849c8386994703f255c6bc692fead36c23fc34 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 8 Jul 2019 13:45:05 -0700 Subject: [PATCH 11/94] [firebase_messaging] add integration tests (#1816) * Initial firebase_messaging integration tests --- packages/firebase_messaging/CHANGELOG.md | 4 ++ .../firebase_messaging/example/pubspec.yaml | 47 +++---------------- .../test_driver/firebase_messaging.dart | 34 ++++++++++++++ .../test_driver/firebase_messaging_test.dart | 7 +++ packages/firebase_messaging/pubspec.yaml | 4 +- 5 files changed, 54 insertions(+), 42 deletions(-) create mode 100644 packages/firebase_messaging/example/test_driver/firebase_messaging.dart create mode 100644 packages/firebase_messaging/example/test_driver/firebase_messaging_test.dart diff --git a/packages/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/CHANGELOG.md index 206ce3796ffa..3bdb90a57bc2 100644 --- a/packages/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.0.6 + +* Additional integration tests. + ## 5.0.5 * On Android, fix crash when calling `deleteInstanceID` with latest Flutter engine. diff --git a/packages/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/example/pubspec.yaml index b6f5dda32bbb..95b80ed7be0d 100644 --- a/packages/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/example/pubspec.yaml @@ -8,47 +8,12 @@ dependencies: path: ../ firebase_core: ^0.4.0 -# For information on the generic Dart part of this file, see the -# following page: https://www.dartlang.org/tools/pub/pubspec +dev_dependencies: + flutter_test: + sdk: flutter + flutter_driver: + sdk: flutter + test: any -# 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_messaging/example/test_driver/firebase_messaging.dart b/packages/firebase_messaging/example/test_driver/firebase_messaging.dart new file mode 100644 index 000000000000..67965b164bbb --- /dev/null +++ b/packages/firebase_messaging/example/test_driver/firebase_messaging.dart @@ -0,0 +1,34 @@ +import 'dart:async'; +import 'package:flutter_driver/driver_extension.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; + +void main() { + final Completer completer = Completer(); + enableFlutterDriverExtension(handler: (_) => completer.future); + tearDownAll(() => completer.complete(null)); + + group('$FirebaseMessaging', () { + final FirebaseMessaging firebaseMessaging = FirebaseMessaging(); + + test('autoInitEnabled', () async { + await firebaseMessaging.setAutoInitEnabled(false); + expect(await firebaseMessaging.autoInitEnabled(), false); + await firebaseMessaging.setAutoInitEnabled(true); + expect(await firebaseMessaging.autoInitEnabled(), true); + }); + + test('subscribeToTopic', () async { + firebaseMessaging.subscribeToTopic('foo'); + }); + + test('unsubscribeFromTopic', () async { + firebaseMessaging.unsubscribeFromTopic('foo'); + }); + + test('deleteInstanceID', () async { + final bool result = await firebaseMessaging.deleteInstanceID(); + expect(result, isTrue); + }); + }); +} diff --git a/packages/firebase_messaging/example/test_driver/firebase_messaging_test.dart b/packages/firebase_messaging/example/test_driver/firebase_messaging_test.dart new file mode 100644 index 000000000000..38fe6c447e05 --- /dev/null +++ b/packages/firebase_messaging/example/test_driver/firebase_messaging_test.dart @@ -0,0 +1,7 @@ +import 'package:flutter_driver/flutter_driver.dart'; + +Future main() async { + final FlutterDriver driver = await FlutterDriver.connect(); + await driver.requestData(null, timeout: const Duration(minutes: 1)); + driver.close(); +} diff --git a/packages/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/pubspec.yaml index f7fdb5b7223a..526de83602fb 100644 --- a/packages/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_messaging -version: 5.0.5 +version: 5.0.6 flutter: plugin: @@ -23,6 +23,8 @@ dev_dependencies: flutter_test: sdk: flutter firebase_core: ^0.4.0 + flutter_driver: + sdk: flutter environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" From 61e844973119f4dd68549f82b4ae2e9f1f9b7946 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 8 Jul 2019 17:42:10 -0700 Subject: [PATCH 12/94] [firebase_messaging] Change signature of subscribe/unsubscribe (#1818) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change signature of subscribe/unsubscribe * Wire up the notifications on the native side * Update unit tests * Skip the tests now that they don’t actually pass --- packages/firebase_messaging/CHANGELOG.md | 5 +++ .../FirebaseMessagingPlugin.java | 34 ++++++++++++++++--- .../test_driver/firebase_messaging.dart | 10 +++--- .../ios/Classes/FirebaseMessagingPlugin.m | 19 ++++++++--- .../lib/firebase_messaging.dart | 8 ++--- packages/firebase_messaging/pubspec.yaml | 2 +- .../test/firebase_messaging_test.dart | 8 ++--- 7 files changed, 65 insertions(+), 21 deletions(-) diff --git a/packages/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/CHANGELOG.md index 3bdb90a57bc2..4bf3c6fa0199 100644 --- a/packages/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/CHANGELOG.md @@ -1,3 +1,8 @@ +## 5.1.0 + +* Changed the return type of `subscribeToTopic` and `unsubscribeFromTopic` to + `Future`. + ## 5.0.6 * Additional integration tests. diff --git a/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java b/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java index 11befeba8642..4ab56e01d299 100644 --- a/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java +++ b/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java @@ -119,12 +119,38 @@ public void onComplete(@NonNull Task task) { result.success(null); } else if ("subscribeToTopic".equals(call.method)) { String topic = call.arguments(); - FirebaseMessaging.getInstance().subscribeToTopic(topic); - result.success(null); + FirebaseMessaging.getInstance() + .subscribeToTopic(topic) + .addOnCompleteListener( + new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (!task.isSuccessful()) { + Exception e = task.getException(); + Log.w(TAG, "subscribeToTopic error", e); + result.error("subscribeToTopic", e.getMessage(), null); + return; + } + result.success(null); + } + }); } else if ("unsubscribeFromTopic".equals(call.method)) { String topic = call.arguments(); - FirebaseMessaging.getInstance().unsubscribeFromTopic(topic); - result.success(null); + FirebaseMessaging.getInstance() + .unsubscribeFromTopic(topic) + .addOnCompleteListener( + new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (!task.isSuccessful()) { + Exception e = task.getException(); + Log.w(TAG, "unsubscribeFromTopic error", e); + result.error("unsubscribeFromTopic", e.getMessage(), null); + return; + } + result.success(null); + } + }); } else if ("getToken".equals(call.method)) { FirebaseInstanceId.getInstance() .getInstanceId() diff --git a/packages/firebase_messaging/example/test_driver/firebase_messaging.dart b/packages/firebase_messaging/example/test_driver/firebase_messaging.dart index 67965b164bbb..7ba46b79e733 100644 --- a/packages/firebase_messaging/example/test_driver/firebase_messaging.dart +++ b/packages/firebase_messaging/example/test_driver/firebase_messaging.dart @@ -18,13 +18,15 @@ void main() { expect(await firebaseMessaging.autoInitEnabled(), true); }); + // TODO(jackson): token retrieval isn't working on test devices yet test('subscribeToTopic', () async { - firebaseMessaging.subscribeToTopic('foo'); - }); + await firebaseMessaging.subscribeToTopic('foo'); + }, skip: true); + // TODO(jackson): token retrieval isn't working on test devices yet test('unsubscribeFromTopic', () async { - firebaseMessaging.unsubscribeFromTopic('foo'); - }); + await firebaseMessaging.unsubscribeFromTopic('foo'); + }, skip: true); test('deleteInstanceID', () async { final bool result = await firebaseMessaging.deleteInstanceID(); diff --git a/packages/firebase_messaging/ios/Classes/FirebaseMessagingPlugin.m b/packages/firebase_messaging/ios/Classes/FirebaseMessagingPlugin.m index 625409274191..225b86f99599 100644 --- a/packages/firebase_messaging/ios/Classes/FirebaseMessagingPlugin.m +++ b/packages/firebase_messaging/ios/Classes/FirebaseMessagingPlugin.m @@ -12,6 +12,13 @@ @interface FLTFirebaseMessagingPlugin () @end #endif +static FlutterError *getFlutterError(NSError *error) { + if (error == nil) return nil; + return [FlutterError errorWithCode:[NSString stringWithFormat:@"Error %ld", error.code] + message:error.domain + details:error.localizedDescription]; +} + @implementation FLTFirebaseMessagingPlugin { FlutterMethodChannel *_channel; NSDictionary *_launchNotification; @@ -77,12 +84,16 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result result(nil); } else if ([@"subscribeToTopic" isEqualToString:method]) { NSString *topic = call.arguments; - [[FIRMessaging messaging] subscribeToTopic:topic]; - result(nil); + [[FIRMessaging messaging] subscribeToTopic:topic + completion:^(NSError *error) { + result(getFlutterError(error)); + }]; } else if ([@"unsubscribeFromTopic" isEqualToString:method]) { NSString *topic = call.arguments; - [[FIRMessaging messaging] unsubscribeFromTopic:topic]; - result(nil); + [[FIRMessaging messaging] unsubscribeFromTopic:topic + completion:^(NSError *error) { + result(getFlutterError(error)); + }]; } else if ([@"getToken" isEqualToString:method]) { [[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult *_Nullable instanceIDResult, diff --git a/packages/firebase_messaging/lib/firebase_messaging.dart b/packages/firebase_messaging/lib/firebase_messaging.dart index d048f14d7196..f40420c6dbe5 100644 --- a/packages/firebase_messaging/lib/firebase_messaging.dart +++ b/packages/firebase_messaging/lib/firebase_messaging.dart @@ -86,13 +86,13 @@ class FirebaseMessaging { /// /// [topic] must match the following regular expression: /// "[a-zA-Z0-9-_.~%]{1,900}". - void subscribeToTopic(String topic) { - _channel.invokeMethod('subscribeToTopic', topic); + Future subscribeToTopic(String topic) { + return _channel.invokeMethod('subscribeToTopic', topic); } /// Unsubscribe from topic in background. - void unsubscribeFromTopic(String topic) { - _channel.invokeMethod('unsubscribeFromTopic', topic); + Future unsubscribeFromTopic(String topic) { + return _channel.invokeMethod('unsubscribeFromTopic', topic); } /// Resets Instance ID and revokes all tokens. In iOS, it also unregisters from remote notifications. diff --git a/packages/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/pubspec.yaml index 526de83602fb..67402e1882aa 100644 --- a/packages/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_messaging -version: 5.0.6 +version: 5.1.0 flutter: plugin: diff --git a/packages/firebase_messaging/test/firebase_messaging_test.dart b/packages/firebase_messaging/test/firebase_messaging_test.dart index aefea5981bda..a4e6d7c04756 100644 --- a/packages/firebase_messaging/test/firebase_messaging_test.dart +++ b/packages/firebase_messaging/test/firebase_messaging_test.dart @@ -123,13 +123,13 @@ void main() { const String myTopic = 'Flutter'; - test('subscribe to topic', () { - firebaseMessaging.subscribeToTopic(myTopic); + test('subscribe to topic', () async { + await firebaseMessaging.subscribeToTopic(myTopic); verify(mockChannel.invokeMethod('subscribeToTopic', myTopic)); }); - test('unsubscribe from topic', () { - firebaseMessaging.unsubscribeFromTopic(myTopic); + test('unsubscribe from topic', () async { + await firebaseMessaging.unsubscribeFromTopic(myTopic); verify(mockChannel.invokeMethod('unsubscribeFromTopic', myTopic)); }); From 36b9fc84a2c954be4164e6e323ae17f547e765f5 Mon Sep 17 00:00:00 2001 From: Amol Gangadhare Date: Tue, 9 Jul 2019 10:17:55 +0530 Subject: [PATCH 13/94] [image_picker] android: use getFileExtensionFromUrl to get extension instead of cursor(#1804) --- packages/image_picker/CHANGELOG.md | 4 +++ .../plugins/imagepicker/FileUtils.java | 27 +++++++------------ packages/image_picker/pubspec.yaml | 2 +- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/packages/image_picker/CHANGELOG.md b/packages/image_picker/CHANGELOG.md index 145fd4995a8e..a1c108b37368 100644 --- a/packages/image_picker/CHANGELOG.md +++ b/packages/image_picker/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.0+13 + +* Bugfix Android: Fix a crash occurs in some scenarios when user picks up image from gallery. + ## 0.6.0+12 * Use class instead of struct for `GIFInfo` in iOS implementation. diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/FileUtils.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/FileUtils.java index 85995d890848..15900bea5cc3 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/FileUtils.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/FileUtils.java @@ -29,7 +29,6 @@ import android.provider.DocumentsContract; import android.provider.MediaStore; import android.text.TextUtils; -import android.webkit.MimeTypeMap; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -141,7 +140,7 @@ private static String getPathFromRemoteUri(final Context context, final Uri uri) OutputStream outputStream = null; boolean success = false; try { - String extension = getImageExtension(context, uri); + String extension = getImageExtension(uri); inputStream = context.getContentResolver().openInputStream(uri); file = File.createTempFile("image_picker", extension, context.getCacheDir()); outputStream = new FileOutputStream(file); @@ -168,31 +167,23 @@ private static String getPathFromRemoteUri(final Context context, final Uri uri) } /** @return extension of image with dot, or default .jpg if it none. */ - private static String getImageExtension(Context context, Uri uriImage) { + private static String getImageExtension(Uri uriImage) { String extension = null; - Cursor cursor = null; try { - cursor = - context - .getContentResolver() - .query(uriImage, new String[] {MediaStore.MediaColumns.MIME_TYPE}, null, null, null); - - if (cursor != null && cursor.moveToNext()) { - String mimeType = cursor.getString(0); - - extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType); - } - } finally { - if (cursor != null) { - cursor.close(); + String imagePath = uriImage.getPath(); + if (imagePath != null && imagePath.lastIndexOf(".") != -1) { + extension = imagePath.substring(imagePath.lastIndexOf(".") + 1); } + } catch (Exception e) { + extension = null; } - if (extension == null) { + if (extension == null || extension.isEmpty()) { //default extension for matches the previous behavior of the plugin extension = "jpg"; } + return "." + extension; } diff --git a/packages/image_picker/pubspec.yaml b/packages/image_picker/pubspec.yaml index 4d4027156d91..c0c5b7d2a3b2 100755 --- a/packages/image_picker/pubspec.yaml +++ b/packages/image_picker/pubspec.yaml @@ -5,7 +5,7 @@ authors: - Flutter Team - Rhodes Davis Jr. homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker -version: 0.6.0+12 +version: 0.6.0+13 flutter: plugin: From 9bf69f3d1a6afeb3d5fbfb8c19310a76f0a27aa8 Mon Sep 17 00:00:00 2001 From: creativecreatorormaybenot <19204050+creativecreatorormaybenot@users.noreply.github.com> Date: Tue, 9 Jul 2019 16:43:37 +0000 Subject: [PATCH 14/94] [in_app_purchase] Fixed code example error & README links (#1751) ```dart const Set _kIds = ['product1', 'product2'].toSet(); ``` That is not a valid assignment. Hence, I fixed it and on the way I also updated all the links in the README that either did not work at all or did not work from the [pub page](https://pub.dev/packages/in_app_purchase#-readme-tab-). --- packages/in_app_purchase/CHANGELOG.md | 4 ++++ packages/in_app_purchase/README.md | 11 ++++++----- packages/in_app_purchase/pubspec.yaml | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/in_app_purchase/CHANGELOG.md b/packages/in_app_purchase/CHANGELOG.md index 32f56899826e..32ba5b1147ca 100644 --- a/packages/in_app_purchase/CHANGELOG.md +++ b/packages/in_app_purchase/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0+4 + +* Fixed code error in `README.md` and adjusted links to work on Pub. + ## 0.2.0+3 * Update the `README.md` so that the code samples compile with the latest Flutter/Dart version. diff --git a/packages/in_app_purchase/README.md b/packages/in_app_purchase/README.md index 3b8d1a4df04c..ce564d14fea3 100644 --- a/packages/in_app_purchase/README.md +++ b/packages/in_app_purchase/README.md @@ -26,14 +26,14 @@ guides: * [In-App Purchase (App Store)](https://developer.apple.com/in-app-purchase/) * [Google Play Biling Overview](https://developer.android.com/google/play/billing/billing_overview) -You can check out the [example app README](example/README.md) for steps on how +You can check out the [example app README](https://github.com/flutter/plugins/blob/master/packages/in_app_purchase/example/README.md) for steps on how to configure in app purchases in both stores. Once you've configured your in app purchases in their respective stores, you're able to start using the plugin. There's two basic options available to you to use. -1. [in_app_purchase.dart](lib/src/in_app_purchase.dart), +1. [in_app_purchase.dart](https://github.com/flutter/plugins/tree/master/packages/in_app_purchase/lib/src/in_app_purchase), the generic idiommatic Flutter API. This exposes the most basic IAP-related functionality. The goal is that Flutter apps should be able to use this API surface on its own for the vast majority of cases. If you use this you should @@ -42,8 +42,8 @@ use. below. 2. Dart APIs exposing the underlying platform APIs as directly as possible: - [store_kit_wrappers.dart](lib/src/store_kit_wrappers.dart) and - [billing_client_wrappers.dart](lib/src/billing_client_wrappers.dart). These + [store_kit_wrappers.dart](https://github.com/flutter/plugins/blob/master/packages/in_app_purchase/lib/src/store_kit_wrappers) and + [billing_client_wrappers.dart](https://github.com/flutter/plugins/blob/master/packages/in_app_purchase/lib/src/billing_client_wrappers). These API surfaces should expose all the platform-specific behavior and allow for more fine-tuned control when needed. However if you use this you'll need to code your purchase handling logic significantly differently depending on @@ -87,7 +87,8 @@ if (!available) { ### Loading products for sale ```dart -Set _kIds = ['product1', 'product2'].toSet(); +// Set literals require Dart 2.2. Alternatively, use `Set _kIds = ['product1', 'product2'].toSet()`. +const Set _kIds = {'product1', 'product2'}; final ProductDetailsResponse response = await InAppPurchaseConnection.instance.queryProductDetails(_kIds); if (!response.notFoundIDs.isEmpty) { // Handle the error. diff --git a/packages/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/pubspec.yaml index 3987990e1c77..5838ab1ff29b 100644 --- a/packages/in_app_purchase/pubspec.yaml +++ b/packages/in_app_purchase/pubspec.yaml @@ -2,7 +2,7 @@ name: in_app_purchase description: A Flutter plugin for in-app purchases. Exposes APIs for making in-app purchases through the App Store and Google Play. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase -version: 0.2.0+3 +version: 0.2.0+4 dependencies: async: ^2.0.8 From 433e98266e86ee2920a03558b7e759ac20933794 Mon Sep 17 00:00:00 2001 From: Miller Adulu Date: Tue, 9 Jul 2019 23:45:12 +0300 Subject: [PATCH 15/94] [image_picker] Update README example (#1823) --- packages/image_picker/CHANGELOG.md | 4 ++++ packages/image_picker/README.md | 4 ++-- packages/image_picker/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/image_picker/CHANGELOG.md b/packages/image_picker/CHANGELOG.md index a1c108b37368..a26a34bcbe84 100644 --- a/packages/image_picker/CHANGELOG.md +++ b/packages/image_picker/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.0+14 + +* Fix typo in README. + ## 0.6.0+13 * Bugfix Android: Fix a crash occurs in some scenarios when user picks up image from gallery. diff --git a/packages/image_picker/README.md b/packages/image_picker/README.md index 101a46cd14d2..201113b2e771 100755 --- a/packages/image_picker/README.md +++ b/packages/image_picker/README.md @@ -71,7 +71,7 @@ Android system -- although very rarely -- sometimes kills the MainActivity after ```dart Future retrieveLostData() async { - final RetrieveLostDataResponse response = + final LostDataResponse response = await ImagePicker.retrieveLostData(); if (response == null) { return; @@ -90,4 +90,4 @@ Future retrieveLostData() async { } ``` -There's no way to detect when this happens, so calling this method at the right place is essential. We recommend to wire this into some kind of start up check. Please refer to the example app to see how we used it. \ No newline at end of file +There's no way to detect when this happens, so calling this method at the right place is essential. We recommend to wire this into some kind of start up check. Please refer to the example app to see how we used it. diff --git a/packages/image_picker/pubspec.yaml b/packages/image_picker/pubspec.yaml index c0c5b7d2a3b2..bd9b19008fe6 100755 --- a/packages/image_picker/pubspec.yaml +++ b/packages/image_picker/pubspec.yaml @@ -5,7 +5,7 @@ authors: - Flutter Team - Rhodes Davis Jr. homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker -version: 0.6.0+13 +version: 0.6.0+14 flutter: plugin: From 236354433a2bb248fadeef5ca2a20532c74d2e27 Mon Sep 17 00:00:00 2001 From: Sergey Chuvashev Date: Wed, 10 Jul 2019 00:47:21 +0400 Subject: [PATCH 16/94] [Connectivity] Android: Updated check network info logic (#1761) --- packages/connectivity/CHANGELOG.md | 4 ++++ .../connectivity/ConnectivityPlugin.java | 17 +++++++---------- packages/connectivity/pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/connectivity/CHANGELOG.md b/packages/connectivity/CHANGELOG.md index 6d5f53851f4d..4aa2f43cefec 100644 --- a/packages/connectivity/CHANGELOG.md +++ b/packages/connectivity/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.3+4 + +* [Android] Updated logic to retrieve network info. + ## 0.4.3+3 * Support for TYPE_MOBILE_HIPRI on Android. diff --git a/packages/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java b/packages/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java index cb48c25bd396..830e7010621a 100644 --- a/packages/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java +++ b/packages/connectivity/android/src/main/java/io/flutter/plugins/connectivity/ConnectivityPlugin.java @@ -99,11 +99,15 @@ public void onMethodCall(MethodCall call, Result result) { } private void handleCheck(MethodCall call, final Result result) { + result.success(checkNetworkType()); + } + + private String checkNetworkType() { NetworkInfo info = manager.getActiveNetworkInfo(); if (info != null && info.isConnected()) { - result.success(getNetworkType(info.getType())); + return getNetworkType(info.getType()); } else { - result.success("none"); + return "none"; } } @@ -154,14 +158,7 @@ private BroadcastReceiver createReceiver(final EventSink events) { return new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - boolean isLost = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); - if (isLost) { - events.success("none"); - return; - } - - int type = intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, -1); - events.success(getNetworkType(type)); + events.success(checkNetworkType()); } }; } diff --git a/packages/connectivity/pubspec.yaml b/packages/connectivity/pubspec.yaml index ac6c8d090af8..788e1d0d12ff 100644 --- a/packages/connectivity/pubspec.yaml +++ b/packages/connectivity/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for discovering the state of the network (WiFi & mobile/cellular) connectivity on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/connectivity -version: 0.4.3+3 +version: 0.4.3+4 flutter: plugin: From b8b43ea6a8ea0afe77656ba68fec5a416b2f90dc Mon Sep 17 00:00:00 2001 From: John MacPherson Date: Tue, 9 Jul 2019 18:21:40 -0400 Subject: [PATCH 17/94] [image_picker] android: return error in the event that permissions are not granted (#1744) --- packages/image_picker/CHANGELOG.md | 4 ++++ .../plugins/imagepicker/ImagePickerDelegate.java | 11 ++++++++++- .../plugins/imagepicker/ImagePickerDelegateTest.java | 8 ++++---- packages/image_picker/pubspec.yaml | 3 ++- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/image_picker/CHANGELOG.md b/packages/image_picker/CHANGELOG.md index a26a34bcbe84..f1741507b0f1 100644 --- a/packages/image_picker/CHANGELOG.md +++ b/packages/image_picker/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.0+15 + +* Android: throws an exception when permissions denied instead of ignoring. + ## 0.6.0+14 * Fix typo in README. diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java index 35c303fd5b99..2f2522f53c5c 100644 --- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java +++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java @@ -408,7 +408,16 @@ public boolean onRequestPermissionsResult( } if (!permissionGranted) { - finishWithSuccess(null); + switch (requestCode) { + case REQUEST_EXTERNAL_IMAGE_STORAGE_PERMISSION: + case REQUEST_EXTERNAL_VIDEO_STORAGE_PERMISSION: + finishWithError("photo_access_denied", "The user did not allow photo access."); + break; + case REQUEST_CAMERA_IMAGE_PERMISSION: + case REQUEST_CAMERA_VIDEO_PERMISSION: + finishWithError("camera_access_denied", "The user did not allow camera access."); + break; + } } return true; diff --git a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java index 3ca2a3765ece..02bb91b7914f 100644 --- a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java +++ b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java @@ -184,7 +184,7 @@ public void takeImageWithCamera_WhenCameraPermissionNotPresent_RequestsForPermis @Test public void - onRequestPermissionsResult_WhenReadExternalStoragePermissionDenied_FinishesWithNull() { + onRequestPermissionsResult_WhenReadExternalStoragePermissionDenied_FinishesWithError() { ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); delegate.onRequestPermissionsResult( @@ -192,7 +192,7 @@ public void takeImageWithCamera_WhenCameraPermissionNotPresent_RequestsForPermis new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, new int[] {PackageManager.PERMISSION_DENIED}); - verify(mockResult).success(null); + verify(mockResult).error("photo_access_denied", "The user did not allow photo access.", null); verifyNoMoreInteractions(mockResult); } @@ -227,7 +227,7 @@ public void takeImageWithCamera_WhenCameraPermissionNotPresent_RequestsForPermis } @Test - public void onRequestPermissionsResult_WhenCameraPermissionDenied_FinishesWithNull() { + public void onRequestPermissionsResult_WhenCameraPermissionDenied_FinishesWithError() { ImagePickerDelegate delegate = createDelegateWithPendingResultAndMethodCall(); delegate.onRequestPermissionsResult( @@ -235,7 +235,7 @@ public void onRequestPermissionsResult_WhenCameraPermissionDenied_FinishesWithNu new String[] {Manifest.permission.CAMERA}, new int[] {PackageManager.PERMISSION_DENIED}); - verify(mockResult).success(null); + verify(mockResult).error("camera_access_denied", "The user did not allow camera access.", null); verifyNoMoreInteractions(mockResult); } diff --git a/packages/image_picker/pubspec.yaml b/packages/image_picker/pubspec.yaml index bd9b19008fe6..58b3db26085e 100755 --- a/packages/image_picker/pubspec.yaml +++ b/packages/image_picker/pubspec.yaml @@ -5,7 +5,8 @@ authors: - Flutter Team - Rhodes Davis Jr. homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker -version: 0.6.0+14 + +version: 0.6.0+15 flutter: plugin: From 19bdccee76eb1063063fa5300b885d3cc70c9019 Mon Sep 17 00:00:00 2001 From: Sebastian Roth Date: Wed, 10 Jul 2019 07:48:11 +0800 Subject: [PATCH 18/94] [google_sign_in] Added NonNull annotations, reduce Guava usage (#844) --- packages/google_sign_in/CHANGELOG.md | 5 +++++ packages/google_sign_in/android/build.gradle | 2 +- .../plugins/googlesignin/GoogleSignInPlugin.java | 16 ++++++++-------- packages/google_sign_in/pubspec.yaml | 2 +- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/google_sign_in/CHANGELOG.md b/packages/google_sign_in/CHANGELOG.md index 0a4e8d21cca8..bbbba373b3d9 100644 --- a/packages/google_sign_in/CHANGELOG.md +++ b/packages/google_sign_in/CHANGELOG.md @@ -1,3 +1,8 @@ +## 4.0.3 + +* Update guava to `27.0.1-android`. +* Add correct @NonNull annotations to reduce compiler warnings. + ## 4.0.2 * Add missing template type parameter to `invokeMethod` calls. diff --git a/packages/google_sign_in/android/build.gradle b/packages/google_sign_in/android/build.gradle index 9162c3080e50..c6e0acdb5ff8 100755 --- a/packages/google_sign_in/android/build.gradle +++ b/packages/google_sign_in/android/build.gradle @@ -48,5 +48,5 @@ android { dependencies { api 'com.google.android.gms:play-services-auth:16.0.1' - implementation 'com.google.guava:guava:20.0' + implementation 'com.google.guava:guava:27.0.1-android' } diff --git a/packages/google_sign_in/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java b/packages/google_sign_in/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java index d2fc260c7b1c..5c292414057d 100755 --- a/packages/google_sign_in/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java +++ b/packages/google_sign_in/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java @@ -7,6 +7,8 @@ import android.accounts.Account; import android.app.Activity; import android.content.Intent; +import android.text.TextUtils; +import androidx.annotation.NonNull; import com.google.android.gms.auth.GoogleAuthUtil; import com.google.android.gms.auth.UserRecoverableAuthException; import com.google.android.gms.auth.api.signin.GoogleSignIn; @@ -20,8 +22,6 @@ import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.RuntimeExecutionException; import com.google.android.gms.tasks.Task; -import com.google.common.base.Joiner; -import com.google.common.base.Strings; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; @@ -107,7 +107,7 @@ public void onMethodCall(MethodCall call, Result result) { /** * A delegate interface that exposes all of the sign-in functionality for other plugins to use. - * The below {@link #Delegate} implementation should be used by any clients unless they need to + * The below {@link Delegate} implementation should be used by any clients unless they need to * override some of these functions, such as for testing. */ public interface IDelegate { @@ -243,7 +243,7 @@ public void init( for (String scope : requestedScopes) { optionsBuilder.requestScopes(new Scope(scope)); } - if (!Strings.isNullOrEmpty(hostedDomain)) { + if (!TextUtils.isEmpty(hostedDomain)) { optionsBuilder.setHostedDomain(hostedDomain); } @@ -270,7 +270,7 @@ public void signInSilently(Result result) { task.addOnCompleteListener( new OnCompleteListener() { @Override - public void onComplete(Task task) { + public void onComplete(@NonNull Task task) { onSignInResult(task); } }); @@ -305,7 +305,7 @@ public void signOut(Result result) { .addOnCompleteListener( new OnCompleteListener() { @Override - public void onComplete(Task task) { + public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { finishWithSuccess(null); } else { @@ -325,7 +325,7 @@ public void disconnect(Result result) { .addOnCompleteListener( new OnCompleteListener() { @Override - public void onComplete(Task task) { + public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { finishWithSuccess(null); } else { @@ -448,7 +448,7 @@ public void getTokens( @Override public String call() throws Exception { Account account = new Account(email, "com.google"); - String scopesStr = "oauth2:" + Joiner.on(' ').join(requestedScopes); + String scopesStr = "oauth2:" + TextUtils.join(" ", requestedScopes); return GoogleAuthUtil.getToken(registrar.context(), account, scopesStr); } }; diff --git a/packages/google_sign_in/pubspec.yaml b/packages/google_sign_in/pubspec.yaml index 4a14005956ca..f9c18839b048 100755 --- a/packages/google_sign_in/pubspec.yaml +++ b/packages/google_sign_in/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Google Sign-In, a secure authentication system for signing in with a Google account on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/google_sign_in -version: 4.0.2 +version: 4.0.3 flutter: plugin: From 408689a6be093d63883267966739ceefb8136905 Mon Sep 17 00:00:00 2001 From: YukiOya Date: Thu, 11 Jul 2019 01:13:41 +0900 Subject: [PATCH 19/94] [in_app_purchase] iOS: Support unsupported UserInfo value types in NSError. (#1819) --- packages/in_app_purchase/CHANGELOG.md | 4 ++++ .../ios/Classes/FIAObjectTranslator.m | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/in_app_purchase/CHANGELOG.md b/packages/in_app_purchase/CHANGELOG.md index 32ba5b1147ca..0fb8ee77157d 100644 --- a/packages/in_app_purchase/CHANGELOG.md +++ b/packages/in_app_purchase/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0+5 + +* iOS: Support unsupported UserInfo value types on NSError. + ## 0.2.0+4 * Fixed code error in `README.md` and adjusted links to work on Pub. diff --git a/packages/in_app_purchase/ios/Classes/FIAObjectTranslator.m b/packages/in_app_purchase/ios/Classes/FIAObjectTranslator.m index c393a46867a8..b64df0538aa6 100644 --- a/packages/in_app_purchase/ios/Classes/FIAObjectTranslator.m +++ b/packages/in_app_purchase/ios/Classes/FIAObjectTranslator.m @@ -153,11 +153,18 @@ + (NSDictionary *)getMapFromNSError:(NSError *)error { if (!error) { return nil; } - return @{ - @"code" : @(error.code), - @"domain" : error.domain ?: @"", - @"userInfo" : error.userInfo ?: @{} - }; + NSMutableDictionary *userInfo = [NSMutableDictionary new]; + for (NSErrorUserInfoKey key in error.userInfo) { + id value = error.userInfo[key]; + if ([value isKindOfClass:[NSError class]]) { + userInfo[key] = [FIAObjectTranslator getMapFromNSError:value]; + } else if ([value isKindOfClass:[NSURL class]]) { + userInfo[key] = [value absoluteString]; + } else { + userInfo[key] = value; + } + } + return @{@"code" : @(error.code), @"domain" : error.domain ?: @"", @"userInfo" : userInfo}; } @end From 738f445c432e42c14d491af31d7839d643780dee Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 10 Jul 2019 09:49:17 -0700 Subject: [PATCH 20/94] [in_app_purchase]fix version (#1827) --- packages/in_app_purchase/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/pubspec.yaml index 5838ab1ff29b..b2388983d965 100644 --- a/packages/in_app_purchase/pubspec.yaml +++ b/packages/in_app_purchase/pubspec.yaml @@ -2,7 +2,7 @@ name: in_app_purchase description: A Flutter plugin for in-app purchases. Exposes APIs for making in-app purchases through the App Store and Google Play. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase -version: 0.2.0+4 +version: 0.2.0+5 dependencies: async: ^2.0.8 From e919c02f0eb9cd47304b35f00d3478f4bfbb4cd1 Mon Sep 17 00:00:00 2001 From: nekolab Date: Thu, 11 Jul 2019 01:05:25 +0800 Subject: [PATCH 21/94] [url_launcher]: add option to enable DOM storage in android webview (#1782) --- packages/url_launcher/CHANGELOG.md | 4 + .../urllauncher/UrlLauncherPlugin.java | 6 + packages/url_launcher/example/lib/main.dart | 147 ++++++++++-------- packages/url_launcher/lib/url_launcher.dart | 4 + packages/url_launcher/pubspec.yaml | 2 +- .../url_launcher/test/url_launcher_test.dart | 24 +++ 6 files changed, 123 insertions(+), 64 deletions(-) diff --git a/packages/url_launcher/CHANGELOG.md b/packages/url_launcher/CHANGELOG.md index 2a448106287f..20b64b11cd5f 100644 --- a/packages/url_launcher/CHANGELOG.md +++ b/packages/url_launcher/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.0.5 + +* Add `enableDomStorage` field to `launch` to enable DOM storage in Android WebView. + ## 5.0.4 * Update Dart code to conform to current Dart formatter. diff --git a/packages/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncherPlugin.java b/packages/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncherPlugin.java index 888d3c34fc2e..30d067664b85 100644 --- a/packages/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncherPlugin.java +++ b/packages/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncherPlugin.java @@ -68,6 +68,7 @@ private void launch(MethodCall call, Result result, String url) { Intent launchIntent; boolean useWebView = call.argument("useWebView"); boolean enableJavaScript = call.argument("enableJavaScript"); + boolean enableDomStorage = call.argument("enableDomStorage"); Activity activity = mRegistrar.activity(); if (activity == null) { result.error("NO_ACTIVITY", "Launching a URL requires a foreground activity.", null); @@ -77,6 +78,7 @@ private void launch(MethodCall call, Result result, String url) { launchIntent = new Intent(activity, WebViewActivity.class); launchIntent.putExtra("url", url); launchIntent.putExtra("enableJavaScript", enableJavaScript); + launchIntent.putExtra("enableDomStorage", enableDomStorage); } else { launchIntent = new Intent(Intent.ACTION_VIEW); launchIntent.setData(Uri.parse(url)); @@ -105,10 +107,14 @@ public void onCreate(Bundle savedInstanceState) { Intent intent = getIntent(); String url = intent.getStringExtra("url"); Boolean enableJavaScript = intent.getBooleanExtra("enableJavaScript", false); + Boolean enableDomStorage = intent.getBooleanExtra("enableDomStorage", false); webview.loadUrl(url); if (enableJavaScript) { webview.getSettings().setJavaScriptEnabled(enableJavaScript); } + if (enableDomStorage) { + webview.getSettings().setDomStorageEnabled(enableDomStorage); + } // Open new urls inside the webview itself. webview.setWebViewClient( new WebViewClient() { diff --git a/packages/url_launcher/example/lib/main.dart b/packages/url_launcher/example/lib/main.dart index 2a38c9d58fc3..66b5e9f538e9 100644 --- a/packages/url_launcher/example/lib/main.dart +++ b/packages/url_launcher/example/lib/main.dart @@ -65,6 +65,19 @@ class _MyHomePageState extends State { } } + Future _launchInWebViewWithDomStorage(String url) async { + if (await canLaunch(url)) { + await launch( + url, + forceSafariVC: true, + forceWebView: true, + enableDomStorage: true, + ); + } else { + throw 'Could not launch $url'; + } + } + Future _launchUniversalLinkIos(String url) async { if (await canLaunch('https://youtube.com')) { final bool nativeAppLaunchSucceeded = await launch( @@ -104,69 +117,77 @@ class _MyHomePageState extends State { appBar: AppBar( title: Text(widget.title), ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: TextField( - onChanged: (String text) => _phone = text, - decoration: const InputDecoration( - hintText: 'Input the phone number to launch')), - ), - RaisedButton( - onPressed: () => setState(() { - _launched = _makePhoneCall('tel:$_phone'); - }), - child: const Text('Make phone call'), - ), - const Padding( - padding: EdgeInsets.all(16.0), - child: Text(toLaunch), - ), - RaisedButton( - onPressed: () => setState(() { - _launched = _launchInBrowser(toLaunch); - }), - child: const Text('Launch in browser'), - ), - const Padding(padding: EdgeInsets.all(16.0)), - RaisedButton( - onPressed: () => setState(() { - _launched = _launchInWebViewOrVC(toLaunch); - }), - child: const Text('Launch in app'), - ), - const Padding(padding: EdgeInsets.all(16.0)), - RaisedButton( - onPressed: () => setState(() { - _launched = _launchInWebViewWithJavaScript(toLaunch); - }), - child: const Text('Launch in app(JavaScript ON)'), - ), - RaisedButton( - onPressed: () => setState(() { - _launched = _launchUniversalLinkIos(toLaunch); - }), - child: const Text( - 'Launch a universal link in a native app, fallback to Safari.(Youtube)'), - ), - const Padding(padding: EdgeInsets.all(16.0)), - RaisedButton( - onPressed: () => setState(() { - _launched = _launchInWebViewOrVC(toLaunch); - Timer(const Duration(seconds: 5), () { - print('Closing WebView after 5 seconds...'); - closeWebView(); - }); - }), - child: const Text('Launch in app + close after 5 seconds'), - ), - const Padding(padding: EdgeInsets.all(16.0)), - FutureBuilder(future: _launched, builder: _launchStatus), - ], - ), + body: ListView( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: TextField( + onChanged: (String text) => _phone = text, + decoration: const InputDecoration( + hintText: 'Input the phone number to launch')), + ), + RaisedButton( + onPressed: () => setState(() { + _launched = _makePhoneCall('tel:$_phone'); + }), + child: const Text('Make phone call'), + ), + const Padding( + padding: EdgeInsets.all(16.0), + child: Text(toLaunch), + ), + RaisedButton( + onPressed: () => setState(() { + _launched = _launchInBrowser(toLaunch); + }), + child: const Text('Launch in browser'), + ), + const Padding(padding: EdgeInsets.all(16.0)), + RaisedButton( + onPressed: () => setState(() { + _launched = _launchInWebViewOrVC(toLaunch); + }), + child: const Text('Launch in app'), + ), + RaisedButton( + onPressed: () => setState(() { + _launched = _launchInWebViewWithJavaScript(toLaunch); + }), + child: const Text('Launch in app(JavaScript ON)'), + ), + RaisedButton( + onPressed: () => setState(() { + _launched = _launchInWebViewWithDomStorage(toLaunch); + }), + child: const Text('Launch in app(DOM storage ON)'), + ), + const Padding(padding: EdgeInsets.all(16.0)), + RaisedButton( + onPressed: () => setState(() { + _launched = _launchUniversalLinkIos(toLaunch); + }), + child: const Text( + 'Launch a universal link in a native app, fallback to Safari.(Youtube)'), + ), + const Padding(padding: EdgeInsets.all(16.0)), + RaisedButton( + onPressed: () => setState(() { + _launched = _launchInWebViewOrVC(toLaunch); + Timer(const Duration(seconds: 5), () { + print('Closing WebView after 5 seconds...'); + closeWebView(); + }); + }), + child: const Text('Launch in app + close after 5 seconds'), + ), + const Padding(padding: EdgeInsets.all(16.0)), + FutureBuilder(future: _launched, builder: _launchStatus), + ], + ), + ], ), ); } diff --git a/packages/url_launcher/lib/url_launcher.dart b/packages/url_launcher/lib/url_launcher.dart index a942b5053e63..edae489b8dc0 100644 --- a/packages/url_launcher/lib/url_launcher.dart +++ b/packages/url_launcher/lib/url_launcher.dart @@ -42,6 +42,8 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/url_launcher'); /// WebViews. /// [enableJavaScript] is an Android only setting. If true, WebView enable /// javascript. +/// [enableDomStorage] is an Android only setting. If true, WebView enable +/// DOM storage. /// /// Note that if any of the above are set to true but the URL is not a web URL, /// this will throw a [PlatformException]. @@ -57,6 +59,7 @@ Future launch( bool forceSafariVC, bool forceWebView, bool enableJavaScript, + bool enableDomStorage, bool universalLinksOnly, Brightness statusBarBrightness, }) async { @@ -86,6 +89,7 @@ Future launch( 'useSafariVC': forceSafariVC ?? isWebURL, 'useWebView': forceWebView ?? false, 'enableJavaScript': enableJavaScript ?? false, + 'enableDomStorage': enableDomStorage ?? false, 'universalLinksOnly': universalLinksOnly ?? false, }, ); diff --git a/packages/url_launcher/pubspec.yaml b/packages/url_launcher/pubspec.yaml index a71b26adcf3c..0c0711222338 100644 --- a/packages/url_launcher/pubspec.yaml +++ b/packages/url_launcher/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for launching a URL on Android and iOS. Supports web, phone, SMS, and email schemes. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher -version: 5.0.4 +version: 5.0.5 flutter: plugin: diff --git a/packages/url_launcher/test/url_launcher_test.dart b/packages/url_launcher/test/url_launcher_test.dart index 0a6acc59b951..db746902f3d3 100644 --- a/packages/url_launcher/test/url_launcher_test.dart +++ b/packages/url_launcher/test/url_launcher_test.dart @@ -40,6 +40,7 @@ void main() { 'useSafariVC': true, 'useWebView': false, 'enableJavaScript': false, + 'enableDomStorage': false, 'universalLinksOnly': false, }) ], @@ -56,6 +57,7 @@ void main() { 'useSafariVC': true, 'useWebView': false, 'enableJavaScript': false, + 'enableDomStorage': false, 'universalLinksOnly': false, }) ], @@ -73,6 +75,7 @@ void main() { 'useSafariVC': false, 'useWebView': false, 'enableJavaScript': false, + 'enableDomStorage': false, 'universalLinksOnly': true, }) ], @@ -89,6 +92,7 @@ void main() { 'useSafariVC': true, 'useWebView': true, 'enableJavaScript': false, + 'enableDomStorage': false, 'universalLinksOnly': false, }) ], @@ -106,6 +110,25 @@ void main() { 'useSafariVC': true, 'useWebView': true, 'enableJavaScript': true, + 'enableDomStorage': false, + 'universalLinksOnly': false, + }) + ], + ); + }); + + test('launch force WebView enable DOM storage', () async { + await launch('http://example.com/', + forceWebView: true, enableDomStorage: true); + expect( + log, + [ + isMethodCall('launch', arguments: { + 'url': 'http://example.com/', + 'useSafariVC': true, + 'useWebView': true, + 'enableJavaScript': false, + 'enableDomStorage': true, 'universalLinksOnly': false, }) ], @@ -122,6 +145,7 @@ void main() { 'useSafariVC': false, 'useWebView': false, 'enableJavaScript': false, + 'enableDomStorage': false, 'universalLinksOnly': false, }) ], From d4cd9ec1bde707e2374128ab5785a4a92951b84e Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 10 Jul 2019 11:04:52 -0700 Subject: [PATCH 22/94] Revert "[google_sign_in] Added NonNull annotations, reduce Guava usage (#844) (#1828) --- packages/google_sign_in/CHANGELOG.md | 10 +++++++--- packages/google_sign_in/android/build.gradle | 2 +- .../plugins/googlesignin/GoogleSignInPlugin.java | 16 ++++++++-------- packages/google_sign_in/pubspec.yaml | 2 +- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/google_sign_in/CHANGELOG.md b/packages/google_sign_in/CHANGELOG.md index bbbba373b3d9..7c89f3f71a39 100644 --- a/packages/google_sign_in/CHANGELOG.md +++ b/packages/google_sign_in/CHANGELOG.md @@ -1,7 +1,11 @@ -## 4.0.3 +## 4.0.4 -* Update guava to `27.0.1-android`. -* Add correct @NonNull annotations to reduce compiler warnings. +* Revert changes in 4.0.3. + +## 4.0.3 + +* Update guava to `27.0.1-android`. +* Add correct @NonNull annotations to reduce compiler warnings. ## 4.0.2 diff --git a/packages/google_sign_in/android/build.gradle b/packages/google_sign_in/android/build.gradle index c6e0acdb5ff8..9162c3080e50 100755 --- a/packages/google_sign_in/android/build.gradle +++ b/packages/google_sign_in/android/build.gradle @@ -48,5 +48,5 @@ android { dependencies { api 'com.google.android.gms:play-services-auth:16.0.1' - implementation 'com.google.guava:guava:27.0.1-android' + implementation 'com.google.guava:guava:20.0' } diff --git a/packages/google_sign_in/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java b/packages/google_sign_in/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java index 5c292414057d..d2fc260c7b1c 100755 --- a/packages/google_sign_in/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java +++ b/packages/google_sign_in/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java @@ -7,8 +7,6 @@ import android.accounts.Account; import android.app.Activity; import android.content.Intent; -import android.text.TextUtils; -import androidx.annotation.NonNull; import com.google.android.gms.auth.GoogleAuthUtil; import com.google.android.gms.auth.UserRecoverableAuthException; import com.google.android.gms.auth.api.signin.GoogleSignIn; @@ -22,6 +20,8 @@ import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.RuntimeExecutionException; import com.google.android.gms.tasks.Task; +import com.google.common.base.Joiner; +import com.google.common.base.Strings; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; @@ -107,7 +107,7 @@ public void onMethodCall(MethodCall call, Result result) { /** * A delegate interface that exposes all of the sign-in functionality for other plugins to use. - * The below {@link Delegate} implementation should be used by any clients unless they need to + * The below {@link #Delegate} implementation should be used by any clients unless they need to * override some of these functions, such as for testing. */ public interface IDelegate { @@ -243,7 +243,7 @@ public void init( for (String scope : requestedScopes) { optionsBuilder.requestScopes(new Scope(scope)); } - if (!TextUtils.isEmpty(hostedDomain)) { + if (!Strings.isNullOrEmpty(hostedDomain)) { optionsBuilder.setHostedDomain(hostedDomain); } @@ -270,7 +270,7 @@ public void signInSilently(Result result) { task.addOnCompleteListener( new OnCompleteListener() { @Override - public void onComplete(@NonNull Task task) { + public void onComplete(Task task) { onSignInResult(task); } }); @@ -305,7 +305,7 @@ public void signOut(Result result) { .addOnCompleteListener( new OnCompleteListener() { @Override - public void onComplete(@NonNull Task task) { + public void onComplete(Task task) { if (task.isSuccessful()) { finishWithSuccess(null); } else { @@ -325,7 +325,7 @@ public void disconnect(Result result) { .addOnCompleteListener( new OnCompleteListener() { @Override - public void onComplete(@NonNull Task task) { + public void onComplete(Task task) { if (task.isSuccessful()) { finishWithSuccess(null); } else { @@ -448,7 +448,7 @@ public void getTokens( @Override public String call() throws Exception { Account account = new Account(email, "com.google"); - String scopesStr = "oauth2:" + TextUtils.join(" ", requestedScopes); + String scopesStr = "oauth2:" + Joiner.on(' ').join(requestedScopes); return GoogleAuthUtil.getToken(registrar.context(), account, scopesStr); } }; diff --git a/packages/google_sign_in/pubspec.yaml b/packages/google_sign_in/pubspec.yaml index f9c18839b048..7d12a470ecb2 100755 --- a/packages/google_sign_in/pubspec.yaml +++ b/packages/google_sign_in/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Google Sign-In, a secure authentication system for signing in with a Google account on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/google_sign_in -version: 4.0.3 +version: 4.0.4 flutter: plugin: From a1867b7b4f86170f6fd3fec5bdfda85351167df9 Mon Sep 17 00:00:00 2001 From: Gregor Weber <33162310+The-Redhat@users.noreply.github.com> Date: Wed, 10 Jul 2019 21:12:42 +0200 Subject: [PATCH 23/94] [quick_actions]make QuickActions testable (#1067) --- packages/quick_actions/CHANGELOG.md | 4 ++ packages/quick_actions/example/lib/main.dart | 2 +- packages/quick_actions/lib/quick_actions.dart | 16 +++-- packages/quick_actions/pubspec.yaml | 8 ++- .../test/quick_actions_test.dart | 58 +++++++++++++++++++ 5 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 packages/quick_actions/test/quick_actions_test.dart diff --git a/packages/quick_actions/CHANGELOG.md b/packages/quick_actions/CHANGELOG.md index 61fb69e28c5b..328199d6c5b8 100644 --- a/packages/quick_actions/CHANGELOG.md +++ b/packages/quick_actions/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.1 + +* Added unit tests. + ## 0.3.0+2 * Add missing template type parameter to `invokeMethod` calls. diff --git a/packages/quick_actions/example/lib/main.dart b/packages/quick_actions/example/lib/main.dart index 3c0a75f971f6..7ca344dd0ab7 100644 --- a/packages/quick_actions/example/lib/main.dart +++ b/packages/quick_actions/example/lib/main.dart @@ -36,7 +36,7 @@ class _MyHomePageState extends State { @override void initState() { super.initState(); - final QuickActions quickActions = const QuickActions(); + final QuickActions quickActions = QuickActions(); quickActions.initialize((String shortcutType) { if (shortcutType == 'action_main') { print('The user tapped on the "Main view" action.'); diff --git a/packages/quick_actions/lib/quick_actions.dart b/packages/quick_actions/lib/quick_actions.dart index c4292b5f6fdd..7b60df586319 100644 --- a/packages/quick_actions/lib/quick_actions.dart +++ b/packages/quick_actions/lib/quick_actions.dart @@ -36,13 +36,21 @@ class ShortcutItem { /// Quick actions plugin. class QuickActions { - const QuickActions(); + factory QuickActions() => _instance; + + @visibleForTesting + QuickActions.withMethodChannel(this.channel); + + static final QuickActions _instance = + QuickActions.withMethodChannel(_kChannel); + + final MethodChannel channel; /// Initializes this plugin. /// /// Call this once before any further interaction with the the plugin. void initialize(QuickActionHandler handler) { - _kChannel.setMethodCallHandler((MethodCall call) async { + channel.setMethodCallHandler((MethodCall call) async { assert(call.method == 'launch'); handler(call.arguments); }); @@ -52,12 +60,12 @@ class QuickActions { Future setShortcutItems(List items) async { final List> itemsList = items.map(_serializeItem).toList(); - await _kChannel.invokeMethod('setShortcutItems', itemsList); + await channel.invokeMethod('setShortcutItems', itemsList); } /// Removes all [ShortcutItem]s registered for the app. Future clearShortcutItems() => - _kChannel.invokeMethod('clearShortcutItems'); + channel.invokeMethod('clearShortcutItems'); Map _serializeItem(ShortcutItem item) { return { diff --git a/packages/quick_actions/pubspec.yaml b/packages/quick_actions/pubspec.yaml index e324ae087c64..3887c597c837 100644 --- a/packages/quick_actions/pubspec.yaml +++ b/packages/quick_actions/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for creating shortcuts on home screen, also known as Quick Actions on iOS and App Shortcuts on Android. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/quick_actions -version: 0.3.0+2 +version: 0.3.1 flutter: plugin: @@ -16,6 +16,12 @@ dependencies: sdk: flutter meta: ^1.0.5 +dev_dependencies: + test: ^1.3.0 + mockito: ^3.0.0 + flutter_test: + sdk: flutter + environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" flutter: ">=1.5.0 <2.0.0" diff --git a/packages/quick_actions/test/quick_actions_test.dart b/packages/quick_actions/test/quick_actions_test.dart new file mode 100644 index 000000000000..91f500af7fe8 --- /dev/null +++ b/packages/quick_actions/test/quick_actions_test.dart @@ -0,0 +1,58 @@ +// 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 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:quick_actions/quick_actions.dart'; + +void main() { + QuickActions quickActions; + final List log = []; + + setUp(() { + quickActions = QuickActions(); + quickActions.channel.setMockMethodCallHandler( + (MethodCall methodCall) async { + log.add(methodCall); + return null; + }, + ); + }); + + test('setShortcutItems with demo data', () async { + const String type = 'type'; + const String localizedTitle = 'localizedTitle'; + const String icon = 'icon'; + await quickActions.setShortcutItems( + const [ + ShortcutItem(type: type, localizedTitle: localizedTitle, icon: icon) + ], + ); + expect( + log, + [ + isMethodCall( + 'setShortcutItems', + arguments: >[ + { + 'type': type, + 'localizedTitle': localizedTitle, + 'icon': icon, + } + ], + ), + ], + ); + log.clear(); + }); + + test('clearShortcutItems', () { + quickActions.clearShortcutItems(); + expect( + log, + [ + isMethodCall('clearShortcutItems', arguments: null), + ], + ); + }); +} From 9eac5bba9b6dfc127734b45d0b46f52dce1c2a2b Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 10 Jul 2019 13:35:18 -0700 Subject: [PATCH 24/94] [all_plugins] Compile all plugins together (#1776) --- .gitignore | 2 + examples/all_plugins/android/app/build.gradle | 8 +- .../android/app/src/main/AndroidManifest.xml | 5 +- .../all_plugins/android/gradle.properties | 2 + examples/all_plugins/ios/Runner/Info.plist | 2 + examples/all_plugins/pubspec.yaml | 73 +------------------ script/build_all_plugins_app.sh | 5 +- 7 files changed, 19 insertions(+), 78 deletions(-) diff --git a/.gitignore b/.gitignore index 9a6811785789..5cfb9504ab1d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ .dart_tool/ pubspec.lock +examples/all_plugins/pubspec.yaml + Podfile Podfile.lock Pods/ diff --git a/examples/all_plugins/android/app/build.gradle b/examples/all_plugins/android/app/build.gradle index 013bfdcec927..389706e34fb4 100644 --- a/examples/all_plugins/android/app/build.gradle +++ b/examples/all_plugins/android/app/build.gradle @@ -35,10 +35,11 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "io.plugins.all_plugins" minSdkVersion 16 + multiDexEnabled true targetSdkVersion 28 versionCode flutterVersionCode.toInteger() versionName flutterVersionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { @@ -56,6 +57,7 @@ flutter { dependencies { testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + androidTestImplementation 'androidx.test:runner:1.1.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + api 'androidx.exifinterface:exifinterface:1.0.0' } diff --git a/examples/all_plugins/android/app/src/main/AndroidManifest.xml b/examples/all_plugins/android/app/src/main/AndroidManifest.xml index cc094789065c..fc8cb90afaa3 100644 --- a/examples/all_plugins/android/app/src/main/AndroidManifest.xml +++ b/examples/all_plugins/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,8 @@ + package="io.plugins.all_plugins" + xmlns:tools="http://schemas.android.com/tools"> + + + + diff --git a/packages/firebase_in_app_messaging/example/android/app/src/main/AndroidManifest.xml b/packages/firebase_in_app_messaging/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..d2fa82033723 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/packages/firebase_in_app_messaging/example/android/app/src/main/java/com/example/firebase_in_app_messaging_example/MainActivity.java b/packages/firebase_in_app_messaging/example/android/app/src/main/java/com/example/firebase_in_app_messaging_example/MainActivity.java new file mode 100644 index 000000000000..98218250276a --- /dev/null +++ b/packages/firebase_in_app_messaging/example/android/app/src/main/java/com/example/firebase_in_app_messaging_example/MainActivity.java @@ -0,0 +1,13 @@ +package com.example.firebase_in_app_messaging_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_in_app_messaging/example/android/app/src/main/res/drawable/launch_background.xml b/packages/firebase_in_app_messaging/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000000..304732f88420 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/firebase_in_app_messaging/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/firebase_in_app_messaging/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/firebase_in_app_messaging/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/firebase_in_app_messaging/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/firebase_in_app_messaging/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/android/app/src/main/res/values/styles.xml b/packages/firebase_in_app_messaging/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000000..00fa4417cfbe --- /dev/null +++ b/packages/firebase_in_app_messaging/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/packages/firebase_in_app_messaging/example/android/app/src/profile/AndroidManifest.xml b/packages/firebase_in_app_messaging/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000000..94dd5928d625 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/firebase_in_app_messaging/example/android/build.gradle b/packages/firebase_in_app_messaging/example/android/build.gradle new file mode 100644 index 000000000000..aade91d06b62 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.3.0' + classpath 'com.google.gms:google-services:4.2.0' + + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/packages/firebase_in_app_messaging/example/android/gradle.properties b/packages/firebase_in_app_messaging/example/android/gradle.properties new file mode 100644 index 000000000000..2bd6f4fda009 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx1536M + diff --git a/packages/firebase_in_app_messaging/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/firebase_in_app_messaging/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..2819f022f1fd --- /dev/null +++ b/packages/firebase_in_app_messaging/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip diff --git a/packages/firebase_in_app_messaging/example/android/settings.gradle b/packages/firebase_in_app_messaging/example/android/settings.gradle new file mode 100644 index 000000000000..5a2f14fb18f6 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/packages/firebase_in_app_messaging/example/ios/Flutter/AppFrameworkInfo.plist b/packages/firebase_in_app_messaging/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000000..6b4c0f78a785 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/packages/firebase_in_app_messaging/example/ios/Flutter/Debug.xcconfig b/packages/firebase_in_app_messaging/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000000..e8efba114687 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/firebase_in_app_messaging/example/ios/Flutter/Release.xcconfig b/packages/firebase_in_app_messaging/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000000..399e9340e6f6 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/firebase_in_app_messaging/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_in_app_messaging/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..3b7693aef91e --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,600 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 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, ); }; }; + 9031715A22DD332B00CA8C68 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9031715922DD332B00CA8C68 /* 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 */; }; + 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 */; }; + E638726B1F84F369FCA09810 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 914982FDACC51A62D1FAC1F1 /* libPods-Runner.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2D51D38D6F347D924BF73402 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 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 = ""; }; + 4DBCB98EE08F0263FFB39A45 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; 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 = ""; }; + 9031715922DD332B00CA8C68 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 914982FDACC51A62D1FAC1F1 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 9697814F64329B9DFDDD2D22 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + E638726B1F84F369FCA09810 /* libPods-Runner.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3273157BD1F69AB58A8F6978 /* Pods */ = { + isa = PBXGroup; + children = ( + 2D51D38D6F347D924BF73402 /* Pods-Runner.debug.xcconfig */, + 4DBCB98EE08F0263FFB39A45 /* Pods-Runner.release.xcconfig */, + 9697814F64329B9DFDDD2D22 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 9308F32363B77379BD52E16A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 914982FDACC51A62D1FAC1F1 /* libPods-Runner.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 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 */, + 3273157BD1F69AB58A8F6978 /* Pods */, + 9308F32363B77379BD52E16A /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 9031715922DD332B00CA8C68 /* GoogleService-Info.plist */, + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 97C146F21CF9000F007C117D /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9FEE87118A15F39DB7049483 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 9CB2B92FB733B57CFCD2086E /* [CP] Embed Pods Frameworks */, + 4E58458F4BA4D6603A0A2A9C /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = TA9VLBVN24; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + 9031715A22DD332B00CA8C68 /* GoogleService-Info.plist 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"; + }; + 4E58458F4BA4D6603A0A2A9C /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.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"; + }; + 9CB2B92FB733B57CFCD2086E /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9FEE87118A15F39DB7049483 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, + 97C146F31CF9000F007C117D /* main.m in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = TA9VLBVN24; + 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.example.firebaseInAppMessagingExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = TA9VLBVN24; + 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.example.firebaseInAppMessagingExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = TA9VLBVN24; + 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.example.firebaseInAppMessagingExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/firebase_in_app_messaging/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_in_app_messaging/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000000..37add4ed8194 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/AppDelegate.h b/packages/firebase_in_app_messaging/example/ios/Runner/AppDelegate.h new file mode 100644 index 000000000000..36e21bbf9cf4 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner/AppDelegate.h @@ -0,0 +1,6 @@ +#import +#import + +@interface AppDelegate : FlutterAppDelegate + +@end diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/AppDelegate.m b/packages/firebase_in_app_messaging/example/ios/Runner/AppDelegate.m new file mode 100644 index 000000000000..59a72e90be12 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner/AppDelegate.m @@ -0,0 +1,13 @@ +#include "AppDelegate.h" +#include "GeneratedPluginRegistrant.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [GeneratedPluginRegistrant registerWithRegistry:self]; + // Override point for customization after application launch. + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +@end diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000000..d36b1fab2d9d --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..3d43d11e66f4de3da27ed045ca4fe38ad8b48094 GIT binary patch literal 11112 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 P-1+_A+?hGkL;m(J7kc&K literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..28c6bf03016f6c994b70f38d1b7346e5831b531f GIT binary patch literal 564 zcmV-40?Yl0P)Px$?ny*JR5%f>l)FnDQ543{x%ZCiu33$Wg!pQFfT_}?5Q|_VSlIbLC`dpoMXL}9 zHfd9&47Mo(7D231gb+kjFxZHS4-m~7WurTH&doVX2KI5sU4v(sJ1@T9eCIKPjsqSr z)C01LsCxk=72-vXmX}CQD#BD;Cthymh&~=f$Q8nn0J<}ZrusBy4PvRNE}+1ceuj8u z0mW5k8fmgeLnTbWHGwfKA3@PdZxhn|PypR&^p?weGftrtCbjF#+zk_5BJh7;0`#Wr zgDpM_;Ax{jO##IrT`Oz;MvfwGfV$zD#c2xckpcXC6oou4ML~ezCc2EtnsQTB4tWNg z?4bkf;hG7IMfhgNI(FV5Gs4|*GyMTIY0$B=_*mso9Ityq$m^S>15>-?0(zQ<8Qy<_TjHE33(?_M8oaM zyc;NxzRVK@DL6RJnX%U^xW0Gpg(lXp(!uK1v0YgHjs^ZXSQ|m#lV7ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 zcmds$`#;kQ7{|XelZftyR5~xW7?MLxS4^|Hw3&P7^y)@A9Fj{Xm1~_CIV^XZ%SLBn zA;!r`GqGHg=7>xrB{?psZQs88ZaedDoagm^KF{a*>G|dJWRSe^I$DNW008I^+;Kjt z>9p3GNR^I;v>5_`+91i(*G;u5|L+Bu6M=(afLjtkya#yZ175|z$pU~>2#^Z_pCZ7o z1c6UNcv2B3?; zX%qdxCXQpdKRz=#b*q0P%b&o)5ZrNZt7$fiETSK_VaY=mb4GK`#~0K#~9^ zcY!`#Af+4h?UMR-gMKOmpuYeN5P*RKF!(tb`)oe0j2BH1l?=>y#S5pMqkx6i{*=V9JF%>N8`ewGhRE(|WohnD59R^$_36{4>S zDFlPC5|k?;SPsDo87!B{6*7eqmMdU|QZ84>6)Kd9wNfh90=y=TFQay-0__>=<4pk& zYDjgIhL-jQ9o>z32K)BgAH+HxamL{ZL~ozu)Qqe@a`FpH=oQRA8=L-m-1dam(Ix2V z?du;LdMO+ooBelr^_y4{|44tmgH^2hSzPFd;U^!1p>6d|o)(-01z{i&Kj@)z-yfWQ)V#3Uo!_U}q3u`(fOs`_f^ueFii1xBNUB z6MecwJN$CqV&vhc+)b(p4NzGGEgwWNs z@*lUV6LaduZH)4_g!cE<2G6#+hJrWd5(|p1Z;YJ7ifVHv+n49btR}dq?HHDjl{m$T z!jLZcGkb&XS2OG~u%&R$(X+Z`CWec%QKt>NGYvd5g20)PU(dOn^7%@6kQb}C(%=vr z{?RP(z~C9DPnL{q^@pVw@|Vx~@3v!9dCaBtbh2EdtoNHm4kGxp>i#ct)7p|$QJs+U z-a3qtcPvhihub?wnJqEt>zC@)2suY?%-96cYCm$Q8R%-8$PZYsx3~QOLMDf(piXMm zB=<63yQk1AdOz#-qsEDX>>c)EES%$owHKue;?B3)8aRd}m~_)>SL3h2(9X;|+2#7X z+#2)NpD%qJvCQ0a-uzZLmz*ms+l*N}w)3LRQ*6>|Ub-fyptY(keUxw+)jfwF5K{L9 z|Cl_w=`!l_o><384d&?)$6Nh(GAm=4p_;{qVn#hI8lqewW7~wUlyBM-4Z|)cZr?Rh z=xZ&Ol>4(CU85ea(CZ^aO@2N18K>ftl8>2MqetAR53_JA>Fal`^)1Y--Am~UDa4th zKfCYpcXky$XSFDWBMIl(q=Mxj$iMBX=|j9P)^fDmF(5(5$|?Cx}DKEJa&XZP%OyE`*GvvYQ4PV&!g2|L^Q z?YG}tx;sY@GzMmsY`7r$P+F_YLz)(e}% zyakqFB<6|x9R#TdoP{R$>o7y(-`$$p0NxJ6?2B8tH)4^yF(WhqGZlM3=9Ibs$%U1w zWzcss*_c0=v_+^bfb`kBFsI`d;ElwiU%frgRB%qBjn@!0U2zZehBn|{%uNIKBA7n= zzE`nnwTP85{g;8AkYxA68>#muXa!G>xH22D1I*SiD~7C?7Za+9y7j1SHiuSkKK*^O zsZ==KO(Ua#?YUpXl{ViynyT#Hzk=}5X$e04O@fsMQjb}EMuPWFO0e&8(2N(29$@Vd zn1h8Yd>6z(*p^E{c(L0Lg=wVdupg!z@WG;E0k|4a%s7Up5C0c)55XVK*|x9RQeZ1J@1v9MX;>n34(i>=YE@Iur`0Vah(inE3VUFZNqf~tSz{1fz3Fsn_x4F>o(Yo;kpqvBe-sbwH(*Y zu$JOl0b83zu$JMvy<#oH^Wl>aWL*?aDwnS0iEAwC?DK@aT)GHRLhnz2WCvf3Ba;o=aY7 z2{Asu5MEjGOY4O#Ggz@@J;q*0`kd2n8I3BeNuMmYZf{}pg=jTdTCrIIYuW~luKecn z+E-pHY%ohj@uS0%^ z&(OxwPFPD$+#~`H?fMvi9geVLci(`K?Kj|w{rZ9JgthFHV+=6vMbK~0)Ea<&WY-NC zy-PnZft_k2tfeQ*SuC=nUj4H%SQ&Y$gbH4#2sT0cU0SdFs=*W*4hKGpuR1{)mV;Qf5pw4? zfiQgy0w3fC*w&Bj#{&=7033qFR*<*61B4f9K%CQvxEn&bsWJ{&winp;FP!KBj=(P6 z4Z_n4L7cS;ao2)ax?Tm|I1pH|uLpDSRVghkA_UtFFuZ0b2#>!8;>-_0ELjQSD-DRd z4im;599VHDZYtnWZGAB25W-e(2VrzEh|etsv2YoP#VbIZ{aFkwPrzJ#JvCvA*mXS& z`}Q^v9(W4GiSs}#s7BaN!WA2bniM$0J(#;MR>uIJ^uvgD3GS^%*ikdW6-!VFUU?JV zZc2)4cMsX@j z5HQ^e3BUzOdm}yC-xA%SY``k$rbfk z;CHqifhU*jfGM@DkYCecD9vl*qr58l6x<8URB=&%{!Cu3RO*MrKZ4VO}V6R0a zZw3Eg^0iKWM1dcTYZ0>N899=r6?+adUiBKPciJw}L$=1f4cs^bio&cr9baLF>6#BM z(F}EXe-`F=f_@`A7+Q&|QaZ??Txp_dB#lg!NH=t3$G8&06MFhwR=Iu*Im0s_b2B@| znW>X}sy~m#EW)&6E&!*0%}8UAS)wjt+A(io#wGI@Z2S+Ms1Cxl%YVE800007ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 zcmV-m2cP(fP)x~L`~4d)Rspd&<9kFh{hn*KP1LP0~$;u(LfAu zp%fx&qLBcRHx$G|3q(bv@+b;o0*D|jwD-Q9uQR(l*ST}s+uPgQ-MeFwZ#GS?b332? z&Tk$&_miXn3IGq)AmQ)3sisq{raD4(k*bHvpCe-TdWq^NRTEVM)i9xbgQ&ccnUVx* zEY%vS%gDcSg=!tuIK8$Th2_((_h^+7;R|G{n06&O2#6%LK`a}n?h_fL18btz<@lFG za}xS}u?#DBMB> zw^b($1Z)`9G?eP95EKi&$eOy@K%h;ryrR3la%;>|o*>CgB(s>dDcNOXg}CK9SPmD? zmr-s{0wRmxUnbDrYfRvnZ@d z6johZ2sMX{YkGSKWd}m|@V7`Degt-43=2M?+jR%8{(H$&MLLmS;-|JxnX2pnz;el1jsvqQz}pGSF<`mqEXRQ5sC4#BbwnB_4` zc5bFE-Gb#JV3tox9fp-vVEN{(tOCpRse`S+@)?%pz+zVJXSooTrNCUg`R6`hxwb{) zC@{O6MKY8tfZ5@!yy=p5Y|#+myRL=^{tc(6YgAnkg3I(Cd!r5l;|;l-MQ8B`;*SCE z{u)uP^C$lOPM z5d~UhKhRRmvv{LIa^|oavk1$QiEApSrP@~Jjbg`<*dW4TO?4qG%a%sTPUFz(QtW5( zM)lA+5)0TvH~aBaOAs|}?u2FO;yc-CZ1gNM1dAxJ?%m?YsGR`}-xk2*dxC}r5j$d* zE!#Vtbo69h>V4V`BL%_&$} z+oJAo@jQ^Tk`;%xw-4G>hhb&)B?##U+(6Fi7nno`C<|#PVA%$Y{}N-?(Gc$1%tr4Pc}}hm~yY#fTOe!@v9s-ik$dX~|ygArPhByaXn8 zpI^FUjNWMsTFKTP3X7m?UK)3m zp6rI^_zxRYrx6_QmhoWoDR`fp4R7gu6;gdO)!KexaoO2D88F9x#TM1(9Bn7g;|?|o z)~$n&Lh#hCP6_LOPD>a)NmhW})LADx2kq=X7}7wYRj-0?dXr&bHaRWCfSqvzFa=sn z-8^gSyn-RmH=BZ{AJZ~!8n5621GbUJV7Qvs%JNv&$%Q17s_X%s-41vAPfIR>;x0Wlqr5?09S>x#%Qkt>?(&XjFRY}*L6BeQ3 z<6XEBh^S7>AbwGm@XP{RkeEKj6@_o%oV?hDuUpUJ+r#JZO?!IUc;r0R?>mi)*ZpQ) z#((dn=A#i_&EQn|hd)N$#A*fjBFuiHcYvo?@y1 z5|fV=a^a~d!c-%ZbMNqkMKiSzM{Yq=7_c&1H!mXk60Uv32dV;vMg&-kQ)Q{+PFtwc zj|-uQ;b^gts??J*9VxxOro}W~Q9j4Em|zSRv)(WSO9$F$s=Ydu%Q+5DOid~lwk&we zY%W(Z@ofdwPHncEZzZgmqS|!gTj3wQq9rxQy+^eNYKr1mj&?tm@wkO*9@UtnRMG>c aR{jt9+;fr}hV%pg00001^@s67{VYS000c7NklQEG_j zup^)eW&WUIApqy$=APz8jE@awGp)!bsTjDbrJO`$x^ZR^dr;>)LW>{ zs70vpsD38v)19rI=GNk1b(0?Js9~rjsQsu*K;@SD40RB-3^gKU-MYC7G!Bw{fZsqp zih4iIi;Hr_xZ033Iu{sQxLS=}yBXgLMn40d++>aQ0#%8D1EbGZp7+ z5=mK?t31BkVYbGOxE9`i748x`YgCMwL$qMsChbSGSE1`p{nSmadR zcQ#R)(?!~dmtD0+D2!K zR9%!Xp1oOJzm(vbLvT^$IKp@+W2=-}qTzTgVtQ!#Y7Gxz}stUIm<1;oBQ^Sh2X{F4ibaOOx;5ZGSNK z0maF^@(UtV$=p6DXLgRURwF95C=|U8?osGhgOED*b z7woJ_PWXBD>V-NjQAm{~T%sjyJ{5tn2f{G%?J!KRSrrGvQ1(^`YLA5B!~eycY(e5_ z*%aa{at13SxC(=7JT7$IQF~R3sy`Nn%EMv!$-8ZEAryB*yB1k&stni)=)8-ODo41g zkJu~roIgAih94tb=YsL%iH5@^b~kU9M-=aqgXIrbtxMpFy5mekFm#edF9z7RQ6V}R zBIhbXs~pMzt0VWy1Fi$^fh+1xxLDoK09&5&MJl(q#THjPm(0=z2H2Yfm^a&E)V+a5 zbi>08u;bJsDRUKR9(INSc7XyuWv(JsD+BB*0hS)FO&l&7MdViuur@-<-EHw>kHRGY zqoT}3fDv2-m{NhBG8X}+rgOEZ;amh*DqN?jEfQdqxdj08`Sr=C-KmT)qU1 z+9Cl)a1mgXxhQiHVB}l`m;-RpmKy?0*|yl?FXvJkFxuu!fKlcmz$kN(a}i*saM3nr z0!;a~_%Xqy24IxA2rz<+08=B-Q|2PT)O4;EaxP^6qixOv7-cRh?*T?zZU`{nIM-at zTKYWr9rJ=tppQ9I#Z#mLgINVB!pO-^FOcvFw6NhV0gztuO?g ztoA*C-52Q-Z-P#xB4HAY3KQVd%dz1S4PA3vHp0aa=zAO?FCt zC_GaTyVBg2F!bBr3U@Zy2iJgIAt>1sf$JWA9kh{;L+P*HfUBX1Zy{4MgNbDfBV_ly z!y#+753arsZUt@366jIC0klaC@ckuk!qu=pAyf7&QmiBUT^L1&tOHzsK)4n|pmrVT zs2($4=?s~VejTFHbFdDOwG;_58LkIj1Fh@{glkO#F1>a==ymJS$z;gdedT1zPx4Kj ztjS`y_C}%af-RtpehdQDt3a<=W5C4$)9W@QAse;WUry$WYmr51ml9lkeunUrE`-3e zmq1SgSOPNEE-Mf+AGJ$g0M;3@w!$Ej;hMh=v=I+Lpz^n%Pg^MgwyqOkNyu2c^of)C z1~ALor3}}+RiF*K4+4{(1%1j3pif1>sv0r^mTZ?5Jd-It!tfPfiG_p$AY*Vfak%FG z4z#;wLtw&E&?}w+eKG^=#jF7HQzr8rV0mY<1YAJ_uGz~$E13p?F^fPSzXSn$8UcI$ z8er9{5w5iv0qf8%70zV71T1IBB1N}R5Kp%NO0=5wJalZt8;xYp;b{1K) zHY>2wW-`Sl{=NpR%iu3(u6l&)rc%%cSA#aV7WCowfbFR4wcc{LQZv~o1u_`}EJA3>ki`?9CKYTA!rhO)if*zRdd}Kn zEPfYbhoVE~!FI_2YbC5qAj1kq;xP6%J8+?2PAs?`V3}nyFVD#sV3+uP`pi}{$l9U^ zSz}_M9f7RgnnRhaoIJgT8us!1aB&4!*vYF07Hp&}L zCRlop0oK4DL@ISz{2_BPlezc;xj2|I z23RlDNpi9LgTG_#(w%cMaS)%N`e>~1&a3<{Xy}>?WbF>OOLuO+j&hc^YohQ$4F&ze z+hwnro1puQjnKm;vFG~o>`kCeUIlkA-2tI?WBKCFLMBY=J{hpSsQ=PDtU$=duS_hq zHpymHt^uuV1q@uc4bFb{MdG*|VoW@15Osrqt2@8ll0qO=j*uOXn{M0UJX#SUztui9FN4)K3{9!y8PC-AHHvpVTU;x|-7P+taAtyglk#rjlH2 z5Gq8ik}BPaGiM{#Woyg;*&N9R2{J0V+WGB69cEtH7F?U~Kbi6ksi*`CFXsi931q7Y zGO82?whBhN%w1iDetv%~wM*Y;E^)@Vl?VDj-f*RX>{;o_=$fU!&KAXbuadYZ46Zbg z&6jMF=49$uL^73y;;N5jaHYv)BTyfh&`qVLYn?`o6BCA_z-0niZz=qPG!vonK3MW_ zo$V96zM!+kJRs{P-5-rQVse0VBH*n6A58)4uc&gfHMa{gIhV2fGf{st>E8sKyP-$8zp~wJX^A*@DI&-;8>gANXZj zU)R+Y)PB?=)a|Kj>8NXEu^S_h^7R`~Q&7*Kn!xyvzVv&^>?^iu;S~R2e-2fJx-oUb cX)(b1KSk$MOV07*qoM6N<$f&6$jw%VRuvdN2+38CZWny1cRtlsl+0_KtW)EU14Ei(F!UtWuj4IK+3{sK@>rh zs1Z;=(DD&U6+tlyL?UnHVN^&g6QhFi2#HS+*qz;(>63G(`|jRtW|nz$Pv7qTovP!^ zP_jES{mr@O-02w%!^a?^1ZP!_KmQiz0L~jZ=W@Qt`8wzOoclQsAS<5YdH;a(4bGLE zk8s}1If(PSIgVi!XE!5kA?~z*sobvNyohr;=Q_@h2@$6Flyej3J)D-6YfheRGl`HEcPk|~huT_2-U?PfL=4BPV)f1o!%rQ!NMt_MYw-5bUSwQ9Z&zC>u zOrl~UJglJNa%f50Ok}?WB{on`Ci`p^Y!xBA?m@rcJXLxtrE0FhRF3d*ir>yzO|BD$ z3V}HpFcCh6bTzY}Nt_(W%QYd3NG)jJ4<`F<1Od) zfQblTdC&h2lCz`>y?>|9o2CdvC8qZeIZt%jN;B7Hdn2l*k4M4MFEtq`q_#5?}c$b$pf_3y{Y!cRDafZBEj-*OD|gz#PBDeu3QoueOesLzB+O zxjf2wvf6Wwz>@AiOo2mO4=TkAV+g~%_n&R;)l#!cBxjuoD$aS-`IIJv7cdX%2{WT7 zOm%5rs(wqyPE^k5SIpUZ!&Lq4<~%{*>_Hu$2|~Xa;iX*tz8~G6O3uFOS?+)tWtdi| zV2b#;zRN!m@H&jd=!$7YY6_}|=!IU@=SjvGDFtL;aCtw06U;-v^0%k0FOyESt z1Wv$={b_H&8FiRV?MrzoHWd>%v6KTRU;-v^Miiz+@q`(BoT!+<37CKhoKb)|8!+RG z6BQFU^@fRW;s8!mOf2QViKQGk0TVER6EG1`#;Nm39Do^PoT!+<37AD!%oJe86(=et zZ~|sLzU>V-qYiU6V8$0GmU7_K8|Fd0B?+9Un1BhKAz#V~Fk^`mJtlCX#{^8^M8!me z8Yg;8-~>!e<-iG;h*0B1kBKm}hItVGY6WnjVpgnTTAC$rqQ^v)4KvOtpY|sIj@WYg zyw##ZZ5AC2IKNC;^hwg9BPk0wLStlmBr;E|$5GoAo$&Ui_;S9WY62n3)i49|T%C#i017z3J=$RF|KyZWnci*@lW4 z=AKhNN6+m`Q!V3Ye68|8y@%=am>YD0nG99M)NWc20%)gwO!96j7muR}Fr&54SxKP2 zP30S~lt=a*qDlbu3+Av57=9v&vr<6g0&`!8E2fq>I|EJGKs}t|{h7+KT@)LfIV-3K zK)r_fr2?}FFyn*MYoLC>oV-J~eavL2ho4a4^r{E-8m2hi>~hA?_vIG4a*KT;2eyl1 zh_hUvUJpNCFwBvRq5BI*srSle>c6%n`#VNsyC|MGa{(P&08p=C9+WUw9Hl<1o9T4M zdD=_C0F7#o8A_bRR?sFNmU0R6tW`ElnF8p53IdHo#S9(JoZCz}fHwJ6F<&?qrpVqE zte|m%89JQD+XwaPU#%#lVs-@-OL);|MdfINd6!XwP2h(eyafTUsoRkA%&@fe?9m@jw-v(yTTiV2(*fthQH9}SqmsRPVnwwbV$1E(_lkmo&S zF-truCU914_$jpqjr(>Ha4HkM4YMT>m~NosUu&UZ>zirfHo%N6PPs9^_o$WqPA0#5 z%tG>qFCL+b*0s?sZ;Sht0nE7Kl>OVXy=gjWxxK;OJ3yGd7-pZf7JYNcZo2*1SF`u6 zHJyRRxGw9mDlOiXqVMsNe#WX`fC`vrtjSQ%KmLcl(lC>ZOQzG^%iql2w-f_K@r?OE zwCICifM#L-HJyc7Gm>Ern?+Sk3&|Khmu4(~3qa$(m6Ub^U0E5RHq49za|XklN#?kP zl;EstdW?(_4D>kwjWy2f!LM)y?F94kyU3`W!6+AyId-89v}sXJpuic^NLL7GJItl~ zsiuB98AI-(#Mnm|=A-R6&2fwJ0JVSY#Q>&3$zFh|@;#%0qeF=j5Ajq@4i0tIIW z&}sk$&fGwoJpe&u-JeGLi^r?dO`m=y(QO{@h zQqAC7$rvz&5+mo3IqE?h=a~6m>%r5Quapvzq;{y~p zJpyXOBgD9VrW7@#p6l7O?o3feml(DtSL>D^R) zZUY%T2b0-vBAFN7VB;M88!~HuOXi4KcI6aRQ&h|XQ0A?m%j2=l1f0cGP}h(oVfJ`N zz#PpmFC*ieab)zJK<4?^k=g%OjPnkANzbAbmGZHoVRk*mTfm75s_cWVa`l*f$B@xu z5E*?&@seIo#*Y~1rBm!7sF9~~u6Wrj5oICUOuz}CS)jdNIznfzCA(stJ(7$c^e5wN z?lt>eYgbA!kvAR7zYSD&*r1$b|(@;9dcZ^67R0 zXAXJKa|5Sdmj!g578Nwt6d$sXuc&MWezA0Whd`94$h{{?1IwXP4)Tx4obDK%xoFZ_Z zjjHJ_P@R_e5blG@yEjnaJb`l;s%Lb2&=8$&Ct-fV`E^4CUs)=jTk!I}2d&n!f@)bm z@ z_4Dc86+3l2*p|~;o-Sb~oXb_RuLmoifDU^&Te$*FevycC0*nE3Xws8gsWp|Rj2>SM zns)qcYj?^2sd8?N!_w~4v+f-HCF|a$TNZDoNl$I1Uq87euoNgKb6&r26TNrfkUa@o zfdiFA@p{K&mH3b8i!lcoz)V{n8Q@g(vR4ns4r6w;K z>1~ecQR0-<^J|Ndg5fvVUM9g;lbu-){#ghGw(fg>L zh)T5Ljb%lWE;V9L!;Cqk>AV1(rULYF07ZBJbGb9qbSoLAd;in9{)95YqX$J43-dY7YU*k~vrM25 zxh5_IqO0LYZW%oxQ5HOzmk4x{atE*vipUk}sh88$b2tn?!ujEHn`tQLe&vo}nMb&{ zio`xzZ&GG6&ZyN3jnaQy#iVqXE9VT(3tWY$n-)uWDQ|tc{`?fq2F`oQ{;d3aWPg4Hp-(iE{ry>MIPWL> iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000000..89c2725b70f1 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/firebase_in_app_messaging/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000000..f2e259c7c939 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Base.lproj/Main.storyboard b/packages/firebase_in_app_messaging/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000000..3950f04ab0f9 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/GoogleService-Info.plist b/packages/firebase_in_app_messaging/example/ios/Runner/GoogleService-Info.plist new file mode 100644 index 000000000000..0ad19e34cfee --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 417703151161-0kmftqj80per9egdcai8c89sefjdptfg.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.417703151161-0kmftqj80per9egdcai8c89sefjdptfg + API_KEY + AIzaSyAirg5nBv4fsGWF82ITldAd04thCp04WQ0 + GCM_SENDER_ID + 417703151161 + PLIST_VERSION + 1 + BUNDLE_ID + com.example.firebaseInAppMessagingExample + PROJECT_ID + fiamflutter + STORAGE_BUCKET + fiamflutter.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:417703151161:ios:2ad9dffe6e82f02c + DATABASE_URL + https://fiamflutter.firebaseio.com + + \ No newline at end of file diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/Info.plist b/packages/firebase_in_app_messaging/example/ios/Runner/Info.plist new file mode 100644 index 000000000000..9afd5ae7969f --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + firebase_in_app_messaging_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/packages/firebase_in_app_messaging/example/ios/Runner/main.m b/packages/firebase_in_app_messaging/example/ios/Runner/main.m new file mode 100644 index 000000000000..dff6597e4513 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/ios/Runner/main.m @@ -0,0 +1,9 @@ +#import +#import +#import "AppDelegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/packages/firebase_in_app_messaging/example/lib/main.dart b/packages/firebase_in_app_messaging/example/lib/main.dart new file mode 100644 index 000000000000..0df4cb951dd6 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/lib/main.dart @@ -0,0 +1,119 @@ +import 'dart:async'; + +import 'package:firebase_analytics/firebase_analytics.dart'; +import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart'; +import 'package:flutter/material.dart'; + +void main() => runApp(MyApp()); + +class MyApp extends StatelessWidget { + static FirebaseAnalytics analytics = FirebaseAnalytics(); + static FirebaseInAppMessaging fiam = FirebaseInAppMessaging(); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('In-App Messaging example'), + ), + body: Builder(builder: (BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + AnalyticsEventExample(), + ProgrammaticTriggersExample(fiam), + ], + ), + ); + }), + )); + } +} + +class ProgrammaticTriggersExample extends StatelessWidget { + const ProgrammaticTriggersExample(this.fiam); + + final FirebaseInAppMessaging fiam; + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + children: [ + Text( + "Programmatic Trigger", + style: TextStyle( + fontStyle: FontStyle.italic, + fontSize: 18, + ), + ), + const SizedBox(height: 8), + const Text("Manually trigger events programmatically "), + const SizedBox(height: 8), + RaisedButton( + onPressed: () { + fiam.triggerEvent('chicken_event'); + Scaffold.of(context).showSnackBar(SnackBar( + content: const Text("Triggering event: chicken_event"))); + }, + color: Colors.blue, + child: Text( + "Programmatic Triggers".toUpperCase(), + style: TextStyle(color: Colors.white), + ), + ) + ], + ), + ), + ); + } +} + +class AnalyticsEventExample extends StatelessWidget { + Future _sendAnalyticsEvent() async { + await MyApp.analytics + .logEvent(name: 'awesome_event', parameters: { + 'int': 42, // not required? + }); + } + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + children: [ + Text( + "Log an analytics event", + style: TextStyle( + fontStyle: FontStyle.italic, + fontSize: 18, + ), + ), + const SizedBox(height: 8), + const Text("Trigger an analytics event"), + const SizedBox(height: 8), + RaisedButton( + onPressed: () { + _sendAnalyticsEvent(); + Scaffold.of(context).showSnackBar(SnackBar( + content: + const Text("Firing analytics event: awesome_event"))); + }, + color: Colors.blue, + child: Text( + "Log event".toUpperCase(), + style: TextStyle(color: Colors.white), + ), + ), + ], + ), + ), + ); + } +} diff --git a/packages/firebase_in_app_messaging/example/pubspec.yaml b/packages/firebase_in_app_messaging/example/pubspec.yaml new file mode 100644 index 000000000000..dc1b1fc5adb2 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/pubspec.yaml @@ -0,0 +1,26 @@ +name: firebase_in_app_messaging_example +description: Demonstrates how to use the firebase_in_app_messaging plugin. +publish_to: 'none' + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + cupertino_icons: ^0.1.2 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_driver: + sdk: flutter + test: any + + firebase_in_app_messaging: + path: ../ + firebase_core: ^0.4.0 + firebase_analytics: ^3.0.3 + +flutter: + uses-material-design: true diff --git a/packages/firebase_in_app_messaging/example/test_driver/firebase_in_app_messaging.dart b/packages/firebase_in_app_messaging/example/test_driver/firebase_in_app_messaging.dart new file mode 100644 index 000000000000..62953cee0316 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/test_driver/firebase_in_app_messaging.dart @@ -0,0 +1,32 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart'; +import 'package:flutter_driver/driver_extension.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + final Completer completer = Completer(); + enableFlutterDriverExtension(handler: (_) => completer.future); + tearDownAll(() => completer.complete(null)); + + group('firebase_in_app_messaging', () { + FirebaseInAppMessaging fiam; + + setUp(() { + fiam = FirebaseInAppMessaging(); + }); + + test('triggerEvent', () { + expect(fiam.triggerEvent('someEvent'), completes); + }); + + test('logging', () { + expect(fiam.setMessagesSuppressed(true), completes); + expect(fiam.setAutomaticDataCollectionEnabled(true), completes); + }); + }); +} diff --git a/packages/firebase_in_app_messaging/example/test_driver/firebase_in_app_messaging_test.dart b/packages/firebase_in_app_messaging/example/test_driver/firebase_in_app_messaging_test.dart new file mode 100644 index 000000000000..cc11eae240e3 --- /dev/null +++ b/packages/firebase_in_app_messaging/example/test_driver/firebase_in_app_messaging_test.dart @@ -0,0 +1,7 @@ +import 'package:flutter_driver/flutter_driver.dart'; + +void main() async { + final FlutterDriver driver = await FlutterDriver.connect(); + await driver.requestData(null, timeout: const Duration(minutes: 1)); + driver.close(); +} diff --git a/packages/firebase_in_app_messaging/ios/.gitignore b/packages/firebase_in_app_messaging/ios/.gitignore new file mode 100644 index 000000000000..710ec6cf1c71 --- /dev/null +++ b/packages/firebase_in_app_messaging/ios/.gitignore @@ -0,0 +1,36 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig diff --git a/packages/firebase_in_app_messaging/ios/Assets/.gitkeep b/packages/firebase_in_app_messaging/ios/Assets/.gitkeep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/firebase_in_app_messaging/ios/Classes/FirebaseInAppMessagingPlugin.h b/packages/firebase_in_app_messaging/ios/Classes/FirebaseInAppMessagingPlugin.h new file mode 100644 index 000000000000..4f6f7dfaba56 --- /dev/null +++ b/packages/firebase_in_app_messaging/ios/Classes/FirebaseInAppMessagingPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface FirebaseInAppMessagingPlugin : NSObject +@end diff --git a/packages/firebase_in_app_messaging/ios/Classes/FirebaseInAppMessagingPlugin.m b/packages/firebase_in_app_messaging/ios/Classes/FirebaseInAppMessagingPlugin.m new file mode 100644 index 000000000000..306330eeae8e --- /dev/null +++ b/packages/firebase_in_app_messaging/ios/Classes/FirebaseInAppMessagingPlugin.m @@ -0,0 +1,47 @@ +#import "FirebaseInAppMessagingPlugin.h" + +#import + +@implementation FirebaseInAppMessagingPlugin ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *channel = + [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_in_app_messaging" + binaryMessenger:[registrar messenger]]; + FirebaseInAppMessagingPlugin *instance = [[FirebaseInAppMessagingPlugin alloc] init]; + [registrar addMethodCallDelegate:instance channel:channel]; +} + +- (instancetype)init { + self = [super init]; + if (self) { + if (![FIRApp appNamed:@"__FIRAPP_DEFAULT"]) { + NSLog(@"Configuring the default Firebase app..."); + [FIRApp configure]; + NSLog(@"Configured the default Firebase app %@.", [FIRApp defaultApp].name); + } + } + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + if ([@"triggerEvent" isEqualToString:call.method]) { + NSString *eventName = call.arguments[@"eventName"]; + FIRInAppMessaging *fiam = [FIRInAppMessaging inAppMessaging]; + [fiam triggerEvent:eventName]; + result(nil); + } else if ([@"setMessagesSuppressed" isEqualToString:call.method]) { + NSNumber *suppress = [NSNumber numberWithBool:call.arguments]; + FIRInAppMessaging *fiam = [FIRInAppMessaging inAppMessaging]; + fiam.messageDisplaySuppressed = [suppress boolValue]; + result(nil); + } else if ([@"setAutomaticDataCollectionEnabled" isEqualToString:call.method]) { + NSNumber *enabled = [NSNumber numberWithBool:call.arguments]; + FIRInAppMessaging *fiam = [FIRInAppMessaging inAppMessaging]; + fiam.automaticDataCollectionEnabled = [enabled boolValue]; + result(nil); + } else { + result(FlutterMethodNotImplemented); + } +} + +@end diff --git a/packages/firebase_in_app_messaging/ios/firebase_in_app_messaging.podspec b/packages/firebase_in_app_messaging/ios/firebase_in_app_messaging.podspec new file mode 100644 index 000000000000..f635f4a85656 --- /dev/null +++ b/packages/firebase_in_app_messaging/ios/firebase_in_app_messaging.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_in_app_messaging' + s.version = '0.0.1' + s.summary = 'InAppMessaging Plugin for Firebase' + s.description = <<-DESC +A new flutter plugin project. + DESC + s.homepage = 'http://example.com' + 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.dependency 'Flutter' + s.dependency 'Firebase' + s.dependency 'Firebase/InAppMessagingDisplay' + s.static_framework = true + + s.ios.deployment_target = '8.0' +end + diff --git a/packages/firebase_in_app_messaging/lib/firebase_in_app_messaging.dart b/packages/firebase_in_app_messaging/lib/firebase_in_app_messaging.dart new file mode 100644 index 000000000000..d6e6084a5269 --- /dev/null +++ b/packages/firebase_in_app_messaging/lib/firebase_in_app_messaging.dart @@ -0,0 +1,38 @@ +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; + +class FirebaseInAppMessaging { + @visibleForTesting + static const MethodChannel channel = + MethodChannel('plugins.flutter.io/firebase_in_app_messaging'); + + static FirebaseInAppMessaging _instance = FirebaseInAppMessaging(); + + /// Gets the instance of In-App Messaging for the default Firebase app. + static FirebaseInAppMessaging get instance => _instance; + + /// Triggers an analytics event. + Future triggerEvent(String eventName) async { + await channel.invokeMethod( + 'triggerEvent', {'eventName': eventName}); + } + + /// Enables or disables suppression of message displays. + Future setMessagesSuppressed(bool suppress) async { + if (suppress == null) { + throw ArgumentError.notNull('suppress'); + } + await channel.invokeMethod('setMessagesSuppressed', suppress); + } + + /// Disable data collection for the app. + Future setAutomaticDataCollectionEnabled(bool enabled) async { + if (enabled == null) { + throw ArgumentError.notNull('enabled'); + } + await channel.invokeMethod( + 'setAutomaticDataCollectionEnabled', enabled); + } +} diff --git a/packages/firebase_in_app_messaging/pubspec.yaml b/packages/firebase_in_app_messaging/pubspec.yaml new file mode 100644 index 000000000000..a965545f93bb --- /dev/null +++ b/packages/firebase_in_app_messaging/pubspec.yaml @@ -0,0 +1,25 @@ +name: firebase_in_app_messaging +description: Flutter plugin for Firebase In-App Messaging. +version: 0.0.1 +author: Flutter Team +homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_in_app_messaging + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + meta: ^1.1.6 + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_driver: + sdk: flutter + test: any + +flutter: + plugin: + androidPackage: com.example.firebase_in_app_messaging + pluginClass: FirebaseInAppMessagingPlugin diff --git a/packages/firebase_in_app_messaging/test/firebase_in_app_messaging_test.dart b/packages/firebase_in_app_messaging/test/firebase_in_app_messaging_test.dart new file mode 100644 index 000000000000..200ea1527d0a --- /dev/null +++ b/packages/firebase_in_app_messaging/test/firebase_in_app_messaging_test.dart @@ -0,0 +1,54 @@ +import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$FirebaseInAppMessaging', () { + final List log = []; + + setUp(() { + log.clear(); + FirebaseInAppMessaging.channel + .setMockMethodCallHandler((MethodCall methodcall) async { + log.add(methodcall); + return true; + }); + }); + + test('triggerEvent', () async { + final FirebaseInAppMessaging fiam = FirebaseInAppMessaging(); + await fiam.triggerEvent('someEvent'); + expect(log, [ + isMethodCall('triggerEvent', + arguments: {"eventName": "someEvent"}), + ]); + }); + + test('setMessagesSuppressed', () async { + final FirebaseInAppMessaging fiam = FirebaseInAppMessaging(); + await fiam.setMessagesSuppressed(true); + expect(log, + [isMethodCall('setMessagesSuppressed', arguments: true)]); + + log.clear(); + fiam.setMessagesSuppressed(false); + expect(log, [ + isMethodCall('setMessagesSuppressed', arguments: false), + ]); + }); + + test('setDataCollectionEnabled', () async { + final FirebaseInAppMessaging fiam = FirebaseInAppMessaging(); + await fiam.setAutomaticDataCollectionEnabled(true); + expect(log, [ + isMethodCall('setAutomaticDataCollectionEnabled', arguments: true) + ]); + + log.clear(); + fiam.setAutomaticDataCollectionEnabled(false); + expect(log, [ + isMethodCall('setAutomaticDataCollectionEnabled', arguments: false), + ]); + }); + }); +} From 49d237348242d3df6ba76f1992e2b8f25247223c Mon Sep 17 00:00:00 2001 From: tatiesmars Date: Thu, 18 Jul 2019 18:52:04 +0700 Subject: [PATCH 76/94] [firebase_ml_vision] Add support for cloud text recognizer (#1847) --- packages/firebase_ml_vision/CHANGELOG.md | 4 + .../firebasemlvision/TextRecognizer.java | 10 +- .../example/lib/camera_preview_scanner.dart | 12 +- .../example/lib/detector_painters.dart | 2 +- .../example/lib/picture_scanner.dart | 13 + .../ios/Classes/TextRecognizer.m | 12 +- .../lib/src/firebase_vision.dart | 15 +- .../lib/src/text_recognizer.dart | 12 +- packages/firebase_ml_vision/pubspec.yaml | 2 +- .../test/firebase_ml_vision_test.dart | 270 +++++++++++++++++- 10 files changed, 342 insertions(+), 10 deletions(-) diff --git a/packages/firebase_ml_vision/CHANGELOG.md b/packages/firebase_ml_vision/CHANGELOG.md index 058b0d053560..f25d393d393f 100644 --- a/packages/firebase_ml_vision/CHANGELOG.md +++ b/packages/firebase_ml_vision/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.1 + +* Add support for cloud text recognizer. + ## 0.9.0+3 * Automatically use version from pubspec.yaml when reporting usage to Firebase. diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/TextRecognizer.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/TextRecognizer.java index 55aa3c8bc5d7..9a0f82343ff4 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/TextRecognizer.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/TextRecognizer.java @@ -21,7 +21,15 @@ public class TextRecognizer implements Detector { private final FirebaseVisionTextRecognizer recognizer; TextRecognizer(FirebaseVision vision, Map options) { - recognizer = vision.getOnDeviceTextRecognizer(); + final String modelType = (String) options.get("modelType"); + if (modelType.equals("onDevice")) { + recognizer = vision.getOnDeviceTextRecognizer(); + } else if (modelType.equals("cloud")) { + recognizer = vision.getCloudTextRecognizer(); + } else { + final String message = String.format("No model for type: %s", modelType); + throw new IllegalArgumentException(message); + } } @Override diff --git a/packages/firebase_ml_vision/example/lib/camera_preview_scanner.dart b/packages/firebase_ml_vision/example/lib/camera_preview_scanner.dart index c8c5eedf7a64..f40e20d6591c 100644 --- a/packages/firebase_ml_vision/example/lib/camera_preview_scanner.dart +++ b/packages/firebase_ml_vision/example/lib/camera_preview_scanner.dart @@ -29,6 +29,8 @@ class _CameraPreviewScannerState extends State { final ImageLabeler _cloudImageLabeler = FirebaseVision.instance.cloudImageLabeler(); final TextRecognizer _recognizer = FirebaseVision.instance.textRecognizer(); + final TextRecognizer _cloudRecognizer = + FirebaseVision.instance.cloudTextRecognizer(); @override void initState() { @@ -72,6 +74,8 @@ class _CameraPreviewScannerState extends State { switch (_currentDetector) { case Detector.text: return _recognizer.processImage; + case Detector.cloudText: + return _cloudRecognizer.processImage; case Detector.barcode: return _barcodeDetector.detectInImage; case Detector.label: @@ -119,7 +123,8 @@ class _CameraPreviewScannerState extends State { painter = LabelDetectorPainter(imageSize, _scanResults); break; default: - assert(_currentDetector == Detector.text); + assert(_currentDetector == Detector.text || + _currentDetector == Detector.cloudText); if (_scanResults is! VisionText) return noResultsText; painter = TextDetectorPainter(imageSize, _scanResults); } @@ -200,6 +205,10 @@ class _CameraPreviewScannerState extends State { child: Text('Detect Text'), value: Detector.text, ), + const PopupMenuItem( + child: Text('Detect Cloud Text'), + value: Detector.cloudText, + ), ], ), ], @@ -222,6 +231,7 @@ class _CameraPreviewScannerState extends State { _imageLabeler.close(); _cloudImageLabeler.close(); _recognizer.close(); + _cloudRecognizer.close(); }); _currentDetector = null; diff --git a/packages/firebase_ml_vision/example/lib/detector_painters.dart b/packages/firebase_ml_vision/example/lib/detector_painters.dart index 684503b1086c..d8d7316f2509 100644 --- a/packages/firebase_ml_vision/example/lib/detector_painters.dart +++ b/packages/firebase_ml_vision/example/lib/detector_painters.dart @@ -7,7 +7,7 @@ import 'dart:ui' as ui; import 'package:firebase_ml_vision/firebase_ml_vision.dart'; import 'package:flutter/material.dart'; -enum Detector { barcode, face, label, cloudLabel, text } +enum Detector { barcode, face, label, cloudLabel, text, cloudText } class BarcodeDetectorPainter extends CustomPainter { BarcodeDetectorPainter(this.absoluteImageSize, this.barcodeLocations); diff --git a/packages/firebase_ml_vision/example/lib/picture_scanner.dart b/packages/firebase_ml_vision/example/lib/picture_scanner.dart index 88b1c5a1f0bb..182a55a46020 100644 --- a/packages/firebase_ml_vision/example/lib/picture_scanner.dart +++ b/packages/firebase_ml_vision/example/lib/picture_scanner.dart @@ -29,6 +29,8 @@ class _PictureScannerState extends State { final ImageLabeler _cloudImageLabeler = FirebaseVision.instance.cloudImageLabeler(); final TextRecognizer _recognizer = FirebaseVision.instance.textRecognizer(); + final TextRecognizer _cloudRecognizer = + FirebaseVision.instance.cloudTextRecognizer(); Future _getAndScanImage() async { setState(() { @@ -93,6 +95,9 @@ class _PictureScannerState extends State { case Detector.text: results = await _recognizer.processImage(visionImage); break; + case Detector.cloudText: + results = await _cloudRecognizer.processImage(visionImage); + break; default: return; } @@ -121,6 +126,9 @@ class _PictureScannerState extends State { case Detector.text: painter = TextDetectorPainter(_imageSize, results); break; + case Detector.cloudText: + painter = TextDetectorPainter(_imageSize, results); + break; default: break; } @@ -185,6 +193,10 @@ class _PictureScannerState extends State { child: Text('Detect Text'), value: Detector.text, ), + const PopupMenuItem( + child: Text('Detect Cloud Text'), + value: Detector.cloudText, + ), ], ), ], @@ -207,6 +219,7 @@ class _PictureScannerState extends State { _imageLabeler.close(); _cloudImageLabeler.close(); _recognizer.close(); + _cloudRecognizer.close(); super.dispose(); } } diff --git a/packages/firebase_ml_vision/ios/Classes/TextRecognizer.m b/packages/firebase_ml_vision/ios/Classes/TextRecognizer.m index fa9bdd3158e2..cc8cc9306a12 100644 --- a/packages/firebase_ml_vision/ios/Classes/TextRecognizer.m +++ b/packages/firebase_ml_vision/ios/Classes/TextRecognizer.m @@ -8,7 +8,17 @@ @implementation TextRecognizer - (instancetype)initWithVision:(FIRVision *)vision options:(NSDictionary *)options { self = [super init]; if (self) { - _recognizer = [vision onDeviceTextRecognizer]; + if ([@"onDevice" isEqualToString:options[@"modelType"]]) { + _recognizer = [vision onDeviceTextRecognizer]; + } else if ([@"cloud" isEqualToString:options[@"modelType"]]) { + _recognizer = [vision cloudTextRecognizer]; + } else { + NSString *reason = + [NSString stringWithFormat:@"Invalid model type: %@", options[@"modelType"]]; + @throw [[NSException alloc] initWithName:NSInvalidArgumentException + reason:reason + userInfo:nil]; + } } return self; } diff --git a/packages/firebase_ml_vision/lib/src/firebase_vision.dart b/packages/firebase_ml_vision/lib/src/firebase_vision.dart index 6f6b0446e3ea..d0f593cff8f8 100644 --- a/packages/firebase_ml_vision/lib/src/firebase_vision.dart +++ b/packages/firebase_ml_vision/lib/src/firebase_vision.dart @@ -67,7 +67,12 @@ class FirebaseVision { } /// Creates an instance of [TextRecognizer]. - TextRecognizer textRecognizer() => TextRecognizer._(nextHandle++); + TextRecognizer textRecognizer() { + return TextRecognizer._( + modelType: ModelType.onDevice, + handle: nextHandle++, + ); + } /// Creates a cloud instance of [ImageLabeler]. ImageLabeler cloudImageLabeler([CloudImageLabelerOptions options]) { @@ -77,6 +82,14 @@ class FirebaseVision { handle: nextHandle++, ); } + + /// Creates a cloud instance of [TextRecognizer]. + TextRecognizer cloudTextRecognizer() { + return TextRecognizer._( + modelType: ModelType.cloud, + handle: nextHandle++, + ); + } } /// Represents an image object used for both on-device and cloud API detectors. diff --git a/packages/firebase_ml_vision/lib/src/text_recognizer.dart b/packages/firebase_ml_vision/lib/src/text_recognizer.dart index 888f5fd5e03b..98936f66a906 100644 --- a/packages/firebase_ml_vision/lib/src/text_recognizer.dart +++ b/packages/firebase_ml_vision/lib/src/text_recognizer.dart @@ -19,7 +19,13 @@ part of firebase_ml_vision; /// await textRecognizer.processImage(image); /// ``` class TextRecognizer { - TextRecognizer._(this._handle); + TextRecognizer._({ + @required this.modelType, + @required int handle, + }) : _handle = handle, + assert(modelType != null); + + final ModelType modelType; final int _handle; bool _hasBeenOpened = false; @@ -35,7 +41,9 @@ class TextRecognizer { 'TextRecognizer#processImage', { 'handle': _handle, - 'options': {}, + 'options': { + 'modelType': _enumToString(modelType), + }, }..addAll(visionImage._serialize()), ); diff --git a/packages/firebase_ml_vision/pubspec.yaml b/packages/firebase_ml_vision/pubspec.yaml index 765b72b16a09..c2138b1866d0 100644 --- a/packages/firebase_ml_vision/pubspec.yaml +++ b/packages/firebase_ml_vision/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_ml_vision description: Flutter plugin for Firebase machine learning vision services. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_ml_vision -version: 0.9.0+3 +version: 0.9.1 dependencies: flutter: diff --git a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart index 9420ddad85a0..85e069774b9a 100644 --- a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart +++ b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart @@ -83,7 +83,9 @@ void main() { }, ], }, - 'options': {}, + 'options': { + 'modelType': 'onDevice', + }, }, ), ]); @@ -778,7 +780,268 @@ void main() { expect(block.confidence, 0.5); block = text.blocks[1]; + // TODO(jackson): Use const Rect when available in minimum Flutter SDK + // ignore: prefer_const_constructors + expect(block.boundingBox, Rect.fromLTWH(14.0, 13.0, 16.0, 15.0)); + expect(block.text, 'hello'); + expect(block.cornerPoints, const [ + Offset(18.0, 17.0), + Offset(20.0, 19.0), + ]); + expect(block.confidence, 0.6); + }); + }); + + group('$TextLine', () { + test('processImage', () async { + final VisionText text = await recognizer.processImage(image); + + TextLine line = text.blocks[0].lines[0]; + // TODO(jackson): Use const Rect when available in minimum Flutter SDK + // ignore: prefer_const_constructors + expect(line.boundingBox, Rect.fromLTWH(5, 6, 7, 8)); + expect(line.text, 'friend'); + expect(line.cornerPoints, const [ + Offset(9.0, 10.0), + Offset(11.0, 12.0), + ]); + expect(line.recognizedLanguages, hasLength(2)); + expect(line.recognizedLanguages[0].languageCode, 'ef'); + expect(line.recognizedLanguages[1].languageCode, 'gh'); + expect(line.confidence, 0.3); + + line = text.blocks[0].lines[1]; + // TODO(jackson): Use const Rect when available in minimum Flutter SDK + // ignore: prefer_const_constructors + expect(line.boundingBox, Rect.fromLTWH(8.0, 7.0, 4.0, 5.0)); + expect(line.text, 'how'); + expect(line.cornerPoints, const [ + Offset(10.0, 9.0), + Offset(12.0, 11.0), + ]); + expect(line.confidence, 0.4); + }); + }); + + group('$TextElement', () { + test('processImage', () async { + final VisionText text = await recognizer.processImage(image); + + TextElement element = text.blocks[0].lines[0].elements[0]; // ignore: prefer_const_constructors + expect(element.boundingBox, Rect.fromLTWH(1.0, 2.0, 3.0, 4.0)); + expect(element.text, 'hello'); + expect(element.cornerPoints, const [ + Offset(5.0, 6.0), + Offset(7.0, 8.0), + ]); + expect(element.recognizedLanguages, hasLength(2)); + expect(element.recognizedLanguages[0].languageCode, 'ab'); + expect(element.recognizedLanguages[1].languageCode, 'cd'); + expect(element.confidence, 0.1); + + element = text.blocks[0].lines[0].elements[1]; + // TODO(jackson): Use const Rect when available in minimum Flutter SDK + // ignore: prefer_const_constructors + expect(element.boundingBox, Rect.fromLTWH(4.0, 3.0, 2.0, 1.0)); + expect(element.text, 'my'); + expect(element.cornerPoints, const [ + Offset(6.0, 5.0), + Offset(8.0, 7.0), + ]); + expect(element.confidence, 0.2); + }); + }); + + test('processImage', () async { + final VisionText text = await recognizer.processImage(image); + + expect(text.text, 'testext'); + expect(log, [ + isMethodCall( + 'TextRecognizer#processImage', + arguments: { + 'handle': 0, + 'type': 'file', + 'path': 'empty', + 'bytes': null, + 'metadata': null, + 'options': { + 'modelType': 'onDevice', + }, + }, + ), + ]); + }); + + test('processImage no bounding box', () async { + returnValue = { + 'blocks': [ + { + 'text': '', + 'points': [], + 'recognizedLanguages': [], + 'lines': [], + }, + ], + }; + + final VisionText text = await recognizer.processImage(image); + + final TextBlock block = text.blocks[0]; + expect(block.boundingBox, null); + }); + }); + + group('Cloud $TextRecognizer', () { + TextRecognizer recognizer; + final FirebaseVisionImage image = FirebaseVisionImage.fromFilePath( + 'empty', + ); + + setUp(() { + recognizer = FirebaseVision.instance.cloudTextRecognizer(); + final List elements = [ + { + 'text': 'hello', + 'left': 1.0, + 'top': 2.0, + 'width': 3.0, + 'height': 4.0, + 'points': [ + [5.0, 6.0], + [7.0, 8.0], + ], + 'recognizedLanguages': [ + { + 'languageCode': 'ab', + }, + { + 'languageCode': 'cd', + } + ], + 'confidence': 0.1, + }, + { + 'text': 'my', + 'left': 4.0, + 'top': 3.0, + 'width': 2.0, + 'height': 1.0, + 'points': [ + [6.0, 5.0], + [8.0, 7.0], + ], + 'recognizedLanguages': [], + 'confidence': 0.2, + }, + ]; + + final List lines = [ + { + 'text': 'friend', + 'left': 5.0, + 'top': 6.0, + 'width': 7.0, + 'height': 8.0, + 'points': [ + [9.0, 10.0], + [11.0, 12.0], + ], + 'recognizedLanguages': [ + { + 'languageCode': 'ef', + }, + { + 'languageCode': 'gh', + } + ], + 'elements': elements, + 'confidence': 0.3, + }, + { + 'text': 'how', + 'left': 8.0, + 'top': 7.0, + 'width': 4.0, + 'height': 5.0, + 'points': [ + [10.0, 9.0], + [12.0, 11.0], + ], + 'recognizedLanguages': [], + 'elements': [], + 'confidence': 0.4, + }, + ]; + + final List blocks = [ + { + 'text': 'friend', + 'left': 13.0, + 'top': 14.0, + 'width': 15.0, + 'height': 16.0, + 'points': [ + [17.0, 18.0], + [19.0, 20.0], + ], + 'recognizedLanguages': [ + { + 'languageCode': 'ij', + }, + { + 'languageCode': 'kl', + } + ], + 'lines': lines, + 'confidence': 0.5, + }, + { + 'text': 'hello', + 'left': 14.0, + 'top': 13.0, + 'width': 16.0, + 'height': 15.0, + 'points': [ + [18.0, 17.0], + [20.0, 19.0], + ], + 'recognizedLanguages': [], + 'lines': [], + 'confidence': 0.6, + }, + ]; + + final dynamic visionText = { + 'text': 'testext', + 'blocks': blocks, + }; + + returnValue = visionText; + }); + + group('$TextBlock', () { + test('processImage', () async { + final VisionText text = await recognizer.processImage(image); + + expect(text.blocks, hasLength(2)); + + TextBlock block = text.blocks[0]; + // TODO(jackson): Use const Rect when available in minimum Flutter SDK + // ignore: prefer_const_constructors + expect(block.boundingBox, Rect.fromLTWH(13.0, 14.0, 15.0, 16.0)); + expect(block.text, 'friend'); + expect(block.cornerPoints, const [ + Offset(17.0, 18.0), + Offset(19.0, 20.0), + ]); + expect(block.recognizedLanguages, hasLength(2)); + expect(block.recognizedLanguages[0].languageCode, 'ij'); + expect(block.recognizedLanguages[1].languageCode, 'kl'); + expect(block.confidence, 0.5); + + block = text.blocks[1]; // TODO(jackson): Use const Rect when available in minimum Flutter SDK // ignore: prefer_const_constructors expect(block.boundingBox, Rect.fromLTWH(14.0, 13.0, 16.0, 15.0)); @@ -827,6 +1090,7 @@ void main() { final VisionText text = await recognizer.processImage(image); TextElement element = text.blocks[0].lines[0].elements[0]; + // TODO(jackson): Use const Rect when available in minimum Flutter SDK // ignore: prefer_const_constructors expect(element.boundingBox, Rect.fromLTWH(1.0, 2.0, 3.0, 4.0)); expect(element.text, 'hello'); @@ -865,7 +1129,9 @@ void main() { 'path': 'empty', 'bytes': null, 'metadata': null, - 'options': {}, + 'options': { + 'modelType': 'cloud', + }, }, ), ]); From 319adc2eb91e26b1de34bf07d8e626f98df333bd Mon Sep 17 00:00:00 2001 From: Ianko Leite Date: Thu, 18 Jul 2019 16:53:05 -0400 Subject: [PATCH 77/94] [video_player] Fix race condition on disposing the VideoController. (#1562) --- packages/video_player/CHANGELOG.md | 4 ++++ packages/video_player/lib/video_player.dart | 4 ++++ packages/video_player/pubspec.yaml | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/video_player/CHANGELOG.md b/packages/video_player/CHANGELOG.md index 46f766ace4e1..d96ebfecb839 100644 --- a/packages/video_player/CHANGELOG.md +++ b/packages/video_player/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.1+5 + +* Fix race condition while disposing the VideoController. + ## 0.10.1+4 * Fixed syntax error in README.md. diff --git a/packages/video_player/lib/video_player.dart b/packages/video_player/lib/video_player.dart index fb42096d9709..3990f53f0d1d 100644 --- a/packages/video_player/lib/video_player.dart +++ b/packages/video_player/lib/video_player.dart @@ -223,6 +223,10 @@ class VideoPlayerController extends ValueNotifier { } void eventListener(dynamic event) { + if (_isDisposed) { + return; + } + final Map map = event; switch (map['event']) { case 'initialized': diff --git a/packages/video_player/pubspec.yaml b/packages/video_player/pubspec.yaml index dd5d0b5a75f5..bbb2dcda02ef 100644 --- a/packages/video_player/pubspec.yaml +++ b/packages/video_player/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player description: Flutter plugin for displaying inline video with other Flutter widgets on Android and iOS. author: Flutter Team -version: 0.10.1+4 +version: 0.10.1+5 homepage: https://github.com/flutter/plugins/tree/master/packages/video_player flutter: From ddaa3054794c7dfd79e3ee5d989ea29e68602fb5 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Fri, 19 Jul 2019 16:12:30 -0700 Subject: [PATCH 78/94] [camera] Implement initialize and add documentation (#1838) --- .../camera/lib/new/src/camera_controller.dart | 85 ++++++++++++++++--- .../lib/new/src/common/camera_interface.dart | 7 +- packages/camera/test/camera_test.dart | 64 ++++++++++++++ 3 files changed, 142 insertions(+), 14 deletions(-) diff --git a/packages/camera/lib/new/src/camera_controller.dart b/packages/camera/lib/new/src/camera_controller.dart index 4ae6b472a3a7..4296f39d7002 100644 --- a/packages/camera/lib/new/src/camera_controller.dart +++ b/packages/camera/lib/new/src/camera_controller.dart @@ -12,14 +12,21 @@ import 'common/camera_interface.dart'; /// /// Use [CameraController.availableCameras] to get a list of available cameras. /// -/// This class is used as a simple interface that works for Android and iOS. +/// This class is used as a simple interface to control a camera on Android or +/// iOS. /// -/// When using iOS, simultaneously calling [start] on two [CameraController]s -/// will throw a [PlatformException]. +/// Only one instance of [CameraController] can be active at a time. If you call +/// [initialize] on a [CameraController] while another is active, the old +/// controller will be disposed before initializing the new controller. /// -/// When using Android, simultaneously calling [start] on two -/// [CameraController]s may throw a [PlatformException] depending on the -/// hardware resources of the device. +/// Example using [CameraController]: +/// +/// ```dart +/// final List cameras = async CameraController.availableCameras(); +/// final CameraController controller = CameraController(description: cameras[0]); +/// controller.initialize(); +/// controller.start(); +/// ``` class CameraController { /// Default constructor. /// @@ -28,7 +35,6 @@ class CameraController { /// /// This will choose the best [CameraConfigurator] for the current device. factory CameraController({@required CameraDescription description}) { - assert(description != null); return CameraController._( description: description, configurator: _createDefaultConfigurator(description), @@ -59,6 +65,14 @@ class CameraController { ); } + static const String _isNotInitializedMessage = 'Initialize was not called.'; + static const String _isDisposedMessage = 'This controller has been disposed.'; + + // Keep only one active instance of CameraController. + static CameraController _instance; + + bool _isDisposed = false; + /// Details for the camera this controller accesses. final CameraDescription description; @@ -68,6 +82,8 @@ class CameraController { /// Api used by the [configurator]. final CameraApi api; + bool get isDisposed => _isDisposed; + /// Retrieves a list of available cameras for the current device. /// /// This will choose the best [CameraAPI] for the current device. @@ -75,14 +91,54 @@ class CameraController { throw UnimplementedError('$defaultTargetPlatform not supported'); } - /// Begins the flow of data between the inputs and outputs connected the camera instance. - Future start() => configurator.start(); + /// Initializes the camera on the device. + /// + /// You must call [dispose] when you are done using the camera, otherwise it + /// will remain locked and be unavailable to other applications. + /// + /// Only one instance of [CameraController] can be active at a time. If you + /// call [initialize] on a [CameraController] while another is active, the old + /// controller will be disposed before initializing the new controller. + Future initialize() { + if (_instance == this) { + return Future.value(); + } + + final Completer completer = Completer(); + + if (_instance != null) { + _instance + .dispose() + .then((_) => configurator.initialize()) + .then((_) => completer.complete()); + } + _instance = this; + + return completer.future; + } + + /// Begins the flow of data between the inputs and outputs connected to the camera instance. + Future start() { + assert(!_isDisposed, _isDisposedMessage); + assert(_instance != this, _isNotInitializedMessage); + + return configurator.start(); + } + + /// Stops the flow of data between the inputs and outputs connected to the camera instance. + Future stop() { + assert(!_isDisposed, _isDisposedMessage); + assert(_instance != this, _isNotInitializedMessage); - /// Stops the flow of data between the inputs and outputs connected the camera instance. - Future stop() => configurator.stop(); + return configurator.stop(); + } /// Deallocate all resources and disables further use of the controller. - Future dispose() => configurator.dispose(); + Future dispose() { + _instance = null; + _isDisposed = true; + return configurator.dispose(); + } static CameraConfigurator _createDefaultConfigurator( CameraDescription description, @@ -101,10 +157,15 @@ class CameraController { } static CameraApi _getCameraApi(CameraDescription description) { + return CameraApi.iOS; + + // TODO(bparrishMines): Uncomment this when platform specific code is added. + /* throw ArgumentError.value( description.runtimeType, 'description.runtimeType', 'Failed to get $CameraApi from', ); + */ } } diff --git a/packages/camera/lib/new/src/common/camera_interface.dart b/packages/camera/lib/new/src/common/camera_interface.dart index 8b5ca9d4e4a3..99ead09550c9 100644 --- a/packages/camera/lib/new/src/common/camera_interface.dart +++ b/packages/camera/lib/new/src/common/camera_interface.dart @@ -38,12 +38,15 @@ abstract class CameraConfigurator { /// You must call [addPreviewTexture] first or this will only return null. int get previewTextureId; - /// Begins the flow of data between the inputs and outputs connected the camera instance. + /// Initializes the camera on the device. + Future initialize(); + + /// Begins the flow of data between the inputs and outputs connected to the camera instance. /// /// This will start updating the texture with id: [previewTextureId]. Future start(); - /// Stops the flow of data between the inputs and outputs connected the camera instance. + /// Stops the flow of data between the inputs and outputs connected to the camera instance. Future stop(); /// Dispose all resources and disables further use of this configurator. diff --git a/packages/camera/test/camera_test.dart b/packages/camera/test/camera_test.dart index ae6c38f9b1f9..39b08ecd8020 100644 --- a/packages/camera/test/camera_test.dart +++ b/packages/camera/test/camera_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:camera/new/camera.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:camera/new/src/camera_testing.dart'; @@ -33,6 +34,41 @@ void main() { CameraTesting.nextHandle = 0; }); + group('$CameraController', () { + test('Initializing a second controller closes the first', () { + final MockCameraDescription description = MockCameraDescription(); + final MockCameraConfigurator configurator = MockCameraConfigurator(); + + final CameraController controller1 = + CameraController.customConfigurator( + description: description, + configurator: configurator, + ); + + controller1.initialize(); + + final CameraController controller2 = + CameraController.customConfigurator( + description: description, + configurator: configurator, + ); + + controller2.initialize(); + + expect( + () => controller1.start(), + throwsA(isInstanceOf()), + ); + + expect( + () => controller1.stop(), + throwsA(isInstanceOf()), + ); + + expect(controller1.isDisposed, isTrue); + }); + }); + group('$NativeTexture', () { test('allocate', () async { final NativeTexture texture = await NativeTexture.allocate(); @@ -48,3 +84,31 @@ void main() { }); }); } + +class MockCameraDescription extends CameraDescription { + @override + LensDirection get direction => LensDirection.unknown; + + @override + String get name => 'none'; +} + +class MockCameraConfigurator extends CameraConfigurator { + @override + Future addPreviewTexture() => Future.value(7); + + @override + Future dispose() => Future.value(); + + @override + Future initialize() => Future.value(); + + @override + int get previewTextureId => 7; + + @override + Future start() => Future.value(); + + @override + Future stop() => Future.value(); +} From e8294e4dea4b61df7f507d8af5701cf7c2cbff74 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sat, 20 Jul 2019 09:36:05 -0700 Subject: [PATCH 79/94] Fix Android compile warning (#1883) --- packages/firebase_core/CHANGELOG.md | 4 ++++ .../io/flutter/plugins/firebase/core/FirebaseCorePlugin.java | 4 ++-- packages/firebase_core/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/firebase_core/CHANGELOG.md b/packages/firebase_core/CHANGELOG.md index 0f573c5afad3..aaae8721e850 100644 --- a/packages/firebase_core/CHANGELOG.md +++ b/packages/firebase_core/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+7 + +* Fix Android compilation warning. + ## 0.4.0+6 * Automatically use version from pubspec.yaml when reporting usage to Firebase. diff --git a/packages/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FirebaseCorePlugin.java b/packages/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FirebaseCorePlugin.java index 3d60df1bfeb3..ef82fbf92573 100644 --- a/packages/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FirebaseCorePlugin.java +++ b/packages/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FirebaseCorePlugin.java @@ -32,7 +32,7 @@ private FirebaseCorePlugin(Context context) { this.context = context; } - private Map asMap(FirebaseApp app) { + private Map asMap(FirebaseApp app) { Map appMap = new HashMap<>(); appMap.put("name", app.getName()); FirebaseOptions options = app.getOptions(); @@ -80,7 +80,7 @@ public void onMethodCall(MethodCall call, final Result result) { } case "FirebaseApp#appNamed": { - String name = (String) call.arguments(); + String name = call.arguments(); try { FirebaseApp app = FirebaseApp.getInstance(name); result.success(asMap(app)); diff --git a/packages/firebase_core/pubspec.yaml b/packages/firebase_core/pubspec.yaml index 36972e90ba26..db6da67197af 100644 --- a/packages/firebase_core/pubspec.yaml +++ b/packages/firebase_core/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Core, enabling connecting to multiple Firebase apps. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_core -version: 0.4.0+6 +version: 0.4.0+7 flutter: plugin: From d20a66ebbeb4278b7cd45934f3c0ba15230cb051 Mon Sep 17 00:00:00 2001 From: creativecreatorormaybenot <19204050+creativecreatorormaybenot@users.noreply.github.com> Date: Sun, 21 Jul 2019 03:35:04 +0000 Subject: [PATCH 80/94] [share] Specify explicit type for invokeMethod & const for Rect (#1881) --- packages/share/CHANGELOG.md | 6 ++++++ packages/share/lib/share.dart | 5 +---- packages/share/pubspec.yaml | 4 ++-- packages/share/test/share_test.dart | 15 ++++----------- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/packages/share/CHANGELOG.md b/packages/share/CHANGELOG.md index 38bd86675e98..b2567e4e096c 100644 --- a/packages/share/CHANGELOG.md +++ b/packages/share/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.6.2+1 + +* Specify explicit type for `invokeMethod`. +* Use `const` for `Rect`. +* Updated minimum Flutter SDK to 1.6.0. + ## 0.6.2 * Add optional subject to fill email subject in case user selects email app. diff --git a/packages/share/lib/share.dart b/packages/share/lib/share.dart index 7bbaae827fec..3707a2f7c704 100644 --- a/packages/share/lib/share.dart +++ b/packages/share/lib/share.dart @@ -49,9 +49,6 @@ class Share { params['originHeight'] = sharePositionOrigin.height; } - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - return channel.invokeMethod('share', params); + return channel.invokeMethod('share', params); } } diff --git a/packages/share/pubspec.yaml b/packages/share/pubspec.yaml index ba36708478df..a051b4480eaa 100644 --- a/packages/share/pubspec.yaml +++ b/packages/share/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for sharing content via the platform share UI, using the ACTION_SEND intent on Android and UIActivityViewController on iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/share -version: 0.6.2 +version: 0.6.2+1 flutter: plugin: @@ -24,4 +24,4 @@ dev_dependencies: environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" - flutter: ">=0.1.4 <2.0.0" + flutter: ">=1.6.0 <2.0.0" diff --git a/packages/share/test/share_test.dart b/packages/share/test/share_test.dart index b7ca6a60c1d7..275c052d7264 100644 --- a/packages/share/test/share_test.dart +++ b/packages/share/test/share_test.dart @@ -17,10 +17,8 @@ void main() { mockChannel = MockMethodChannel(); // Re-pipe to mockito for easier verifies. Share.channel.setMockMethodCallHandler((MethodCall call) async { - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - mockChannel.invokeMethod(call.method, call.arguments); + // The explicit type can be void as the only method call has a return type of void. + mockChannel.invokeMethod(call.method, call.arguments); }); }); @@ -44,14 +42,9 @@ void main() { await Share.share( 'some text to share', subject: 'some subject to share', - // TODO(jackson): Use const Rect when available in minimum Flutter SDK - // ignore: prefer_const_constructors - sharePositionOrigin: Rect.fromLTWH(1.0, 2.0, 3.0, 4.0), + sharePositionOrigin: const Rect.fromLTWH(1.0, 2.0, 3.0, 4.0), ); - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - verify(mockChannel.invokeMethod('share', { + verify(mockChannel.invokeMethod('share', { 'text': 'some text to share', 'subject': 'some subject to share', 'originX': 1.0, From 88992d9a83f99a4674df0d0bf8faa9bd4d72b6a0 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 22 Jul 2019 08:28:14 -0700 Subject: [PATCH 81/94] Recommend 4.3.0 version of google-services in READMEs/examples (#1885) --- packages/android_alarm_manager/CHANGELOG.md | 4 ++++ packages/android_alarm_manager/example/android/build.gradle | 1 - packages/android_alarm_manager/pubspec.yaml | 2 +- packages/cloud_firestore/CHANGELOG.md | 4 ++++ packages/cloud_firestore/example/android/build.gradle | 2 +- packages/cloud_firestore/pubspec.yaml | 2 +- packages/cloud_functions/CHANGELOG.md | 4 ++++ packages/cloud_functions/example/android/build.gradle | 2 +- packages/cloud_functions/pubspec.yaml | 2 +- packages/firebase_admob/CHANGELOG.md | 4 ++++ packages/firebase_admob/example/android/build.gradle | 2 +- packages/firebase_admob/pubspec.yaml | 2 +- packages/firebase_analytics/CHANGELOG.md | 4 ++++ packages/firebase_analytics/example/android/build.gradle | 2 +- packages/firebase_analytics/pubspec.yaml | 2 +- packages/firebase_auth/CHANGELOG.md | 4 ++++ packages/firebase_auth/README.md | 2 +- packages/firebase_auth/example/android/build.gradle | 2 +- packages/firebase_auth/pubspec.yaml | 2 +- packages/firebase_core/CHANGELOG.md | 4 ++++ packages/firebase_core/pubspec.yaml | 2 +- packages/firebase_crashlytics/CHANGELOG.md | 4 ++++ packages/firebase_crashlytics/README.md | 2 +- packages/firebase_crashlytics/example/android/build.gradle | 2 +- packages/firebase_crashlytics/pubspec.yaml | 2 +- packages/firebase_database/CHANGELOG.md | 4 ++++ packages/firebase_database/example/android/build.gradle | 2 +- packages/firebase_database/pubspec.yaml | 2 +- packages/firebase_dynamic_links/CHANGELOG.md | 4 ++++ packages/firebase_dynamic_links/example/android/build.gradle | 2 +- packages/firebase_dynamic_links/pubspec.yaml | 2 +- packages/firebase_in_app_messaging/CHANGELOG.md | 4 ++++ packages/firebase_in_app_messaging/README.md | 2 +- .../firebase_in_app_messaging/example/android/build.gradle | 2 +- packages/firebase_in_app_messaging/pubspec.yaml | 2 +- packages/firebase_messaging/CHANGELOG.md | 4 ++++ packages/firebase_messaging/README.md | 2 +- packages/firebase_messaging/example/android/build.gradle | 2 +- packages/firebase_messaging/example/pubspec.yaml | 1 + packages/firebase_messaging/pubspec.yaml | 3 +-- packages/firebase_ml_vision/CHANGELOG.md | 4 ++++ packages/firebase_ml_vision/example/android/build.gradle | 2 +- packages/firebase_ml_vision/pubspec.yaml | 2 +- packages/firebase_performance/CHANGELOG.md | 4 ++++ packages/firebase_performance/example/android/build.gradle | 2 +- packages/firebase_performance/pubspec.yaml | 2 +- packages/firebase_remote_config/CHANGELOG.md | 4 ++++ packages/firebase_remote_config/README.md | 2 +- packages/firebase_remote_config/example/android/build.gradle | 2 +- packages/firebase_remote_config/pubspec.yaml | 2 +- packages/firebase_storage/CHANGELOG.md | 4 ++++ packages/firebase_storage/example/android/build.gradle | 2 +- packages/firebase_storage/pubspec.yaml | 2 +- 53 files changed, 100 insertions(+), 37 deletions(-) diff --git a/packages/android_alarm_manager/CHANGELOG.md b/packages/android_alarm_manager/CHANGELOG.md index 31f02e161ab8..1b58c6a394eb 100644 --- a/packages/android_alarm_manager/CHANGELOG.md +++ b/packages/android_alarm_manager/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.1+8 + +* Remove dependency on google-services in the Android example. + ## 0.4.1+7 * Fix possible crash on Android devices with APIs below 19. diff --git a/packages/android_alarm_manager/example/android/build.gradle b/packages/android_alarm_manager/example/android/build.gradle index 6ca85f908e0b..541636cc492a 100644 --- a/packages/android_alarm_manager/example/android/build.gradle +++ b/packages/android_alarm_manager/example/android/build.gradle @@ -6,7 +6,6 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' } } diff --git a/packages/android_alarm_manager/pubspec.yaml b/packages/android_alarm_manager/pubspec.yaml index c142c5737c0a..a59e7babee77 100644 --- a/packages/android_alarm_manager/pubspec.yaml +++ b/packages/android_alarm_manager/pubspec.yaml @@ -1,7 +1,7 @@ name: android_alarm_manager description: Flutter plugin for accessing the Android AlarmManager service, and running Dart code in the background when alarms fire. -version: 0.4.1+7 +version: 0.4.1+8 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/android_alarm_manager diff --git a/packages/cloud_firestore/CHANGELOG.md b/packages/cloud_firestore/CHANGELOG.md index b078cfd0a41d..f3a81406954c 100644 --- a/packages/cloud_firestore/CHANGELOG.md +++ b/packages/cloud_firestore/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.12.7+1 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.12.7 * Methods of `Transaction` no longer require `await`. diff --git a/packages/cloud_firestore/example/android/build.gradle b/packages/cloud_firestore/example/android/build.gradle index a144a1922d98..695de848ec30 100755 --- a/packages/cloud_firestore/example/android/build.gradle +++ b/packages/cloud_firestore/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/cloud_firestore/pubspec.yaml b/packages/cloud_firestore/pubspec.yaml index b488e30ccff8..08348e413ea7 100755 --- a/packages/cloud_firestore/pubspec.yaml +++ b/packages/cloud_firestore/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Cloud Firestore, a cloud-hosted, noSQL database live synchronization and offline support on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/cloud_firestore -version: 0.12.7 +version: 0.12.7+1 flutter: plugin: diff --git a/packages/cloud_functions/CHANGELOG.md b/packages/cloud_functions/CHANGELOG.md index 3e8796b82d1a..e4661c25bd6a 100644 --- a/packages/cloud_functions/CHANGELOG.md +++ b/packages/cloud_functions/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+3 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.4.0+2 * Automatically use version from pubspec.yaml when reporting usage to Firebase. diff --git a/packages/cloud_functions/example/android/build.gradle b/packages/cloud_functions/example/android/build.gradle index 6ca85f908e0b..359119307d55 100644 --- a/packages/cloud_functions/example/android/build.gradle +++ b/packages/cloud_functions/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/cloud_functions/pubspec.yaml b/packages/cloud_functions/pubspec.yaml index dd6d6e0927c4..20034a7acce9 100644 --- a/packages/cloud_functions/pubspec.yaml +++ b/packages/cloud_functions/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_functions description: Flutter plugin for Cloud Functions. -version: 0.4.0+2 +version: 0.4.0+3 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/cloud_functions diff --git a/packages/firebase_admob/CHANGELOG.md b/packages/firebase_admob/CHANGELOG.md index 733b453c0e87..03ca09e32284 100644 --- a/packages/firebase_admob/CHANGELOG.md +++ b/packages/firebase_admob/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.0+3 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.9.0+2 * On Android, no longer crashes when registering the plugin if no activity is available. diff --git a/packages/firebase_admob/example/android/build.gradle b/packages/firebase_admob/example/android/build.gradle index a144a1922d98..695de848ec30 100644 --- a/packages/firebase_admob/example/android/build.gradle +++ b/packages/firebase_admob/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_admob/pubspec.yaml b/packages/firebase_admob/pubspec.yaml index 9aea18eb3983..717d5c759ed3 100644 --- a/packages/firebase_admob/pubspec.yaml +++ b/packages/firebase_admob/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase AdMob, supporting banner, interstitial (full-screen), and rewarded video ads author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_admob -version: 0.9.0+2 +version: 0.9.0+3 flutter: plugin: diff --git a/packages/firebase_analytics/CHANGELOG.md b/packages/firebase_analytics/CHANGELOG.md index 5d980af9d53e..320289c2d858 100644 --- a/packages/firebase_analytics/CHANGELOG.md +++ b/packages/firebase_analytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.0.2 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 4.0.1 * Refactor unit tests to use `setMockMethodCallHandler`. diff --git a/packages/firebase_analytics/example/android/build.gradle b/packages/firebase_analytics/example/android/build.gradle index a144a1922d98..695de848ec30 100755 --- a/packages/firebase_analytics/example/android/build.gradle +++ b/packages/firebase_analytics/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_analytics/pubspec.yaml b/packages/firebase_analytics/pubspec.yaml index d1ce5ad21484..324fac8ac189 100755 --- a/packages/firebase_analytics/pubspec.yaml +++ b/packages/firebase_analytics/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Google Analytics for Firebase, an app measuremen solution that provides insight on app usage and user engagement on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_analytics -version: 4.0.1 +version: 4.0.2 flutter: plugin: diff --git a/packages/firebase_auth/CHANGELOG.md b/packages/firebase_auth/CHANGELOG.md index 1839016e5267..1728a08e358f 100644 --- a/packages/firebase_auth/CHANGELOG.md +++ b/packages/firebase_auth/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.11.1+12 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.11.1+11 * On iOS, `getIdToken()` now uses the `refresh` parameter instead of always using `true`. diff --git a/packages/firebase_auth/README.md b/packages/firebase_auth/README.md index 00c9136e7e56..c7d2e62914af 100755 --- a/packages/firebase_auth/README.md +++ b/packages/firebase_auth/README.md @@ -27,7 +27,7 @@ dependencies { // Example existing classpath classpath 'com.android.tools.build:gradle:3.2.1' // Add the google services classpath - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } ``` diff --git a/packages/firebase_auth/example/android/build.gradle b/packages/firebase_auth/example/android/build.gradle index 4e7865bfca32..47c36fc2c29c 100755 --- a/packages/firebase_auth/example/android/build.gradle +++ b/packages/firebase_auth/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.1' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_auth/pubspec.yaml b/packages/firebase_auth/pubspec.yaml index 18bca1002fb4..238c1d38128d 100755 --- a/packages/firebase_auth/pubspec.yaml +++ b/packages/firebase_auth/pubspec.yaml @@ -4,7 +4,7 @@ description: Flutter plugin for Firebase Auth, enabling Android and iOS like Google, Facebook and Twitter. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_auth -version: "0.11.1+11" +version: "0.11.1+12" flutter: plugin: diff --git a/packages/firebase_core/CHANGELOG.md b/packages/firebase_core/CHANGELOG.md index aaae8721e850..04845d383e94 100644 --- a/packages/firebase_core/CHANGELOG.md +++ b/packages/firebase_core/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+8 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.4.0+7 * Fix Android compilation warning. diff --git a/packages/firebase_core/pubspec.yaml b/packages/firebase_core/pubspec.yaml index db6da67197af..aa8f37e26ba1 100644 --- a/packages/firebase_core/pubspec.yaml +++ b/packages/firebase_core/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Core, enabling connecting to multiple Firebase apps. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_core -version: 0.4.0+7 +version: 0.4.0+8 flutter: plugin: diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index f0feb192864b..fb9c747d0023 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.4+12 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.0.4+11 * Fixed an issue where `Crashlytics#getStackTraceElements` didn't handle functions without classes. diff --git a/packages/firebase_crashlytics/README.md b/packages/firebase_crashlytics/README.md index 784a4330e003..1876b3f10ea1 100644 --- a/packages/firebase_crashlytics/README.md +++ b/packages/firebase_crashlytics/README.md @@ -35,7 +35,7 @@ dependencies { // Example existing classpath classpath 'com.android.tools.build:gradle:3.2.1' // Add the google services classpath - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' // Add fabric classpath classpath 'io.fabric.tools:gradle:1.26.1' } diff --git a/packages/firebase_crashlytics/example/android/build.gradle b/packages/firebase_crashlytics/example/android/build.gradle index 3b6a3b564da7..faeab902b866 100644 --- a/packages/firebase_crashlytics/example/android/build.gradle +++ b/packages/firebase_crashlytics/example/android/build.gradle @@ -9,7 +9,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.2' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' classpath 'io.fabric.tools:gradle:1.26.1' } } diff --git a/packages/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/pubspec.yaml index 4ca07da6f6c0..04b106c57540 100644 --- a/packages/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_crashlytics description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. -version: 0.0.4+11 +version: 0.0.4+12 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_crashlytics diff --git a/packages/firebase_database/CHANGELOG.md b/packages/firebase_database/CHANGELOG.md index 0e032e4dc2d3..eedce557e0f1 100644 --- a/packages/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.5 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 3.0.4 * Updated transactions implementation on Android for compatibility with diff --git a/packages/firebase_database/example/android/build.gradle b/packages/firebase_database/example/android/build.gradle index 6ca85f908e0b..359119307d55 100755 --- a/packages/firebase_database/example/android/build.gradle +++ b/packages/firebase_database/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_database/pubspec.yaml b/packages/firebase_database/pubspec.yaml index d91420632811..19c3a4e88e76 100755 --- a/packages/firebase_database/pubspec.yaml +++ b/packages/firebase_database/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database with realtime data syncing across Android and iOS clients, and offline access. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_database -version: 3.0.4 +version: 3.0.5 flutter: plugin: diff --git a/packages/firebase_dynamic_links/CHANGELOG.md b/packages/firebase_dynamic_links/CHANGELOG.md index 64b41dc9ee3a..e6f491de59b0 100644 --- a/packages/firebase_dynamic_links/CHANGELOG.md +++ b/packages/firebase_dynamic_links/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+6 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.4.0+5 * Fix the bug below properly by allowing the activity to be null (but still registering the plugin). If activity is null, we don't get a latestIntent, instead we expect the intent listener to grab it. diff --git a/packages/firebase_dynamic_links/example/android/build.gradle b/packages/firebase_dynamic_links/example/android/build.gradle index 4e919286ae32..3759d2af578f 100644 --- a/packages/firebase_dynamic_links/example/android/build.gradle +++ b/packages/firebase_dynamic_links/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_dynamic_links/pubspec.yaml b/packages/firebase_dynamic_links/pubspec.yaml index 587bcbcfcbf3..69cfe7f4dc97 100644 --- a/packages/firebase_dynamic_links/pubspec.yaml +++ b/packages/firebase_dynamic_links/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_dynamic_links description: Flutter plugin for Google Dynamic Links for Firebase, an app solution for creating and handling links across multiple platforms. -version: 0.4.0+5 +version: 0.4.0+6 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_dynamic_links diff --git a/packages/firebase_in_app_messaging/CHANGELOG.md b/packages/firebase_in_app_messaging/CHANGELOG.md index d0bd041d0ff6..90e5ad1611f2 100644 --- a/packages/firebase_in_app_messaging/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.1+1 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.0.1 * Initial release. diff --git a/packages/firebase_in_app_messaging/README.md b/packages/firebase_in_app_messaging/README.md index cff93544a80e..9e008fac9220 100644 --- a/packages/firebase_in_app_messaging/README.md +++ b/packages/firebase_in_app_messaging/README.md @@ -21,7 +21,7 @@ dependencies { // Example existing classpath classpath 'com.android.tools.build:gradle:3.3.0' // Add the google services classpath - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } ``` diff --git a/packages/firebase_in_app_messaging/example/android/build.gradle b/packages/firebase_in_app_messaging/example/android/build.gradle index aade91d06b62..647e14dce1a0 100644 --- a/packages/firebase_in_app_messaging/example/android/build.gradle +++ b/packages/firebase_in_app_messaging/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_in_app_messaging/pubspec.yaml b/packages/firebase_in_app_messaging/pubspec.yaml index a965545f93bb..6f47318d4d2f 100644 --- a/packages/firebase_in_app_messaging/pubspec.yaml +++ b/packages/firebase_in_app_messaging/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_in_app_messaging description: Flutter plugin for Firebase In-App Messaging. -version: 0.0.1 +version: 0.0.1+1 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_in_app_messaging diff --git a/packages/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/CHANGELOG.md index d63ae0f801f2..76fe5f3c10c0 100644 --- a/packages/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.1.3 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 5.1.2 * Updates to README and example with explanations of differences in data format. diff --git a/packages/firebase_messaging/README.md b/packages/firebase_messaging/README.md index 51f78851efc3..fced940d7b7f 100644 --- a/packages/firebase_messaging/README.md +++ b/packages/firebase_messaging/README.md @@ -29,7 +29,7 @@ dependencies { // Example existing classpath classpath 'com.android.tools.build:gradle:3.2.1' // Add the google services classpath - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } ``` 3. Add the apply plugin to the `[project]/android/app/build.gradle` file. diff --git a/packages/firebase_messaging/example/android/build.gradle b/packages/firebase_messaging/example/android/build.gradle index 6ca85f908e0b..359119307d55 100644 --- a/packages/firebase_messaging/example/android/build.gradle +++ b/packages/firebase_messaging/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/example/pubspec.yaml index 95b80ed7be0d..f5b1516d82d6 100644 --- a/packages/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/example/pubspec.yaml @@ -2,6 +2,7 @@ name: firebase_messaging_example description: Demonstrates how to use the firebase_messaging plugin. dependencies: + firebase_analytics: any flutter: sdk: flutter firebase_messaging: diff --git a/packages/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/pubspec.yaml index 20efc36817d9..cdfa9b11d659 100644 --- a/packages/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/pubspec.yaml @@ -3,8 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_messaging - -version: 5.1.2 +version: 5.1.3 flutter: plugin: diff --git a/packages/firebase_ml_vision/CHANGELOG.md b/packages/firebase_ml_vision/CHANGELOG.md index f25d393d393f..10cbf8ea279f 100644 --- a/packages/firebase_ml_vision/CHANGELOG.md +++ b/packages/firebase_ml_vision/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.1+1 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.9.1 * Add support for cloud text recognizer. diff --git a/packages/firebase_ml_vision/example/android/build.gradle b/packages/firebase_ml_vision/example/android/build.gradle index 4e919286ae32..3759d2af578f 100644 --- a/packages/firebase_ml_vision/example/android/build.gradle +++ b/packages/firebase_ml_vision/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_ml_vision/pubspec.yaml b/packages/firebase_ml_vision/pubspec.yaml index c2138b1866d0..abc6566e8e8f 100644 --- a/packages/firebase_ml_vision/pubspec.yaml +++ b/packages/firebase_ml_vision/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_ml_vision description: Flutter plugin for Firebase machine learning vision services. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_ml_vision -version: 0.9.1 +version: 0.9.1+1 dependencies: flutter: diff --git a/packages/firebase_performance/CHANGELOG.md b/packages/firebase_performance/CHANGELOG.md index f906a5d89c81..64e95feed5a8 100644 --- a/packages/firebase_performance/CHANGELOG.md +++ b/packages/firebase_performance/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.0+4 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.3.0+3 * Fix bug that caused `invokeMethod` to fail with Dart code obfuscation diff --git a/packages/firebase_performance/example/android/build.gradle b/packages/firebase_performance/example/android/build.gradle index a144a1922d98..695de848ec30 100644 --- a/packages/firebase_performance/example/android/build.gradle +++ b/packages/firebase_performance/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_performance/pubspec.yaml b/packages/firebase_performance/pubspec.yaml index 01ab9f345c24..f864e84745b7 100644 --- a/packages/firebase_performance/pubspec.yaml +++ b/packages/firebase_performance/pubspec.yaml @@ -4,7 +4,7 @@ description: Flutter plugin for Google Performance Monitoring for Firebase, an a iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_performance -version: 0.3.0+3 +version: 0.3.0+4 dependencies: flutter: diff --git a/packages/firebase_remote_config/CHANGELOG.md b/packages/firebase_remote_config/CHANGELOG.md index 0ad8709eb290..bdc6d78948a5 100644 --- a/packages/firebase_remote_config/CHANGELOG.md +++ b/packages/firebase_remote_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0+5 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 0.2.0+4 * Fixed a bug where `RemoteConfigValue` could incorrectly report a remote `source` for default values. diff --git a/packages/firebase_remote_config/README.md b/packages/firebase_remote_config/README.md index 027c4ee0a91f..07f0c223d90b 100644 --- a/packages/firebase_remote_config/README.md +++ b/packages/firebase_remote_config/README.md @@ -23,7 +23,7 @@ dependencies { // Example existing classpath classpath 'com.android.tools.build:gradle:3.2.1' // Add the google services classpath - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } ``` diff --git a/packages/firebase_remote_config/example/android/build.gradle b/packages/firebase_remote_config/example/android/build.gradle index 6ca85f908e0b..359119307d55 100644 --- a/packages/firebase_remote_config/example/android/build.gradle +++ b/packages/firebase_remote_config/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_remote_config/pubspec.yaml b/packages/firebase_remote_config/pubspec.yaml index 64ec8715cdf8..5875219ecc3d 100644 --- a/packages/firebase_remote_config/pubspec.yaml +++ b/packages/firebase_remote_config/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Remote Config. Update your application re-releasing. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_remote_config -version: 0.2.0+4 +version: 0.2.0+5 dependencies: flutter: diff --git a/packages/firebase_storage/CHANGELOG.md b/packages/firebase_storage/CHANGELOG.md index a9a946249e2b..d9fbd1d1fe6c 100644 --- a/packages/firebase_storage/CHANGELOG.md +++ b/packages/firebase_storage/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.4 + +* Update google-services Android gradle plugin to 4.3.0 in documentation and examples. + ## 3.0.3 * Fix inconsistency of `getPath`, on Android the path returned started with a `/` but on iOS it did not diff --git a/packages/firebase_storage/example/android/build.gradle b/packages/firebase_storage/example/android/build.gradle index a144a1922d98..695de848ec30 100755 --- a/packages/firebase_storage/example/android/build.gradle +++ b/packages/firebase_storage/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.0' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.google.gms:google-services:4.3.0' } } diff --git a/packages/firebase_storage/pubspec.yaml b/packages/firebase_storage/pubspec.yaml index 6569799b60de..c479081607f1 100755 --- a/packages/firebase_storage/pubspec.yaml +++ b/packages/firebase_storage/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Storage, a powerful, simple, and cost-effective object storage service for Android and iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_storage -version: 3.0.3 +version: 3.0.4 flutter: plugin: From 2d9cd26f29c0c2482b37e89b4be6500cdb70dd0a Mon Sep 17 00:00:00 2001 From: Prakhar Srivastav Date: Mon, 22 Jul 2019 09:55:41 -0700 Subject: [PATCH 82/94] [firebase_in_app_messaging] add firebase_in_app_messaging in README (#1875) * add firebase_in_app_messaging in README * Update FlutterFire.md * Update CODEOWNERS --- CODEOWNERS | 1 + FlutterFire.md | 6 ++++++ README.md | 1 + 3 files changed, 8 insertions(+) diff --git a/CODEOWNERS b/CODEOWNERS index a5c22c9beb25..802ffe484501 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -18,6 +18,7 @@ packages/firebase_core/* @collinjackson @kroikie packages/firebase_crashlytics/* @kroikie @collinjackson packages/firebase_database/* @collinjackson @kroikie packages/firebase_dynamic_links/* @bparrishMines +packages/firebase_in_app_messaging/* @collinjackson packages/firebase_messaging/* @collinjackson @kroikie packages/firebase_ml_vision/* @bparrishMines packages/firebase_performance/* @bparrishMines @collinjackson diff --git a/FlutterFire.md b/FlutterFire.md index aaff76251097..ae039e6062d1 100644 --- a/FlutterFire.md +++ b/FlutterFire.md @@ -23,6 +23,7 @@ The plugins are still under development, and some APIs might not be available ye | [firebase_crashlytics][crash_pub] | ![pub package][crash_badge] | [Firebase Crashlytics][crash_product] | [`packages/firebase_crashlytics`][crash_code] | | [firebase_database][database_pub] | ![pub package][database_badge] | [Firebase Realtime Database][database_product] | [`packages/firebase_database`][database_code] | | [firebase_dynamic_links][dynamic_links_pub] | ![pub package][dynamic_links_badge] | [Firebase Dynamic Links][dynamic_links_product] | [`packages/firebase_dynamic_links`][dynamic_links_code] | +| [in_app_messaging][in_app_messaging_pub] | ![pub package][in_app_messaging_badge] | [Firebase In-App Messaging][in_app_messaging_product] | [`packages/firebase_in_app_messaging`][in_app_messaging_code] | | [firebase_messaging][messaging_pub] | ![pub package][messaging_badge] | [Firebase Cloud Messaging][messaging_product] | [`packages/firebase_messaging`][messaging_code] | | [firebase_ml_vision][ml_vision_pub] | ![pub package][ml_vision_badge] | [Firebase ML Kit][ml_vision_product] | [`packages/firebase_ml_vision`][ml_vision_code] | | [firebase_performance][performance_pub] | ![pub package][performance_badge] | [Firebase Performance Monitoring][performance_product] | [`packages/firebase_performance`][performance_code] | @@ -74,6 +75,11 @@ The plugins are still under development, and some APIs might not be available ye [functions_code]: https://github.com/flutter/plugins/tree/master/packages/cloud_functions [functions_badge]: https://img.shields.io/pub/v/cloud_functions.svg +[in_app_messaging_pub]: https://pub.dartlang.org/packages/firebase_in_app_messaging +[in_app_messaging_product]: https://firebase.google.com/products/in-app-messaging/ +[in_app_messaging_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_in_app_messaging +[in_app_messaging_badge]: https://img.shields.io/pub/v/firebase_in_app_messaging.svg + [messaging_pub]: https://pub.dartlang.org/packages/firebase_messaging [messaging_product]: https://firebase.google.com/products/cloud-messaging/ [messaging_code]: https://github.com/flutter/plugins/tree/master/packages/firebase_messaging diff --git a/README.md b/README.md index 514814a19479..f6695a7658a6 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ These are the available plugins in this repository. | [firebase_crashlytics](./packages/firebase_crashlytics/) | [![pub package](https://img.shields.io/pub/v/firebase_crashlytics.svg)](https://pub.dev/packages/firebase_crashlytics) | | [firebase_database](./packages/firebase_database/) | [![pub package](https://img.shields.io/pub/v/firebase_database.svg)](https://pub.dev/packages/firebase_database) | | [firebase_dynamic_links](./packages/firebase_dynamic_links/) | [![pub package](https://img.shields.io/pub/v/firebase_dynamic_links.svg)](https://pub.dev/packages/firebase_dynamic_links) | +| [firebase_in_app_messaging](./packages/firebase_in_app_messaging/) | [![pub package](https://img.shields.io/pub/v/firebase_in_app_messaging.svg)](https://pub.dev/packages/firebase_in_app_messaging) | | [firebase_messaging](./packages/firebase_messaging/) | [![pub package](https://img.shields.io/pub/v/firebase_messaging.svg)](https://pub.dev/packages/firebase_messaging) | | [firebase_ml_vision](./packages/firebase_ml_vision/) | [![pub package](https://img.shields.io/pub/v/firebase_ml_vision.svg)](https://pub.dev/packages/firebase_ml_vision) | | [firebase_performance](./packages/firebase_performance/) | [![pub package](https://img.shields.io/pub/v/firebase_performance.svg)](https://pub.dev/packages/firebase_performance) | From 4528a65475d96b8c347fa52254b16ba38b9725ae Mon Sep 17 00:00:00 2001 From: Greg Moore Date: Mon, 22 Jul 2019 17:42:31 -0400 Subject: [PATCH 83/94] [camera] Fix camera memory leak on IOS (#1745) Needed to unregister the stream handler when disposing of the camera Per the flutter documentation, the stream handler should be unregistered using setStreamHandler with nil. https://api.flutter.dev/objcdoc/Classes/FlutterEventChannel.html#/c:objc(cs)FlutterEventChannel(im)setStreamHandler: --- packages/camera/CHANGELOG.md | 4 ++++ packages/camera/ios/Classes/CameraPlugin.m | 2 ++ packages/camera/pubspec.yaml | 4 ++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/camera/CHANGELOG.md b/packages/camera/CHANGELOG.md index c096a9a8ad54..2d09af5b8953 100644 --- a/packages/camera/CHANGELOG.md +++ b/packages/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.2+2 + +* Fix memory leak related to not unregistering stream handler in FlutterEventChannel when disposing camera. + ## 0.5.2+1 * Fix bug that prevented video recording with audio. diff --git a/packages/camera/ios/Classes/CameraPlugin.m b/packages/camera/ios/Classes/CameraPlugin.m index 7bbd82555127..4c001926ae25 100644 --- a/packages/camera/ios/Classes/CameraPlugin.m +++ b/packages/camera/ios/Classes/CameraPlugin.m @@ -456,6 +456,8 @@ - (CVPixelBufferRef)copyPixelBuffer { - (FlutterError *_Nullable)onCancelWithArguments:(id _Nullable)arguments { _eventSink = nil; + // need to unregister stream handler when disposing the camera + [_eventChannel setStreamHandler:nil]; return nil; } diff --git a/packages/camera/pubspec.yaml b/packages/camera/pubspec.yaml index 9aab9b96633a..a7e65c706ef1 100644 --- a/packages/camera/pubspec.yaml +++ b/packages/camera/pubspec.yaml @@ -2,8 +2,8 @@ name: camera description: A Flutter plugin for getting information about and controlling the camera on Android and iOS. Supports previewing the camera feed, capturing images, capturing video, and streaming image buffers to dart. -version: 0.5.2+1 -publish_to: none +version: 0.5.2+2 + authors: - Flutter Team - Luigi Agosti From f8ebf95ea02119a8dae04c965ea299e054f6782c Mon Sep 17 00:00:00 2001 From: Michael Klimushyn Date: Mon, 22 Jul 2019 17:12:20 -0700 Subject: [PATCH 84/94] [location_background] Ignore for CI (#1890) This pacakge should be removed entirely soon, so remove it from CI so we don't spend further time on analyzer failures. --- script/common.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/script/common.sh b/script/common.sh index c3183fac2432..749561c94381 100644 --- a/script/common.sh +++ b/script/common.sh @@ -24,11 +24,12 @@ function check_changed_packages() { fi # Filter out any packages that don't have a pubspec.yaml: they have probably - # been deleted in this PR. + # been deleted in this PR. Also filter out `location_background` since it + # should be removed soon. CHANGED_PACKAGES="" CHANGED_PACKAGE_LIST=() for package in "${packages[@]}"; do - if [[ -f "$REPO_DIR/packages/$package/pubspec.yaml" ]]; then + if [ -f "$REPO_DIR/packages/$package/pubspec.yaml" ] && [ $package != "location_background" ]; then CHANGED_PACKAGES="${CHANGED_PACKAGES},$package" CHANGED_PACKAGE_LIST=("${CHANGED_PACKAGE_LIST[@]}" "$package") fi From 6282877c11eeea357ed8f33797393dc7eb918cbf Mon Sep 17 00:00:00 2001 From: Pedro Massango Date: Tue, 23 Jul 2019 01:16:00 +0100 Subject: [PATCH 85/94] [android_intent] Added "action_location_source_settings" action to start Location Settings Activity (#1867) --- .../android_alarm_manager.iml | 19 -------- packages/android_intent/CHANGELOG.md | 4 ++ packages/android_intent/README.md | 2 + .../androidintent/AndroidIntentPlugin.java | 2 + packages/android_intent/android_intent.iml | 15 ------- packages/android_intent/example/lib/main.dart | 13 ++++++ packages/android_intent/pubspec.yaml | 2 +- packages/camera/camera.iml | 16 ------- packages/connectivity/connectivity.iml | 15 ------- packages/device_info/device_info.iml | 15 ------- packages/firebase_admob/firebase_admob.iml | 15 ------- packages/firebase_core/firebase_core.iml | 18 -------- .../firebase_dynamic_links.iml | 19 -------- .../firebase_messaging/firebase_messaging.iml | 44 ------------------- .../firebase_performance.iml | 19 -------- .../firebase_remote_config.iml | 19 -------- packages/in_app_purchase/in_app_purchase.iml | 19 -------- packages/local_auth/local_auth.iml | 15 ------- packages/package_info/package_info.iml | 15 ------- packages/quick_actions/quick_actions.iml | 15 ------- packages/video_player/video_player.iml | 16 ------- 21 files changed, 22 insertions(+), 295 deletions(-) delete mode 100644 packages/android_alarm_manager/android_alarm_manager.iml delete mode 100644 packages/android_intent/android_intent.iml delete mode 100644 packages/camera/camera.iml delete mode 100644 packages/connectivity/connectivity.iml delete mode 100644 packages/device_info/device_info.iml delete mode 100644 packages/firebase_admob/firebase_admob.iml delete mode 100644 packages/firebase_core/firebase_core.iml delete mode 100644 packages/firebase_dynamic_links/firebase_dynamic_links.iml delete mode 100644 packages/firebase_messaging/firebase_messaging.iml delete mode 100644 packages/firebase_performance/firebase_performance.iml delete mode 100644 packages/firebase_remote_config/firebase_remote_config.iml delete mode 100644 packages/in_app_purchase/in_app_purchase.iml delete mode 100644 packages/local_auth/local_auth.iml delete mode 100644 packages/package_info/package_info.iml delete mode 100644 packages/quick_actions/quick_actions.iml delete mode 100644 packages/video_player/video_player.iml diff --git a/packages/android_alarm_manager/android_alarm_manager.iml b/packages/android_alarm_manager/android_alarm_manager.iml deleted file mode 100644 index 4fe26707b4fb..000000000000 --- a/packages/android_alarm_manager/android_alarm_manager.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/packages/android_intent/CHANGELOG.md b/packages/android_intent/CHANGELOG.md index 3622c65a0130..ea1b8f85c626 100644 --- a/packages/android_intent/CHANGELOG.md +++ b/packages/android_intent/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.2 + +* Added "action_location_source_settings" action to start Location Settings Activity. + ## 0.3.1+1 * Fix Gradle version. diff --git a/packages/android_intent/README.md b/packages/android_intent/README.md index 37278707e4b1..5a9243e6914b 100644 --- a/packages/android_intent/README.md +++ b/packages/android_intent/README.md @@ -27,6 +27,8 @@ for it in the plugin and use an action constant to refer to it. For instance: `'action_view'` translates to `android.os.Intent.ACTION_VIEW` +`'action_location_source_settings'` translates to `android.settings.LOCATION_SOURCE_SETTINGS` + Feel free to add support for additional Android intents. The Dart values supported for the arguments parameter, and their corresponding diff --git a/packages/android_intent/android/src/main/java/io/flutter/plugins/androidintent/AndroidIntentPlugin.java b/packages/android_intent/android/src/main/java/io/flutter/plugins/androidintent/AndroidIntentPlugin.java index 87689362d973..9c924d6fa524 100644 --- a/packages/android_intent/android/src/main/java/io/flutter/plugins/androidintent/AndroidIntentPlugin.java +++ b/packages/android_intent/android/src/main/java/io/flutter/plugins/androidintent/AndroidIntentPlugin.java @@ -44,6 +44,8 @@ private String convertAction(String action) { return Intent.ACTION_VOICE_COMMAND; case "settings": return Settings.ACTION_SETTINGS; + case "action_location_source_settings": + return Settings.ACTION_LOCATION_SOURCE_SETTINGS; default: return action; } diff --git a/packages/android_intent/android_intent.iml b/packages/android_intent/android_intent.iml deleted file mode 100644 index 9d5dae19540c..000000000000 --- a/packages/android_intent/android_intent.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/android_intent/example/lib/main.dart b/packages/android_intent/example/lib/main.dart index 07d2e99438ff..c94ffe50aef5 100644 --- a/packages/android_intent/example/lib/main.dart +++ b/packages/android_intent/example/lib/main.dart @@ -125,6 +125,13 @@ class ExplicitIntentsWidget extends StatelessWidget { intent.launch(); } + void _openLocationSettingsConfiguration() { + final AndroidIntent intent = const AndroidIntent( + action: 'action_location_source_settings', + ); + intent.launch(); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -160,6 +167,12 @@ class ExplicitIntentsWidget extends StatelessWidget { 'Tap here to test explicit intent fallback to implicit.'), onPressed: _testExplicitIntentFallback, ), + RaisedButton( + child: const Text( + 'Tap here to open Location Settings Configuration', + ), + onPressed: _openLocationSettingsConfiguration, + ) ], ), ), diff --git a/packages/android_intent/pubspec.yaml b/packages/android_intent/pubspec.yaml index a1d00c4ca970..cf205a693daf 100644 --- a/packages/android_intent/pubspec.yaml +++ b/packages/android_intent/pubspec.yaml @@ -2,7 +2,7 @@ name: android_intent description: Flutter plugin for launching Android Intents. Not supported on iOS. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/android_intent -version: 0.3.1+1 +version: 0.3.2 flutter: plugin: diff --git a/packages/camera/camera.iml b/packages/camera/camera.iml deleted file mode 100644 index 0c1c01a2c7b8..000000000000 --- a/packages/camera/camera.iml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/connectivity/connectivity.iml b/packages/connectivity/connectivity.iml deleted file mode 100644 index 9d5dae19540c..000000000000 --- a/packages/connectivity/connectivity.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/device_info/device_info.iml b/packages/device_info/device_info.iml deleted file mode 100644 index 9d5dae19540c..000000000000 --- a/packages/device_info/device_info.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/firebase_admob/firebase_admob.iml b/packages/firebase_admob/firebase_admob.iml deleted file mode 100644 index 9d5dae19540c..000000000000 --- a/packages/firebase_admob/firebase_admob.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/firebase_core/firebase_core.iml b/packages/firebase_core/firebase_core.iml deleted file mode 100644 index a6a44fee50b4..000000000000 --- a/packages/firebase_core/firebase_core.iml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/firebase_dynamic_links/firebase_dynamic_links.iml b/packages/firebase_dynamic_links/firebase_dynamic_links.iml deleted file mode 100644 index 73e7ebd0d508..000000000000 --- a/packages/firebase_dynamic_links/firebase_dynamic_links.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/firebase_messaging/firebase_messaging.iml b/packages/firebase_messaging/firebase_messaging.iml deleted file mode 100644 index dff626c24d4a..000000000000 --- a/packages/firebase_messaging/firebase_messaging.iml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/firebase_performance/firebase_performance.iml b/packages/firebase_performance/firebase_performance.iml deleted file mode 100644 index 73e7ebd0d508..000000000000 --- a/packages/firebase_performance/firebase_performance.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/firebase_remote_config/firebase_remote_config.iml b/packages/firebase_remote_config/firebase_remote_config.iml deleted file mode 100644 index 0fbaf2c3a822..000000000000 --- a/packages/firebase_remote_config/firebase_remote_config.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase.iml b/packages/in_app_purchase/in_app_purchase.iml deleted file mode 100644 index 429df7daf76a..000000000000 --- a/packages/in_app_purchase/in_app_purchase.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/local_auth/local_auth.iml b/packages/local_auth/local_auth.iml deleted file mode 100644 index 9d5dae19540c..000000000000 --- a/packages/local_auth/local_auth.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/package_info/package_info.iml b/packages/package_info/package_info.iml deleted file mode 100644 index 9d5dae19540c..000000000000 --- a/packages/package_info/package_info.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/quick_actions/quick_actions.iml b/packages/quick_actions/quick_actions.iml deleted file mode 100644 index 9d5dae19540c..000000000000 --- a/packages/quick_actions/quick_actions.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/video_player/video_player.iml b/packages/video_player/video_player.iml deleted file mode 100644 index 033806516ca3..000000000000 --- a/packages/video_player/video_player.iml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file From 41da2ae7179852f9fd7589fa8b9211c30e1de4d9 Mon Sep 17 00:00:00 2001 From: Jaime Herencia Enjuto Date: Tue, 23 Jul 2019 16:56:57 +0200 Subject: [PATCH 86/94] [firebase_dynamic_links] Change architecture to work correctly on async links and launch links (#1687) * [firebase_dynamic_links] Changed architecture to be able to difference between the dynamic link which opened the app and links clicked on app active or in background. * [firebase_dynamic_links] Improvements provided by @bparrishMines * [firebase_dynamic_links] Renaming configure to onLink * [firebase_dynamic_links] Renaming getLaunchLink to getInitialLink --- packages/firebase_dynamic_links/CHANGELOG.md | 8 ++ packages/firebase_dynamic_links/README.md | 27 ++++- .../FirebaseDynamicLinksPlugin.java | 110 +++++++++++------- .../example/lib/main.dart | 34 +++--- .../ios/Classes/FirebaseDynamicLinksPlugin.m | 96 ++++++++++----- .../lib/src/firebase_dynamic_links.dart | 55 ++++++++- packages/firebase_dynamic_links/pubspec.yaml | 2 +- .../test/firebase_dynamic_links_test.dart | 8 +- 8 files changed, 237 insertions(+), 103 deletions(-) diff --git a/packages/firebase_dynamic_links/CHANGELOG.md b/packages/firebase_dynamic_links/CHANGELOG.md index e6f491de59b0..04e18d9e9815 100644 --- a/packages/firebase_dynamic_links/CHANGELOG.md +++ b/packages/firebase_dynamic_links/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.5.0 + +* **Breaking change**. Changed architecture and method names to be able to differentiate between +the dynamic link which opened the app and links clicked during app execution (active and background). +`retrieveDynamicLink` has been replaced with two different functions: +- `getInitialLink` a future to retrieve the link that opened the app +- `onLink` a callback to listen to links opened while the app is active or in background + ## 0.4.0+6 * Update google-services Android gradle plugin to 4.3.0 in documentation and examples. diff --git a/packages/firebase_dynamic_links/README.md b/packages/firebase_dynamic_links/README.md index b3250deb6a56..e5b755d6f421 100644 --- a/packages/firebase_dynamic_links/README.md +++ b/packages/firebase_dynamic_links/README.md @@ -97,7 +97,8 @@ Receiving dynamic links on *iOS* requires a couple more steps than *Android*. If applinks:YOUR_SUBDOMAIN.page.link ``` -4. To receive a dynamic link, call the `retrieveDynamicLink()` method from `FirebaseDynamicLinks`: +4. To receive a dynamic link, call the `getInitialLink()` method from `FirebaseDynamicLinks` which gets the link that opened the app (or null if it was not opened via a dynamic link) +and configure listeners for link callbacks when the application is active or in background calling `onLink`. ```dart void main() { @@ -117,16 +118,30 @@ class MyHomeWidgetState extends State { @override void initState() { super.initState(); - _retrieveDynamicLink(); + this.initDynamicLinks(); } - Future _retrieveDynamicLink() async { - final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.retrieveDynamicLink(); + void initDynamicLinks() async { + final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getInitialLink(); final Uri deepLink = data?.link; if (deepLink != null) { - Navigator.pushNamed(context, deepLink.path); // deeplink.path == '/helloworld' + Navigator.pushNamed(context, deepLink.path); } + + FirebaseDynamicLinks.instance.onLink( + onSuccess: (PendingDynamicLinkData dynamicLink) async { + final Uri deepLink = dynamicLink?.link; + + if (deepLink != null) { + Navigator.pushNamed(context, deepLink.path); + } + }, + onError: (OnLinkErrorException e) async { + print('onLinkError'); + print(e.message); + } + ); } . . @@ -134,7 +149,7 @@ class MyHomeWidgetState extends State { } ``` -If your app did not open from a dynamic link, `retrieveDynamicLink()` will return `null`. +If your app did not open from a dynamic link, `getInitialLink()` will return `null`. ## Getting Started diff --git a/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java b/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java index c4ed3a5903f6..5cc4debaa404 100644 --- a/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java +++ b/packages/firebase_dynamic_links/android/src/main/java/io/flutter/plugins/firebasedynamiclinks/FirebaseDynamicLinksPlugin.java @@ -5,6 +5,7 @@ import androidx.annotation.NonNull; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; import com.google.firebase.dynamiclinks.DynamicLink; import com.google.firebase.dynamiclinks.FirebaseDynamicLinks; @@ -14,7 +15,7 @@ import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugin.common.PluginRegistry; +import io.flutter.plugin.common.PluginRegistry.NewIntentListener; import io.flutter.plugin.common.PluginRegistry.Registrar; import java.util.ArrayList; import java.util.HashMap; @@ -22,30 +23,53 @@ import java.util.Map; /** FirebaseDynamicLinksPlugin */ -public class FirebaseDynamicLinksPlugin implements MethodCallHandler { - private Registrar registrar; - private Intent latestIntent; +public class FirebaseDynamicLinksPlugin implements MethodCallHandler, NewIntentListener { + private final Registrar registrar; + private final MethodChannel channel; - private FirebaseDynamicLinksPlugin(Registrar registrar) { + private FirebaseDynamicLinksPlugin(Registrar registrar, MethodChannel channel) { this.registrar = registrar; - if (registrar.activity() != null) { - latestIntent = registrar.activity().getIntent(); - } + this.channel = channel; + } - registrar.addNewIntentListener( - new PluginRegistry.NewIntentListener() { - @Override - public boolean onNewIntent(Intent intent) { - latestIntent = intent; - return false; - } - }); + @Override + public boolean onNewIntent(Intent intent) { + FirebaseDynamicLinks.getInstance() + .getDynamicLink(intent) + .addOnSuccessListener( + registrar.activity(), + new OnSuccessListener() { + @Override + public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) { + if (pendingDynamicLinkData != null) { + Map dynamicLink = + getMapFromPendingDynamicLinkData(pendingDynamicLinkData); + channel.invokeMethod("onLinkSuccess", dynamicLink); + } + } + }) + .addOnFailureListener( + registrar.activity(), + new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + Map exception = new HashMap<>(); + exception.put("code", e.getClass().getSimpleName()); + exception.put("message", e.getMessage()); + exception.put("details", null); + channel.invokeMethod("onLinkError", exception); + } + }); + + return false; } public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_dynamic_links"); - channel.setMethodCallHandler(new FirebaseDynamicLinksPlugin(registrar)); + final FirebaseDynamicLinksPlugin plugin = new FirebaseDynamicLinksPlugin(registrar, channel); + registrar.addNewIntentListener(plugin); + channel.setMethodCallHandler(plugin); } @Override @@ -66,8 +90,8 @@ public void onMethodCall(MethodCall call, Result result) { builder.setLongLink(url); buildShortDynamicLink(builder, call, createShortLinkListener(result)); break; - case "FirebaseDynamicLinks#retrieveDynamicLink": - handleRetrieveDynamicLink(result); + case "FirebaseDynamicLinks#getInitialLink": + handleGetInitialDynamicLink(result); break; default: result.notImplemented(); @@ -75,40 +99,38 @@ public void onMethodCall(MethodCall call, Result result) { } } - private void handleRetrieveDynamicLink(final Result result) { - if (latestIntent == null) { - result.success(null); - return; - } + private Map getMapFromPendingDynamicLinkData( + PendingDynamicLinkData pendingDynamicLinkData) { + Map dynamicLink = new HashMap<>(); + dynamicLink.put("link", pendingDynamicLinkData.getLink().toString()); + + Map androidData = new HashMap<>(); + androidData.put("clickTimestamp", pendingDynamicLinkData.getClickTimestamp()); + androidData.put("minimumVersion", pendingDynamicLinkData.getMinimumAppVersion()); + dynamicLink.put("android", androidData); + return dynamicLink; + } + + private void handleGetInitialDynamicLink(final Result result) { FirebaseDynamicLinks.getInstance() - .getDynamicLink(latestIntent) - .addOnCompleteListener( + .getDynamicLink(registrar.activity().getIntent()) + .addOnSuccessListener( registrar.activity(), - new OnCompleteListener() { + new OnSuccessListener() { @Override - public void onComplete(@NonNull Task task) { - if (task.isSuccessful()) { - PendingDynamicLinkData data = task.getResult(); - if (data != null) { - Map dynamicLink = new HashMap<>(); - dynamicLink.put("link", data.getLink().toString()); - - Map androidData = new HashMap<>(); - androidData.put("clickTimestamp", data.getClickTimestamp()); - androidData.put("minimumVersion", data.getMinimumAppVersion()); - - dynamicLink.put("android", androidData); - - latestIntent = null; - result.success(dynamicLink); - return; - } + public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) { + if (pendingDynamicLinkData != null) { + Map dynamicLink = + getMapFromPendingDynamicLinkData(pendingDynamicLinkData); + result.success(dynamicLink); + return; } result.success(null); } }) .addOnFailureListener( + registrar.activity(), new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { diff --git a/packages/firebase_dynamic_links/example/lib/main.dart b/packages/firebase_dynamic_links/example/lib/main.dart index 443b79d986db..6784e2d0e2ef 100644 --- a/packages/firebase_dynamic_links/example/lib/main.dart +++ b/packages/firebase_dynamic_links/example/lib/main.dart @@ -24,7 +24,7 @@ class _MainScreen extends StatefulWidget { State createState() => _MainScreenState(); } -class _MainScreenState extends State<_MainScreen> with WidgetsBindingObserver { +class _MainScreenState extends State<_MainScreen> { String _linkMessage; bool _isCreatingLink = false; String _testString = @@ -36,31 +36,29 @@ class _MainScreenState extends State<_MainScreen> with WidgetsBindingObserver { @override void initState() { super.initState(); - _retrieveDynamicLink(); - WidgetsBinding.instance.addObserver(this); + initDynamicLinks(); } - @override - void dispose() { - super.dispose(); - WidgetsBinding.instance.removeObserver(this); - } - - @override - void didChangeAppLifecycleState(AppLifecycleState state) { - if (state == AppLifecycleState.resumed) { - _retrieveDynamicLink(); - } - } - - Future _retrieveDynamicLink() async { + void initDynamicLinks() async { final PendingDynamicLinkData data = - await FirebaseDynamicLinks.instance.retrieveDynamicLink(); + await FirebaseDynamicLinks.instance.getInitialLink(); final Uri deepLink = data?.link; if (deepLink != null) { Navigator.pushNamed(context, deepLink.path); } + + FirebaseDynamicLinks.instance.onLink( + onSuccess: (PendingDynamicLinkData dynamicLink) async { + final Uri deepLink = dynamicLink?.link; + + if (deepLink != null) { + Navigator.pushNamed(context, deepLink.path); + } + }, onError: (OnLinkErrorException e) async { + print('onLinkError'); + print(e.message); + }); } Future _createDynamicLink(bool short) async { diff --git a/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m b/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m index a98b382cc09a..4ab04a4e8723 100644 --- a/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m +++ b/packages/firebase_dynamic_links/ios/Classes/FirebaseDynamicLinksPlugin.m @@ -9,9 +9,39 @@ details:error.localizedDescription]; } +static NSMutableDictionary *getDictionaryFromDynamicLink(FIRDynamicLink *dynamicLink) { + if (dynamicLink != nil) { + NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; + dictionary[@"link"] = dynamicLink.url.absoluteString; + + NSMutableDictionary *iosData = [[NSMutableDictionary alloc] init]; + if (dynamicLink.minimumAppVersion) { + iosData[@"minimumVersion"] = dynamicLink.minimumAppVersion; + } + dictionary[@"ios"] = iosData; + return dictionary; + } else { + return nil; + } +} + +static NSMutableDictionary *getDictionaryFromFlutterError(FlutterError *error) { + if (error == nil) { + return nil; + } + + NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; + dictionary[@"code"] = error.code; + dictionary[@"message"] = error.message; + dictionary[@"details"] = error.details; + return dictionary; +} + @interface FLTFirebaseDynamicLinksPlugin () -@property(nonatomic, retain) FIRDynamicLink *dynamicLink; +@property(nonatomic, retain) FlutterMethodChannel *channel; +@property(nonatomic, retain) FIRDynamicLink *initialLink; @property(nonatomic, retain) FlutterError *flutterError; +@property(nonatomic) BOOL initiated; @end @implementation FLTFirebaseDynamicLinksPlugin @@ -19,7 +49,8 @@ + (void)registerWithRegistrar:(NSObject *)registrar { FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/firebase_dynamic_links" binaryMessenger:[registrar messenger]]; - FLTFirebaseDynamicLinksPlugin *instance = [[FLTFirebaseDynamicLinksPlugin alloc] init]; + FLTFirebaseDynamicLinksPlugin *instance = + [[FLTFirebaseDynamicLinksPlugin alloc] initWithChannel:channel]; [registrar addMethodCallDelegate:instance channel:channel]; [registrar addApplicationDelegate:instance]; @@ -29,9 +60,11 @@ + (void)registerWithRegistrar:(NSObject *)registrar { } } -- (instancetype)init { +- (instancetype)initWithChannel:(FlutterMethodChannel *)channel { self = [super init]; if (self) { + _initiated = NO; + _channel = channel; if (![FIRApp appNamed:@"__FIRAPP_DEFAULT"]) { NSLog(@"Configuring the default Firebase app..."); [FIRApp configure]; @@ -54,11 +87,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [FIRDynamicLinkComponents shortenURL:url options:options completion:[self createShortLinkCompletion:result]]; - } else if ([@"FirebaseDynamicLinks#retrieveDynamicLink" isEqualToString:call.method]) { - NSMutableDictionary *dict = [self retrieveDynamicLink]; + } else if ([@"FirebaseDynamicLinks#getInitialLink" isEqualToString:call.method]) { + _initiated = YES; + NSMutableDictionary *dict = [self getInitialLink]; if (dict == nil && self.flutterError) { result(self.flutterError); - self.flutterError = nil; } else { result(dict); } @@ -67,21 +100,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } } -- (NSMutableDictionary *)retrieveDynamicLink { - if (_dynamicLink != nil) { - NSMutableDictionary *dynamicLink = [[NSMutableDictionary alloc] init]; - dynamicLink[@"link"] = _dynamicLink.url.absoluteString; - - NSMutableDictionary *iosData = [[NSMutableDictionary alloc] init]; - if (_dynamicLink.minimumAppVersion) { - iosData[@"minimumVersion"] = _dynamicLink.minimumAppVersion; - } - _dynamicLink = nil; - dynamicLink[@"ios"] = iosData; - return dynamicLink; - } else { - return nil; - } +- (NSMutableDictionary *)getInitialLink { + return getDictionaryFromDynamicLink(_initialLink); } - (BOOL)application:(UIApplication *)application @@ -100,27 +120,49 @@ - (BOOL)application:(UIApplication *)application - (BOOL)checkForDynamicLink:(NSURL *)url { FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url]; if (dynamicLink) { - if (dynamicLink.url) _dynamicLink = dynamicLink; + if (dynamicLink.url) _initialLink = dynamicLink; return YES; } return NO; } -- (BOOL)application:(UIApplication *)application - continueUserActivity:(NSUserActivity *)userActivity - restorationHandler:(void (^)(NSArray *))restorationHandler { - usleep(50000); +- (BOOL)onLink:(NSUserActivity *)userActivity { + BOOL handled = [[FIRDynamicLinks dynamicLinks] + handleUniversalLink:userActivity.webpageURL + completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { + if (error) { + FlutterError *flutterError = getFlutterError(error); + [self.channel invokeMethod:@"onLinkError" + arguments:getDictionaryFromFlutterError(flutterError)]; + } else { + NSMutableDictionary *dictionary = getDictionaryFromDynamicLink(dynamicLink); + [self.channel invokeMethod:@"onLinkSuccess" arguments:dictionary]; + } + }]; + return handled; +} + +- (BOOL)onInitialLink:(NSUserActivity *)userActivity { BOOL handled = [[FIRDynamicLinks dynamicLinks] handleUniversalLink:userActivity.webpageURL completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { if (error) { self.flutterError = getFlutterError(error); } - self.dynamicLink = dynamicLink; + self.initialLink = dynamicLink; }]; return handled; } +- (BOOL)application:(UIApplication *)application + continueUserActivity:(NSUserActivity *)userActivity + restorationHandler:(void (^)(NSArray *))restorationHandler { + if (_initiated) { + return [self onLink:userActivity]; + } + return [self onInitialLink:userActivity]; +} + - (FIRDynamicLinkShortenerCompletion)createShortLinkCompletion:(FlutterResult)result { return ^(NSURL *_Nullable shortURL, NSArray *_Nullable warnings, NSError *_Nullable error) { if (error) { diff --git a/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart b/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart index 647cb8c267d0..c247fe82bb28 100644 --- a/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart +++ b/packages/firebase_dynamic_links/lib/src/firebase_dynamic_links.dart @@ -4,6 +4,11 @@ part of firebase_dynamic_links; +typedef OnLinkSuccessCallback = Future Function( + PendingDynamicLinkData linkData); +typedef OnLinkErrorCallback = Future Function( + OnLinkErrorException error); + /// Firebase Dynamic Links API. /// /// You can get an instance by calling [FirebaseDynamicLinks.instance]. @@ -17,16 +22,23 @@ class FirebaseDynamicLinks { /// Singleton of [FirebaseDynamicLinks]. static final FirebaseDynamicLinks instance = FirebaseDynamicLinks._(); - /// Attempts to retrieve a pending dynamic link. + OnLinkSuccessCallback _onLinkSuccess; + OnLinkErrorCallback _onLinkError; + + /// Attempts to retrieve the dynamic link which launched the app. /// /// This method always returns a Future. That Future completes to null if /// there is no pending dynamic link or any call to this method after the /// the first attempt. - Future retrieveDynamicLink() async { + Future getInitialLink() async { final Map linkData = await channel.invokeMapMethod( - 'FirebaseDynamicLinks#retrieveDynamicLink'); + 'FirebaseDynamicLinks#getInitialLink'); + return getPendingDynamicLinkDataFromMap(linkData); + } + PendingDynamicLinkData getPendingDynamicLinkDataFromMap( + Map linkData) { if (linkData == null) return null; PendingDynamicLinkDataAndroid androidData; @@ -50,6 +62,33 @@ class FirebaseDynamicLinks { iosData, ); } + + /// Configures onLink listeners: it has two methods for success and failure. + void onLink({ + OnLinkSuccessCallback onSuccess, + OnLinkErrorCallback onError, + }) { + _onLinkSuccess = onSuccess; + _onLinkError = onError; + channel.setMethodCallHandler(_handleMethod); + } + + Future _handleMethod(MethodCall call) async { + switch (call.method) { + case "onLinkSuccess": + final Map data = + call.arguments.cast(); + final PendingDynamicLinkData linkData = + getPendingDynamicLinkDataFromMap(data); + return _onLinkSuccess(linkData); + case "onLinkError": + final Map data = + call.arguments.cast(); + final OnLinkErrorException e = OnLinkErrorException._( + data['code'], data['message'], data['details']); + return _onLinkError(e); + } + } } /// Provides data from received dynamic link. @@ -104,3 +143,13 @@ class PendingDynamicLinkDataIOS { /// declares higher [minimumVersion] than currently installed. final String minimumVersion; } + +class OnLinkErrorException { + OnLinkErrorException._(this.code, this.message, this.details); + + final String code; + + final String message; + + final dynamic details; +} diff --git a/packages/firebase_dynamic_links/pubspec.yaml b/packages/firebase_dynamic_links/pubspec.yaml index 69cfe7f4dc97..73848496a15b 100644 --- a/packages/firebase_dynamic_links/pubspec.yaml +++ b/packages/firebase_dynamic_links/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_dynamic_links description: Flutter plugin for Google Dynamic Links for Firebase, an app solution for creating and handling links across multiple platforms. -version: 0.4.0+6 +version: 0.5.0 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_dynamic_links diff --git a/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart b/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart index acf7121c7f22..e89dfef03df3 100644 --- a/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart +++ b/packages/firebase_dynamic_links/test/firebase_dynamic_links_test.dart @@ -26,7 +26,7 @@ void main() { return returnUrl; case 'DynamicLinkParameters#shortenUrl': return returnUrl; - case 'FirebaseDynamicLinks#retrieveDynamicLink': + case 'FirebaseDynamicLinks#getInitialLink': return { 'link': 'https://google.com', 'android': { @@ -44,9 +44,9 @@ void main() { log.clear(); }); - test('retrieveDynamicLink', () async { + test('getInitialLink', () async { final PendingDynamicLinkData data = - await FirebaseDynamicLinks.instance.retrieveDynamicLink(); + await FirebaseDynamicLinks.instance.getInitialLink(); expect(data.link, Uri.parse('https://google.com')); @@ -57,7 +57,7 @@ void main() { expect(log, [ isMethodCall( - 'FirebaseDynamicLinks#retrieveDynamicLink', + 'FirebaseDynamicLinks#getInitialLink', arguments: null, ) ]); From ed53cab392dda8495d927ff8a703fad4e59bdfea Mon Sep 17 00:00:00 2001 From: Ali EP Date: Tue, 23 Jul 2019 22:50:22 +0430 Subject: [PATCH 87/94] [firebase_ml_vision] adds facial contours (#1599) --- .gitignore | 4 + packages/firebase_ml_vision/CHANGELOG.md | 4 + packages/firebase_ml_vision/README.md | 12 ++ .../firebasemlvision/FaceDetector.java | 54 +++++++ .../example/android/app/build.gradle | 1 + .../example/assets/test_face.jpg | Bin 78450 -> 35944 bytes .../example/test_driver/face_detector.dart | 9 +- .../ios/Classes/FaceDetector.m | 51 +++++++ .../lib/src/face_detector.dart | 59 ++++++++ packages/firebase_ml_vision/pubspec.yaml | 2 +- .../test/firebase_ml_vision_test.dart | 135 ++++++++++++++++++ 11 files changed, 329 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5cfb9504ab1d..625ff5896c3b 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,7 @@ GeneratedPluginRegistrant.m GeneratedPluginRegistrant.java build/ .flutter-plugins + +.project +.classpath +.settings diff --git a/packages/firebase_ml_vision/CHANGELOG.md b/packages/firebase_ml_vision/CHANGELOG.md index 10cbf8ea279f..b2fe1d37d699 100644 --- a/packages/firebase_ml_vision/CHANGELOG.md +++ b/packages/firebase_ml_vision/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.2 + +* Add detection of `FaceContour`s when using the `FaceDetector`. See `README.md` for more information. + ## 0.9.1+1 * Update google-services Android gradle plugin to 4.3.0 in documentation and examples. diff --git a/packages/firebase_ml_vision/README.md b/packages/firebase_ml_vision/README.md index 5e6b9dbd38d7..be7e6578f3ab 100644 --- a/packages/firebase_ml_vision/README.md +++ b/packages/firebase_ml_vision/README.md @@ -25,6 +25,18 @@ android { } ``` +If you're using the on-device `Face Contour Detection`, include the latest matching [ML Kit: Face Detection Model](https://firebase.google.com/support/release-notes/android) dependency in your app-level build.gradle file. + +``` +android { + dependencies { + // ... + + api 'com.google.firebase:firebase-ml-vision-face-model:17.0.2' + } +} +``` + If you receive compilation errors, try an earlier version of [ML Kit: Image Labeling](https://firebase.google.com/support/release-notes/android). Optional but recommended: If you use the on-device API, configure your app to automatically download the ML model to the device after your app is installed from the Play Store. To do so, add the following declaration to your app's AndroidManifest.xml file: diff --git a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FaceDetector.java b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FaceDetector.java index 245c2109074a..eba06e71eecd 100644 --- a/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FaceDetector.java +++ b/packages/firebase_ml_vision/android/src/main/java/io/flutter/plugins/firebasemlvision/FaceDetector.java @@ -5,7 +5,9 @@ import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.ml.vision.FirebaseVision; import com.google.firebase.ml.vision.common.FirebaseVisionImage; +import com.google.firebase.ml.vision.common.FirebaseVisionPoint; import com.google.firebase.ml.vision.face.FirebaseVisionFace; +import com.google.firebase.ml.vision.face.FirebaseVisionFaceContour; import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetector; import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetectorOptions; import com.google.firebase.ml.vision.face.FirebaseVisionFaceLandmark; @@ -63,6 +65,8 @@ public void onSuccess(List firebaseVisionFaces) { faceData.put("landmarks", getLandmarkData(face)); + faceData.put("contours", getContourData(face)); + faces.add(faceData); } @@ -95,6 +99,34 @@ private Map getLandmarkData(FirebaseVisionFace face) { return landmarks; } + private Map> getContourData(FirebaseVisionFace face) { + Map> contours = new HashMap<>(); + + contours.put("allPoints", contourPosition(face, FirebaseVisionFaceContour.ALL_POINTS)); + contours.put("face", contourPosition(face, FirebaseVisionFaceContour.FACE)); + contours.put("leftEye", contourPosition(face, FirebaseVisionFaceContour.LEFT_EYE)); + contours.put( + "leftEyebrowBottom", contourPosition(face, FirebaseVisionFaceContour.LEFT_EYEBROW_BOTTOM)); + contours.put( + "leftEyebrowTop", contourPosition(face, FirebaseVisionFaceContour.LEFT_EYEBROW_TOP)); + contours.put( + "lowerLipBottom", contourPosition(face, FirebaseVisionFaceContour.LOWER_LIP_BOTTOM)); + contours.put("lowerLipTop", contourPosition(face, FirebaseVisionFaceContour.LOWER_LIP_TOP)); + contours.put("noseBottom", contourPosition(face, FirebaseVisionFaceContour.NOSE_BOTTOM)); + contours.put("noseBridge", contourPosition(face, FirebaseVisionFaceContour.NOSE_BRIDGE)); + contours.put("rightEye", contourPosition(face, FirebaseVisionFaceContour.RIGHT_EYE)); + contours.put( + "rightEyebrowBottom", + contourPosition(face, FirebaseVisionFaceContour.RIGHT_EYEBROW_BOTTOM)); + contours.put( + "rightEyebrowTop", contourPosition(face, FirebaseVisionFaceContour.RIGHT_EYEBROW_TOP)); + contours.put( + "upperLipBottom", contourPosition(face, FirebaseVisionFaceContour.UPPER_LIP_BOTTOM)); + contours.put("upperLipTop", contourPosition(face, FirebaseVisionFaceContour.UPPER_LIP_TOP)); + + return contours; + } + private double[] landmarkPosition(FirebaseVisionFace face, int landmarkInt) { FirebaseVisionFaceLandmark landmark = face.getLandmark(landmarkInt); if (landmark != null) { @@ -104,6 +136,22 @@ private double[] landmarkPosition(FirebaseVisionFace face, int landmarkInt) { return null; } + private List contourPosition(FirebaseVisionFace face, int contourInt) { + FirebaseVisionFaceContour contour = face.getContour(contourInt); + if (contour != null) { + List contourPoints = contour.getPoints(); + List result = new ArrayList(); + + for (int i = 0; i < contourPoints.size(); i++) { + result.add(new double[] {contourPoints.get(i).getX(), contourPoints.get(i).getY()}); + } + + return result; + } + + return null; + } + private FirebaseVisionFaceDetectorOptions parseOptions(Map options) { int classification = (boolean) options.get("enableClassification") @@ -115,6 +163,11 @@ private FirebaseVisionFaceDetectorOptions parseOptions(Map optio ? FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS : FirebaseVisionFaceDetectorOptions.NO_LANDMARKS; + int contours = + (boolean) options.get("enableContours") + ? FirebaseVisionFaceDetectorOptions.ALL_CONTOURS + : FirebaseVisionFaceDetectorOptions.NO_CONTOURS; + int mode; switch ((String) options.get("mode")) { case "accurate": @@ -131,6 +184,7 @@ private FirebaseVisionFaceDetectorOptions parseOptions(Map optio new FirebaseVisionFaceDetectorOptions.Builder() .setClassificationMode(classification) .setLandmarkMode(landmark) + .setContourMode(contours) .setMinFaceSize((float) ((double) options.get("minFaceSize"))) .setPerformanceMode(mode); diff --git a/packages/firebase_ml_vision/example/android/app/build.gradle b/packages/firebase_ml_vision/example/android/app/build.gradle index 96c685ea27a2..edd72b27f848 100644 --- a/packages/firebase_ml_vision/example/android/app/build.gradle +++ b/packages/firebase_ml_vision/example/android/app/build.gradle @@ -48,6 +48,7 @@ android { dependencies { api 'com.google.firebase:firebase-ml-vision-image-label-model:17.0.2' + api 'com.google.firebase:firebase-ml-vision-face-model:17.0.2' } } diff --git a/packages/firebase_ml_vision/example/assets/test_face.jpg b/packages/firebase_ml_vision/example/assets/test_face.jpg index f87458b4db81e33e1b32e68accf5cd1da3d54912..a384f3c243b690f8591f6f3ddbe403e411fe1e9b 100644 GIT binary patch literal 35944 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 mKIFZuMGky;Qd*$N$;<;WBgp literal 78450 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⪻A^I&_P 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�L<(7)pjYSKO2I32jH27s zkyU7YmuUI$P$OC9i-tl6hGaKe9}ZL2#D_O})aR{|*K1t_>7PHuS@z`%2sn3@#rk#J zb~V#+lRRElV82<#wNbE>L~b_ zORRt=h34Uxs(xF2n$amMDr#l!mlzWfQU%u53;)5b`2%wg$)xilN6&SXL(Zk)f|$eo znzqM9GY3~*WQ5`Y&IFUYpoO5_m*S5Z$76eity|>23S?ZnqXUbUY@=87%MKOFyQ(C2 zOSS|m{8>@$#C320OvT?P%a9Fg2294_(tlRD)&;C6`ZQ+`>4|jz2cT(t<|uD@aKCl^ zjG6fzN59rqW6E}b#hftZ#I-$xN6X|WE|2z7e0|Sfj%6|9>V9S844zpRp?Dxy^m-3| zO?rYjUywa@h+#-_em8pej(oyN0>%zgZ1b)d-wWiE7#RYAUXWDK;A2jhmX%&cpVfHHcW))PQ) zLj4VCsrxRL8A~smzo~!qakbSJ%#h(Q8!W@jgr^ToSgIE8Gk#-z*vtKxs?6CF(pjub zETQ-YhGa@E)Y+R&f9Rf`BN6+1z7P7OkWir)ESBv+Hh$wFt#Whww<4=USmoJ33nx?X zg=T#BdCJeGsdw+5CjNCk16L%M0LudfXr0o^1^7xwxW5L)-e9AHUcGTdR3gEF(d&KK z-|L`-VWH}&ZO2P`b#6^`7gtZ+V6N>`r5$FB_2qxHVFGeC0esfIz{|kc-+NWA%C~LB zdVFHtN+R86dkMdzS2vq~r(JBE+t(#$w!idz_n6TWLmCIw3vmF`&fz<)IIP3E~O?D^-DX`#b*8zV^Yu}6uo$~Mw<9T_r&x{ zKyz@(h5Kd_)k$P`t0Gb|C@fSt)ne!{Vn9VlW|+ZE3Lg`j@|rz~e;nmXbE6|u#QjL6 zTB5M&@<8g>(p(lrBv4o?H|i~mMPVpVOmnU5=bQ3`D#BP_qL+BEjF3!mY7vend6K*D z+P;+oHTd9dN|g#t*QKsEm*mPkS<0V14qDS@e=ob+Y|GcZwS&ieM%I;;qqG2yEo*7<+JUQHS|FX2`1@4w9+B_H z*6o`j&O=7Ex7_obEe?hv28LFMNhP$ld72f=FW z!H)sGk6vT|-ny0cRd3T#=6&;f~>X-_0xdC9^VXNDc=# z!lzfB1sBXbl+cSW5KCx_R1+k_`{SUg-Oe>b5qW9TTkq~eL0Q&%Xe5k&8g-KSSe!5* z-ZT3p|C^)-1y%puS?-nS>NAhdCQ+%6P6yvSenfLg%pBe?6r3;#1%F@t-Uq0OVT9bJ zln_I*rk>Z3gtb~fmctAQ6xGHfioNjgH3#{W&2sVC{3Ciq?6sL!JUH~`?(Nhh_qNrP z@L!l-utr7ndJpv26nvN9fZo-u0EJZipdX=``^whqKf!B9rwvQBKD?4CHMT}=b?Ic@ z04ldQ*_MzT+3GkcD#TjB{dOQolycrIhIUCbb5tTSA12z)11)b9f07!p-zv49NBIt4 zEM6Ac(MgwXcfxB(UG=WKyJbX`1vq-+Za@(~?KYb|;+?1HCULp?>u?62w(u6#IW1pi zEj~D^sF#K>^jlMNlO<`SMoj;30jG!_(#NDUB)DZ#B0_RPB!M0*QxXx;jHKK?S0MWN z&Y!u$;MZ*ce(+&Vcjx;`MrpYZYW(2i{`QjmkVDdxjS9-#Mt;>>!ce@&;<&U9kELZ~ z%C**vLA<{B!CO+2Ny-Lrm?Sr+tf!||k;|n+1PimP`sjEUh00Gsy&`v`g{0aQ4SAw) zFuR%o&QVlop)%LBTJO!TzUIiiwo_ zd?B!jMjEkWGclJ1Q}J=iKFun|b%5XQiYa{k2e{<(iM9gmmBR*?5|>g1Ra{~1rB?rG z20nr?;>tWJ4Qy}B2~E8&qq=BO0TTf-dW9`eH?-d^Y2@=qA5HeXF!+YS?bUwd7C+7I zrVLY5r+^X$HK#8v*)=KH;`O?h6Q4gwxz+xhjn^7l8;OXBKB0Qep`t6mJD(Pw{y+|r zvliUULN!?B7i2Zh>N0jgHWcK>X>(=A$em6A@5*O<`*-4SwaqR!z8eq_f`UyBE&+PdjC9pIx0 z&!e^4(Jv&mNxK&DWr&Y0?j~{u7q8yRX-uX$>i4cr1e)6Z1JGi*H*sPgr+w=&A2>+` z7yf9twph|27ivN>F^HQuA>KUQv2rMiXRb#@D5AaucveZAqNmfl&VbLifiNjneS#4n z9wkv8YzX|m_c(7+i)pVkvYtBpmpq*HonZ;(8tjCm^SA#FJpmPW} zPkW?gRynwtxmTh&XAsePh~di1Oj1;i@DK3R42&Y>5e2YxR(J(u&m z$3_-jCEfOHY$fa^ws;&LZ`r6vSJ%=ptH#UK%BWEpMFod;6A!ZRfk)TW{?;mQaZ<`( ztBpVhYej-ghEAj9LG~s}Q_qdD&s>&_264Sr^$CX9-<>k7jYx;k!2_$ri5863B!y6* zIBecPJNDQB-Q{6E*c`C?!G%P4`tZhXghI`MO zqBYJpMnPuAYaXR|rk^k1k<~3G<;~b0YkYj1l+KlT8}cQzO4FB8Drsxa&WCm?jIY1K z_XqoCy_c|4gT$V@M2wa9Q4BRxMpfCn=#1p!hjXkAoHHA|BO(w%+%DppRK52>4 zvnf)TGUmC}GBybMCUOLu9>Rp9(toPwPef$#SgCqPQbhD3w)5)=nIsgtqlx#Fj5-gS zJ2^ND4yZ2?+6iU(J5C3&eplTEMcn!|?L66k_HkuU!sm{m*~Z#2uU}{E048@LA0o3A znxY6Mbg@O6HV-nEd?x`Qz7$?|Qfak4`PKuf**|GouBV3+*NlalS`~PeB9VnRj{$2^28HwKUx(&^ z<a!;-<_WD@MocwRIe`ejZT z%ylXo#o)Pz-$MBXD7M%Q0w2L<7^tYIa_x}d{f8zjl8N$5 z(U#_(Hm9ND3e&72FHND99H+f6jPl=bk{CR30Bqkvh>8||*CYs2=p9Z~R+&)7b8s-3 zjOb1i{b!kORg8{at#_B;Rksj#G|HGRI6z;m>Jy__jjt` zYqTjTU9J4`?V!uB_0O!mVp)AUX07Yu1=~mNOKi^fmUAvsZ&Di=*eu-8WqI&3Bj5iD zRTO*5ni)k*0%PvK7MLfEJHZGKgXL!XV7d7 z{kHAit>neeWb}B(bkij?L6~jM5HmAWmwHITCzaR0YtoZ@iEp&2B>gDfOBMIn(-aN&qS9oxr{lv53HSD`kxZ0Bk$u4Ub7V1l7v_9n z608ko{ytD0;!&mq4Ynws(>Wc$Ya<+@Y@58QQ zSPN6ZKXAgftzvgSry__kPwdkfbdaRTRD z^o9RZ;=9O3GyFuZedkD#YKG)qWg>eM;*t0f{?K0~kyU-JZ9S_tnaBQd2A;LnUFv7Q z)tx+|*QfDE>4{YaEuBRC0t5T9;@};ZaMEX`ZKhe}Gz_Vi@B#dgG*+XWp zsriaBxWa=s(+c)Z1Kj>TlO?vpwsO-=nPB_^*-t1}30S3tZo6WrwC|(MTbl1U*|^P) zm{CqM#Xn0yy=kW~{_@7?*`bC@0l^{g3r!~^IBA-#zr<~D4Rgp63mZ*T%oWODmTY6o z&MAqV^{H(GA>JGFL<~T0wDY_(XZZxv_>0ROA5N{`3!JKSSWshfkK?K2he&nJ;^NjT zGM8)Q&u$E3V~;^$v#ns7A0VSGSPe?=$p5{c(GScbnXh_Q?#}uwz3JG@ zbe7d=Y*LdH!tO0SUMEfsp9tJZ*p#MRwHBP+Q0<~rVSr4C25a6{f@vgVLx|>MPeTOE zQ25~4pRLDkn|Nez`6uz`@)R}3f+K54>Qw`sAQ^}Z?NSv2Cb zjA7qJ*j9t)@^A@E`-b~*%(nOZXa%Z)r#~j00@bT{`h=hJLF{~OetVM4;BfMu=#v@o zDY~B$8F~GeYL25-;E+}Q`j=*! zb#Wtyjcqa37UybT=6F>)<|b|826#VY+`twlG>AB$@Y*%1lA+^g{4LD7qDP@SJ#%7P zZ?{=G0*#b?RQz3Xaw5?Gy?k@FIqv1+
q+6Bq5;tq+UTQiq^FC}O?YaZkw4o-Xh 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 UkoZ-8tfsLL=H?aV)&I@@AK&o?>;M1& diff --git a/packages/firebase_ml_vision/example/test_driver/face_detector.dart b/packages/firebase_ml_vision/example/test_driver/face_detector.dart index 1f94b4061cae..666b200e301c 100644 --- a/packages/firebase_ml_vision/example/test_driver/face_detector.dart +++ b/packages/firebase_ml_vision/example/test_driver/face_detector.dart @@ -6,7 +6,10 @@ part of 'firebase_ml_vision.dart'; void faceDetectorTests() { group('$FaceDetector', () { - final FaceDetector detector = FirebaseVision.instance.faceDetector(); + final FaceDetector detector = FirebaseVision.instance.faceDetector( + FaceDetectorOptions( + enableContours: true, mode: FaceDetectorMode.accurate), + ); test('processImage', () async { final String tmpFilename = await _loadImage('assets/test_face.jpg'); @@ -16,6 +19,10 @@ void faceDetectorTests() { final List faces = await detector.processImage(visionImage); expect(faces.length, 1); + expect( + faces[0].getContour(FaceContourType.allPoints).positionsList, + isNotEmpty, + ); }); test('close', () { diff --git a/packages/firebase_ml_vision/ios/Classes/FaceDetector.m b/packages/firebase_ml_vision/ios/Classes/FaceDetector.m index 75122b244b77..3f036b403857 100644 --- a/packages/firebase_ml_vision/ios/Classes/FaceDetector.m +++ b/packages/firebase_ml_vision/ios/Classes/FaceDetector.m @@ -68,6 +68,35 @@ - (void)handleDetection:(FIRVisionImage *)image result:(FlutterResult)result { @"rightMouth" : [FaceDetector getLandmarkPosition:face landmark:FIRFaceLandmarkTypeMouthRight], }, + @"contours" : @{ + @"allPoints" : [FaceDetector getContourPoints:face contour:FIRFaceContourTypeAll], + @"face" : [FaceDetector getContourPoints:face contour:FIRFaceContourTypeFace], + @"leftEye" : [FaceDetector getContourPoints:face contour:FIRFaceContourTypeLeftEye], + @"leftEyebrowBottom" : + [FaceDetector getContourPoints:face + contour:FIRFaceContourTypeLeftEyebrowBottom], + @"leftEyebrowTop" : + [FaceDetector getContourPoints:face contour:FIRFaceContourTypeLeftEyebrowTop], + @"lowerLipBottom" : + [FaceDetector getContourPoints:face contour:FIRFaceContourTypeLowerLipBottom], + @"lowerLipTop" : [FaceDetector getContourPoints:face + contour:FIRFaceContourTypeLowerLipTop], + @"noseBottom" : [FaceDetector getContourPoints:face + contour:FIRFaceContourTypeNoseBottom], + @"noseBridge" : [FaceDetector getContourPoints:face + contour:FIRFaceContourTypeNoseBridge], + @"rightEye" : [FaceDetector getContourPoints:face + contour:FIRFaceContourTypeRightEye], + @"rightEyebrowBottom" : + [FaceDetector getContourPoints:face + contour:FIRFaceContourTypeRightEyebrowBottom], + @"rightEyebrowTop" : + [FaceDetector getContourPoints:face contour:FIRFaceContourTypeRightEyebrowTop], + @"upperLipBottom" : + [FaceDetector getContourPoints:face contour:FIRFaceContourTypeUpperLipBottom], + @"upperLipTop" : [FaceDetector getContourPoints:face + contour:FIRFaceContourTypeUpperLipTop], + } }; [faceData addObject:data]; @@ -86,6 +115,21 @@ + (id)getLandmarkPosition:(FIRVisionFace *)face landmark:(FIRFaceLandmarkType)la return [NSNull null]; } ++ (id)getContourPoints:(FIRVisionFace *)face contour:(FIRFaceContourType)contourType { + FIRVisionFaceContour *contour = [face contourOfType:contourType]; + if (contour) { + NSArray *contourPoints = contour.points; + NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:[contourPoints count]]; + for (int i = 0; i < [contourPoints count]; i++) { + FIRVisionPoint *point = [contourPoints objectAtIndex:i]; + [result insertObject:@[ point.x, point.y ] atIndex:i]; + } + return [result copy]; + } + + return [NSNull null]; +} + + (FIRVisionFaceDetectorOptions *)parseOptions:(NSDictionary *)optionsData { FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init]; @@ -103,6 +147,13 @@ + (FIRVisionFaceDetectorOptions *)parseOptions:(NSDictionary *)optionsData { options.landmarkMode = FIRVisionFaceDetectorLandmarkModeNone; } + NSNumber *enableContours = optionsData[@"enableContours"]; + if (enableContours.boolValue) { + options.contourMode = FIRVisionFaceDetectorContourModeAll; + } else { + options.contourMode = FIRVisionFaceDetectorContourModeNone; + } + NSNumber *enableTracking = optionsData[@"enableTracking"]; options.trackingEnabled = enableTracking.boolValue; diff --git a/packages/firebase_ml_vision/lib/src/face_detector.dart b/packages/firebase_ml_vision/lib/src/face_detector.dart index 4ada4ea3c677..aa4d0d76f560 100644 --- a/packages/firebase_ml_vision/lib/src/face_detector.dart +++ b/packages/firebase_ml_vision/lib/src/face_detector.dart @@ -24,6 +24,24 @@ enum FaceLandmarkType { rightMouth, } +/// Available face contour types detected by [FaceDetector]. +enum FaceContourType { + allPoints, + face, + leftEye, + leftEyebrowBottom, + leftEyebrowTop, + lowerLipBottom, + lowerLipTop, + noseBottom, + noseBridge, + rightEye, + rightEyebrowBottom, + rightEyebrowTop, + upperLipBottom, + upperLipTop +} + /// Detector for detecting faces in an input image. /// /// A face detector is created via @@ -59,6 +77,7 @@ class FaceDetector { 'options': { 'enableClassification': options.enableClassification, 'enableLandmarks': options.enableLandmarks, + 'enableContours': options.enableContours, 'enableTracking': options.enableTracking, 'minFaceSize': options.minFaceSize, 'mode': _enumToString(options.mode), @@ -98,6 +117,7 @@ class FaceDetectorOptions { const FaceDetectorOptions({ this.enableClassification = false, this.enableLandmarks = false, + this.enableContours = false, this.enableTracking = false, this.minFaceSize = 0.1, this.mode = FaceDetectorMode.fast, @@ -112,6 +132,9 @@ class FaceDetectorOptions { /// Whether to detect [FaceLandmark]s. final bool enableLandmarks; + /// Whether to detect [FaceContour]s. + final bool enableContours; + /// Whether to enable face tracking. /// /// If enabled, the detector will maintain a consistent ID for each face when @@ -154,9 +177,25 @@ class Face { type, Offset(pos[0], pos[1]), ); + })), + _contours = Map.fromIterables( + FaceContourType.values, + FaceContourType.values.map((FaceContourType type) { + /// added empty map to pass the tests + final List arr = + (data['contours'] ?? {})[_enumToString(type)]; + return (arr == null) + ? null + : FaceContour._( + type, + arr + .map((dynamic pos) => Offset(pos[0], pos[1])) + .toList(), + ); })); final Map _landmarks; + final Map _contours; /// The axis-aligned bounding rectangle of the detected face. /// @@ -212,6 +251,11 @@ class Face { /// /// Null if landmark was not detected. FaceLandmark getLandmark(FaceLandmarkType landmark) => _landmarks[landmark]; + + /// Gets the contour based on the provided [FaceContourType]. + /// + /// Null if contour was not detected. + FaceContour getContour(FaceContourType contour) => _contours[contour]; } /// Represent a face landmark. @@ -228,3 +272,18 @@ class FaceLandmark { /// The point (0, 0) is defined as the upper-left corner of the image. final Offset position; } + +/// Represent a face contour. +/// +/// Contours of facial features. +class FaceContour { + FaceContour._(this.type, this.positionsList); + + /// The [FaceContourType] of this contour. + final FaceContourType type; + + /// Gets a 2D point [List] for contour positions. + /// + /// The point (0, 0) is defined as the upper-left corner of the image. + final List positionsList; +} diff --git a/packages/firebase_ml_vision/pubspec.yaml b/packages/firebase_ml_vision/pubspec.yaml index abc6566e8e8f..05bdfe95d299 100644 --- a/packages/firebase_ml_vision/pubspec.yaml +++ b/packages/firebase_ml_vision/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_ml_vision description: Flutter plugin for Firebase machine learning vision services. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_ml_vision -version: 0.9.1+1 +version: 0.9.2 dependencies: flutter: diff --git a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart index 85e069774b9a..59dea115f83f 100644 --- a/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart +++ b/packages/firebase_ml_vision/test/firebase_ml_vision_test.dart @@ -526,6 +526,64 @@ void main() { 'rightEye': [16.1, 17.1], 'rightMouth': [18.1, 19.1], }, + 'contours': { + 'allPoints': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'face': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'leftEye': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'leftEyebrowBottom': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'leftEyebrowTop': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'lowerLipBottom': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'lowerLipTop': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'noseBottom': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'noseBridge': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'rightEye': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'rightEyebrowBottom': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'rightEyebrowTop': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'upperLipBottom': [ + [1.1, 2.2], + [3.3, 4.4], + ], + 'upperLipTop': [ + [1.1, 2.2], + [3.3, 4.4], + ], + }, }, ]; }); @@ -538,6 +596,7 @@ void main() { enableClassification: true, enableLandmarks: true, enableTracking: false, + enableContours: true, minFaceSize: 0.5, mode: FaceDetectorMode.accurate, ), @@ -561,6 +620,7 @@ void main() { 'options': { 'enableClassification': true, 'enableLandmarks': true, + 'enableContours': true, 'enableTracking': false, 'minFaceSize': 0.5, 'mode': 'accurate', @@ -598,6 +658,81 @@ void main() { expect(p(FaceLandmarkType.rightEar), const Offset(14.1, 15.1)); expect(p(FaceLandmarkType.rightEye), const Offset(16.1, 17.1)); expect(p(FaceLandmarkType.rightMouth), const Offset(18.1, 19.1)); + + List c(FaceContourType type) { + return face.getContour(type).positionsList; + } + + expect( + c(FaceContourType.allPoints), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.face), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.leftEye), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.leftEyebrowBottom), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.leftEyebrowTop), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.lowerLipBottom), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.lowerLipTop), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.noseBottom), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.noseBridge), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.rightEye), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.rightEyebrowBottom), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.rightEyebrowTop), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.upperLipBottom), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); + expect( + c(FaceContourType.upperLipTop), + containsAllInOrder( + [const Offset(1.1, 2.2), const Offset(3.3, 4.4)]), + ); }); test('processImage with null landmark', () async { From d0e798f1b89c25b22c5f817191f430afe86d2815 Mon Sep 17 00:00:00 2001 From: Colas Broux Date: Wed, 24 Jul 2019 16:11:28 +0200 Subject: [PATCH 88/94] [android_alarm_manager] Added support for setting alarms which work when the phone is in doze mode (#1895) --- packages/android_alarm_manager/CHANGELOG.md | 4 +++ .../androidalarmmanager/AlarmService.java | 36 +++++++++++++++++-- .../AndroidAlarmManagerPlugin.java | 27 ++++++++++---- .../lib/android_alarm_manager.dart | 15 ++++++-- packages/android_alarm_manager/pubspec.yaml | 2 +- 5 files changed, 73 insertions(+), 11 deletions(-) diff --git a/packages/android_alarm_manager/CHANGELOG.md b/packages/android_alarm_manager/CHANGELOG.md index 1b58c6a394eb..af2d8b7cf53e 100644 --- a/packages/android_alarm_manager/CHANGELOG.md +++ b/packages/android_alarm_manager/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2 + +* Added support for setting alarms which work when the phone is in doze mode. + ## 0.4.1+8 * Remove dependency on google-services in the Android example. diff --git a/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AlarmService.java b/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AlarmService.java index c55925061c61..16a6375a8070 100644 --- a/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AlarmService.java +++ b/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AlarmService.java @@ -217,6 +217,8 @@ public void notImplemented() { private static void scheduleAlarm( Context context, int requestCode, + boolean alarmClock, + boolean allowWhileIdle, boolean repeating, boolean exact, boolean wakeup, @@ -228,6 +230,8 @@ private static void scheduleAlarm( addPersistentAlarm( context, requestCode, + alarmClock, + allowWhileIdle, repeating, exact, wakeup, @@ -250,17 +254,31 @@ private static void scheduleAlarm( // Schedule the alarm. AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + + if (alarmClock) { + AlarmManagerCompat.setAlarmClock(manager, startMillis, pendingIntent, pendingIntent); + return; + } + if (exact) { if (repeating) { manager.setRepeating(clock, startMillis, intervalMillis, pendingIntent); } else { - AlarmManagerCompat.setExact(manager, clock, startMillis, pendingIntent); + if (allowWhileIdle) { + AlarmManagerCompat.setExactAndAllowWhileIdle(manager, clock, startMillis, pendingIntent); + } else { + AlarmManagerCompat.setExact(manager, clock, startMillis, pendingIntent); + } } } else { if (repeating) { manager.setInexactRepeating(clock, startMillis, intervalMillis, pendingIntent); } else { - manager.set(clock, startMillis, pendingIntent); + if (allowWhileIdle) { + AlarmManagerCompat.setAndAllowWhileIdle(manager, clock, startMillis, pendingIntent); + } else { + manager.set(clock, startMillis, pendingIntent); + } } } } @@ -270,6 +288,8 @@ public static void setOneShot(Context context, AndroidAlarmManagerPlugin.OneShot scheduleAlarm( context, request.requestCode, + request.alarmClock, + request.allowWhileIdle, repeating, request.exact, request.wakeup, @@ -282,9 +302,13 @@ public static void setOneShot(Context context, AndroidAlarmManagerPlugin.OneShot public static void setPeriodic( Context context, AndroidAlarmManagerPlugin.PeriodicRequest request) { final boolean repeating = true; + final boolean allowWhileIdle = false; + final boolean alarmClock = false; scheduleAlarm( context, request.requestCode, + alarmClock, + allowWhileIdle, repeating, request.exact, request.wakeup, @@ -317,6 +341,8 @@ private static String getPersistentAlarmKey(int requestCode) { private static void addPersistentAlarm( Context context, int requestCode, + boolean alarmClock, + boolean allowWhileIdle, boolean repeating, boolean exact, boolean wakeup, @@ -324,6 +350,8 @@ private static void addPersistentAlarm( long intervalMillis, long callbackHandle) { HashMap alarmSettings = new HashMap<>(); + alarmSettings.put("alarmClock", alarmClock); + alarmSettings.put("allowWhileIdle", allowWhileIdle); alarmSettings.put("repeating", repeating); alarmSettings.put("exact", exact); alarmSettings.put("wakeup", wakeup); @@ -389,6 +417,8 @@ public static void reschedulePersistentAlarms(Context context) { } try { JSONObject alarm = new JSONObject(json); + boolean alarmClock = alarm.getBoolean("alarmClock"); + boolean allowWhileIdle = alarm.getBoolean("allowWhileIdle"); boolean repeating = alarm.getBoolean("repeating"); boolean exact = alarm.getBoolean("exact"); boolean wakeup = alarm.getBoolean("wakeup"); @@ -398,6 +428,8 @@ public static void reschedulePersistentAlarms(Context context) { scheduleAlarm( context, requestCode, + alarmClock, + allowWhileIdle, repeating, exact, wakeup, diff --git a/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AndroidAlarmManagerPlugin.java b/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AndroidAlarmManagerPlugin.java index b81df8c050a9..6a7239314caa 100644 --- a/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AndroidAlarmManagerPlugin.java +++ b/packages/android_alarm_manager/android/src/main/java/io/flutter/plugins/androidalarmmanager/AndroidAlarmManagerPlugin.java @@ -166,17 +166,28 @@ public boolean onViewDestroy(FlutterNativeView nativeView) { static final class OneShotRequest { static OneShotRequest fromJson(JSONArray json) throws JSONException { int requestCode = json.getInt(0); - boolean exact = json.getBoolean(1); - boolean wakeup = json.getBoolean(2); - long startMillis = json.getLong(3); - boolean rescheduleOnReboot = json.getBoolean(4); - long callbackHandle = json.getLong(5); + boolean alarmClock = json.getBoolean(1); + boolean allowWhileIdle = json.getBoolean(2); + boolean exact = json.getBoolean(3); + boolean wakeup = json.getBoolean(4); + long startMillis = json.getLong(5); + boolean rescheduleOnReboot = json.getBoolean(6); + long callbackHandle = json.getLong(7); return new OneShotRequest( - requestCode, exact, wakeup, startMillis, rescheduleOnReboot, callbackHandle); + requestCode, + alarmClock, + allowWhileIdle, + exact, + wakeup, + startMillis, + rescheduleOnReboot, + callbackHandle); } final int requestCode; + final boolean alarmClock; + final boolean allowWhileIdle; final boolean exact; final boolean wakeup; final long startMillis; @@ -185,12 +196,16 @@ static OneShotRequest fromJson(JSONArray json) throws JSONException { OneShotRequest( int requestCode, + boolean alarmClock, + boolean allowWhileIdle, boolean exact, boolean wakeup, long startMillis, boolean rescheduleOnReboot, long callbackHandle) { this.requestCode = requestCode; + this.alarmClock = alarmClock; + this.allowWhileIdle = allowWhileIdle; this.exact = exact; this.wakeup = wakeup; this.startMillis = startMillis; diff --git a/packages/android_alarm_manager/lib/android_alarm_manager.dart b/packages/android_alarm_manager/lib/android_alarm_manager.dart index 52486e989d85..228112a847c8 100644 --- a/packages/android_alarm_manager/lib/android_alarm_manager.dart +++ b/packages/android_alarm_manager/lib/android_alarm_manager.dart @@ -83,9 +83,16 @@ class AndroidAlarmManager { /// The timer is uniquely identified by `id`. Calling this function again /// again with the same `id` will cancel and replace the existing timer. /// + /// If `alarmClock` is passed as `true`, the timer will be created with + /// Android's `AlarmManagerCompat.setAlarmClock`. + /// + /// If `allowWhileIdle` is passed as `true`, the timer will be created with + /// Android's `AlarmManagerCompat.setExactAndAllowWhileIdle` or + /// `AlarmManagerCompat.setAndAllowWhileIdle`. + /// /// If `exact` is passed as `true`, the timer will be created with Android's - /// `AlarmManager.setRepeating`. When `exact` is `false` (the default), the - /// timer will be created with `AlarmManager.setInexactRepeating`. + /// `AlarmManagerCompat.setExact`. When `exact` is `false` (the default), the + /// timer will be created with `AlarmManager.set`. /// /// If `wakeup` is passed as `true`, the device will be woken up when the /// alarm fires. If `wakeup` is false (the default), the device will not be @@ -101,6 +108,8 @@ class AndroidAlarmManager { Duration delay, int id, dynamic Function() callback, { + bool alarmClock = false, + bool allowWhileIdle = false, bool exact = false, bool wakeup = false, bool rescheduleOnReboot = false, @@ -113,6 +122,8 @@ class AndroidAlarmManager { } final bool r = await _channel.invokeMethod('Alarm.oneShot', [ id, + alarmClock, + allowWhileIdle, exact, wakeup, first, diff --git a/packages/android_alarm_manager/pubspec.yaml b/packages/android_alarm_manager/pubspec.yaml index a59e7babee77..90907d9908a0 100644 --- a/packages/android_alarm_manager/pubspec.yaml +++ b/packages/android_alarm_manager/pubspec.yaml @@ -1,7 +1,7 @@ name: android_alarm_manager description: Flutter plugin for accessing the Android AlarmManager service, and running Dart code in the background when alarms fire. -version: 0.4.1+8 +version: 0.4.2 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/android_alarm_manager From a0acfa72fe1968161d85c998c6834bc3d5919158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlio=20Cesar=20Bueno=20Cotta?= Date: Wed, 24 Jul 2019 12:31:23 -0300 Subject: [PATCH 89/94] [path_provider] Add support to access getApplicationSupportDirectory on Android (#1891) * add support to access android filesDir --- packages/path_provider/CHANGELOG.md | 6 ++++++ .../plugins/pathprovider/PathProviderPlugin.java | 13 ++++++++++++- packages/path_provider/lib/path_provider.dart | 7 +++---- packages/path_provider/pubspec.yaml | 2 +- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/path_provider/CHANGELOG.md b/packages/path_provider/CHANGELOG.md index ea956fcc766f..2e7f5ad33464 100644 --- a/packages/path_provider/CHANGELOG.md +++ b/packages/path_provider/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.2.0 + +* On Android, `getApplicationSupportDirectory` is now supported using `getFilesDir`. +* `getExternalStorageDirectory` now returns `null` instead of throwing an + exception if no external files directory is available. + ## 1.1.2 * `getExternalStorageDirectory` now uses `getExternalFilesDir` on Android. diff --git a/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java b/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java index ae432639f75a..f8448cbc15d6 100644 --- a/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java +++ b/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java @@ -10,6 +10,7 @@ import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.PluginRegistry.Registrar; import io.flutter.util.PathUtils; +import java.io.File; public class PathProviderPlugin implements MethodCallHandler { private final Registrar mRegistrar; @@ -37,6 +38,8 @@ public void onMethodCall(MethodCall call, Result result) { case "getStorageDirectory": result.success(getPathProviderStorageDirectory()); break; + case "getApplicationSupportDirectory": + result.success(getApplicationSupportDirectory()); default: result.notImplemented(); } @@ -46,11 +49,19 @@ private String getPathProviderTemporaryDirectory() { return mRegistrar.context().getCacheDir().getPath(); } + private String getApplicationSupportDirectory() { + return PathUtils.getFilesDir(mRegistrar.context()); + } + private String getPathProviderApplicationDocumentsDirectory() { return PathUtils.getDataDirectory(mRegistrar.context()); } private String getPathProviderStorageDirectory() { - return mRegistrar.context().getExternalFilesDir(null).getAbsolutePath(); + final File dir = mRegistrar.context().getExternalFilesDir(null); + if (dir == null) { + return null; + } + return dir.getAbsolutePath(); } } diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 10755873c321..f834566cd71e 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -39,15 +39,14 @@ Future getTemporaryDirectory() async { /// On iOS, this uses the `NSApplicationSupportDirectory` API. /// If this directory does not exist, it is created automatically. /// -/// On Android, this function throws an [UnsupportedError]. +/// On Android, this function uses the `getFilesDir` API on the context. Future getApplicationSupportDirectory() async { - if (!Platform.isIOS) - throw UnsupportedError("getApplicationSupportDirectory requires iOS"); final String path = await _channel.invokeMethod('getApplicationSupportDirectory'); if (path == null) { return null; } + return Directory(path); } @@ -58,7 +57,7 @@ Future getApplicationSupportDirectory() async { /// [getApplicationSupportDirectory] instead if the data is not user-generated. /// /// On Android, this uses the `getDataDirectory` API on the context. Consider -/// using getExternalStorageDirectory instead if data is intended to be visible +/// using [getExternalStorageDirectory] instead if data is intended to be visible /// to the user. Future getApplicationDocumentsDirectory() async { final String path = diff --git a/packages/path_provider/pubspec.yaml b/packages/path_provider/pubspec.yaml index 96f248625b8a..2eed0ae7bd9d 100644 --- a/packages/path_provider/pubspec.yaml +++ b/packages/path_provider/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for getting commonly used locations on the Android & iOS file systems, such as the temp and app data directories. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider -version: 1.1.2 +version: 1.2.0 flutter: plugin: From af86b9db204d4fee2d0eeabb2325007ec5f20424 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Wed, 24 Jul 2019 14:26:05 -0700 Subject: [PATCH 90/94] [package_info] [location_background] Fix remaining Android compiler warnings (#1884) * Fix Android compiler warnings * Fix deprecation warnings for location plugin * Specify min Flutter SDK --- packages/location_background/CHANGELOG.md | 4 ++++ .../lib/location_background_plugin.dart | 17 ++++------------- packages/location_background/pubspec.yaml | 4 ++-- packages/package_info/CHANGELOG.md | 4 ++++ .../plugins/packageinfo/PackageInfoPlugin.java | 4 ++-- packages/package_info/pubspec.yaml | 2 +- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/packages/location_background/CHANGELOG.md b/packages/location_background/CHANGELOG.md index e9815106d525..25c67329556f 100644 --- a/packages/location_background/CHANGELOG.md +++ b/packages/location_background/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.0+2 + +* Fix Dart deprecation warnings. + ## 0.1.0+1 * Log a more detailed warning at build time about the previous AndroidX diff --git a/packages/location_background/lib/location_background_plugin.dart b/packages/location_background/lib/location_background_plugin.dart index 479862e7209d..f5ff556966fb 100644 --- a/packages/location_background/lib/location_background_plugin.dart +++ b/packages/location_background/lib/location_background_plugin.dart @@ -117,11 +117,8 @@ class LocationBackgroundPlugin { final CallbackHandle handle = PluginUtilities.getCallbackHandle(_backgroundCallbackDispatcher); assert(handle != null, 'Unable to lookup callback.'); - _channel - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - .invokeMethod(_kStartHeadlessService, [handle.toRawHandle()]); + _channel.invokeMethod( + _kStartHeadlessService, [handle.toRawHandle()]); } // The method channel we'll use to communicate with the native portion of our @@ -147,10 +144,7 @@ class LocationBackgroundPlugin { throw ArgumentError.notNull('callback'); } final CallbackHandle handle = PluginUtilities.getCallbackHandle(callback); - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - return _channel.invokeMethod(_kMonitorLocationChanges, [ + return _channel.invokeMethod(_kMonitorLocationChanges, [ handle.toRawHandle(), pauseLocationUpdatesAutomatically, showsBackgroundLocationIndicator, @@ -160,8 +154,5 @@ class LocationBackgroundPlugin { /// Stop all location updates. Future cancelLocationUpdates() => - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - _channel.invokeMethod(_kCancelLocationUpdates); + _channel.invokeMethod(_kCancelLocationUpdates); } diff --git a/packages/location_background/pubspec.yaml b/packages/location_background/pubspec.yaml index ed3b828a81c0..158d3cb77dc0 100644 --- a/packages/location_background/pubspec.yaml +++ b/packages/location_background/pubspec.yaml @@ -2,7 +2,7 @@ name: location_background_plugin description: A new flutter plugin project. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/location_background -version: 0.1.0+1 +version: 0.1.0+2 publish_to: none dependencies: @@ -20,4 +20,4 @@ flutter: environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" - flutter: ">=0.4.4 <2.0.0" + flutter: ">=1.5.0 <2.0.0" diff --git a/packages/package_info/CHANGELOG.md b/packages/package_info/CHANGELOG.md index ebd4bf205714..c2deb475c2f3 100644 --- a/packages/package_info/CHANGELOG.md +++ b/packages/package_info/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+6 + +* Fix Android compiler warnings. + ## 0.4.0+5 * Add iOS-specific warning to README.md. diff --git a/packages/package_info/android/src/main/java/io/flutter/plugins/packageinfo/PackageInfoPlugin.java b/packages/package_info/android/src/main/java/io/flutter/plugins/packageinfo/PackageInfoPlugin.java index e9d3bfb92042..81fae62a1f4f 100644 --- a/packages/package_info/android/src/main/java/io/flutter/plugins/packageinfo/PackageInfoPlugin.java +++ b/packages/package_info/android/src/main/java/io/flutter/plugins/packageinfo/PackageInfoPlugin.java @@ -39,7 +39,7 @@ public void onMethodCall(MethodCall call, Result result) { PackageManager pm = context.getPackageManager(); PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0); - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("appName", info.applicationInfo.loadLabel(pm).toString()); map.put("packageName", context.getPackageName()); map.put("version", info.versionName); @@ -54,11 +54,11 @@ public void onMethodCall(MethodCall call, Result result) { } } + @SuppressWarnings("deprecation") private static long getLongVersionCode(PackageInfo info) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { return info.getLongVersionCode(); } - //noinspection deprecation return info.versionCode; } } diff --git a/packages/package_info/pubspec.yaml b/packages/package_info/pubspec.yaml index 33afe89f4e96..5a2d29444511 100644 --- a/packages/package_info/pubspec.yaml +++ b/packages/package_info/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for querying information about the application package, such as CFBundleVersion on iOS or versionCode on Android. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/package_info -version: 0.4.0+5 +version: 0.4.0+6 flutter: plugin: From a7f8c431c0d94a4455bb03906d8d5a60ecabc169 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Wed, 24 Jul 2019 17:45:06 -0700 Subject: [PATCH 91/94] Final release of the location_background plugin. (#1901) * Update README --- packages/location_background/CHANGELOG.md | 4 ++++ packages/location_background/README.md | 2 ++ packages/location_background/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/location_background/CHANGELOG.md b/packages/location_background/CHANGELOG.md index 25c67329556f..00776c5aff31 100644 --- a/packages/location_background/CHANGELOG.md +++ b/packages/location_background/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.0+3 + +* Update README.md indicating package support status. + ## 0.1.0+2 * Fix Dart deprecation warnings. diff --git a/packages/location_background/README.md b/packages/location_background/README.md index f10adaa31bbe..d4d6b128ebba 100644 --- a/packages/location_background/README.md +++ b/packages/location_background/README.md @@ -2,6 +2,8 @@ An example Flutter plugin that showcases background execution using iOS location services. +**This plugin is not being actively maintained and is not for production use.** An [archive](https://github.com/flutter/plugins/tree/af86b9db204d4fee2d0eeabb2325007ec5f20424/packages/location_background) of previous versions can be found in the Flutter plugins repository. + ## Getting Started **_NOTE: This plugin does not currently have an Android implementation._** diff --git a/packages/location_background/pubspec.yaml b/packages/location_background/pubspec.yaml index 158d3cb77dc0..37be671a585d 100644 --- a/packages/location_background/pubspec.yaml +++ b/packages/location_background/pubspec.yaml @@ -2,7 +2,7 @@ name: location_background_plugin description: A new flutter plugin project. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/location_background -version: 0.1.0+2 +version: 0.1.0+3 publish_to: none dependencies: From fa7961e9108088b5106ed2b14f7f1f0f41ec9b18 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Wed, 24 Jul 2019 17:48:39 -0700 Subject: [PATCH 92/94] Remove the location_background plugin (#1902) --- packages/location_background/CHANGELOG.md | 29 - packages/location_background/LICENSE | 27 - packages/location_background/README.md | 40 -- .../location_background/android/.gitignore | 8 - .../location_background/android/build.gradle | 47 -- .../android/gradle.properties | 1 - .../android/settings.gradle | 1 - .../android/src/main/AndroidManifest.xml | 3 - .../LocationBackgroundPlugin.java | 27 - .../location_background/example/.gitignore | 11 - .../location_background/example/.metadata | 8 - .../location_background/example/README.md | 8 - .../example/android/.gitignore | 10 - .../example/android/app/build.gradle | 60 --- .../example/android/app/gradle.properties | 2 - .../gradle/wrapper/gradle-wrapper.properties | 5 - .../android/app/src/main/AndroidManifest.xml | 39 -- .../MainActivity.java | 13 - .../main/res/drawable/launch_background.xml | 12 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 544 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 442 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 721 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1031 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 1443 -> 0 bytes .../app/src/main/res/values/styles.xml | 8 - .../example/android/build.gradle | 29 - .../example/android/gradle.properties | 1 - .../gradle/wrapper/gradle-wrapper.properties | 6 - .../example/android/settings.gradle | 15 - .../example/ios/.gitignore | 42 -- .../ios/Flutter/AppFrameworkInfo.plist | 30 -- .../example/ios/Flutter/Debug.xcconfig | 2 - .../example/ios/Flutter/Release.xcconfig | 2 - .../ios/Runner.xcodeproj/project.pbxproj | 506 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/xcschemes/Runner.xcscheme | 91 ---- .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../example/ios/Runner/AppDelegate.h | 6 - .../example/ios/Runner/AppDelegate.m | 13 - .../AppIcon.appiconset/Contents.json | 122 ----- .../Icon-App-1024x1024@1x.png | Bin 11112 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 564 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 1283 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 1588 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 1025 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 1716 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 1920 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 1283 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 1895 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 2665 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 2665 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 3831 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 1888 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 3294 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 3612 -> 0 bytes .../LaunchImage.imageset/Contents.json | 23 - .../LaunchImage.imageset/LaunchImage.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/README.md | 5 - .../Runner/Base.lproj/LaunchScreen.storyboard | 37 -- .../ios/Runner/Base.lproj/Main.storyboard | 30 -- .../example/ios/Runner/Info.plist | 61 --- .../example/ios/Runner/main.m | 10 - .../example/lib/background.dart | 24 - .../location_background/example/lib/main.dart | 130 ----- .../location_background/example/pubspec.yaml | 59 -- packages/location_background/ios/.gitignore | 31 -- .../location_background/ios/Assets/.gitkeep | 0 .../ios/Classes/LocationBackgroundPlugin.h | 11 - .../ios/Classes/LocationBackgroundPlugin.m | 227 -------- .../ios/location_background_plugin.podspec | 23 - .../lib/location_background_plugin.dart | 158 ------ packages/location_background/pubspec.yaml | 23 - 75 files changed, 2101 deletions(-) delete mode 100644 packages/location_background/CHANGELOG.md delete mode 100644 packages/location_background/LICENSE delete mode 100644 packages/location_background/README.md delete mode 100644 packages/location_background/android/.gitignore delete mode 100644 packages/location_background/android/build.gradle delete mode 100644 packages/location_background/android/gradle.properties delete mode 100644 packages/location_background/android/settings.gradle delete mode 100644 packages/location_background/android/src/main/AndroidManifest.xml delete mode 100644 packages/location_background/android/src/main/java/com/flutter/example/locationbackgroundplugin/LocationBackgroundPlugin.java delete mode 100644 packages/location_background/example/.gitignore delete mode 100644 packages/location_background/example/.metadata delete mode 100644 packages/location_background/example/README.md delete mode 100644 packages/location_background/example/android/.gitignore delete mode 100644 packages/location_background/example/android/app/build.gradle delete mode 100644 packages/location_background/example/android/app/gradle.properties delete mode 100644 packages/location_background/example/android/app/gradle/wrapper/gradle-wrapper.properties delete mode 100644 packages/location_background/example/android/app/src/main/AndroidManifest.xml delete mode 100644 packages/location_background/example/android/app/src/main/java/com/flutter/example/locationbackgroundpluginexample/MainActivity.java delete mode 100644 packages/location_background/example/android/app/src/main/res/drawable/launch_background.xml delete mode 100644 packages/location_background/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 packages/location_background/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 packages/location_background/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 packages/location_background/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 packages/location_background/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 packages/location_background/example/android/app/src/main/res/values/styles.xml delete mode 100644 packages/location_background/example/android/build.gradle delete mode 100644 packages/location_background/example/android/gradle.properties delete mode 100644 packages/location_background/example/android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 packages/location_background/example/android/settings.gradle delete mode 100644 packages/location_background/example/ios/.gitignore delete mode 100644 packages/location_background/example/ios/Flutter/AppFrameworkInfo.plist delete mode 100644 packages/location_background/example/ios/Flutter/Debug.xcconfig delete mode 100644 packages/location_background/example/ios/Flutter/Release.xcconfig delete mode 100644 packages/location_background/example/ios/Runner.xcodeproj/project.pbxproj delete mode 100644 packages/location_background/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 packages/location_background/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 packages/location_background/example/ios/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 packages/location_background/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 packages/location_background/example/ios/Runner/AppDelegate.h delete mode 100644 packages/location_background/example/ios/Runner/AppDelegate.m delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png delete mode 100644 packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md delete mode 100644 packages/location_background/example/ios/Runner/Base.lproj/LaunchScreen.storyboard delete mode 100644 packages/location_background/example/ios/Runner/Base.lproj/Main.storyboard delete mode 100644 packages/location_background/example/ios/Runner/Info.plist delete mode 100644 packages/location_background/example/ios/Runner/main.m delete mode 100644 packages/location_background/example/lib/background.dart delete mode 100644 packages/location_background/example/lib/main.dart delete mode 100644 packages/location_background/example/pubspec.yaml delete mode 100644 packages/location_background/ios/.gitignore delete mode 100644 packages/location_background/ios/Assets/.gitkeep delete mode 100644 packages/location_background/ios/Classes/LocationBackgroundPlugin.h delete mode 100644 packages/location_background/ios/Classes/LocationBackgroundPlugin.m delete mode 100644 packages/location_background/ios/location_background_plugin.podspec delete mode 100644 packages/location_background/lib/location_background_plugin.dart delete mode 100644 packages/location_background/pubspec.yaml diff --git a/packages/location_background/CHANGELOG.md b/packages/location_background/CHANGELOG.md deleted file mode 100644 index 00776c5aff31..000000000000 --- a/packages/location_background/CHANGELOG.md +++ /dev/null @@ -1,29 +0,0 @@ -## 0.1.0+3 - -* Update README.md indicating package support status. - -## 0.1.0+2 - -* Fix Dart deprecation warnings. - -## 0.1.0+1 - -* Log a more detailed warning at build time about the previous AndroidX - migration. - -## 0.1.0 - -* **Breaking change**. Migrate from the deprecated original Android Support - Library to AndroidX. This shouldn't result in any functional changes, but it - requires any Android apps using this plugin to [also - migrate](https://developer.android.com/jetpack/androidx/migrate) if they're - using the original support library. - -## 0.0.2 - -* Added missing flutter_test package dependency. -* Added missing flutter version requirements. - -## 0.0.1 - -* Initial release. diff --git a/packages/location_background/LICENSE b/packages/location_background/LICENSE deleted file mode 100644 index f7480f268093..000000000000 --- a/packages/location_background/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright 2018 The Chromium Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/location_background/README.md b/packages/location_background/README.md deleted file mode 100644 index d4d6b128ebba..000000000000 --- a/packages/location_background/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Flutter Background Execution Sample - LocationBackgroundPlugin - -An example Flutter plugin that showcases background execution using iOS location services. - -**This plugin is not being actively maintained and is not for production use.** An [archive](https://github.com/flutter/plugins/tree/af86b9db204d4fee2d0eeabb2325007ec5f20424/packages/location_background) of previous versions can be found in the Flutter plugins repository. - -## Getting Started - -**_NOTE: This plugin does not currently have an Android implementation._** - -To import, add the following to your Dart file: - -```dart -import 'package:location_background/location_background.dart'; -``` - -Example usage: - -```dart -import 'package:location_background/location_background.dart'; - -final locationManager = LocationBackgroundPlugin(); - -void locationUpdateCallback(Location location) { - print('Location Update: $location'); -} - -Future startMonitoringLocationChanges() => - locationManager.monitorSignificantLocationChanges(locationUpdateCallback); - -Future stopMonitoringLocationChanges() => - locationManager.cancelLocationUpdates(); -``` - -**WARNING:** do not maintain volatile state or perform long running operations in the location update callback. There is no guarantee from the system for how long a process can perform background processing after a location update, and the Dart isolate may shutdown during execution at the request of the system. - -For help getting started with Flutter, view our online -[documentation](https://flutter.io/). - -For help on editing plugin code, view the [documentation](https://flutter.io/platform-plugins/#edit-code). diff --git a/packages/location_background/android/.gitignore b/packages/location_background/android/.gitignore deleted file mode 100644 index c6cbe562a427..000000000000 --- a/packages/location_background/android/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures diff --git a/packages/location_background/android/build.gradle b/packages/location_background/android/build.gradle deleted file mode 100644 index be694b19b05c..000000000000 --- a/packages/location_background/android/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ -def PLUGIN = "location_background"; -def ANDROIDX_WARNING = "flutterPluginsAndroidXWarning"; -gradle.buildFinished { buildResult -> - if (buildResult.failure && !rootProject.ext.has(ANDROIDX_WARNING)) { - println ' *********************************************************' - println 'WARNING: This version of ' + PLUGIN + ' will break your Android build if it or its dependencies aren\'t compatible with AndroidX.' - println ' See https://goo.gl/CP92wY for more information on the problem and how to fix it.' - println ' This warning prints for all Android build failures. The real root cause of the error may be unrelated.' - println ' *********************************************************' - rootProject.ext.set(ANDROIDX_WARNING, true); - } -} - -group 'com.flutter.example.locationbackgroundplugin' -version '1.0-SNAPSHOT' - -buildscript { - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:3.3.0' - } -} - -rootProject.allprojects { - repositories { - google() - jcenter() - } -} - -apply plugin: 'com.android.library' - -android { - compileSdkVersion 28 - - defaultConfig { - minSdkVersion 16 - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - lintOptions { - disable 'InvalidPackage' - } -} diff --git a/packages/location_background/android/gradle.properties b/packages/location_background/android/gradle.properties deleted file mode 100644 index 8bd86f680510..000000000000 --- a/packages/location_background/android/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M diff --git a/packages/location_background/android/settings.gradle b/packages/location_background/android/settings.gradle deleted file mode 100644 index 9de328a10a64..000000000000 --- a/packages/location_background/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'location_background_plugin' diff --git a/packages/location_background/android/src/main/AndroidManifest.xml b/packages/location_background/android/src/main/AndroidManifest.xml deleted file mode 100644 index 63ea5ef7db02..000000000000 --- a/packages/location_background/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/packages/location_background/android/src/main/java/com/flutter/example/locationbackgroundplugin/LocationBackgroundPlugin.java b/packages/location_background/android/src/main/java/com/flutter/example/locationbackgroundplugin/LocationBackgroundPlugin.java deleted file mode 100644 index 015bec387247..000000000000 --- a/packages/location_background/android/src/main/java/com/flutter/example/locationbackgroundplugin/LocationBackgroundPlugin.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.flutter.example.locationbackgroundplugin; - -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; -import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugin.common.PluginRegistry.Registrar; - -// TODO(bkonyi): add Android implementation. -// This would likely involve something along the lines of: -// - Create a LocationBackgroundPluginService which extends Service -// - Use requestLocationUpdates with minDistance parameter set to 500m to match -// iOS behaviour. See https://developer.android.com/reference/android/location/LocationManager -// - Similar plugin structure to `android_alarm_manager` found here: -// https://github.com/flutter/plugins/tree/master/packages/android_alarm_manager -public class LocationBackgroundPlugin implements MethodCallHandler { - public static void registerWith(Registrar registrar) { - final MethodChannel channel = - new MethodChannel(registrar.messenger(), "location_background_plugin"); - channel.setMethodCallHandler(new LocationBackgroundPlugin()); - } - - @Override - public void onMethodCall(MethodCall call, Result result) { - result.notImplemented(); - } -} diff --git a/packages/location_background/example/.gitignore b/packages/location_background/example/.gitignore deleted file mode 100644 index af17aaf5b6d4..000000000000 --- a/packages/location_background/example/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -.DS_Store -.atom/ -.dart_tool/ -.idea -.vscode/ -.packages -.pub/ -build/ -ios/.generated/ -packages -.flutter-plugins diff --git a/packages/location_background/example/.metadata b/packages/location_background/example/.metadata deleted file mode 100644 index 2937c45a1609..000000000000 --- a/packages/location_background/example/.metadata +++ /dev/null @@ -1,8 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: d6d874474b21b512aac03f1dcd0d3b88835cdcdd - channel: master diff --git a/packages/location_background/example/README.md b/packages/location_background/example/README.md deleted file mode 100644 index dc994c5c7fcb..000000000000 --- a/packages/location_background/example/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Flutter Background Plugin Example for iOS. - -Demonstrates how to use the LocationBackgroundPlugin, a sample plugin showcasing Flutter background execution on iOS. - -## Getting Started - -For help getting started with Flutter, view our online -[documentation](https://flutter.io/). diff --git a/packages/location_background/example/android/.gitignore b/packages/location_background/example/android/.gitignore deleted file mode 100644 index 65b7315af1b6..000000000000 --- a/packages/location_background/example/android/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -*.iml -*.class -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures -GeneratedPluginRegistrant.java diff --git a/packages/location_background/example/android/app/build.gradle b/packages/location_background/example/android/app/build.gradle deleted file mode 100644 index cde213b0cc17..000000000000 --- a/packages/location_background/example/android/app/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion 28 - - lintOptions { - disable 'InvalidPackage' - } - - defaultConfig { - applicationId "com.flutter.example.locationbackgroundpluginexample" - minSdkVersion 16 - targetSdkVersion 28 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' -} diff --git a/packages/location_background/example/android/app/gradle.properties b/packages/location_background/example/android/app/gradle.properties deleted file mode 100644 index 5465fec0ecad..000000000000 --- a/packages/location_background/example/android/app/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -android.enableJetifier=true -android.useAndroidX=true \ No newline at end of file diff --git a/packages/location_background/example/android/app/gradle/wrapper/gradle-wrapper.properties b/packages/location_background/example/android/app/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 9a4163a4f5ee..000000000000 --- a/packages/location_background/example/android/app/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/packages/location_background/example/android/app/src/main/AndroidManifest.xml b/packages/location_background/example/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index a59dc3e84742..000000000000 --- a/packages/location_background/example/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/packages/location_background/example/android/app/src/main/java/com/flutter/example/locationbackgroundpluginexample/MainActivity.java b/packages/location_background/example/android/app/src/main/java/com/flutter/example/locationbackgroundpluginexample/MainActivity.java deleted file mode 100644 index 6dc54e746158..000000000000 --- a/packages/location_background/example/android/app/src/main/java/com/flutter/example/locationbackgroundpluginexample/MainActivity.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.flutter.example.locationbackgroundpluginexample; - -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/location_background/example/android/app/src/main/res/drawable/launch_background.xml b/packages/location_background/example/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f88420..000000000000 --- a/packages/location_background/example/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/packages/location_background/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/location_background/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4b7b0906d62b1847e87f15cdcacf6a4f29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ diff --git a/packages/location_background/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/location_background/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17987b79bb8a35cc66c3c1fd44f5a5526c1b78be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ diff --git a/packages/location_background/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/location_background/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d34e7a88e3f88bea192c3a370d44689c3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof diff --git a/packages/location_background/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/location_background/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372eebdb28e45604e46eeda8dd24651419bc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` diff --git a/packages/location_background/example/android/app/src/main/res/values/styles.xml b/packages/location_background/example/android/app/src/main/res/values/styles.xml deleted file mode 100644 index 00fa4417cfbe..000000000000 --- a/packages/location_background/example/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/packages/location_background/example/android/build.gradle b/packages/location_background/example/android/build.gradle deleted file mode 100644 index 541636cc492a..000000000000 --- a/packages/location_background/example/android/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -buildscript { - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:3.3.0' - } -} - -allprojects { - repositories { - google() - jcenter() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/packages/location_background/example/android/gradle.properties b/packages/location_background/example/android/gradle.properties deleted file mode 100644 index 8bd86f680510..000000000000 --- a/packages/location_background/example/android/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M diff --git a/packages/location_background/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/location_background/example/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 2819f022f1fd..000000000000 --- a/packages/location_background/example/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Fri Jun 23 08:50:38 CEST 2017 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip diff --git a/packages/location_background/example/android/settings.gradle b/packages/location_background/example/android/settings.gradle deleted file mode 100644 index 5a2f14fb18f6..000000000000 --- a/packages/location_background/example/android/settings.gradle +++ /dev/null @@ -1,15 +0,0 @@ -include ':app' - -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() - -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} - -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} diff --git a/packages/location_background/example/ios/.gitignore b/packages/location_background/example/ios/.gitignore deleted file mode 100644 index 1e1aafd63360..000000000000 --- a/packages/location_background/example/ios/.gitignore +++ /dev/null @@ -1,42 +0,0 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -*.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/flutter_assets/ -/Flutter/App.framework -/Flutter/Flutter.framework -/Flutter/Generated.xcconfig -/ServiceDefinitions.json - -Pods/ diff --git a/packages/location_background/example/ios/Flutter/AppFrameworkInfo.plist b/packages/location_background/example/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 6c2de8086bcd..000000000000 --- a/packages/location_background/example/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - 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/location_background/example/ios/Flutter/Debug.xcconfig b/packages/location_background/example/ios/Flutter/Debug.xcconfig deleted file mode 100644 index e8efba114687..000000000000 --- a/packages/location_background/example/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/packages/location_background/example/ios/Flutter/Release.xcconfig b/packages/location_background/example/ios/Flutter/Release.xcconfig deleted file mode 100644 index 399e9340e6f6..000000000000 --- a/packages/location_background/example/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/packages/location_background/example/ios/Runner.xcodeproj/project.pbxproj b/packages/location_background/example/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index c60c8d57e75d..000000000000 --- a/packages/location_background/example/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,506 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 6F4EF35D20C87745003EB65D /* ios in Resources */ = {isa = PBXBuildFile; fileRef = 6F4EF35C20C87745003EB65D /* ios */; }; - 6F4EF35F20CEE77B003EB65D /* (null) in Resources */ = {isa = PBXBuildFile; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; - 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; }; - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; - 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - A3F65306835CE59B322AC687 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A34E313CEC116C1DD761CAB8 /* libPods-Runner.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; - 6F4EF35C20C87745003EB65D /* ios */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ios; path = ../../ios; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A34E313CEC116C1DD761CAB8 /* 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 */, - A3F65306835CE59B322AC687 /* libPods-Runner.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 0A21A2A450A05E43A5F34456 /* Pods */ = { - isa = PBXGroup; - children = ( - ); - name = Pods; - sourceTree = ""; - }; - 338C65C4CFC9350F63D48DBD /* Frameworks */ = { - isa = PBXGroup; - children = ( - A34E313CEC116C1DD761CAB8 /* libPods-Runner.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, - 3B80C3931E831B6300D905FE /* App.framework */, - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 6F4EF35C20C87745003EB65D /* ios */, - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - 0A21A2A450A05E43A5F34456 /* Pods */, - 338C65C4CFC9350F63D48DBD /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - ); - path = Runner; - sourceTree = ""; - }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 97C146F21CF9000F007C117D /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 474F0BE029A66AFB612AF012 /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 9F1ECFBAB8123D3164715BB1 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0910; - ORGANIZATIONNAME = "The Chromium Authors"; - TargetAttributes = { - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = U8PR3Q5466; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 6F4EF35F20CEE77B003EB65D /* (null) in Resources */, - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, - 6F4EF35D20C87745003EB65D /* ios 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"; - }; - 474F0BE029A66AFB612AF012 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; - 9F1ECFBAB8123D3164715BB1 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${PODS_ROOT}/../.symlinks/flutter/ios_debug_sim_unopt/Flutter.framework", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, - 97C146F31CF9000F007C117D /* main.m in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ARCHS = arm64; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = U8PR3Q5466; - 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.flutter.example.locationBackgroundPluginExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ARCHS = arm64; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = U8PR3Q5466; - 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.flutter.example.locationBackgroundPluginExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/packages/location_background/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/location_background/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1d526a16ed0f..000000000000 --- a/packages/location_background/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/packages/location_background/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/location_background/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index f5a8db1a8aa1..000000000000 --- a/packages/location_background/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/location_background/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/location_background/example/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14c74e..000000000000 --- a/packages/location_background/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/packages/location_background/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/location_background/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d68..000000000000 --- a/packages/location_background/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/packages/location_background/example/ios/Runner/AppDelegate.h b/packages/location_background/example/ios/Runner/AppDelegate.h deleted file mode 100644 index 36e21bbf9cf4..000000000000 --- a/packages/location_background/example/ios/Runner/AppDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import - -@interface AppDelegate : FlutterAppDelegate - -@end diff --git a/packages/location_background/example/ios/Runner/AppDelegate.m b/packages/location_background/example/ios/Runner/AppDelegate.m deleted file mode 100644 index 59a72e90be12..000000000000 --- a/packages/location_background/example/ios/Runner/AppDelegate.m +++ /dev/null @@ -1,13 +0,0 @@ -#include "AppDelegate.h" -#include "GeneratedPluginRegistrant.h" - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [GeneratedPluginRegistrant registerWithRegistry:self]; - // Override point for customization after application launch. - return [super application:application didFinishLaunchingWithOptions:launchOptions]; -} - -@end diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fab2d9d..000000000000 --- a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index 3d43d11e66f4de3da27ed045ca4fe38ad8b48094..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11112 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 P-1+_A+?hGkL;m(J7kc&K diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 28c6bf03016f6c994b70f38d1b7346e5831b531f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 564 zcmV-40?Yl0P)Px$?ny*JR5%f>l)FnDQ543{x%ZCiu33$Wg!pQFfT_}?5Q|_VSlIbLC`dpoMXL}9 zHfd9&47Mo(7D231gb+kjFxZHS4-m~7WurTH&doVX2KI5sU4v(sJ1@T9eCIKPjsqSr z)C01LsCxk=72-vXmX}CQD#BD;Cthymh&~=f$Q8nn0J<}ZrusBy4PvRNE}+1ceuj8u z0mW5k8fmgeLnTbWHGwfKA3@PdZxhn|PypR&^p?weGftrtCbjF#+zk_5BJh7;0`#Wr zgDpM_;Ax{jO##IrT`Oz;MvfwGfV$zD#c2xckpcXC6oou4ML~ezCc2EtnsQTB4tWNg z?4bkf;hG7IMfhgNI(FV5Gs4|*GyMTIY0$B=_*mso9Ityq$m^S>15>-?0(zQ<8Qy<_TjHE33(?_M8oaM zyc;NxzRVK@DL6RJnX%U^xW0Gpg(lXp(!uK1v0YgHjs^ZXSQ|m#lV7ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index f091b6b0bca859a3f474b03065bef75ba58a9e4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index d0ef06e7edb86cdfe0d15b4b0d98334a86163658..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1716 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 diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index c8f9ed8f5cee1c98386d13b17e89f719e83555b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index a6d6b8609df07bf62e5100a53a01510388bd2b22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index a6d6b8609df07bf62e5100a53a01510388bd2b22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 75b2d164a5a98e212cca15ea7bf2ab5de5108680..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3831 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 diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index c4df70d39da7941ef3f6dcb7f06a192d8dcb308d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b70f1..000000000000 --- a/packages/location_background/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/location_background/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/location_background/example/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c7c939..000000000000 --- a/packages/location_background/example/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/location_background/example/ios/Runner/Base.lproj/Main.storyboard b/packages/location_background/example/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index 996dae97aa46..000000000000 --- a/packages/location_background/example/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/location_background/example/ios/Runner/Info.plist b/packages/location_background/example/ios/Runner/Info.plist deleted file mode 100644 index a6231bd83d15..000000000000 --- a/packages/location_background/example/ios/Runner/Info.plist +++ /dev/null @@ -1,61 +0,0 @@ - - - - - NSLocationAlwaysAndWhenInUseUsageDescription - This is the plist item for NSLocationWhenInUseUsageDescription - NSLocationWhenInUseUsageDescription - This is the plist item for NSLocationAlwaysUsageDescription - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - location_background_plugin_example - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - location-services - gps - armv7 - - UIBackgroundModes - - location - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - LSApplicationCategoryType - - UIViewControllerBasedStatusBarAppearance - - - diff --git a/packages/location_background/example/ios/Runner/main.m b/packages/location_background/example/ios/Runner/main.m deleted file mode 100644 index f012886fefc4..000000000000 --- a/packages/location_background/example/ios/Runner/main.m +++ /dev/null @@ -1,10 +0,0 @@ -#import -#import -#import "AppDelegate.h" -#import "LocationBackgroundPlugin.h" - -int main(int argc, char* argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/packages/location_background/example/lib/background.dart b/packages/location_background/example/lib/background.dart deleted file mode 100644 index 95ee633c448b..000000000000 --- a/packages/location_background/example/lib/background.dart +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file - -import 'dart:isolate'; -import 'dart:ui'; -import 'package:location_background_plugin/location_background_plugin.dart'; - -const String kLocationPluginPortName = 'location_plugin_port'; - -/// This is an example of a callback for LocationBackgroundPlugin's -/// `startMonitoringLocation`. A callback can be defined anywhere in an -/// application's code, but cannot be from another program. -class LocationMonitor { - static void locationCallback(Location location) { - print('Background Location: $location'); - // We use isolate ports to communicate between the main isolate and spawned - // isolates since they do not share memory. The port lookup will return - // null if the UI isolate has explicitly removed the mapping on shutdown. - final SendPort uiSendPort = - IsolateNameServer.lookupPortByName(kLocationPluginPortName); - uiSendPort?.send(location.toJson()); - } -} diff --git a/packages/location_background/example/lib/main.dart b/packages/location_background/example/lib/main.dart deleted file mode 100644 index 986890919b51..000000000000 --- a/packages/location_background/example/lib/main.dart +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file - -import 'dart:isolate'; -import 'dart:ui' hide TextStyle; - -import 'package:flutter/material.dart'; -import 'package:location_background_plugin/location_background_plugin.dart'; - -import 'background.dart'; - -void main() { - runApp(MyApp()); -} - -class MyApp extends StatefulWidget { - @override - _MyAppState createState() { - return _MyAppState(); - } -} - -class _MyAppState extends State { - ReceivePort _foregroundPort = ReceivePort(); - LocationBackgroundPlugin _locationPlugin; - Location _lastLocation; - bool _isTracking = false; - - @override - void initState() { - _lastLocation = Location(-1.0, 0.0, 0.0, -1.0, -1.0); - super.initState(); - initPlatformState(); - } - - void initPlatformState() { - // The IsolateNameServer allows for us to create a mapping between a String - // and a SendPort that is managed by the Flutter engine. A SendPort can - // then be looked up elsewhere, like a background callback, to establish - // communication channels between isolates that were not spawned by one - // another. - if (!IsolateNameServer.registerPortWithName( - _foregroundPort.sendPort, kLocationPluginPortName)) { - throw 'Unable to register port!'; - } - - // Listen on the port for location updates from our background callback. - _foregroundPort.listen((dynamic message) { - final Location location = Location.fromJson(message); - print('UI Location: $location'); - setState(() { - _lastLocation = location; - }); - }, onDone: () { - // Remove the port mapping just in case the UI is shutting down but - // background isolate is continuing to run. - IsolateNameServer.removePortNameMapping(kLocationPluginPortName); - }); - _locationPlugin ??= LocationBackgroundPlugin(); - } - - String _padZero2(int i) => i.toString().padLeft(2, '0'); - - String _formatTime(DateTime t) { - t = t.toLocal(); - final int hour = t.hour; - final String minute = _padZero2(t.minute); - final String second = _padZero2(t.second); - final int year = t.year; - return '$hour:$minute:$second $year'; - } - - @override - Widget build(BuildContext context) { - const TextStyle boldText = TextStyle(fontWeight: FontWeight.bold); - return MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Background Plugin Demo'), - ), - body: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Center( - child: Text( - 'Update Time:', - style: boldText, - )), - Center(child: Text('${_formatTime(_lastLocation.time)}')), - const Center( - child: Text( - 'Location:', - style: boldText, - )), - Center( - child: Text( - '(${_lastLocation.latitude}, ${_lastLocation.longitude})')), - const Center( - child: Text( - 'Altitude:', - style: boldText, - )), - Center(child: Text('${_lastLocation.altitude} m')), - const Center( - child: Text( - 'Speed (meters per second)', - style: boldText, - )), - Center(child: Text('${_lastLocation.speed} m/s')), - Center( - child: RaisedButton( - child: - Text(_isTracking ? 'Stop Tracking' : 'Start Tracking'), - onPressed: () async { - if (!_isTracking) { - await _locationPlugin.monitorSignificantLocationChanges( - LocationMonitor.locationCallback); - } else { - await _locationPlugin.cancelLocationUpdates(); - } - setState(() { - _isTracking = !_isTracking; - }); - }, - )) - ]))); - } -} diff --git a/packages/location_background/example/pubspec.yaml b/packages/location_background/example/pubspec.yaml deleted file mode 100644 index bdcb7dad255a..000000000000 --- a/packages/location_background/example/pubspec.yaml +++ /dev/null @@ -1,59 +0,0 @@ -name: location_background_plugin_example -description: Demonstrates how to use the location_background_plugin plugin. - -dependencies: - flutter: - sdk: flutter - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.0 - - location_background_plugin: - path: ../ - -dev_dependencies: - flutter_test: - sdk: flutter - -# For information on the generic Dart part of this file, see the -# following page: https://www.dartlang.org/tools/pub/pubspec - -# The following section is specific to Flutter. -flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.io/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.io/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.io/custom-fonts/#from-packages diff --git a/packages/location_background/ios/.gitignore b/packages/location_background/ios/.gitignore deleted file mode 100644 index 956c87f3aa28..000000000000 --- a/packages/location_background/ios/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -.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/location_background/ios/Assets/.gitkeep b/packages/location_background/ios/Assets/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/packages/location_background/ios/Classes/LocationBackgroundPlugin.h b/packages/location_background/ios/Classes/LocationBackgroundPlugin.h deleted file mode 100644 index a84a129df1f8..000000000000 --- a/packages/location_background/ios/Classes/LocationBackgroundPlugin.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import - -#import - -@interface LocationBackgroundPlugin : NSObject { -} -@end diff --git a/packages/location_background/ios/Classes/LocationBackgroundPlugin.m b/packages/location_background/ios/Classes/LocationBackgroundPlugin.m deleted file mode 100644 index 24211c429541..000000000000 --- a/packages/location_background/ios/Classes/LocationBackgroundPlugin.m +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "LocationBackgroundPlugin.h" - -#import - -@implementation LocationBackgroundPlugin { - CLLocationManager *_locationManager; - FlutterEngine *_headlessEngine; - FlutterMethodChannel *_callbackChannel; - FlutterMethodChannel *_mainChannel; - NSObject *_registrar; - NSUserDefaults *_persistentState; - int64_t _onLocationUpdateHandle; -} - -static LocationBackgroundPlugin *instance = nil; - -#pragma mark FlutterPlugin Methods - -+ (void)registerWithRegistrar:(NSObject *)registrar { - @synchronized(self) { - if (instance == nil) { - instance = [[LocationBackgroundPlugin alloc] init:registrar]; - [registrar addApplicationDelegate:instance]; - } - } -} - -// When iOS relaunches us due to a significant location change, we need to -// reinitialize our plugin state. This includes relaunching the headless -// service, retrieving our cached callback handles and location manager -// settings, and restarting the location manager to actually receive the -// location event. -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Check to see if we're being launched due to a location event. - if (launchOptions[UIApplicationLaunchOptionsLocationKey] != nil) { - // Restart the headless service. - [self startHeadlessService:[self getCallbackDispatcherHandle]]; - // Grab our callback handles and location manager state. - _onLocationUpdateHandle = [self getLocationCallbackHandle]; - _locationManager.pausesLocationUpdatesAutomatically = - [self getPausesLocationUpdatesAutomatically]; - if (@available(iOS 11.0, *)) { - _locationManager.showsBackgroundLocationIndicator = - [self getShowsBackgroundLocationIndicator]; - } - if (@available(iOS 9.0, *)) { - _locationManager.allowsBackgroundLocationUpdates = YES; - } - // Finally, restart monitoring for location changes to get our location. - [self->_locationManager startMonitoringSignificantLocationChanges]; - } - - // Note: if we return NO, this vetos the launch of the application. - return YES; -} - -- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - NSArray *arguments = call.arguments; - if ([@"monitorLocationChanges" isEqualToString:call.method]) { - NSAssert(arguments.count == 4, @"Invalid argument count for 'monitorLocationChanges'"); - [self monitorLocationChanges:arguments]; - result(@(YES)); - } else if ([@"startHeadlessService" isEqualToString:call.method]) { - NSAssert(arguments.count == 1, @"Invalid argument count for 'startHeadlessService'"); - [self startHeadlessService:[arguments[0] longValue]]; - } else if ([@"cancelLocationUpdates" isEqualToString:call.method]) { - NSAssert(arguments.count == 0, @"Invalid argument count for 'cancelLocationUpdates'"); - [self stopUpdatingLocation]; - result(nil); - } else { - NSLog(@"Unknown method: %@\n", call.method); - result(FlutterMethodNotImplemented); - } -} - -#pragma mark LocationManagerDelegate Methods - -// Location events come in here from our LocationManager and are forwarded to -// onLocationEvent. -- (void)locationManager:(CLLocationManager *)manager - didUpdateLocations:(NSArray *)locations { - for (CLLocation *location in locations) { - [self onLocationEvent:location]; - } -} - -#pragma mark LocationBackgroundPlugin Methods - -- (instancetype)init:(NSObject *)registrar { - self = [super init]; - NSAssert(self, @"super init cannot be nil"); - _persistentState = [NSUserDefaults standardUserDefaults]; - _locationManager = [[CLLocationManager alloc] init]; - [_locationManager setDelegate:self]; - [_locationManager requestAlwaysAuthorization]; - - _headlessEngine = [[FlutterEngine alloc] initWithName:@"io.flutter.plugins.location_background" - project:nil]; - _registrar = registrar; - - // This is the method channel used to communicate with the UI Isolate. - _mainChannel = - [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/ios_background_location" - binaryMessenger:[registrar messenger]]; - [registrar addMethodCallDelegate:self channel:_mainChannel]; - - // This is the method channel used to communicate with - // `_backgroundCallbackDispatcher` defined in the Dart portion of our plugin. - // Note: we don't add a MethodCallDelegate for this channel now since our - // BinaryMessenger needs to be initialized first, which is done in - // `startHeadlessService` below. - _callbackChannel = [FlutterMethodChannel - methodChannelWithName:@"plugins.flutter.io/ios_background_location_callback" - binaryMessenger:_headlessEngine]; - return self; -} - -- (int64_t)getCallbackDispatcherHandle { - id handle = [_persistentState objectForKey:@"callback_dispatcher_handle"]; - if (handle == nil) { - return 0; - } - return [handle longLongValue]; -} - -- (void)setCallbackDispatcherHandle:(int64_t)handle { - [_persistentState setObject:[NSNumber numberWithLongLong:handle] - forKey:@"callback_dispatcher_handle"]; -} - -- (int64_t)getLocationCallbackHandle { - id handle = [_persistentState objectForKey:@"location_callback_handle"]; - if (handle == nil) { - return 0; - } - return [handle longLongValue]; -} - -- (void)setLocationCallbackHandle:(int64_t)handle { - [_persistentState setObject:[NSNumber numberWithLongLong:handle] - forKey:@"location_callback_handle"]; -} - -- (BOOL)getPausesLocationUpdatesAutomatically { - return [_persistentState boolForKey:@"pauses_location_updates_automatically"]; -} - -- (void)setPausesLocationUpdatesAutomatically:(BOOL)pause { - [_persistentState setBool:pause forKey:@"pauses_location_updates_automatically"]; -} - -- (BOOL)getShowsBackgroundLocationIndicator { - return [_persistentState boolForKey:@"shows_background_location_indicator"]; -} - -- (void)setShowsBackgroundLocationIndicator:(BOOL)pause { - [_persistentState setBool:pause forKey:@"shows_background_location_indicator"]; -} - -// Initializes and starts the background isolate which will process location -// events. `handle` is the handle to the callback dispatcher which we specified -// in the Dart portion of the plugin. -- (void)startHeadlessService:(int64_t)handle { - [self setCallbackDispatcherHandle:handle]; - - // Lookup the information for our callback dispatcher from the callback cache. - // This cache is populated when `PluginUtilities.getCallbackHandle` is called - // and the resulting handle maps to a `FlutterCallbackInformation` object. - // This object contains information needed by the engine to start a headless - // runner, which includes the callback name as well as the path to the file - // containing the callback. - FlutterCallbackInformation *info = [FlutterCallbackCache lookupCallbackInformation:handle]; - NSAssert(info != nil, @"failed to find callback"); - NSString *entrypoint = info.callbackName; - NSString *uri = info.callbackLibraryPath; - - // Here we actually launch the background isolate to start executing our - // callback dispatcher, `_backgroundCallbackDispatcher`, in Dart. - [_headlessEngine runWithEntrypoint:entrypoint libraryURI:uri]; - - // The headless runner needs to be initialized before we can register it as a - // MethodCallDelegate or else we get an illegal memory access. If we don't - // want to make calls from `_backgroundCallDispatcher` back to native code, - // we don't need to add a MethodCallDelegate for this channel. - [_registrar addMethodCallDelegate:self channel:_callbackChannel]; -} - -// Start receiving location updates. -- (void)monitorLocationChanges:(NSArray *)arguments { - _onLocationUpdateHandle = [arguments[0] longLongValue]; - [self setLocationCallbackHandle:_onLocationUpdateHandle]; - _locationManager.pausesLocationUpdatesAutomatically = arguments[1]; - if (@available(iOS 11.0, *)) { - _locationManager.showsBackgroundLocationIndicator = arguments[2]; - [self setShowsBackgroundLocationIndicator:_locationManager.showsBackgroundLocationIndicator]; - } - _locationManager.activityType = [arguments[3] integerValue]; - if (@available(iOS 9.0, *)) { - _locationManager.allowsBackgroundLocationUpdates = YES; - } - - [self setPausesLocationUpdatesAutomatically:_locationManager.pausesLocationUpdatesAutomatically]; - [self->_locationManager startMonitoringSignificantLocationChanges]; -} - -// Stop the location updates. -- (void)stopUpdatingLocation { - [self->_locationManager stopUpdatingLocation]; -} - -// Sends location events to our `_backgroundCallDispatcher` in Dart code via -// the MethodChannel we established earlier. -- (void)onLocationEvent:(CLLocation *)location { - [_callbackChannel invokeMethod:@"onLocationEvent" - arguments:@[ - @(_onLocationUpdateHandle), @(location.timestamp.timeIntervalSince1970), - @(location.coordinate.latitude), @(location.coordinate.longitude), - @(location.horizontalAccuracy), @(location.speed) - ]]; -} - -@end diff --git a/packages/location_background/ios/location_background_plugin.podspec b/packages/location_background/ios/location_background_plugin.podspec deleted file mode 100644 index 8e629e14ed8b..000000000000 --- a/packages/location_background/ios/location_background_plugin.podspec +++ /dev/null @@ -1,23 +0,0 @@ - - -# -# NOTE: This podspec is NOT to be published. It is only used as a local source! -# - -Pod::Spec.new do |s| -s.name = 'location_background_plugin' -s.version = '0.0.1' -s.summary = 'High-performance, high-fidelity mobile apps.' -s.description = <<-DESC -Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. -DESC -s.homepage = 'https://flutter.io' -s.license = { :type => 'MIT' } -s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } -s.source = { :path => '.'} -s.source_files = 'Classes/**/*' -s.public_header_files = 'Classes/**/*.h' -s.dependency 'Flutter' -s.ios.deployment_target = '8.0' -# s.vendored_frameworks = 'Flutter.framework' -end diff --git a/packages/location_background/lib/location_background_plugin.dart b/packages/location_background/lib/location_background_plugin.dart deleted file mode 100644 index f5ff556966fb..000000000000 --- a/packages/location_background/lib/location_background_plugin.dart +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -// Required for PluginUtilities. -import 'dart:ui'; - -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -/// Types of location activities for iOS. -/// -/// See https://developer.apple.com/documentation/corelocation/clactivitytype -enum LocationActivityType { - other, - automotiveNavigation, - fitness, - otherNavigation, -} - -/// A representation of a location update. -class Location { - Location( - this._time, this.latitude, this.longitude, this.altitude, this.speed); - - factory Location.fromJson(String jsonLocation) { - final Map location = json.decode(jsonLocation); - return Location(location['time'], location['latitude'], - location['longitude'], location['altitude'], location['speed']); - } - - final double _time; - final double latitude; - final double longitude; - final double altitude; - final double speed; - - DateTime get time => - DateTime.fromMillisecondsSinceEpoch((_time * 1000).round(), isUtc: true); - - @override - String toString() => - '[$time] ($latitude, $longitude) altitude: $altitude m/s: $speed'; - - String toJson() { - final Map location = { - 'time': _time, - 'latitude': latitude, - 'longitude': longitude, - 'altitude': altitude, - 'speed': speed, - }; - return json.encode(location); - } -} - -// When we start the background service isolate, we only ever enter it once. -// To communicate between the native plugin and this entrypoint, we'll use -// MethodChannels to open a persistent communication channel to trigger -// callbacks. -void _backgroundCallbackDispatcher() { - const String kOnLocationEvent = 'onLocationEvent'; - const MethodChannel _channel = - MethodChannel('plugins.flutter.io/ios_background_location_callback'); - - // Setup Flutter state needed for MethodChannels. - WidgetsFlutterBinding.ensureInitialized(); - - // Reference to the onLocationEvent callback. - Function onLocationEvent; - - // This is where the magic happens and we handle background events from the - // native portion of the plugin. Here we massage the location data into a - // `Location` object which we then pass to the provided callback. - _channel.setMethodCallHandler((MethodCall call) async { - final dynamic args = call.arguments; - - Function _performCallbackLookup() { - final CallbackHandle handle = - CallbackHandle.fromRawHandle(call.arguments[0]); - - // PluginUtilities.getCallbackFromHandle performs a lookup based on the - // handle we retrieved earlier. - final Function closure = PluginUtilities.getCallbackFromHandle(handle); - - if (closure == null) { - print('Fatal Error: Callback lookup failed!'); - exit(-1); - } - return closure; - } - - if (call.method == kOnLocationEvent) { - onLocationEvent ??= _performCallbackLookup(); - final Location location = - Location(args[1], args[2], args[3], args[4], args[5]); - onLocationEvent(location); - } else { - assert(false, "No handler defined for method type: '${call.method}'"); - } - }); -} - -class LocationBackgroundPlugin { - LocationBackgroundPlugin( - {this.pauseLocationUpdatesAutomatically = false, - this.showsBackgroundLocationIndicator = true, - this.activityType = LocationActivityType.other}) { - // Start the headless location service. The parameter here is a handle to - // a callback managed by the Flutter engine, which allows for us to pass - // references to our callbacks between isolates. - print("Starting LocationBackgroundPlugin service"); - final CallbackHandle handle = - PluginUtilities.getCallbackHandle(_backgroundCallbackDispatcher); - assert(handle != null, 'Unable to lookup callback.'); - _channel.invokeMethod( - _kStartHeadlessService, [handle.toRawHandle()]); - } - - // The method channel we'll use to communicate with the native portion of our - // plugin. - static const MethodChannel _channel = - MethodChannel('plugins.flutter.io/ios_background_location'); - - static const String _kCancelLocationUpdates = 'cancelLocationUpdates'; - static const String _kMonitorLocationChanges = 'monitorLocationChanges'; - static const String _kStartHeadlessService = 'startHeadlessService'; - - bool pauseLocationUpdatesAutomatically; - bool showsBackgroundLocationIndicator; - LocationActivityType activityType; - - /// Start getting significant location updates through `callback`. - /// - /// `callback` is invoked on a background isolate and will not have direct - /// access to the state held by the main isolate (or any other isolate). - Future monitorSignificantLocationChanges( - void Function(Location location) callback) { - if (callback == null) { - throw ArgumentError.notNull('callback'); - } - final CallbackHandle handle = PluginUtilities.getCallbackHandle(callback); - return _channel.invokeMethod(_kMonitorLocationChanges, [ - handle.toRawHandle(), - pauseLocationUpdatesAutomatically, - showsBackgroundLocationIndicator, - activityType.index - ]).then((dynamic result) => result); - } - - /// Stop all location updates. - Future cancelLocationUpdates() => - _channel.invokeMethod(_kCancelLocationUpdates); -} diff --git a/packages/location_background/pubspec.yaml b/packages/location_background/pubspec.yaml deleted file mode 100644 index 37be671a585d..000000000000 --- a/packages/location_background/pubspec.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: location_background_plugin -description: A new flutter plugin project. -author: Flutter Team -homepage: https://github.com/flutter/plugins/tree/master/packages/location_background -version: 0.1.0+3 -publish_to: none - -dependencies: - flutter: - sdk: flutter - -dev_dependencies: - flutter_test: - sdk: flutter - -flutter: - plugin: - androidPackage: com.flutter.example.locationbackgroundplugin - pluginClass: LocationBackgroundPlugin - -environment: - sdk: ">=2.0.0-dev.28.0 <3.0.0" - flutter: ">=1.5.0 <2.0.0" From 589f4e19e24ec8a52b3206b806ceff0aebb72b8a Mon Sep 17 00:00:00 2001 From: Christian Hoffmann <352753+hffmnn@users.noreply.github.com> Date: Thu, 25 Jul 2019 17:31:59 +0200 Subject: [PATCH 93/94] [firebase_crashlytics] runtime exceptions (#1803) * update AUTHORS file * add new method recordError * rename onError to recordFlutterError Co-Authored-By: Collin Jackson --- AUTHORS | 3 +- packages/firebase_crashlytics/CHANGELOG.md | 5 ++ .../example/lib/main.dart | 22 ++++-- .../example/test_driver/crashlytics.dart | 4 +- .../lib/src/firebase_crashlytics.dart | 68 +++++++++++-------- packages/firebase_crashlytics/pubspec.yaml | 5 +- .../test/firebase_crashlytics_test.dart | 28 +++++++- 7 files changed, 97 insertions(+), 38 deletions(-) diff --git a/AUTHORS b/AUTHORS index 31a8f62280e0..855e3a4569f2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -40,4 +40,5 @@ Jonathan Younger Jose Sanchez Debkanchan Samadder Audrius Karosevicius -Lukasz Piliszczuk \ No newline at end of file +Lukasz Piliszczuk +SoundReply Solutions GmbH \ No newline at end of file diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index fb9c747d0023..17da29918f4e 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.1.0 + +* **Breaking Change** Renamed `onError` to `reportFlutterError`. +* Added `recordError` method for errors caught using `runZoned`'s `onError`. + ## 0.0.4+12 * Update google-services Android gradle plugin to 4.3.0 in documentation and examples. diff --git a/packages/firebase_crashlytics/example/lib/main.dart b/packages/firebase_crashlytics/example/lib/main.dart index ba10fb26391b..81684ceaa272 100644 --- a/packages/firebase_crashlytics/example/lib/main.dart +++ b/packages/firebase_crashlytics/example/lib/main.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; @@ -10,10 +12,11 @@ void main() { Crashlytics.instance.enableInDevMode = true; // Pass all uncaught errors to Crashlytics. - FlutterError.onError = (FlutterErrorDetails details) { - Crashlytics.instance.onError(details); - }; - runApp(MyApp()); + FlutterError.onError = Crashlytics.instance.recordFlutterError; + + runZoned>(() async { + runApp(MyApp()); + }, onError: Crashlytics.instance.recordError); } class MyApp extends StatefulWidget { @@ -61,6 +64,17 @@ class _MyAppState extends State { // Crashlytics. throw StateError('Uncaught error thrown by app.'); }), + FlatButton( + child: const Text('Async out of bounds'), + onPressed: () { + // Example of an exception that does not get caught + // by `FlutterError.onError` but is caught by the `onError` handler of + // `runZoned`. + Future.delayed(Duration(seconds: 2), () { + final List list = []; + print(list[100]); + }); + }), ], ), ), diff --git a/packages/firebase_crashlytics/example/test_driver/crashlytics.dart b/packages/firebase_crashlytics/example/test_driver/crashlytics.dart index c1a6c1d3df9e..40bb08717189 100644 --- a/packages/firebase_crashlytics/example/test_driver/crashlytics.dart +++ b/packages/firebase_crashlytics/example/test_driver/crashlytics.dart @@ -14,7 +14,7 @@ void main() { enableFlutterDriverExtension(handler: (_) => allTestsCompleter.future); tearDownAll(() => allTestsCompleter.complete(null)); - test('onError', () async { + test('recordFlutterError', () async { // This is currently only testing that we can log errors without crashing. final Crashlytics crashlytics = Crashlytics.instance; await crashlytics.setUserName('testing'); @@ -24,7 +24,7 @@ void main() { crashlytics.setDouble('testDouble', 42.0); crashlytics.setString('testString', 'bar'); Crashlytics.instance.log('testing'); - await crashlytics.onError( + await crashlytics.recordFlutterError( FlutterErrorDetails( exception: 'testing', stack: StackTrace.fromString(''), diff --git a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart index aa5a67ef99e7..1409c50f8bfa 100644 --- a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart +++ b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart @@ -24,35 +24,23 @@ class Crashlytics { static const MethodChannel channel = MethodChannel('plugins.flutter.io/firebase_crashlytics'); - /// Submits non-fatal crash report to Firebase Crashlytics. - Future onError(FlutterErrorDetails details) async { - print('Error caught by Crashlytics plugin:'); + /// Submits report of a non-fatal error caught by the Flutter framework. + /// to Firebase Crashlytics. + Future recordFlutterError(FlutterErrorDetails details) async { + print('Flutter error caught by Crashlytics plugin:'); - bool inDebugMode = false; - if (!enableInDevMode) { - assert(inDebugMode = true); - } + _recordError(details.exceptionAsString(), details.stack, + context: details.context); + } - if (inDebugMode && !enableInDevMode) { - print(Trace.format(details.stack)); - } else { - // Report error - final List stackTraceLines = - Trace.format(details.stack).trimRight().split('\n'); - final List> stackTraceElements = - getStackTraceElements(stackTraceLines); - await channel - .invokeMethod('Crashlytics#onError', { - 'exception': details.exceptionAsString(), - // FlutterErrorDetails.context has been migrated from a String to a - // DiagnosticsNode. Coerce it to a String here in a way that will work - // on both Strings and the new DiagnosticsNode values. See https://groups.google.com/forum/#!topic/flutter-announce/hp1RNIgej38 - 'context': '${details.context}', - 'stackTraceElements': stackTraceElements, - 'logs': _logs.toList(), - 'keys': _prepareKeys(), - }); - } + /// Submits a report of a non-fatal error. + /// + /// For errors generated by the Flutter framework, use [recordFlutterError] instead. + Future recordError(dynamic exception, StackTrace stack, + {dynamic context}) async { + print('Error caught by Crashlytics plugin :'); + + _recordError(exception, stack, context: context); } void crash() { @@ -196,4 +184,30 @@ class Crashlytics { } return elements; } + + Future _recordError(dynamic exception, StackTrace stack, + {dynamic context}) async { + bool inDebugMode = false; + if (!enableInDevMode) { + assert(inDebugMode = true); + } + + if (inDebugMode && !enableInDevMode) { + print(Trace.format(stack)); + } else { + // Report error + final List stackTraceLines = + Trace.format(stack).trimRight().split('\n'); + final List> stackTraceElements = + getStackTraceElements(stackTraceLines); + await channel + .invokeMethod('Crashlytics#onError', { + 'exception': "${exception.toString()}", + 'context': '$context', + 'stackTraceElements': stackTraceElements, + 'logs': _logs.toList(), + 'keys': _prepareKeys(), + }); + } + } } diff --git a/packages/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/pubspec.yaml index 04b106c57540..d2d3d854c2a1 100644 --- a/packages/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/pubspec.yaml @@ -1,7 +1,8 @@ name: firebase_crashlytics -description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the +description: + Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. -version: 0.0.4+12 +version: 0.1.0 author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_crashlytics diff --git a/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart b/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart index 22319891bcf1..5fef5850814d 100644 --- a/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart +++ b/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart @@ -33,7 +33,7 @@ void main() { log.clear(); }); - test('onError', () async { + test('recordFlutterError', () async { final FlutterErrorDetails details = FlutterErrorDetails( exception: 'foo exception', stack: StackTrace.current, @@ -46,7 +46,7 @@ void main() { crashlytics.setInt('testInt', 42); crashlytics.setDouble('testDouble', 42.0); crashlytics.setString('testString', 'bar'); - await crashlytics.onError(details); + await crashlytics.recordFlutterError(details); expect(log[0].method, 'Crashlytics#onError'); expect(log[0].arguments['exception'], 'foo exception'); expect(log[0].arguments['context'], 'foo context'); @@ -66,6 +66,30 @@ void main() { expect(log[0].arguments['keys'][3]['type'], 'string'); }); + test('recordError', () async { + crashlytics.enableInDevMode = true; + crashlytics.log('foo'); + await crashlytics.recordError('foo exception', StackTrace.current, + context: "context"); + expect(log[0].method, 'Crashlytics#onError'); + expect(log[0].arguments['exception'], 'foo exception'); + expect(log[0].arguments['context'], "context"); + expect(log[0].arguments['logs'], isNotEmpty); + expect(log[0].arguments['logs'], contains('foo')); + expect(log[0].arguments['keys'][0]['key'], 'testBool'); + expect(log[0].arguments['keys'][0]['value'], isTrue); + expect(log[0].arguments['keys'][0]['type'], 'boolean'); + expect(log[0].arguments['keys'][1]['key'], 'testInt'); + expect(log[0].arguments['keys'][1]['value'], 42); + expect(log[0].arguments['keys'][1]['type'], 'int'); + expect(log[0].arguments['keys'][2]['key'], 'testDouble'); + expect(log[0].arguments['keys'][2]['value'], 42.0); + expect(log[0].arguments['keys'][2]['type'], 'double'); + expect(log[0].arguments['keys'][3]['key'], 'testString'); + expect(log[0].arguments['keys'][3]['value'], 'bar'); + expect(log[0].arguments['keys'][3]['type'], 'string'); + }); + test('isDebuggable', () async { expect(await crashlytics.isDebuggable(), true); expect( From b16af32608f252cead7eae75f2c9b509de680d81 Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Thu, 25 Jul 2019 17:53:34 -0700 Subject: [PATCH 94/94] [in_app_purchase] Use correct Gradle distribution (#1905) --- packages/in_app_purchase/CHANGELOG.md | 4 ++++ .../android/gradle/wrapper/gradle-wrapper.properties | 2 +- packages/in_app_purchase/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/in_app_purchase/CHANGELOG.md b/packages/in_app_purchase/CHANGELOG.md index e9de56b2cef3..5e3ce5ca35c0 100644 --- a/packages/in_app_purchase/CHANGELOG.md +++ b/packages/in_app_purchase/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0+7 + +* Make Gradle version compatible with the Android Gradle plugin version. + ## 0.2.0+6 * Add missing `hashCode` implementations. diff --git a/packages/in_app_purchase/android/gradle/wrapper/gradle-wrapper.properties b/packages/in_app_purchase/android/gradle/wrapper/gradle-wrapper.properties index fa3b92d587b9..73eba353b126 100644 --- a/packages/in_app_purchase/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/in_app_purchase/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip diff --git a/packages/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/pubspec.yaml index 78af9b15bf1c..1db8d89b73d1 100644 --- a/packages/in_app_purchase/pubspec.yaml +++ b/packages/in_app_purchase/pubspec.yaml @@ -2,7 +2,7 @@ name: in_app_purchase description: A Flutter plugin for in-app purchases. Exposes APIs for making in-app purchases through the App Store and Google Play. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase -version: 0.2.0+6 +version: 0.2.0+7 dependencies: async: ^2.0.8