Skip to content

[Android] Intermittent NullPointerException after canceling a ConnectionStateStreamHandler #468

@cbreezier

Description

@cbreezier

Hi,

I'm seeing very common null pointer exceptions whenever I dispose of a connection state observer, around the same time I disconnect from a device.

D/AndroidRuntime(32230): Shutting down VM
E/AndroidRuntime(32230): FATAL EXCEPTION: main
E/AndroidRuntime(32230): Process: com.wbstech.elumen, PID: 32230
E/AndroidRuntime(32230): java.lang.NullPointerException: Attempt to invoke interface method 'void io.flutter.plugin.common.EventChannel$EventSink.success(java.lang.Object)' on a null object reference
E/AndroidRuntime(32230): 	at com.polidea.flutter_ble_lib.event.ConnectionStateStreamHandler$1.run(ConnectionStateStreamHandler.java:34)
E/AndroidRuntime(32230): 	at android.os.Handler.handleCallback(Handler.java:883)
E/AndroidRuntime(32230): 	at android.os.Handler.dispatchMessage(Handler.java:100)
E/AndroidRuntime(32230): 	at android.os.Looper.loop(Looper.java:214)
E/AndroidRuntime(32230): 	at android.app.ActivityThread.main(ActivityThread.java:7356)
E/AndroidRuntime(32230): 	at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(32230): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
E/AndroidRuntime(32230): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
D/BluetoothGatt(32230): close()

Looking at ConnectionStateStreamHandler:

public class ConnectionStateStreamHandler implements EventChannel.StreamHandler {

...

    @Override
    synchronized public void onCancel(Object o) {
        eventSink = null;
    }

    synchronized public void onNewConnectionState(final ConnectionStateChange connectionState) {
        if (eventSink != null) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    try {
                        eventSink.success(connectionStateChangeJsonConverter.toJson(connectionState));
                    } catch (JSONException e) {
                        eventSink.error("-1", e.getMessage(), e.getStackTrace());
                    }
                }
            });
        }
    }
...
}

I think the if (eventSink != null) check needs to be moved into the async Runnable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions