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

how to use Android DFU Library?

Hi I am now aiming to progress ota with android application.

Following the guidelines on ithub, I created a class DfuService, NotificationActivity. The class internal code has not been modified.

It works when the button is pressed as shown below. But I couldn't see any logs and it doesn't work.

Is there any other way? Do you need to modify nordic module(nRF) code to ota with dfu library?

otaStartButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

final File root = new File(Environment.getExternalStorageDirectory(), "Nordic Semiconductor");

final DfuServiceInitiator starter = new DfuServiceInitiator(SwitchDeviceMac)

.setDeviceName(SwitchDeviceName)
.setKeepBond(false);

starter.createDfuNotificationChannel(OTA.this);
starter.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(false);
starter.setPrepareDataObjectDelay(300L);
starter.setZip(null, root.getPath());
final DfuServiceController controller = starter.start(OTA.this, DfuService.class);
}

});
 
Parents
  • Hello,

    I am not sure if you are aware, but we have an application that is called "nRF Toolbox". It is described here, and that also contains a link to the Github with the source code. 

    nRF Toolbox has a module dedicated for DFU, so perhaps you can check the implementation on Github and use this as a starting point, and to see how it is used. 

    BR,
    Edvin

  • I checked the nRF Toolbox, but there are too many functions different from how to use the library. I only want to'OTA' one Zip file. Is there any easy way? I think I followed the DFU Library exactly, but it's too hard to work.

    It has a structure that calls OTA activity from Main and returns to Main when completed. Can you tell me where the problem in my code is? I'm challenging OTA for the second week... and I'm staying in the same place every day. Please ask for confirmation once, and thank you for the reply.

    otaStartButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    final DfuServiceInitiator starter = new DfuServiceInitiator(SwitchDeviceMac)
                            .setDeviceName(SwitchDeviceName)
                            .setKeepBond(false)
                            .setForceDfu(false)
                            .setPacketsReceiptNotificationsEnabled(Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
                            .setPacketsReceiptNotificationsValue(DfuServiceInitiator.DEFAULT_PRN_VALUE)
                            .setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true)
                            .setPrepareDataObjectDelay(300L);
    
                    final File root = new File(Environment.getExternalStorageDirectory(), "Nordic");
                    final File file = new File(root, "FILE");
    
                    starter.setZip(file.getPath());
                    final DfuServiceController controller = starter.start(OTA.this, DfuService.class);
                }
            });
            
            
            ....
            
            
            import android.app.Activity;
    
    import androidx.annotation.NonNull;
    import androidx.core.app.NotificationCompat;
    
    import no.nordicsemi.android.dfu.BuildConfig;
    import no.nordicsemi.android.dfu.DfuBaseService;
    
    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.
        }
    }
    
    
    ....
    
    package com.example.divide_scan_adver.Nordic;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    
    import com.example.divide_scan_adver.MainActivity;
    
    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, MainActivity.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();
        }
    }

Reply
  • I checked the nRF Toolbox, but there are too many functions different from how to use the library. I only want to'OTA' one Zip file. Is there any easy way? I think I followed the DFU Library exactly, but it's too hard to work.

    It has a structure that calls OTA activity from Main and returns to Main when completed. Can you tell me where the problem in my code is? I'm challenging OTA for the second week... and I'm staying in the same place every day. Please ask for confirmation once, and thank you for the reply.

    otaStartButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    final DfuServiceInitiator starter = new DfuServiceInitiator(SwitchDeviceMac)
                            .setDeviceName(SwitchDeviceName)
                            .setKeepBond(false)
                            .setForceDfu(false)
                            .setPacketsReceiptNotificationsEnabled(Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
                            .setPacketsReceiptNotificationsValue(DfuServiceInitiator.DEFAULT_PRN_VALUE)
                            .setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true)
                            .setPrepareDataObjectDelay(300L);
    
                    final File root = new File(Environment.getExternalStorageDirectory(), "Nordic");
                    final File file = new File(root, "FILE");
    
                    starter.setZip(file.getPath());
                    final DfuServiceController controller = starter.start(OTA.this, DfuService.class);
                }
            });
            
            
            ....
            
            
            import android.app.Activity;
    
    import androidx.annotation.NonNull;
    import androidx.core.app.NotificationCompat;
    
    import no.nordicsemi.android.dfu.BuildConfig;
    import no.nordicsemi.android.dfu.DfuBaseService;
    
    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.
        }
    }
    
    
    ....
    
    package com.example.divide_scan_adver.Nordic;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    
    import com.example.divide_scan_adver.MainActivity;
    
    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, MainActivity.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();
        }
    }

Children
No Data
Related