前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android——NORDIC nRF5x系列 DFU升级 APP实现

Android——NORDIC nRF5x系列 DFU升级 APP实现

作者头像
Winter_world
发布2020-09-25 10:07:38
1.2K0
发布2020-09-25 10:07:38
举报

根据NORDIC官方Android-DFU-Library实现,具体步骤如下:

1、build.gradle配置

implementation 'no.nordicsemi.android:dfu:1.9.0'

2、AndroidMainfest.xml中申请BLE的相关权限、读写权限、定位等。

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 

3、创建DfuService,实现 getNotificationTarget() 方法, 在进行DFU时,该方法会返回一个活动类 ,该活动通过Intent ,FLAG_ACTIVITY_NEW_TASK标志开启,下面步骤是定义的具体活动类。

public class DfuService extends DfuBaseService {


    public DfuService() {
    }

    @Nullable
    @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
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

4、创建NotificationActivity类,继承自Activity,该类主要用于组织APP的其他实例启动。

public class NotificationActivity extends Activity {
    @Override
    protected void onCreate(@Nullable 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, MineDfuActivity.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();


    }
}

5、开启DFU服务

final DfuServiceInitiator starter = new DfuServiceInitiator(MineDeviceActivity.bleDevice.getMac())
                                    .setDeviceName(MineDeviceActivity.bleDevice.getName());
                            // If you want to have experimental buttonless DFU feature supported call additionally:starter.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true);
                            String fileName = urlDfuPackage.substring(urlDfuPackage.lastIndexOf("/"));
                            String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();

                            starter.setZip(directory + fileName);
                            final DfuServiceController controller = starter.start(MyApplication.getContext(), DfuService.class);

//以下是NORDIC DEMO分文件包的格式进行不同处理,我的直接是在固定存储路径下压缩包文件,所以就按照以上写了,以下供参考
// Init packet is required by Bootloader/DFU from SDK 7.0+ if HEX or BIN file is given above.
// In case of a ZIP file, the init packet (a DAT file) must be included inside the ZIP file.
if (mFileType == DfuService.TYPE_AUTO)
    starter.setZip(mFileStreamUri, mFilePath);
else {
    starter.setBinOrHex(mFileType, mFileStreamUri, mFilePath).setInitFile(mInitFileStreamUri, mInitFilePath);
}
final DfuServiceController controller = starter.start(this, DfuService.class);
// You may use the controller to pause, resume or abort the DFU process.

6、以上步骤完成了DFU过程,但是我们拿单板和APP测试也看不到DFU的过程,所以还需要创建DFU进度监听器,可以掌握DFU的动态情况,比如可以在界面显示DFU进度等。

//DFU进度监听器
    private final DfuProgressListener mDfuProgressListener = new DfuProgressListenerAdapter(){

        @Override
        public void onDeviceConnecting(final String deviceAddress) {
            relativeDfuProgress.setVisibility(View.VISIBLE);

        }

        @Override
        public void onDfuProcessStarting(final String deviceAddress) {
            relativeDfuProgress.setVisibility(View.VISIBLE);
        }

        @Override
        public void onEnablingDfuMode(final String deviceAddress) {
            relativeDfuProgress.setVisibility(View.VISIBLE);

        }

        @Override
        public void onFirmwareValidating(final String deviceAddress) {
            relativeDfuProgress.setVisibility(View.VISIBLE);

        }

        @Override
        public void onDeviceDisconnecting(final String deviceAddress) {
            relativeDfuProgress.setVisibility(View.VISIBLE);

        }

        @Override
        public void onDfuCompleted(final String deviceAddress) {
            Toast.makeText(MineDfuActivity.this,"固件升级成功",Toast.LENGTH_SHORT).show();
            // let's wait a bit until we cancel the notification. When canceled immediately it will be recreated by service again.
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
//                    onTransferCompleted();

                    // if this activity is still open and upload process was completed, cancel the notification
                    final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                    manager.cancel(DfuService.NOTIFICATION_ID);
                }
            }, 200);
        }

        @Override
        public void onDfuAborted(final String deviceAddress) {
            // let's wait a bit until we cancel the notification. When canceled immediately it will be recreated by service again.
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
//                    onUploadCanceled();

                    // if this activity is still open and upload process was completed, cancel the notification
                    final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                    manager.cancel(DfuService.NOTIFICATION_ID);
                }
            }, 200);
        }

        @Override
        public void onProgressChanged(final String deviceAddress, final int percent, final float speed, final float avgSpeed, final int currentPart, final int partsTotal) {

            int temp = (percent * 360)/100;
            circleDfuProgress.update(temp,"");

//            if (partsTotal > 1)
//                mTextUploading.setText(getString(R.string.dfu_status_uploading_part, currentPart, partsTotal));
//            else
//                mTextUploading.setText(R.string.dfu_status_uploading);
        }

        @Override
        public void onError(final String deviceAddress, final int error, final int errorType, final String message) {
//            showErrorMessage(message);

            // We have to wait a bit before canceling notification. This is called before DfuService creates the last notification.
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    // if this activity is still open and upload process was completed, cancel the notification
                    final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                    manager.cancel(DfuService.NOTIFICATION_ID);
                }
            }, 200);
        }
    };

7、在当前活动中重写onResume及onPause方法,分别进行监听器的注册和取消注册。

    @Override
    protected void onResume() {
        super.onResume();
        DfuServiceListenerHelper.registerProgressListener(this, mDfuProgressListener);

    }

    @Override
    protected void onPause() {
        super.onPause();
        DfuServiceListenerHelper.unregisterProgressListener(this, mDfuProgressListener);

    }

【参考】

https://github.com/NordicSemiconductor/Android-DFU-Library/tree/release/documentation

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档