Skip to content

Commit 4157ee3

Browse files
Merge pull request firebase#30 from BugsBunnyBR/plugin/firebase_database_null_fix
[Firebase_Database] Fix possible NullPointerException
2 parents cc946c9 + 0338907 commit 4157ee3

File tree

3 files changed

+42
-37
lines changed

3 files changed

+42
-37
lines changed

packages/firebase_database/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 3.0.7
2+
3+
* Fix possible NullPointerException when plugin is registered without a valid Activity.
4+
15
## 3.0.6
26

37
* Update documentation to reflect new repository location.

packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
package io.flutter.plugins.firebase.database;
66

7-
import android.app.Activity;
7+
import android.os.Handler;
88
import android.util.Log;
99
import android.util.SparseArray;
10+
import androidx.annotation.NonNull;
11+
import androidx.annotation.Nullable;
1012
import com.google.android.gms.tasks.Task;
1113
import com.google.android.gms.tasks.TaskCompletionSource;
1214
import com.google.android.gms.tasks.Tasks;
@@ -38,7 +40,7 @@ public class FirebaseDatabasePlugin implements MethodCallHandler {
3840
private static final String TAG = "FirebaseDatabasePlugin";
3941

4042
private final MethodChannel channel;
41-
private final Activity activity;
43+
private final Handler handler = new Handler();
4244
private static final String EVENT_TYPE_CHILD_ADDED = "_EventType.childAdded";
4345
private static final String EVENT_TYPE_CHILD_REMOVED = "_EventType.childRemoved";
4446
private static final String EVENT_TYPE_CHILD_CHANGED = "_EventType.childChanged";
@@ -52,12 +54,11 @@ public class FirebaseDatabasePlugin implements MethodCallHandler {
5254
public static void registerWith(PluginRegistry.Registrar registrar) {
5355
final MethodChannel channel =
5456
new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_database");
55-
channel.setMethodCallHandler(new FirebaseDatabasePlugin(channel, registrar.activity()));
57+
channel.setMethodCallHandler(new FirebaseDatabasePlugin(channel));
5658
}
5759

58-
private FirebaseDatabasePlugin(MethodChannel channel, Activity activity) {
60+
private FirebaseDatabasePlugin(MethodChannel channel) {
5961
this.channel = channel;
60-
this.activity = activity;
6162
}
6263

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

164165
@Override
165-
public void onComplete(DatabaseError error, DatabaseReference ref) {
166+
public void onComplete(@Nullable DatabaseError error, @NonNull DatabaseReference ref) {
166167
if (error != null) {
167168
result.error(String.valueOf(error.getCode()), error.getMessage(), error.getDetails());
168169
} else {
@@ -180,7 +181,8 @@ private class EventObserver implements ChildEventListener, ValueEventListener {
180181
this.handle = handle;
181182
}
182183

183-
private void sendEvent(String eventType, DataSnapshot snapshot, String previousChildName) {
184+
private void sendEvent(
185+
String eventType, @NonNull DataSnapshot snapshot, String previousChildName) {
184186
if (eventType.equals(requestedEventType)) {
185187
Map<String, Object> arguments = new HashMap<>();
186188
Map<String, Object> snapshotMap = new HashMap<>();
@@ -194,45 +196,45 @@ private void sendEvent(String eventType, DataSnapshot snapshot, String previousC
194196
}
195197

196198
@Override
197-
public void onCancelled(DatabaseError error) {
199+
public void onCancelled(@NonNull DatabaseError error) {
198200
Map<String, Object> arguments = new HashMap<>();
199201
arguments.put("handle", handle);
200202
arguments.put("error", asMap(error));
201203
channel.invokeMethod("Error", arguments);
202204
}
203205

204206
@Override
205-
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
207+
public void onChildAdded(@NonNull DataSnapshot snapshot, String previousChildName) {
206208
sendEvent(EVENT_TYPE_CHILD_ADDED, snapshot, previousChildName);
207209
}
208210

209211
@Override
210-
public void onChildRemoved(DataSnapshot snapshot) {
212+
public void onChildRemoved(@NonNull DataSnapshot snapshot) {
211213
sendEvent(EVENT_TYPE_CHILD_REMOVED, snapshot, null);
212214
}
213215

214216
@Override
215-
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
217+
public void onChildChanged(@NonNull DataSnapshot snapshot, String previousChildName) {
216218
sendEvent(EVENT_TYPE_CHILD_CHANGED, snapshot, previousChildName);
217219
}
218220

219221
@Override
220-
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
222+
public void onChildMoved(@NonNull DataSnapshot snapshot, String previousChildName) {
221223
sendEvent(EVENT_TYPE_CHILD_MOVED, snapshot, previousChildName);
222224
}
223225

224226
@Override
225-
public void onDataChange(DataSnapshot snapshot) {
227+
public void onDataChange(@NonNull DataSnapshot snapshot) {
226228
sendEvent(EVENT_TYPE_VALUE, snapshot, null);
227229
}
228230
}
229231

230232
@Override
231-
public void onMethodCall(final MethodCall call, final Result result) {
233+
public void onMethodCall(final MethodCall call, @NonNull final Result result) {
232234
final Map<String, Object> arguments = call.arguments();
233235
FirebaseDatabase database;
234-
String appName = (String) arguments.get("app");
235-
String databaseURL = (String) arguments.get("databaseURL");
236+
String appName = call.argument("app");
237+
String databaseURL = call.argument("databaseURL");
236238
if (appName != null && databaseURL != null) {
237239
database = FirebaseDatabase.getInstance(FirebaseApp.getInstance(appName), databaseURL);
238240
} else if (appName != null) {
@@ -266,7 +268,7 @@ public void onMethodCall(final MethodCall call, final Result result) {
266268

267269
case "FirebaseDatabase#setPersistenceEnabled":
268270
{
269-
Boolean isEnabled = (Boolean) arguments.get("enabled");
271+
Boolean isEnabled = call.argument("enabled");
270272
try {
271273
database.setPersistenceEnabled(isEnabled);
272274
result.success(true);
@@ -279,7 +281,7 @@ public void onMethodCall(final MethodCall call, final Result result) {
279281

280282
case "FirebaseDatabase#setPersistenceCacheSizeBytes":
281283
{
282-
long cacheSize = (Integer) arguments.get("cacheSize");
284+
Long cacheSize = call.argument("cacheSize");
283285
try {
284286
database.setPersistenceCacheSizeBytes(cacheSize);
285287
result.success(true);
@@ -292,8 +294,8 @@ public void onMethodCall(final MethodCall call, final Result result) {
292294

293295
case "DatabaseReference#set":
294296
{
295-
Object value = arguments.get("value");
296-
Object priority = arguments.get("priority");
297+
Object value = call.argument("value");
298+
Object priority = call.argument("priority");
297299
DatabaseReference reference = getReference(database, arguments);
298300
if (priority != null) {
299301
reference.setValue(value, priority, new DefaultCompletionListener(result));
@@ -305,16 +307,15 @@ public void onMethodCall(final MethodCall call, final Result result) {
305307

306308
case "DatabaseReference#update":
307309
{
308-
@SuppressWarnings("unchecked")
309-
Map<String, Object> value = (Map<String, Object>) arguments.get("value");
310+
Map<String, Object> value = call.argument("value");
310311
DatabaseReference reference = getReference(database, arguments);
311312
reference.updateChildren(value, new DefaultCompletionListener(result));
312313
break;
313314
}
314315

315316
case "DatabaseReference#setPriority":
316317
{
317-
Object priority = arguments.get("priority");
318+
Object priority = call.argument("priority");
318319
DatabaseReference reference = getReference(database, arguments);
319320
reference.setPriority(priority, new DefaultCompletionListener(result));
320321
break;
@@ -327,8 +328,9 @@ public void onMethodCall(final MethodCall call, final Result result) {
327328
// Initiate native transaction.
328329
reference.runTransaction(
329330
new Transaction.Handler() {
331+
@NonNull
330332
@Override
331-
public Transaction.Result doTransaction(MutableData mutableData) {
333+
public Transaction.Result doTransaction(@NonNull MutableData mutableData) {
332334
// Tasks are used to allow native execution of doTransaction to wait while Snapshot is
333335
// processed by logic on the Dart side.
334336
final TaskCompletionSource<Map<String, Object>> updateMutableDataTCS =
@@ -337,15 +339,15 @@ public Transaction.Result doTransaction(MutableData mutableData) {
337339
updateMutableDataTCS.getTask();
338340

339341
final Map<String, Object> doTransactionMap = new HashMap<>();
340-
doTransactionMap.put("transactionKey", arguments.get("transactionKey"));
342+
doTransactionMap.put("transactionKey", call.argument("transactionKey"));
341343

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

347349
// Return snapshot to Dart side for update.
348-
activity.runOnUiThread(
350+
handler.post(
349351
new Runnable() {
350352
@Override
351353
public void run() {
@@ -405,7 +407,7 @@ public void notImplemented() {
405407
public void onComplete(
406408
DatabaseError databaseError, boolean committed, DataSnapshot dataSnapshot) {
407409
final Map<String, Object> completionMap = new HashMap<>();
408-
completionMap.put("transactionKey", arguments.get("transactionKey"));
410+
completionMap.put("transactionKey", call.argument("transactionKey"));
409411
if (databaseError != null) {
410412
completionMap.put("error", asMap(databaseError));
411413
}
@@ -418,7 +420,7 @@ public void onComplete(
418420
}
419421

420422
// Invoke transaction completion on the Dart side.
421-
activity.runOnUiThread(
423+
handler.post(
422424
new Runnable() {
423425
public void run() {
424426
result.success(completionMap);
@@ -431,8 +433,8 @@ public void run() {
431433

432434
case "OnDisconnect#set":
433435
{
434-
Object value = arguments.get("value");
435-
Object priority = arguments.get("priority");
436+
Object value = call.argument("value");
437+
Object priority = call.argument("priority");
436438
DatabaseReference reference = getReference(database, arguments);
437439
if (priority != null) {
438440
if (priority instanceof String) {
@@ -456,8 +458,7 @@ public void run() {
456458

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

473474
case "Query#keepSynced":
474475
{
475-
boolean value = (Boolean) arguments.get("value");
476+
Boolean value = call.argument("value");
476477
getQuery(database, arguments).keepSynced(value);
477478
result.success(null);
478479
break;
479480
}
480481

481482
case "Query#observe":
482483
{
483-
String eventType = (String) arguments.get("eventType");
484+
String eventType = call.argument("eventType");
484485
int handle = nextHandle++;
485486
EventObserver observer = new EventObserver(eventType, handle);
486487
observers.put(handle, observer);
487-
if (eventType.equals(EVENT_TYPE_VALUE)) {
488+
if (EVENT_TYPE_VALUE.equals(eventType)) {
488489
getQuery(database, arguments).addValueEventListener(observer);
489490
} else {
490491
getQuery(database, arguments).addChildEventListener(observer);
@@ -496,7 +497,7 @@ public void run() {
496497
case "Query#removeObserver":
497498
{
498499
Query query = getQuery(database, arguments);
499-
int handle = (Integer) arguments.get("handle");
500+
Integer handle = call.argument("handle");
500501
EventObserver observer = observers.get(handle);
501502
if (observer != null) {
502503
if (observer.requestedEventType.equals(EVENT_TYPE_VALUE)) {

packages/firebase_database/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database
33
with realtime data syncing across Android and iOS clients, and offline access.
44
author: Flutter Team <flutter-dev@googlegroups.com>
55
homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_database
6-
version: 3.0.6
6+
version: 3.0.7
77

88
flutter:
99
plugin:

0 commit comments

Comments
 (0)