Skip to content

Commit

Permalink
Merge pull request flutter#30 from BugsBunnyBR/plugin/firebase_databa…
Browse files Browse the repository at this point in the history
…se_null_fix

[Firebase_Database] Fix possible NullPointerException
  • Loading branch information
collinjackson authored Aug 26, 2019
2 parents cc946c9 + 0338907 commit 4157ee3
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 37 deletions.
4 changes: 4 additions & 0 deletions packages/firebase_database/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.0.7

* Fix possible NullPointerException when plugin is registered without a valid Activity.

## 3.0.6

* Update documentation to reflect new repository location.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

package io.flutter.plugins.firebase.database;

import android.app.Activity;
import android.os.Handler;
import android.util.Log;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.TaskCompletionSource;
import com.google.android.gms.tasks.Tasks;
Expand Down Expand Up @@ -38,7 +40,7 @@ public class FirebaseDatabasePlugin implements MethodCallHandler {
private static final String TAG = "FirebaseDatabasePlugin";

private final MethodChannel channel;
private final Activity activity;
private final Handler handler = new Handler();
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";
Expand All @@ -52,12 +54,11 @@ 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, registrar.activity()));
channel.setMethodCallHandler(new FirebaseDatabasePlugin(channel));
}

private FirebaseDatabasePlugin(MethodChannel channel, Activity activity) {
private FirebaseDatabasePlugin(MethodChannel channel) {
this.channel = channel;
this.activity = activity;
}

private DatabaseReference getReference(FirebaseDatabase database, Map<String, Object> arguments) {
Expand Down Expand Up @@ -162,7 +163,7 @@ private class DefaultCompletionListener implements DatabaseReference.CompletionL
}

@Override
public void onComplete(DatabaseError error, DatabaseReference ref) {
public void onComplete(@Nullable DatabaseError error, @NonNull DatabaseReference ref) {
if (error != null) {
result.error(String.valueOf(error.getCode()), error.getMessage(), error.getDetails());
} else {
Expand All @@ -180,7 +181,8 @@ private class EventObserver implements ChildEventListener, ValueEventListener {
this.handle = handle;
}

private void sendEvent(String eventType, DataSnapshot snapshot, String previousChildName) {
private void sendEvent(
String eventType, @NonNull DataSnapshot snapshot, String previousChildName) {
if (eventType.equals(requestedEventType)) {
Map<String, Object> arguments = new HashMap<>();
Map<String, Object> snapshotMap = new HashMap<>();
Expand All @@ -194,45 +196,45 @@ private void sendEvent(String eventType, DataSnapshot snapshot, String previousC
}

@Override
public void onCancelled(DatabaseError error) {
public void onCancelled(@NonNull DatabaseError error) {
Map<String, Object> arguments = new HashMap<>();
arguments.put("handle", handle);
arguments.put("error", asMap(error));
channel.invokeMethod("Error", arguments);
}

@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
public void onChildAdded(@NonNull DataSnapshot snapshot, String previousChildName) {
sendEvent(EVENT_TYPE_CHILD_ADDED, snapshot, previousChildName);
}

@Override
public void onChildRemoved(DataSnapshot snapshot) {
public void onChildRemoved(@NonNull DataSnapshot snapshot) {
sendEvent(EVENT_TYPE_CHILD_REMOVED, snapshot, null);
}

@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
public void onChildChanged(@NonNull DataSnapshot snapshot, String previousChildName) {
sendEvent(EVENT_TYPE_CHILD_CHANGED, snapshot, previousChildName);
}

@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
public void onChildMoved(@NonNull DataSnapshot snapshot, String previousChildName) {
sendEvent(EVENT_TYPE_CHILD_MOVED, snapshot, previousChildName);
}

@Override
public void onDataChange(DataSnapshot snapshot) {
public void onDataChange(@NonNull DataSnapshot snapshot) {
sendEvent(EVENT_TYPE_VALUE, snapshot, null);
}
}

@Override
public void onMethodCall(final MethodCall call, final Result result) {
public void onMethodCall(final MethodCall call, @NonNull final Result result) {
final Map<String, Object> arguments = call.arguments();
FirebaseDatabase database;
String appName = (String) arguments.get("app");
String databaseURL = (String) arguments.get("databaseURL");
String appName = call.argument("app");
String databaseURL = call.argument("databaseURL");
if (appName != null && databaseURL != null) {
database = FirebaseDatabase.getInstance(FirebaseApp.getInstance(appName), databaseURL);
} else if (appName != null) {
Expand Down Expand Up @@ -266,7 +268,7 @@ public void onMethodCall(final MethodCall call, final Result result) {

case "FirebaseDatabase#setPersistenceEnabled":
{
Boolean isEnabled = (Boolean) arguments.get("enabled");
Boolean isEnabled = call.argument("enabled");
try {
database.setPersistenceEnabled(isEnabled);
result.success(true);
Expand All @@ -279,7 +281,7 @@ public void onMethodCall(final MethodCall call, final Result result) {

case "FirebaseDatabase#setPersistenceCacheSizeBytes":
{
long cacheSize = (Integer) arguments.get("cacheSize");
Long cacheSize = call.argument("cacheSize");
try {
database.setPersistenceCacheSizeBytes(cacheSize);
result.success(true);
Expand All @@ -292,8 +294,8 @@ public void onMethodCall(final MethodCall call, final Result result) {

case "DatabaseReference#set":
{
Object value = arguments.get("value");
Object priority = arguments.get("priority");
Object value = call.argument("value");
Object priority = call.argument("priority");
DatabaseReference reference = getReference(database, arguments);
if (priority != null) {
reference.setValue(value, priority, new DefaultCompletionListener(result));
Expand All @@ -305,16 +307,15 @@ public void onMethodCall(final MethodCall call, final Result result) {

case "DatabaseReference#update":
{
@SuppressWarnings("unchecked")
Map<String, Object> value = (Map<String, Object>) arguments.get("value");
Map<String, Object> value = call.argument("value");
DatabaseReference reference = getReference(database, arguments);
reference.updateChildren(value, new DefaultCompletionListener(result));
break;
}

case "DatabaseReference#setPriority":
{
Object priority = arguments.get("priority");
Object priority = call.argument("priority");
DatabaseReference reference = getReference(database, arguments);
reference.setPriority(priority, new DefaultCompletionListener(result));
break;
Expand All @@ -327,8 +328,9 @@ public void onMethodCall(final MethodCall call, final Result result) {
// Initiate native transaction.
reference.runTransaction(
new Transaction.Handler() {
@NonNull
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
public Transaction.Result doTransaction(@NonNull MutableData mutableData) {
// Tasks are used to allow native execution of doTransaction to wait while Snapshot is
// processed by logic on the Dart side.
final TaskCompletionSource<Map<String, Object>> updateMutableDataTCS =
Expand All @@ -337,15 +339,15 @@ public Transaction.Result doTransaction(MutableData mutableData) {
updateMutableDataTCS.getTask();

final Map<String, Object> doTransactionMap = new HashMap<>();
doTransactionMap.put("transactionKey", arguments.get("transactionKey"));
doTransactionMap.put("transactionKey", call.argument("transactionKey"));

final Map<String, Object> snapshotMap = new HashMap<>();
snapshotMap.put("key", mutableData.getKey());
snapshotMap.put("value", mutableData.getValue());
doTransactionMap.put("snapshot", snapshotMap);

// Return snapshot to Dart side for update.
activity.runOnUiThread(
handler.post(
new Runnable() {
@Override
public void run() {
Expand Down Expand Up @@ -405,7 +407,7 @@ public void notImplemented() {
public void onComplete(
DatabaseError databaseError, boolean committed, DataSnapshot dataSnapshot) {
final Map<String, Object> completionMap = new HashMap<>();
completionMap.put("transactionKey", arguments.get("transactionKey"));
completionMap.put("transactionKey", call.argument("transactionKey"));
if (databaseError != null) {
completionMap.put("error", asMap(databaseError));
}
Expand All @@ -418,7 +420,7 @@ public void onComplete(
}

// Invoke transaction completion on the Dart side.
activity.runOnUiThread(
handler.post(
new Runnable() {
public void run() {
result.success(completionMap);
Expand All @@ -431,8 +433,8 @@ public void run() {

case "OnDisconnect#set":
{
Object value = arguments.get("value");
Object priority = arguments.get("priority");
Object value = call.argument("value");
Object priority = call.argument("priority");
DatabaseReference reference = getReference(database, arguments);
if (priority != null) {
if (priority instanceof String) {
Expand All @@ -456,8 +458,7 @@ public void run() {

case "OnDisconnect#update":
{
@SuppressWarnings("unchecked")
Map<String, Object> value = (Map<String, Object>) arguments.get("value");
Map<String, Object> value = call.argument("value");
DatabaseReference reference = getReference(database, arguments);
reference.onDisconnect().updateChildren(value, new DefaultCompletionListener(result));
break;
Expand All @@ -472,19 +473,19 @@ public void run() {

case "Query#keepSynced":
{
boolean value = (Boolean) arguments.get("value");
Boolean value = call.argument("value");
getQuery(database, arguments).keepSynced(value);
result.success(null);
break;
}

case "Query#observe":
{
String eventType = (String) arguments.get("eventType");
String eventType = call.argument("eventType");
int handle = nextHandle++;
EventObserver observer = new EventObserver(eventType, handle);
observers.put(handle, observer);
if (eventType.equals(EVENT_TYPE_VALUE)) {
if (EVENT_TYPE_VALUE.equals(eventType)) {
getQuery(database, arguments).addValueEventListener(observer);
} else {
getQuery(database, arguments).addChildEventListener(observer);
Expand All @@ -496,7 +497,7 @@ public void run() {
case "Query#removeObserver":
{
Query query = getQuery(database, arguments);
int handle = (Integer) arguments.get("handle");
Integer handle = call.argument("handle");
EventObserver observer = observers.get(handle);
if (observer != null) {
if (observer.requestedEventType.equals(EVENT_TYPE_VALUE)) {
Expand Down
2 changes: 1 addition & 1 deletion packages/firebase_database/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_database
version: 3.0.6
version: 3.0.7

flutter:
plugin:
Expand Down

0 comments on commit 4157ee3

Please sign in to comment.