Multiple database support for firebase_database (#316)

Add multiple database support to firebase_database. Includes Android bug fixes for firebase_core.
diff --git a/packages/firebase_core/CHANGELOG.md b/packages/firebase_core/CHANGELOG.md
index 95948be..4a0d1ce 100644
--- a/packages/firebase_core/CHANGELOG.md
+++ b/packages/firebase_core/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.0.2
+
+* Fixes for database URL on Android
+* Make GCM sender id optional on Android
+* Relax GMS dependency to 11.+
+
 ## 0.0.1
 
 * Initial Release
diff --git a/packages/firebase_core/android/build.gradle b/packages/firebase_core/android/build.gradle
index 51919ed..299df5f 100644
--- a/packages/firebase_core/android/build.gradle
+++ b/packages/firebase_core/android/build.gradle
@@ -40,6 +40,6 @@
         disable 'InvalidPackage'
     }
     dependencies {
-        compile 'com.google.firebase:firebase-core:11.6.+'
+        compile 'com.google.firebase:firebase-core:11.+'
     }
 }
diff --git a/packages/firebase_core/android/src/main/java/com/yourcompany/firebasecore/FirebaseCorePlugin.java b/packages/firebase_core/android/src/main/java/com/yourcompany/firebasecore/FirebaseCorePlugin.java
index bd616ad..06df16a 100644
--- a/packages/firebase_core/android/src/main/java/com/yourcompany/firebasecore/FirebaseCorePlugin.java
+++ b/packages/firebase_core/android/src/main/java/com/yourcompany/firebasecore/FirebaseCorePlugin.java
@@ -45,7 +45,7 @@
               new FirebaseOptions.Builder()
                   .setApiKey(optionsMap.get("APIKey"))
                   .setApplicationId(optionsMap.get("googleAppID"))
-                  .setDatabaseUrl(optionsMap.get("databaseUrl"))
+                  .setDatabaseUrl(optionsMap.get("databaseURL"))
                   .setGcmSenderId(optionsMap.get("GCMSenderID"))
                   .setProjectId(optionsMap.get("projectId"))
                   .setStorageBucket(optionsMap.get("storageBucket"))
diff --git a/packages/firebase_core/lib/src/firebase_app.dart b/packages/firebase_core/lib/src/firebase_app.dart
index 4cf599d..7a1bf30 100644
--- a/packages/firebase_core/lib/src/firebase_app.dart
+++ b/packages/firebase_core/lib/src/firebase_app.dart
@@ -39,7 +39,6 @@
       return new Future<FirebaseApp>.sync(() => existingApp);
     }
     assert(options.googleAppID != null);
-    assert(options.gcmSenderID != null);
     _namedApps[name] = new FirebaseApp(name: name, options: options);
     return channel.invokeMethod('FirebaseApp#configure', <String, dynamic>{
       'name': name,
diff --git a/packages/firebase_core/pubspec.yaml b/packages/firebase_core/pubspec.yaml
index 7af6916..16e5287 100644
--- a/packages/firebase_core/pubspec.yaml
+++ b/packages/firebase_core/pubspec.yaml
@@ -2,7 +2,7 @@
 description: Firebase Core plugin for Flutter.
 author: Flutter Team <flutter-dev@googlegroups.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_core
-version: 0.0.1
+version: 0.0.2
 
 flutter:
   plugin:
diff --git a/packages/firebase_database/CHANGELOG.md b/packages/firebase_database/CHANGELOG.md
index 17b1708..15fcc83 100644
--- a/packages/firebase_database/CHANGELOG.md
+++ b/packages/firebase_database/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.2.0
+
+* Support for multiple databases, new dependency on firebase_core
+* Relax GMS dependency to 11.+
+
 ## 0.1.4
 
 * Add FLT prefix to iOS types
diff --git a/packages/firebase_database/android/build.gradle b/packages/firebase_database/android/build.gradle
index fc5d85c..272ce07 100755
--- a/packages/firebase_database/android/build.gradle
+++ b/packages/firebase_database/android/build.gradle
@@ -30,8 +30,8 @@
         disable 'InvalidPackage'
     }
     dependencies {
-        compile 'com.google.firebase:firebase-core:11.4.+'
-        compile 'com.google.firebase:firebase-auth:11.4.+'
-        compile 'com.google.firebase:firebase-database:11.4.+'
+        compile 'com.google.firebase:firebase-core:11.+'
+        compile 'com.google.firebase:firebase-auth:11.+'
+        compile 'com.google.firebase:firebase-database:11.+'
     }
 }
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 59a942d..ce90c3c 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
@@ -9,6 +9,7 @@
 import com.google.android.gms.tasks.Task;
 import com.google.android.gms.tasks.TaskCompletionSource;
 import com.google.android.gms.tasks.Tasks;
