This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

DFU Service not found

DFU Bootloader version (please complete the following information):
- SDK version: 30
- Bonding used: [no]
- Library version: [e.g. 1.11.0]

Device information (please complete the following information):
- Device: Xiaomi Redmi Note 7
- OS: Android 9

Question
When I am trying to start DFU, nothing happens and I get a message "DFU Service not found". My firmware file has .bin extension (if that makes any difference). I can successfully update firmware using nRF Connect app, but not using my code.

This is the main part of my code:

final DfuServiceInitiator starter = new DfuServiceInitiator(bluetoothDevice.getAddress())
.setDeviceName(bluetoothDevice.getName())
.setKeepBond(true)
.setForceDfu(true)
.setForeground(false)
.setDisableNotification(true)
.setPacketsReceiptNotificationsEnabled(Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
.setPacketsReceiptNotificationsValue(DfuServiceInitiator.DEFAULT_PRN_VALUE)
.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true)
.setPrepareDataObjectDelay(300L);

starter.setBinOrHex(DfuService.TYPE_SOFT_DEVICE, fileUri, filePath);
starter.start(this, DfuService.class);




Full code:
FlashActivity.java:

public class FlashActivity extends AppCompatActivity {
    TextView fileText;
    private Uri fileUri;
    private String filePath;
    BluetoothDevice bluetoothDevice;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        
        final Intent intent = getIntent();
        bluetoothDevice = (BluetoothDevice) intent.getExtras().get("Device");
        
        setContentView(R.layout.activity_flash);
    }
    
    public void selectFile(View v){
        Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
        chooseFile.setType("*/*");
        chooseFile = Intent.createChooser(chooseFile, "Choose a file");
        startActivityForResult(chooseFile, 1);
    }
    
    
    
    
    
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
        case 1:
            if (resultCode == -1) {
                fileUri = data.getData();
                filePath = fileUri.getPath();
                fileText = findViewById(R.id.fileText);
                fileText.setText(filePath);
            }
        
            break;
        }
    }
    
    public void clickFlash(View v){
        final DfuServiceInitiator starter = new DfuServiceInitiator(bluetoothDevice.getAddress())
        .setDeviceName(bluetoothDevice.getName())
        .setKeepBond(true)
        .setForceDfu(true)
        .setForeground(false)
        .setDisableNotification(true)
        .setPacketsReceiptNotificationsEnabled(Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
        .setPacketsReceiptNotificationsValue(DfuServiceInitiator.DEFAULT_PRN_VALUE)
        .setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true)
        .setPrepareDataObjectDelay(300L);
        
        
        starter.setBinOrHex(DfuService.TYPE_SOFT_DEVICE, fileUri, filePath);
        starter.start(this, DfuService.class);
    }
}


DfuService.java:

public class DfuService extends DfuBaseService {

    @Override
    protected Class<? extends Activity> getNotificationTarget() {
        /*
         * As a target activity the NotificationActivity is returned, not the MainActivity. This is because
         * the notification must create a new task:
         *
         * intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         *
         * when you press it. You can use NotificationActivity to check whether the new activity
         * is a root activity (that means no other activity was open earlier) or that some
         * other activity is already open. In the latter case the NotificationActivity will just be
         * closed. The system will restore the previous activity. However, if the application has been
         * closed during upload and you click the notification, a NotificationActivity will
         * be launched as a root activity. It will create and start the main activity and
         * terminate itself.
         *
         * This method may be used to restore the target activity in case the application
         * was closed or is open. It may also be used to recreate an activity history using
         * startActivities(...).
         */
        return NotificationActivity.class;
    }

    @Override
    protected boolean isDebug() {
        // Here return true if you want the service to print more logs in LogCat.
        // Library's BuildConfig in current version of Android Studio is always set to DEBUG=false, so
        // make sure you return true or your.app.BuildConfig.DEBUG here.
        return BuildConfig.DEBUG;
    }

    @Override
    protected void updateForegroundNotification(@NonNull final NotificationCompat.Builder builder) {
        // Customize the foreground service notification here.
    }
}

NotificationActivity:

public class NotificationActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // If this activity is the root activity of the task, the app is not running
        if (isTaskRoot()) {
            // Start the app before finishing
            final Intent intent = new Intent(this, WaitActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.putExtras(getIntent().getExtras()); // copy all extras
            startActivity(intent);
        }

        // Now finish, which will drop you to the activity at which you were at the top of the task stack
        finish();
    }
}

Logs

D/BluetoothGatt: connect() - device: EF:EF:DA:98:65:0B, auto: false
registerApp()
D/BluetoothGatt: registerApp() - UUID=3f8b73f3-2108-4f2e-a639-5bcb2ef109ad
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=14
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=14 device=EF:EF:DA:98:65:0B
D/BluetoothGatt: discoverServices() - device: EF:EF:DA:98:65:0B
D/BluetoothGatt: onSearchComplete() = Device=EF:EF:DA:98:65:0B Status=0
W/DfuBaseService: DFU Service not found.
D/BluetoothGatt: cancelOpen() - device: EF:EF:DA:98:65:0B
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=14 device=EF:EF:DA:98:65:0B
W/mple.safety_ap: Accessing hidden method Landroid/bluetooth/BluetoothGatt;->refresh()Z (light greylist, reflection)
D/BluetoothGatt: refresh() - device: EF:EF:DA:98:65:0B
D/BluetoothGatt: cancelOpen() - device: EF:EF:DA:98:65:0B
D/BluetoothGatt: close()

Final remarks
If possible could you provide me a code snippet ? I am not a pro at Android, the docs are not fully clear to me and the code examples from NordicSemiconductor are hard to follow. Thank you

I also asked the same question here: github.com/.../283

Related