NordicSemiconductor / Android-DFU-Library

Device Firmware Update library and Android app
http://www.nordicsemi.com/dfu
BSD 3-Clause "New" or "Revised" License
763 stars 269 forks source link

Cannot listen for DFU updates in non activity class #47

Closed Nallo closed 7 years ago

Nallo commented 7 years ago

Hi folks,

I am currently writing a wrapper around the Android DFU Library aiming at simplify the Bluetooth communication with an electronic device (nRF51822) I am working on.

The idea is the following: having a class (not an Activity) called DeviceManager which exposes a few methods such as:

and an interface called DeviceInterface which requires the following methods to be overwritten:

All the code managing the Bluetooth communication with the device is therefore embedded in the DeviceManagerclass.

I am now working on the DFU part, to let developers updating the firmware of our device therefore, I let the DeviceManager class extending the DfuBaseService class to be able to perform the DFU on my device. The issue I am facing is the following:

after calling the start() method of the DfuServiceInitiator I am not able to get any update either in the DfuProgressListener nor in the DfuLogListener.

Below I am reporting the piece of code that is supposed to start the DFU process (called inside the onLeScan() callback of the Android BluetoothAdapter).

private final BluetoothAdapter.LeScanCallback mScanCallback = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {

        // Code for filter the device based on address and name ....

        final DfuServiceInitiator dfuStarter =
                            new DfuServiceInitiator(device.getAddress())
                            .setKeepBond(true)
                            .setZip(mDfuZipUri)
                            .setDeviceName(device.getName());
        dfuStarter.start(mContext, ShDeviceManager.class);
    }
};

In addition, when my DeviceManager class is being instantiated I set the DfuProgressListener and DfuLogListener as follows.

public DeviceManager(String deviceName, DeviceInterface delegate, Context context) {
    mDeviceName = deviceName;
    bleDelegate = delegate;
    mContext = context;

    final BluetoothManager btManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = btManager.getAdapter();

    DfuServiceListenerHelper.registerLogListener(mContext, mDfuLogListener);
    DfuServiceListenerHelper.registerProgressListener(mContext, mDfuProgressListener);
}

The 2 listeners are declared in the DeviceManager class as follows:

private final DfuLogListener mDfuLogListener = new DfuLogListener() {
    @Override
    public void onLogEvent(String deviceAddress, int level, String message) {
        Log.d("DfuLogListener", String.valueOf(level) + " " + message);
    }
};

private final DfuProgressListener mDfuProgressListener = new DfuProgressListenerAdapter() {
    @Override
    public void onDeviceConnecting(final String deviceAddress) {
        Log.d("DFU", "onDeviceConnecting " + deviceAddress);
    }

    @Override
    public void onDfuProcessStarting(final String deviceAddress) {
        Log.d("DFU", "onDfuProcessStarting " + deviceAddress);
    }

    @Override
    public void onDfuCompleted(final String deviceAddress) {
        Log.d("DFU", "onDfuCompleted " + deviceAddress);
    }

    @Override
    public void onError(final String deviceAddress, final int error, final int errorType, final String message) {
        Log.d("DFU", "onError " + deviceAddress + " " + message);
    }
};

Finally, given that my DeviceManager extends the DfuBaseService class I needed to override the protected Class<? extends Activity> getNotificationTarget() method which in my case I made it returning null. Would this be the issue?

To sum up, given the configuration described above, I cannot see any call to any of the listeners methods.

Hope you guys could drive me toward the right way in overcoming such issue.

Best, Nallo

philips77 commented 7 years ago

Hi,

The getNotificationTarget() method is used when user clicks on the DFU progress notification. You may disable notifications using https://github.com/NordicSemiconductor/Android-DFU-Library/blob/release/dfu/src/main/java/no/nordicsemi/android/dfu/DfuServiceInitiator.java#L83 and then it will not be used. See here: https://github.com/NordicSemiconductor/Android-DFU-Library/blob/release/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java#L1415

Regarding your issue with listeners, check if it's not related to the fact that you start dry from BLE thread, not UI thread (at least on some older Android versions it wasn't called in UI thread). Are you sure you only get it called once? Maybe DFU is started several times if multiple devices found, or so? Also remember that the updates are sent using LocalBroadcastManager, so only the app with DFU service will receive them, and that only one global (for all devices) listener and one per-device listener can be registered using this helper. You'd have to debug where the broadcast go in your code or check nRF Toolbox source code, maybe you'll find a difference.

philips77 commented 7 years ago

Hi, can we close the issue or do you have more questions?

Nallo commented 7 years ago

Hi, yes we can close the issue. It was my fault, I did not add the Service in the Android manifest file therefore, I was not able to listen for the DFU notifications. In order to avoid the same inconvenience in the future I will proposte a pull request that improve the documentation.

Thanks a lot. Stefano

philips77 commented 7 years ago

Great!