dariuszseweryn / RxAndroidBle

An Android Bluetooth Low Energy (BLE) Library with RxJava3 interface
http://polidea.github.io/RxAndroidBle/
Apache License 2.0
3.43k stars 581 forks source link

Crashing if using Application Context instead of Activity context (MIUI, DeadObjectException) #503

Closed marvson closed 5 years ago

marvson commented 5 years ago

Summary

Library version

1.7.1

Preconditions

Using java 8, RxJava2 2.2.3, RxAndroid 2.1.0 with minSdkVersion 18

Steps to reproduce actual result

Using rxBleClient = RxBleClient.create(this.getApplicationContext()); instead of rxBleClient = RxBleClient.create(this);

Minimum code snippet reproducing the issue


package atry.toy.toybluetooth;

import android.Manifest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.polidea.rxandroidble2.RxBleClient;
import com.polidea.rxandroidble2.scan.ScanSettings;
import com.tbruyelle.rxpermissions2.RxPermissions;

import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;

public class MainActivity extends AppCompatActivity {
    RxPermissions rxPermissions;
    RxBleClient rxBleClient;
    Disposable scan;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rxPermissions = new RxPermissions(this);
        rxPermissions.requestEach(
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_ADMIN,
                Manifest.permission.ACCESS_FINE_LOCATION)
                .subscribe();

        rxBleClient = RxBleClient.create(this.getApplicationContext());
        System.out.println("Create scan.");
        scan = rxBleClient.observeStateChanges()
                .switchMap(state -> { // switchMap makes sure that if the state will change the rxBleClient.scanBleDevices() will dispose and thus end the scan
                    switch (state) {

                        case READY:
                            return rxBleClient.scanBleDevices(new ScanSettings.Builder().build());
                        case BLUETOOTH_NOT_AVAILABLE:
                            System.out.println("Not Available");
                        case LOCATION_PERMISSION_NOT_GRANTED:
                            System.out.println("Location not granted");
                        case BLUETOOTH_NOT_ENABLED:
                            System.out.println("Bluetooth not enabled");
                        case LOCATION_SERVICES_NOT_ENABLED:
                            System.out.println("Location not enabled");
                        default:
                            return Observable.empty();
                    }
                })
                .subscribe(
                        rxBleScanResult -> {
                            System.out.println("emmit");
                        },
                        throwable -> {
                            System.out.println(throwable.toString());
                        }
                );
    }
}

Logs from the application running with setting RxBleLog.setLogLevel(RxBleLog.VERBOSE)

The entire log is too big, these are the two parts regarding this issue:

2018-11-20 14:55:51.402 1639-1639/? V/BluetoothAdapterState: isTurningOff()=true
2018-11-20 14:55:51.402 1639-1639/? V/BluetoothAdapterState: isTurningOn()=false
2018-11-20 14:55:51.402 1639-1639/? V/BluetoothAdapterState: isBleTurningOn()=false
2018-11-20 14:55:51.402 1639-1639/? V/BluetoothAdapterState: isBleTurningOff()=false
2018-11-20 14:55:51.402 1639-1639/? W/BluetoothAdapterService: onProfileServiceStateChange() - Profile still running: com.android.bluetooth.hid.HidService
2018-11-20 14:55:51.403 10556-10556/? D/BluetoothA2dp: Proxy object disconnected
2018-11-20 14:55:51.403 1639-1639/? D/BluetoothAdapterService: getAdapterService() - returning com.android.bluetooth.btservice.AdapterService@c9d0c46
2018-11-20 14:55:51.407 1639-1639/? D/HeadsetPhoneState: cleanup
2018-11-20 14:55:51.408 1639-1760/? W/BluetoothAdapterService: setProfileServiceState() - Stopping service com.android.bluetooth.pan.PanService
2018-11-20 14:55:51.413 1385-1456/? D/BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: ON > TURNING_OFF
2018-11-20 14:55:51.413 1385-1456/? D/BluetoothManagerService: bluetoothStateChangeHandler: 12 ->  13
2018-11-20 14:55:51.413 1385-1456/? D/BluetoothManagerService: Sending BLE State Change: ON > TURNING_OFF
2018-11-20 14:55:51.420 1639-1760/? W/BluetoothAdapterService: setProfileServiceState() - Stopping service com.android.bluetooth.map.BluetoothMapService
2018-11-20 14:55:51.428 1667-1667/? D/PhoneStatusBarPolicy: Bluetooth action:android.bluetooth.adapter.action.STATE_CHANGED icon:151126581
2018-11-20 14:55:51.428 1667-1667/? D/PhoneStatusBarPolicy: Bluetooth state changed, state:13
2018-11-20 14:55:51.431 1639-1760/? W/BluetoothAdapterService: setProfileServiceState() - Stopping service com.android.bluetooth.avrcp.AvrcpControllerService
2018-11-20 14:55:51.433 14876-14876/atry.toy.toybluetooth I/System.out: com.polidea.rxandroidble2.exceptions.BleScanException: Bluetooth disabled (code 1)
2018-11-20 14:55:51.434 1385-1385/? D/BluetoothHeadset: Proxy object disconnected
2018-11-20 14:55:51.434 1385-1385/? D/BluetoothA2dp: Proxy object disconnected 

 14876-14876/atry.toy.toybluetooth I/System.out: emmit