+import com.google.firebase.FirebaseApp;
 import com.google.firebase.database.ChildEventListener;
 import com.google.firebase.database.DataSnapshot;
 import com.google.firebase.database.DatabaseError;
@@ -56,15 +57,15 @@
     this.channel = channel;
   }
 
-  private DatabaseReference getReference(Map<String, Object> arguments) {
+  private DatabaseReference getReference(FirebaseDatabase database, Map<String, Object> arguments) {
     String path = (String) arguments.get("path");
-    DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
+    DatabaseReference reference = database.getReference();
     if (path != null) reference = reference.child(path);
     return reference;
   }
 
-  private Query getQuery(Map<String, Object> arguments) {
-    Query query = getReference(arguments);
+  private Query getQuery(FirebaseDatabase database, Map<String, Object> arguments) {
+    Query query = getReference(database, arguments);
     @SuppressWarnings("unchecked")
     Map<String, Object> parameters = (Map<String, Object>) arguments.get("parameters");
     if (parameters == null) return query;
@@ -214,33 +215,41 @@
 
   @Override
   public void onMethodCall(final MethodCall call, final Result result) {
+    final Map<String, Object> arguments = call.arguments();
+    FirebaseDatabase database;
+    String appName = (String) arguments.get("app");
+    if (appName != null) {
+      database = FirebaseDatabase.getInstance(FirebaseApp.getInstance(appName));
+    } else {
+      database = FirebaseDatabase.getInstance();
+    }
     switch (call.method) {
       case "FirebaseDatabase#goOnline":
         {
-          FirebaseDatabase.getInstance().goOnline();
+          database.goOnline();
           result.success(null);
           break;
         }
 
       case "FirebaseDatabase#goOffline":
         {
-          FirebaseDatabase.getInstance().goOffline();
+          database.goOffline();
           result.success(null);
           break;
         }
 
       case "FirebaseDatabase#purgeOutstandingWrites":
         {
-          FirebaseDatabase.getInstance().purgeOutstandingWrites();
+          database.purgeOutstandingWrites();
           result.success(null);
           break;
         }
 
       case "FirebaseDatabase#setPersistenceEnabled":
         {
-          Boolean isEnabled = (Boolean) call.arguments;
+          Boolean isEnabled = (Boolean) arguments.get("enabled");
           try {
-            FirebaseDatabase.getInstance().setPersistenceEnabled(isEnabled);
+            database.setPersistenceEnabled(isEnabled);
             result.success(true);
           } catch (DatabaseException e) {
             // Database is already in use, e.g. after hot reload/restart.
@@ -251,9 +260,9 @@
 
       case "FirebaseDatabase#setPersistenceCacheSizeBytes":
         {
-          long cacheSize = (Integer) call.arguments;
+          long cacheSize = (Integer) arguments.get("cacheSize");
           try {
-            FirebaseDatabase.getInstance().setPersistenceCacheSizeBytes(cacheSize);
+            database.setPersistenceCacheSizeBytes(cacheSize);
             result.success(true);
           } catch (DatabaseException e) {
             // Database is already in use, e.g. after hot reload/restart.
@@ -264,10 +273,9 @@
 
       case "DatabaseReference#set":
         {
-          Map<String, Object> arguments = call.arguments();
           Object value = arguments.get("value");
           Object priority = arguments.get("priority");
-          DatabaseReference reference = getReference(arguments);
+          DatabaseReference reference = getReference(database, arguments);
           if (priority != null) {
             reference.setValue(value, priority, new DefaultCompletionListener(result));
           } else {
@@ -278,27 +286,24 @@
 
       case "DatabaseReference#update":
         {
-          Map<String, Object> arguments = call.arguments();
           @SuppressWarnings("unchecked")
           Map<String, Object> value = (Map<String, Object>) arguments.get("value");
-          DatabaseReference reference = getReference(arguments);
+          DatabaseReference reference = getReference(database, arguments);
           reference.updateChildren(value, new DefaultCompletionListener(result));
           break;
         }
 
       case "DatabaseReference#setPriority":
         {
-          Map<String, Object> arguments = call.arguments();
           Object priority = arguments.get("priority");
-          DatabaseReference reference = getReference(arguments);
+          DatabaseReference reference = getReference(database, arguments);
           reference.setPriority(priority, new DefaultCompletionListener(result));
           break;
         }
 
       case "DatabaseReference#runTransaction":
         {
-          final Map<String, Object> arguments = call.arguments();
-          final DatabaseReference reference = getReference(arguments);
+          final DatabaseReference reference = getReference(database, arguments);
 
           // Initiate native transaction.
           reference.runTransaction(
@@ -395,24 +400,22 @@
 
       case "Query#keepSynced":
         {
-          Map<String, Object> arguments = call.arguments();
           boolean value = (Boolean) arguments.get("value");
-          getQuery(arguments).keepSynced(value);
+          getQuery(database, arguments).keepSynced(value);
           result.success(null);
           break;
         }
 
       case "Query#observe":
         {
-          Map<String, Object> arguments = call.arguments();
           String eventType = (String) arguments.get("eventType");
           int handle = nextHandle++;
           EventObserver observer = new EventObserver(eventType, handle);
           observers.put(handle, observer);
           if (eventType.equals(EVENT_TYPE_VALUE)) {
-            getQuery(arguments).addValueEventListener(observer);
+            getQuery(database, arguments).addValueEventListener(observer);
           } else {
-            getQuery(arguments).addChildEventListener(observer);
+            getQuery(database, arguments).addChildEventListener(observer);
           }
           result.success(handle);
           break;
@@ -420,8 +423,7 @@
 
       case "Query#removeObserver":
         {
-          Map<String, Object> arguments = call.arguments();
-          Query query = getQuery(arguments);
+          Query query = getQuery(database, arguments);
           int handle = (Integer) arguments.get("handle");
           EventObserver observer = observers.get(handle);
           if (observer != null) {
diff --git a/packages/firebase_database/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_database/example/ios/Runner.xcodeproj/project.pbxproj
index 808c822..5a78845 100755
--- a/packages/firebase_database/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/firebase_database/example/ios/Runner.xcodeproj/project.pbxproj
@@ -8,7 +8,6 @@
 
 /* Begin PBXBuildFile section */
 		3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
-		2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
 		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, ); }; };
 		5C6F5A711EC3CCCC008D64B5 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C6F5A701EC3CCCC008D64B5 /* GeneratedPluginRegistrant.m */; };
@@ -43,7 +42,6 @@
 
 /* Begin PBXFileReference section */
 		3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
-		2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
 		3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
 		5C6F5A6F1EC3CCCC008D64B5 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
 		5C6F5A701EC3CCCC008D64B5 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
@@ -91,7 +89,6 @@
 				9740EEB71CF902C7004384FC /* app.flx */,
 				3B80C3931E831B6300D905FE /* App.framework */,
 				3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
-				2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
 				9740EEBA1CF902C7004384FC /* Flutter.framework */,
 				9740EEB21CF90195004384FC /* Debug.xcconfig */,
 				7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
@@ -221,7 +218,6 @@
 				97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
 				9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
 				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
-				2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
 				9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
 				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
 				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
@@ -266,9 +262,12 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
+				"${PODS_ROOT}/../../../../../../flutter/bin/cache/artifacts/engine/ios-release/Flutter.framework",
 			);
 			name = "[CP] Embed Pods Frameworks";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -295,13 +294,16 @@
 			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";
+			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 */
diff --git a/packages/firebase_database/example/lib/main.dart b/packages/firebase_database/example/lib/main.dart
index 60acc55..2cffa41 100755
--- a/packages/firebase_database/example/lib/main.dart
+++ b/packages/firebase_database/example/lib/main.dart
@@ -3,12 +3,29 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:io' show Platform;
 
 import 'package:flutter/material.dart';
 import 'package:firebase_auth/firebase_auth.dart';
+import 'package:firebase_core/firebase_core.dart';
 import 'package:firebase_database/firebase_database.dart';
 import 'package:firebase_database/ui/firebase_animated_list.dart';
 
+final FirebaseApp app = new FirebaseApp(
+  name: 'db2',
+  options: Platform.isIOS
+      ? const FirebaseOptions(
+          googleAppID: '1:297855924061:ios:c6de2b69b03a5be8',
+          gcmSenderID: '297855924061',
+          databaseURL: 'https://flutterfire-cd2f7.firebaseio.com',
+        )
+      : const FirebaseOptions(
+          googleAppID: '1:297855924061:android:669871c998cc21bd',
+          apiKey: 'AIzaSyD_shO5mfO9lhy2TVWhfo1VUmARKlG4suk',
+          databaseURL: 'https://flutterfire-cd2f7.firebaseio.com',
+        ),
+);
+
 void main() {
   runApp(new MyApp());
 }
@@ -30,10 +47,8 @@
 
 class _MyHomePageState extends State<MyHomePage> {
   int _counter;
-  final DatabaseReference _counterRef =
-      FirebaseDatabase.instance.reference().child('counter');
-  final DatabaseReference _messagesRef =
-      FirebaseDatabase.instance.reference().child('messages');
+  DatabaseReference _counterRef;
+  DatabaseReference _messagesRef;
   StreamSubscription<Event> _counterSubscription;
   StreamSubscription<Event> _messagesSubscription;
   bool _anchorToBottom = false;
@@ -45,8 +60,17 @@
   @override
   void initState() {
     super.initState();
-    FirebaseDatabase.instance.setPersistenceEnabled(true);
-    FirebaseDatabase.instance.setPersistenceCacheSizeBytes(10000000);
+    FirebaseApp.configure(name: app.name, options: app.options);
+    // Demonstrates configuring to the database using a file
+    _counterRef = FirebaseDatabase.instance.reference().child('counter');
+    // Demonstrates configuring the database directly
+    final FirebaseDatabase database = new FirebaseDatabase(app: app);
+    _messagesRef = database.reference().child('messages');
+    database.reference().child('counter').once().then((DataSnapshot snapshot) {
+      print('Connected to second database and read ${snapshot.value}');
+    });
+    database.setPersistenceEnabled(true);
+    database.setPersistenceCacheSizeBytes(10000000);
     _counterRef.keepSynced(true);
     _counterSubscription = _counterRef.onValue.listen((Event event) {
       setState(() {
diff --git a/packages/firebase_database/example/pubspec.yaml b/packages/firebase_database/example/pubspec.yaml
index 00a4560..e4b948f 100755
--- a/packages/firebase_database/example/pubspec.yaml
+++ b/packages/firebase_database/example/pubspec.yaml
@@ -8,6 +8,7 @@
     path: ../../firebase_auth
   firebase_database:
     path: ../
+  firebase_core: ^0.0.1
 
 flutter:
   uses-material-design: true
diff --git a/packages/firebase_database/ios/Classes/FirebaseDatabasePlugin.m b/packages/firebase_database/ios/Classes/FirebaseDatabasePlugin.m
index 6e0ac7d..78ee4be 100644
--- a/packages/firebase_database/ios/Classes/FirebaseDatabasePlugin.m
+++ b/packages/firebase_database/ios/Classes/FirebaseDatabasePlugin.m
@@ -30,15 +30,15 @@
 }
 @end
 
-FIRDatabaseReference *getReference(NSDictionary *arguments) {
+FIRDatabaseReference *getReference(FIRDatabase *database, NSDictionary *arguments) {
   NSString *path = arguments[@"path"];
-  FIRDatabaseReference *ref = [FIRDatabase database].reference;
+  FIRDatabaseReference *ref = database.reference;
   if ([path length] > 0) ref = [ref child:path];
   return ref;
 }
 
-FIRDatabaseQuery *getQuery(NSDictionary *arguments) {
-  FIRDatabaseQuery *query = getReference(arguments);
+FIRDatabaseQuery *getQuery(FIRDatabase *database, NSDictionary *arguments) {
+  FIRDatabaseQuery *query = getReference(database, arguments);
   NSDictionary *parameters = arguments[@"parameters"];
   NSString *orderBy = parameters[@"orderBy"];
   if ([orderBy isEqualToString:@"child"]) {
@@ -154,23 +154,30 @@
 }
 
 - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
+  FIRDatabase *database;
+  NSString *appName = call.arguments[@"app"];
+  if (![appName isEqual:[NSNull null]]) {
+    database = [FIRDatabase databaseForApp:[FIRApp appNamed:appName]];
+  } else {
+    database = [FIRDatabase database];
+  }
   void (^defaultCompletionBlock)(NSError *, FIRDatabaseReference *) =
       ^(NSError *error, FIRDatabaseReference *ref) {
         result(error.flutterError);
       };
   if ([@"FirebaseDatabase#goOnline" isEqualToString:call.method]) {
-    [[FIRDatabase database] goOnline];
+    [database goOnline];
     result(nil);
   } else if ([@"FirebaseDatabase#goOffline" isEqualToString:call.method]) {
-    [[FIRDatabase database] goOffline];
+    [database goOffline];
     result(nil);
   } else if ([@"FirebaseDatabase#purgeOutstandingWrites" isEqualToString:call.method]) {
-    [[FIRDatabase database] purgeOutstandingWrites];
+    [database purgeOutstandingWrites];
     result(nil);
   } else if ([@"FirebaseDatabase#setPersistenceEnabled" isEqualToString:call.method]) {
-    NSNumber *value = call.arguments;
+    NSNumber *value = call.arguments[@"enabled"];
     @try {
-      [FIRDatabase database].persistenceEnabled = value.boolValue;
+      database.persistenceEnabled = value.boolValue;
       result([NSNumber numberWithBool:YES]);
     } @catch (NSException *exception) {
       if ([@"FIRDatabaseAlreadyInUse" isEqualToString:exception.name]) {
@@ -181,9 +188,9 @@
       }
     }
   } else if ([@"FirebaseDatabase#setPersistenceCacheSizeBytes" isEqualToString:call.method]) {
-    NSNumber *value = call.arguments;
+    NSNumber *value = call.arguments[@"cacheSize"];
     @try {
-      [FIRDatabase database].persistenceCacheSizeBytes = value.unsignedIntegerValue;
+      database.persistenceCacheSizeBytes = value.unsignedIntegerValue;
       result([NSNumber numberWithBool:YES]);
     } @catch (NSException *exception) {
       if ([@"FIRDatabaseAlreadyInUse" isEqualToString:exception.name]) {
@@ -194,18 +201,18 @@
       }
     }
   } else if ([@"DatabaseReference#set" isEqualToString:call.method]) {
-    [getReference(call.arguments) setValue:call.arguments[@"value"]
-                               andPriority:call.arguments[@"priority"]
-                       withCompletionBlock:defaultCompletionBlock];
+    [getReference(database, call.arguments) setValue:call.arguments[@"value"]
+                                         andPriority:call.arguments[@"priority"]
+                                 withCompletionBlock:defaultCompletionBlock];
   } else if ([@"DatabaseReference#update" isEqualToString:call.method]) {
-    [getReference(call.arguments) updateChildValues:call.arguments[@"value"]
-                                withCompletionBlock:defaultCompletionBlock];
+    [getReference(database, call.arguments) updateChildValues:call.arguments[@"value"]
+                                          withCompletionBlock:defaultCompletionBlock];
   } else if ([@"DatabaseReference#setPriority" isEqualToString:call.method]) {
-    [getReference(call.arguments) setPriority:call.arguments[@"priority"]
-                          withCompletionBlock:defaultCompletionBlock];
+    [getReference(database, call.arguments) setPriority:call.arguments[@"priority"]
+                                    withCompletionBlock:defaultCompletionBlock];
   } else if ([@"DatabaseReference#runTransaction" isEqualToString:call.method]) {
-    [getReference(call.arguments) runTransactionBlock:^FIRTransactionResult *_Nonnull(
-                                      FIRMutableData *_Nonnull currentData) {
+    [getReference(database, call.arguments) runTransactionBlock:^FIRTransactionResult *_Nonnull(
+                                                FIRMutableData *_Nonnull currentData) {
       // Create semaphore to allow native side to wait while snapshot
       // updates occur on the Dart side.
       dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
@@ -249,7 +256,7 @@
             [self.updatedSnapshots objectForKey:call.arguments[@"transactionKey"]][@"value"];
       } else {
         if (result != 0) {
-          NSLog(@"Transaction at %@ timed out.", [getReference(call.arguments) URL]);
+          NSLog(@"Transaction at %@ timed out.", [getReference(database, call.arguments) URL]);
         }
         return [FIRTransactionResult abort];
       }
@@ -268,7 +275,8 @@
         }];
   } else if ([@"Query#observe" isEqualToString:call.method]) {
     FIRDataEventType eventType = parseEventType(call.arguments[@"eventType"]);
-    __block FIRDatabaseHandle handle = [getQuery(call.arguments) observeEventType:eventType
+    __block FIRDatabaseHandle handle = [getQuery(database, call.arguments)
+        observeEventType:eventType
         andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, NSString *previousSiblingKey) {
           [self.channel invokeMethod:@"Event"
                            arguments:@{
@@ -290,11 +298,11 @@
     result([NSNumber numberWithUnsignedInteger:handle]);
   } else if ([@"Query#removeObserver" isEqualToString:call.method]) {
     FIRDatabaseHandle handle = [call.arguments[@"handle"] unsignedIntegerValue];
-    [getQuery(call.arguments) removeObserverWithHandle:handle];
+    [getQuery(database, call.arguments) removeObserverWithHandle:handle];
     result(nil);
   } else if ([@"Query#keepSynced" isEqualToString:call.method]) {
     NSNumber *value = call.arguments[@"value"];
-    [getQuery(call.arguments) keepSynced:value.boolValue];
+    [getQuery(database, call.arguments) keepSynced:value.boolValue];
     result(nil);
   } else {
     result(FlutterMethodNotImplemented);
diff --git a/packages/firebase_database/lib/firebase_database.dart b/packages/firebase_database/lib/firebase_database.dart
index 19a0267..bafa098 100755
--- a/packages/firebase_database/lib/firebase_database.dart
+++ b/packages/firebase_database/lib/firebase_database.dart
@@ -6,6 +6,7 @@
 
 import 'dart:async';
 
+import 'package:firebase_core/firebase_core.dart';
 import 'package:flutter/services.dart';
 import 'package:meta/meta.dart';
 
diff --git a/packages/firebase_database/lib/src/database_reference.dart b/packages/firebase_database/lib/src/database_reference.dart
index ff584cc..aad5968 100644
--- a/packages/firebase_database/lib/src/database_reference.dart
+++ b/packages/firebase_database/lib/src/database_reference.dart
@@ -73,7 +73,12 @@
   Future<Null> set(dynamic value, {dynamic priority}) {
     return _database._channel.invokeMethod(
       'DatabaseReference#set',
-      <String, dynamic>{'path': path, 'value': value, 'priority': priority},
+      <String, dynamic>{
+        'app': _database.app?.name,
+        'path': path,
+        'value': value,
+        'priority': priority,
+      },
     );
   }
 
@@ -81,7 +86,11 @@
   Future<Null> update(Map<String, dynamic> value) {
     return _database._channel.invokeMethod(
       'DatabaseReference#update',
-      <String, dynamic>{'path': path, 'value': value},
+      <String, dynamic>{
+        'app': _database.app?.name,
+        'path': path,
+        'value': value,
+      },
     );
   }
 
@@ -112,7 +121,11 @@
   Future<Null> setPriority(dynamic priority) async {
     return _database._channel.invokeMethod(
       'DatabaseReference#setPriority',
-      <String, dynamic>{'path': path, 'priority': priority},
+      <String, dynamic>{
+        'app': _database.app?.name,
+        'path': path,
+        'priority': priority,
+      },
     );
   }
 
@@ -145,6 +158,7 @@
 
     _database._channel
         .invokeMethod('DatabaseReference#runTransaction', <String, dynamic>{
+      'app': _database.app?.name,
       'path': path,
       'transactionKey': transactionKey,
       'transactionTimeout': timeout.inMilliseconds
diff --git a/packages/firebase_database/lib/src/firebase_database.dart b/packages/firebase_database/lib/src/firebase_database.dart
index bf09655..cc55d14 100644
--- a/packages/firebase_database/lib/src/firebase_database.dart
+++ b/packages/firebase_database/lib/src/firebase_database.dart
@@ -18,7 +18,14 @@
   static final Map<int, TransactionHandler> _transactions =
       <int, TransactionHandler>{};
 
-  FirebaseDatabase._() {
+  static bool _initialized = false;
+
+  /// Gets an instance of [FirebaseDatabase].
+  ///
+  /// If [app] is specified, its options should include a [databaseURL].
+  FirebaseDatabase({this.app}) {
+    assert(app == null || app.options.databaseURL != null);
+    if (_initialized) return;
     _channel.setMethodCallHandler((MethodCall call) async {
       switch (call.method) {
         case 'Event':
@@ -42,9 +49,15 @@
           );
       }
     });
+    _initialized = true;
   }
 
-  static FirebaseDatabase _instance = new FirebaseDatabase._();
+  static FirebaseDatabase _instance = new FirebaseDatabase();
+
+  /// The [FirebaseApp] instance to which this [FirebaseDatabase] belongs.
+  ///
+  /// If null, the default [FirebaseApp] is used.
+  final FirebaseApp app;
 
   /// Gets the instance of FirebaseDatabase for the default Firebase app.
   static FirebaseDatabase get instance => _instance;
@@ -72,9 +85,10 @@
   /// network connectivity at that time).
   Future<bool> setPersistenceEnabled(bool enabled) {
     return _channel.invokeMethod(
-      'FirebaseDatabase#setPersistenceEnabled',
-      enabled,
-    );
+        'FirebaseDatabase#setPersistenceEnabled', <String, dynamic>{
+      'app': app?.name,
+      'enabled': enabled,
+    });
   }
 
   /// Attempts to set the size of the persistence cache.
@@ -96,21 +110,28 @@
   /// or greater than 100 MB are not supported.
   Future<bool> setPersistenceCacheSizeBytes(int cacheSize) {
     return _channel.invokeMethod(
-      'FirebaseDatabase#setPersistenceCacheSizeBytes',
-      cacheSize,
-    );
+        'FirebaseDatabase#setPersistenceCacheSizeBytes', <String, dynamic>{
+      'app': app?.name,
+      'cacheSize': cacheSize,
+    });
   }
 
   /// Resumes our connection to the Firebase Database backend after a previous
   /// [goOffline] call.
   Future<Null> goOnline() {
-    return _channel.invokeMethod('FirebaseDatabase#goOnline');
+    return _channel.invokeMethod(
+      'FirebaseDatabase#goOnline',
+      <String, dynamic>{'app': app?.name},
+    );
   }
 
   /// Shuts down our connection to the Firebase Database backend until
   /// [goOnline] is called.
   Future<Null> goOffline() {
-    return _channel.invokeMethod('FirebaseDatabase#goOffline');
+    return _channel.invokeMethod(
+      'FirebaseDatabase#goOffline',
+      <String, dynamic>{'app': app?.name},
+    );
   }
 
   /// The Firebase Database client automatically queues writes and sends them to
@@ -124,6 +145,9 @@
   /// affected event listeners, and the client will not (re-)send them to the
   /// Firebase Database backend.
   Future<Null> purgeOutstandingWrites() {
-    return _channel.invokeMethod('FirebaseDatabase#purgeOutstandingWrites');
+    return _channel.invokeMethod(
+      'FirebaseDatabase#purgeOutstandingWrites',
+      <String, dynamic>{'app': app?.name},
+    );
   }
 }
diff --git a/packages/firebase_database/lib/src/query.dart b/packages/firebase_database/lib/src/query.dart
index ca1bed0..5107ecd 100644
--- a/packages/firebase_database/lib/src/query.dart
+++ b/packages/firebase_database/lib/src/query.dart
@@ -50,6 +50,7 @@
         _handle = _database._channel.invokeMethod(
           'Query#observe',
           <String, dynamic>{
+            'app': _database.app?.name,
             'path': path,
             'parameters': _parameters,
             'eventType': eventType.toString(),
@@ -64,6 +65,7 @@
           await _database._channel.invokeMethod(
             'Query#removeObserver',
             <String, dynamic>{
+              'app': _database.app?.name,
               'path': path,
               'parameters': _parameters,
               'handle': handle,
@@ -193,6 +195,7 @@
     return _database._channel.invokeMethod(
       'Query#keepSynced',
       <String, dynamic>{
+        'app': _database.app?.name,
         'path': path,
         'parameters': _parameters,
         'value': value
diff --git a/packages/firebase_database/pubspec.yaml b/packages/firebase_database/pubspec.yaml
index 0388f97..0ff945c 100755
--- a/packages/firebase_database/pubspec.yaml
+++ b/packages/firebase_database/pubspec.yaml
@@ -3,7 +3,7 @@
 description: Firebase Database plugin for Flutter.
 author: Flutter Team <flutter-dev@googlegroups.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_database
-version: 0.1.4
+version: 0.2.0
 
 flutter:
   plugin:
@@ -14,6 +14,7 @@
 dependencies:
   flutter:
     sdk: flutter
+  firebase_core: ^0.0.1
   meta: "^1.0.5"
 
 dev_dependencies:
diff --git a/packages/firebase_database/test/firebase_database_test.dart b/packages/firebase_database/test/firebase_database_test.dart
index d89b8c8..adb79c7 100755
--- a/packages/firebase_database/test/firebase_database_test.dart
+++ b/packages/firebase_database/test/firebase_database_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:firebase_core/firebase_core.dart';
 import 'package:firebase_database/firebase_database.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
@@ -16,7 +17,15 @@
 
     int mockHandleId = 0;
     final List<MethodCall> log = <MethodCall>[];
-    final FirebaseDatabase database = FirebaseDatabase.instance;
+    final FirebaseApp app = const FirebaseApp(
+      name: 'testApp',
+      options: const FirebaseOptions(
+        googleAppID: '1:1234567890:ios:42424242424242',
+        gcmSenderID: '1234567890',
+        databaseURL: 'https://fake-database-url.firebaseio.com',
+      ),
+    );
+    final FirebaseDatabase database = new FirebaseDatabase(app: app);
 
     setUp(() async {
       channel.setMockMethodCallHandler((MethodCall methodCall) async {
@@ -82,11 +91,17 @@
         <Matcher>[
           isMethodCall(
             'FirebaseDatabase#setPersistenceEnabled',
-            arguments: false,
+            arguments: <String, dynamic>{
+              'app': app.name,
+              'enabled': false,
+            },
           ),
           isMethodCall(
             'FirebaseDatabase#setPersistenceEnabled',
-            arguments: true,
+            arguments: <String, dynamic>{
+              'app': app.name,
+              'enabled': true,
+            },
           ),
         ],
       );
@@ -99,7 +114,10 @@
         <Matcher>[
           isMethodCall(
             'FirebaseDatabase#setPersistenceCacheSizeBytes',
-            arguments: 42,
+            arguments: <String, dynamic>{
+              'app': app.name,
+              'cacheSize': 42,
+            },
           ),
         ],
       );
@@ -110,7 +128,12 @@
       expect(
         log,
         <Matcher>[
-          isMethodCall('FirebaseDatabase#goOnline', arguments: null),
+          isMethodCall(
+            'FirebaseDatabase#goOnline',
+            arguments: <String, dynamic>{
+              'app': app.name,
+            },
+          ),
         ],
       );
     });
@@ -120,7 +143,12 @@
       expect(
         log,
         <Matcher>[
-          isMethodCall('FirebaseDatabase#goOffline', arguments: null),
+          isMethodCall(
+            'FirebaseDatabase#goOffline',
+            arguments: <String, dynamic>{
+              'app': app.name,
+            },
+          ),
         ],
       );
     });
@@ -132,7 +160,9 @@
         <Matcher>[
           isMethodCall(
             'FirebaseDatabase#purgeOutstandingWrites',
-            arguments: null,
+            arguments: <String, dynamic>{
+              'app': app.name,
+            },
           ),
         ],
       );
@@ -150,6 +180,7 @@
             isMethodCall(
               'DatabaseReference#set',
               arguments: <String, dynamic>{
+                'app': app.name,
                 'path': 'foo',
                 'value': value,
                 'priority': null,
@@ -158,6 +189,7 @@
             isMethodCall(
               'DatabaseReference#set',
               arguments: <String, dynamic>{
+                'app': app.name,
                 'path': 'bar',
                 'value': value,
                 'priority': priority,
@@ -174,7 +206,11 @@
           <Matcher>[
             isMethodCall(
               'DatabaseReference#update',
-              arguments: <String, dynamic>{'path': 'foo', 'value': value},
+              arguments: <String, dynamic>{
+                'app': app.name,
+                'path': 'foo',
+                'value': value,
+              },
             ),
           ],
         );
@@ -188,7 +224,11 @@
           <Matcher>[
             isMethodCall(
               'DatabaseReference#setPriority',
-              arguments: <String, dynamic>{'path': 'foo', 'priority': priority},
+              arguments: <String, dynamic>{
+                'app': app.name,
+                'path': 'foo',
+                'priority': priority,
+              },
             ),
           ],
         );
@@ -211,6 +251,7 @@
             isMethodCall(
               'DatabaseReference#runTransaction',
               arguments: <String, dynamic>{
+                'app': app.name,
                 'path': 'foo',
                 'transactionKey': 0,
                 'transactionTimeout': 5000,
@@ -243,6 +284,7 @@
             isMethodCall(
               'Query#keepSynced',
               arguments: <String, dynamic>{
+                'app': app.name,
                 'path': path,
                 'parameters': <String, dynamic>{},
                 'value': true,
@@ -277,6 +319,7 @@
             isMethodCall(
               'Query#keepSynced',
               arguments: <String, dynamic>{
+                'app': app.name,
                 'path': path,
                 'parameters': expectedParameters,
                 'value': false
@@ -373,6 +416,7 @@
             isMethodCall(
               'Query#observe',
               arguments: <String, dynamic>{
+                'app': app.name,
                 'path': path,
                 'parameters': <String, dynamic>{},
                 'eventType': '_EventType.value',
@@ -381,6 +425,7 @@
             isMethodCall(
               'Query#removeObserver',
               arguments: <String, dynamic>{
+                'app': app.name,
                 'path': path,
                 'parameters': <String, dynamic>{},
                 'handle': 87,