dotintent / FlutterBleLib

Bluetooth Low Energy library for Flutter with support for simulating peripherals
Apache License 2.0
540 stars 199 forks source link

[Android] Intermittent NullPointerException after canceling a ConnectionStateStreamHandler #468

Closed cbreezier closed 4 years ago

cbreezier commented 4 years ago

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.

cbreezier commented 4 years ago

I created https://github.com/Polidea/FlutterBleLib/pull/469

cbreezier commented 4 years ago

@mikolak When might the next release of this library be, which includes this fix?

mikolak commented 4 years ago

I have to release MBA as well to include one other fix and then this one. I'll release them next week at the latest.

mikolak commented 4 years ago

@cbreezier 2.2.5 is out

cbreezier commented 4 years ago

Thank you! @mikolak