2018-11-20 14:55:50.660 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.660 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.661 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.661 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.662 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.662 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.662 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.663 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.663 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.664 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.664 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.665 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.665 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.665 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.666 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.666 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.667 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.667 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.668 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.668 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.668 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.669 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.669 1639-1770/? E/BtGatt.GattService: Exception: android.os.DeadObjectException
2018-11-20 14:55:50.671 14876-14876/atry.toy.toybluetooth I/System.out: emmit

Actual result

There is a spamming of a dead object exception and when we disconnect the bluetooth, there is an exception that doesn't happens when we use the activity context. I'm also unable to start any other scan, and the state change isn't captured.

Expected result

The state change is captured and the text "Bluetooth not enabled" is printed. Also there is no dead object exception.

Why this issue is important

I'm using dagger2 and I have access just to the application context when injecting this dependency (RxBleClient). I can easily fix this but in an ugly way.

dariuszseweryn commented 5 years ago

What device/OS version you test on? The library itself uses Context.getApplicationContext() inside on the Context passed into RxBleClient.create(Context). I doubt that this is the problem. I see in the logs that the BT adapter state has changed but you do not mention it anywhere. Could you add more info?

marvson commented 5 years ago

The library itself uses Context.getApplicationContext() inside on the Context passed into RxBleClient.create(Context). I doubt that this is the problem

This helps a lot. I confirmed that it is OS related. It only happens in Miui 9.6.5, Android 7.1 Nougat. I tried in a Samsung with android 5.1 and it works just fine. And I found this explanation on stackoverflow link seems legit. And when I fixed the process, a thing that you can make in miui, it worked fine. Seems like it optimizes the process killing something important. No clue about what exactly happens but now I know how to fix it. Thank you.

dariuszseweryn commented 5 years ago

I am happy that you have solve the problem

And when I fixed the process, a thing that you can make in miui

Could you add a bit more info that I could learn from? I do not know what you mean by fixed

marvson commented 5 years ago

I don't know the exact naming but "lock the proccess" is more like it. if you tap the button to show all opened apps and drag an app window down, then a lock appears in the top right of that window. It kind of protects the app from being optimized by miui, it also can't be terminated by android.

This actually was't what solved it to me. I just modified to not use dagger2 and to use the activity context, because I don't think it's a good thing asking the user to lock the app, since I can't do it programatically.

dariuszseweryn commented 5 years ago

Weird... You're the first person who is mentioning this kind of a problem with Xiaomi devices. If you or someone else would find more information about the MIUI/Xiaomi implementation — feel free to share.

I see no way in which the library could change to help in this situation so I am closing now. If more info or a path forward will be available — feel free to add it and reopen