Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullPointerException throw when unsubscribe is called #308

Closed
hoanglm4 opened this issue Nov 6, 2017 · 2 comments
Closed

NullPointerException throw when unsubscribe is called #308

hoanglm4 opened this issue Nov 6, 2017 · 2 comments
Assignees
Labels
bug Bug that is caused by the library
Milestone

Comments

@hoanglm4
Copy link

hoanglm4 commented Nov 6, 2017

Summary

Sometimes, when I call unsubscribe, NullPointerException is throw

This is my code:

public class MainActivity extends RxAppCompatActivity {
    private static final String TAG = "MainActivity";
    public static final UUID VUZ_CHAR_UUID = UUID.fromString("25A80002-6478-11E6-BDF4-AD3BCC77759F");

    private Observable<RxBleConnection> connectionObservable;
    private PublishSubject<Void> disconnectTriggerSubject = PublishSubject.create();
    private RxBleDevice bleDevice;
    private Subscription mConnectionSubscription;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        String macAddress = "D0:29:DD:6F:32:DD";
        bleDevice = SampleApplication.getRxBleClient(this).getBleDevice(macAddress);
        connectionObservable = prepareConnectionObservable();
        //noinspection ConstantConditions
        getSupportActionBar().setSubtitle(getString(R.string.mac_address, macAddress));
    }

    private Observable<RxBleConnection> prepareConnectionObservable() {
        return bleDevice
                .establishConnection(false)
                .takeUntil(disconnectTriggerSubject)
                .compose(new ConnectionSharingAdapter())
                .doOnUnsubscribe(() -> Log.d(TAG, "prepareConnectionObservable>> doOnUnsubscribe"));
    }

    private boolean isConnected() {
        return bleDevice.getConnectionState() == RxBleConnection.RxBleConnectionState.CONNECTED;
    }

    @OnClick(R.id.connect)
    public void onConnectToggleClick() {
        if (mConnectionSubscription != null && !mConnectionSubscription.isUnsubscribed()) {
            mConnectionSubscription.unsubscribe();
        }
        if (isConnected()) {
            triggerDisconnect();
        }
        mConnectionSubscription = connectionObservable
                .flatMap(RxBleConnection::discoverServices)
                .flatMap(rxBleDeviceServices -> rxBleDeviceServices.getCharacteristic(VUZ_CHAR_UUID))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        characteristic -> {
                            Log.i(getClass().getSimpleName(), "Hey, connection has been established!");
                        },
                        this::onConnectionFailure,
                        this::onConnectionFinished
                );
    }

    @OnClick(R.id.unscription)
    public void disconnectClick() {
        if (mConnectionSubscription != null) {
            mConnectionSubscription.unsubscribe();
        }
        triggerDisconnect();
    }

    private void triggerDisconnect() {
        disconnectTriggerSubject.onNext(null);
    }

    private void onConnectionFailure(Throwable throwable) {
        Log.d(TAG, "onConnectionFailure>> Connection error: " + throwable);
    }

    private void onConnectionFinished() {
        Log.d(TAG, "onConnectionFinished>> Connection finish");
    }

}

Log crash:

Caused by java.lang.NullPointerException: Attempt to invoke interface method 'void rx.Subscription.unsubscribe()' on a null object reference
       at com.polidea.rxandroidble.internal.serialization.ConnectionOperationQueueImpl.onConnectionUnsubscribed(ConnectionOperationQueueImpl.java:147)
       at com.polidea.rxandroidble.internal.connection.ConnectorImpl$1$2.call(ConnectorImpl.java:68)
       at rx.subscriptions.BooleanSubscription.unsubscribe(BooleanSubscription.java:71)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.subscriptions.CompositeSubscription.unsubscribeFromAll(CompositeSubscription.java:186)
       at rx.subscriptions.CompositeSubscription.unsubscribe(CompositeSubscription.java:175)
       at rx.internal.operators.OnSubscribeRefCount$3.call(OnSubscribeRefCount.java:164)
       at rx.subscriptions.BooleanSubscription.unsubscribe(BooleanSubscription.java:71)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.internal.subscriptions.SequentialSubscription.unsubscribe(SequentialSubscription.java:180)
       at rx.subscriptions.SerialSubscription.unsubscribe(SerialSubscription.java:36)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)
       at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
       at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
       at rx.Subscriber.unsubscribe(Subscriber.java:98)

Library version

1.4.2

Actual result

NullPointerException throw

Expected result

Check NULL in https://github.com/Polidea/RxAndroidBle/blob/master/rxandroidble/src/main/java/com/polidea/rxandroidble/internal/serialization/ConnectionOperationQueueImpl.java#L147 or find cause of this bug.

Thanks

@dariuszseweryn dariuszseweryn added the bug Bug that is caused by the library label Nov 13, 2017
dariuszseweryn added a commit that referenced this issue Nov 13, 2017
…ixes #308)

Without specifcation of `.subscribeOn()` and `.unsubscribeOn()` there was a possibility of a race condition when calling `.doOnSubscribe()` and `.doOnUnsubscribe()` which lead to calling `ConnectionOperationQueueImpl.onConnectionUnsubscribed()` before the `.onConnectionSubscribed()` has returned leading to a `NullPointerException`. By default `.doOnSubscribe()` is called on a thread that calls `.subscribe()` and `.doOnUnsubcribe()` is called on thread that calls `Subscription.unsubscribe()`.
@dariuszseweryn dariuszseweryn added this to the 1.4.3 milestone Nov 13, 2017
@dariuszseweryn dariuszseweryn self-assigned this Nov 13, 2017
@dariuszseweryn
Copy link
Owner

Hello @hoanglm4
I have just pushed a fix for this issue. It should be available in 1.4.3-SNAPSHOT shortly. Could you give it a try?

@hoanglm4
Copy link
Author

Thanks @dariuszseweryn
I will follow it in fabric crashlytics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug that is caused by the library
Projects
None yet
Development

No branches or pull requests

2 participants