[firebase_auth] add type parameters for invokeMethod and bump min flutter version to 1.5.0 (#1655)

diff --git a/packages/firebase_auth/CHANGELOG.md b/packages/firebase_auth/CHANGELOG.md
index d99af30..e3d2190 100644
--- a/packages/firebase_auth/CHANGELOG.md
+++ b/packages/firebase_auth/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 0.11.1+3
+
+* Add missing template type parameter to `invokeMethod` calls.
+* Bump minimum Flutter version to 1.5.0.
+* Replace invokeMethod with invokeMapMethod wherever necessary.
+* FirebaseUser private constructor takes `Map<String, dynamic>` instead of `Map<dynamic, dynamic>`.
+
 ## 0.11.1+2
 
 * Suppress deprecation warning for BinaryMessages. See: https://github.com/flutter/flutter/issues/33446
diff --git a/packages/firebase_auth/lib/src/firebase_auth.dart b/packages/firebase_auth/lib/src/firebase_auth.dart
index 403eba4..f3c79ff 100644
--- a/packages/firebase_auth/lib/src/firebase_auth.dart
+++ b/packages/firebase_auth/lib/src/firebase_auth.dart
@@ -44,20 +44,14 @@
 
     StreamController<FirebaseUser> controller;
     controller = StreamController<FirebaseUser>.broadcast(onListen: () {
-      // 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
-      _handle = channel.invokeMethod('startListeningAuthState',
+      _handle = channel.invokeMethod<int>('startListeningAuthState',
           <String, String>{"app": app.name}).then<int>((dynamic v) => v);
       _handle.then((int handle) {
         _authStateChangedControllers[handle] = controller;
       });
     }, onCancel: () {
       _handle.then((int handle) 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
-        await channel.invokeMethod("stopListeningAuthState",
+        await channel.invokeMethod<void>("stopListeningAuthState",
             <String, dynamic>{"id": handle, "app": app.name});
         _authStateChangedControllers.remove(handle);
       });
@@ -78,11 +72,9 @@
   /// Errors:
   ///   • `ERROR_OPERATION_NOT_ALLOWED` - Indicates that Anonymous accounts are not enabled.
   Future<FirebaseUser> signInAnonymously() async {
-    final Map<dynamic, dynamic> data = await 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('signInAnonymously', <String, String>{"app": app.name});
+    final Map<String, dynamic> data = await channel
+        .invokeMapMethod<String, dynamic>(
+            'signInAnonymously', <String, String>{"app": app.name});
     final FirebaseUser currentUser = FirebaseUser._(data, app);
     return currentUser;
   }
@@ -102,10 +94,8 @@
   }) async {
     assert(email != null);
     assert(password != null);
-    // 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
-    final Map<dynamic, dynamic> data = await channel.invokeMethod(
+    final Map<String, dynamic> data =
+        await channel.invokeMapMethod<String, dynamic>(
       'createUserWithEmailAndPassword',
       <String, String>{'email': email, 'password': password, 'app': app.name},
     );
@@ -126,14 +116,10 @@
     @required String email,
   }) async {
     assert(email != null);
-    // 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
-    final List<dynamic> providers = await channel.invokeMethod(
+    return await channel.invokeListMethod<String>(
       'fetchSignInMethodsForEmail',
       <String, String>{'email': email, 'app': app.name},
     );
-    return providers?.cast<String>();
   }
 
   /// Triggers the Firebase Authentication backend to send a password-reset
@@ -147,10 +133,7 @@
     @required String email,
   }) async {
     assert(email != null);
-    // 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 await channel.invokeMethod(
+    return await channel.invokeMethod<void>(
       'sendPasswordResetEmail',
       <String, String>{'email': email, 'app': app.name},
     );
@@ -173,10 +156,7 @@
     assert(androidPackageName != null);
     assert(androidInstallIfNotAvailable != null);
     assert(androidMinimumVersion != null);
-    // 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
-    await channel.invokeMethod(
+    await channel.invokeMethod<void>(
       'sendLinkToEmail',
       <String, dynamic>{
         'email': email,
@@ -193,7 +173,7 @@
 
   /// Checks if link is an email sign-in link.
   Future<bool> isSignInWithEmailLink(String link) async {
-    return await channel.invokeMethod(
+    return await channel.invokeMethod<bool>(
       'isSignInWithEmailLink',
       <String, String>{'link': link, 'app': app.name},
     );
@@ -209,7 +189,8 @@
   ///   • `ERROR_INVALID` - Indicates the email address is invalid.
   Future<FirebaseUser> signInWithEmailAndLink(
       {String email, String link}) async {
-    final Map<dynamic, dynamic> data = await channel.invokeMethod(
+    final Map<String, dynamic> data =
+        await channel.invokeMapMethod<String, dynamic>(
       'signInWithEmailAndLink',
       <String, dynamic>{
         'app': app.name,
@@ -272,10 +253,8 @@
   ///       This can only occur when using [EmailAuthProvider.getCredentialWithLink] to obtain the credential.
   Future<FirebaseUser> signInWithCredential(AuthCredential credential) async {
     assert(credential != null);
-    // 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
-    final Map<dynamic, dynamic> data = await channel.invokeMethod(
+    final Map<String, dynamic> data =
+        await channel.invokeMapMethod<String, dynamic>(
       'signInWithCredential',
       <String, dynamic>{
         'app': app.name,
@@ -356,10 +335,7 @@
       'app': app.name,
     };
 
-    // 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
-    await channel.invokeMethod('verifyPhoneNumber', params);
+    await channel.invokeMethod<void>('verifyPhoneNumber', params);
   }
 
   /// Tries to sign in a user with a given Custom Token [token].
@@ -382,10 +358,8 @@
   ///     Ensure your app's SHA1 is correct in the Firebase console.
   Future<FirebaseUser> signInWithCustomToken({@required String token}) async {
     assert(token != null);
-    // 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
-    final Map<dynamic, dynamic> data = await channel.invokeMethod(
+    final Map<String, dynamic> data =
+        await channel.invokeMapMethod<String, dynamic>(
       'signInWithCustomToken',
       <String, String>{'token': token, 'app': app.name},
     );
@@ -399,19 +373,14 @@
   /// the [onAuthStateChanged] stream.
   Future<void> signOut() async {
     return await 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("signOut", <String, String>{'app': app.name});
+        .invokeMethod<void>("signOut", <String, String>{'app': app.name});
   }
 
   /// Returns the currently signed-in [FirebaseUser] or [null] if there is none.
   Future<FirebaseUser> currentUser() async {
-    final Map<dynamic, dynamic> data = await 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("currentUser", <String, String>{'app': app.name});
+    final Map<String, dynamic> data = await channel
+        .invokeMapMethod<String, dynamic>(
+            "currentUser", <String, String>{'app': app.name});
     final FirebaseUser currentUser =
         data == null ? null : FirebaseUser._(data, app);
     return currentUser;
@@ -422,10 +391,8 @@
   /// code should follow the conventions defined by the IETF in BCP47.
   Future<void> setLanguageCode(String language) async {
     assert(language != null);
-    // 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
-    await FirebaseAuth.channel.invokeMethod('setLanguageCode', <String, String>{
+    await FirebaseAuth.channel
+        .invokeMethod<void>('setLanguageCode', <String, String>{
       'language': language,
       'app': app.name,
     });
@@ -479,7 +446,7 @@
     final int id = call.arguments["id"];
 
     final FirebaseUser currentUser =
-        data != null ? FirebaseUser._(data, app) : null;
+        data != null ? FirebaseUser._(data.cast<String, dynamic>(), app) : null;
     _authStateChangedControllers[id].add(currentUser);
   }
 }
diff --git a/packages/firebase_auth/lib/src/firebase_user.dart b/packages/firebase_auth/lib/src/firebase_user.dart
index 9210a27..60e3416 100644
--- a/packages/firebase_auth/lib/src/firebase_user.dart
+++ b/packages/firebase_auth/lib/src/firebase_user.dart
@@ -6,7 +6,7 @@
 
 /// Represents a user.
 class FirebaseUser extends UserInfo {
-  FirebaseUser._(Map<dynamic, dynamic> data, FirebaseApp app)
+  FirebaseUser._(Map<String, dynamic> data, FirebaseApp app)
       : providerData = data['providerData']
             .map<UserInfo>((dynamic item) => UserInfo._(item, app))
             .toList(),
@@ -35,10 +35,7 @@
   /// Completes with an error if the user is signed out.
   Future<String> getIdToken({bool refresh = false}) async {
     return await FirebaseAuth.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('getIdToken', <String, dynamic>{
+        .invokeMethod<String>('getIdToken', <String, dynamic>{
       'refresh': refresh,
       'app': _app.name,
     });
@@ -63,10 +60,8 @@
   ///       This can only occur when using [EmailAuthProvider.getCredentialWithLink] to obtain the credential.
   Future<FirebaseUser> linkWithCredential(AuthCredential credential) async {
     assert(credential != null);
-    // 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
-    final Map<dynamic, dynamic> data = await FirebaseAuth.channel.invokeMethod(
+    final Map<String, dynamic> data =
+        await FirebaseAuth.channel.invokeMapMethod<String, dynamic>(
       'linkWithCredential',
       <String, dynamic>{
         'app': _app.name,
@@ -80,10 +75,7 @@
 
   /// Initiates email verification for the user.
   Future<void> sendEmailVerification() 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
-    await FirebaseAuth.channel.invokeMethod(
+    await FirebaseAuth.channel.invokeMethod<void>(
         'sendEmailVerification', <String, String>{'app': _app.name});
   }
 
@@ -91,19 +83,13 @@
   /// attached providers, display name, and so on).
   Future<void> reload() async {
     await FirebaseAuth.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('reload', <String, String>{'app': _app.name});
+        .invokeMethod<void>('reload', <String, String>{'app': _app.name});
   }
 
   /// Deletes the user record from your Firebase project's database.
   Future<void> delete() async {
     await FirebaseAuth.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('delete', <String, String>{'app': _app.name});
+        .invokeMethod<void>('delete', <String, String>{'app': _app.name});
   }
 
   /// Updates the email address of the user.
@@ -124,10 +110,7 @@
   ///   • `ERROR_OPERATION_NOT_ALLOWED` - Indicates that Email & Password accounts are not enabled.
   Future<void> updateEmail(String email) async {
     assert(email != null);
-    // 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 await FirebaseAuth.channel.invokeMethod(
+    return await FirebaseAuth.channel.invokeMethod<void>(
       'updateEmail',
       <String, String>{'email': email, 'app': _app.name},
     );
@@ -170,10 +153,7 @@
   ///   • `ERROR_OPERATION_NOT_ALLOWED` - Indicates that Email & Password accounts are not enabled.
   Future<void> updatePassword(String password) async {
     assert(password != null);
-    // 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 await FirebaseAuth.channel.invokeMethod(
+    return await FirebaseAuth.channel.invokeMethod<void>(
       'updatePassword',
       <String, String>{'password': password, 'app': _app.name},
     );
@@ -188,10 +168,7 @@
     assert(userUpdateInfo != null);
     final Map<String, String> data = userUpdateInfo._updateData;
     data['app'] = _app.name;
-    // 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 await FirebaseAuth.channel.invokeMethod(
+    return await FirebaseAuth.channel.invokeMethod<void>(
       'updateProfile',
       data,
     );
@@ -216,10 +193,7 @@
   Future<FirebaseUser> reauthenticateWithCredential(
       AuthCredential credential) async {
     assert(credential != null);
-    // 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
-    await FirebaseAuth.channel.invokeMethod(
+    await FirebaseAuth.channel.invokeMethod<void>(
       'reauthenticateWithCredential',
       <String, dynamic>{
         'app': _app.name,
@@ -245,10 +219,7 @@
   ///   • `ERROR_REQUIRES_RECENT_LOGIN` - If the user's last sign-in time does not meet the security threshold. Use reauthenticate methods to resolve.
   Future<void> unlinkFromProvider(String provider) async {
     assert(provider != null);
-    // 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 await FirebaseAuth.channel.invokeMethod(
+    return await FirebaseAuth.channel.invokeMethod<void>(
       'unlinkFromProvider',
       <String, String>{'provider': provider, 'app': _app.name},
     );
diff --git a/packages/firebase_auth/lib/src/user_metadata.dart b/packages/firebase_auth/lib/src/user_metadata.dart
index 11f9076..66c1fed 100644
--- a/packages/firebase_auth/lib/src/user_metadata.dart
+++ b/packages/firebase_auth/lib/src/user_metadata.dart
@@ -8,7 +8,7 @@
 class FirebaseUserMetadata {
   FirebaseUserMetadata._(this._data);
 
-  final Map<dynamic, dynamic> _data;
+  final Map<String, dynamic> _data;
 
   int get creationTimestamp => _data['creationTimestamp'];
 
diff --git a/packages/firebase_auth/pubspec.yaml b/packages/firebase_auth/pubspec.yaml
index 6248321..1ad651d 100755
--- a/packages/firebase_auth/pubspec.yaml
+++ b/packages/firebase_auth/pubspec.yaml
@@ -4,7 +4,7 @@
   like Google, Facebook and Twitter.
 author: Flutter Team <flutter-dev@googlegroups.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_auth
-version: "0.11.1+2"
+version: "0.11.1+3"
 
 flutter:
   plugin:
@@ -30,4 +30,4 @@
 
 environment:
   sdk: ">=2.0.0-dev.28.0 <3.0.0"
-  flutter: ">=0.1.4 <2.0.0"
+  flutter: ">=1.5.0 <2.0.0"