android ble dfu设备升级步骤详解

1.dfu升级功能要借助第三方库 所以我们首先要依赖

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

2.然后第二步,我们需要创建两个类,具体如下

public class DfuService extends DfuBaseService {


    @Override
    protected Class<? extends Activity> getNotificationTarget() {
        return NotificationActivity.class;
    }

    @Override
    protected boolean isDebug() {
        return true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

public class NotificationActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        if (isTaskRoot()) {
//            // Start the app before finishing
//            final Intent intent = new Intent(this, UpdateZipActivity.class);
//            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//            intent.putExtras(getIntent().getExtras()); // copy all extras
//            startActivity(intent);
//        }
//
//        finish();
    }
}

3:接下里第三步就是升级逻辑了 这里整理了一个工具类

public class DfuUtils {

    private static DfuUtils dfuUtils;
    private DfuServiceController serviceController;
    private DfuServiceInitiator starter;

    public static DfuUtils getInstance() {
        if (dfuUtils == null) {
            synchronized (DfuUtils.class) {
                if (dfuUtils == null) {
                    dfuUtils = new DfuUtils();

                }
            }
        }
        return dfuUtils;
    }

    public void setmDfuProgressListener(Context mContext, DfuProgressListener dfuProgressListener) {
        DfuServiceListenerHelper.registerProgressListener(mContext, dfuProgressListener); //监听升级进度
    }

    //开始升级
    public void startUpdate(Context mContext, String deviceMac, String deviceName, String mDeviceZipFilePath) {
        if (mDeviceZipFilePath == null) {
            ToastUtils.showShort(mContext, mContext.getResources().getString(R.string.update_no_path));
            return;
        }
        //闪退问题解决 兼容   启动前台通知的问题,因为这个库在升级的时候会在通知栏显示进度,
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            DfuServiceInitiator.createDfuNotificationChannel(mContext);
        }

        starter = new DfuServiceInitiator(deviceMac)
                .setDeviceName(deviceName)//设备名称
                .setKeepBond(false)//保持设备绑定 官方demo为false
                .setForceDfu(false)
                .setPacketsReceiptNotificationsEnabled(false)
                .setPacketsReceiptNotificationsValue(12)
                .setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true);//官方ndemo为true
        // If you want to have experimental buttonless DFU feature supported call additionally:
        starter.setZip(mDeviceZipFilePath);
        serviceController = starter.start(mContext, DfuService.class); //启动升级服务
    }

    //暂停升级
    public void pauseDevice(Context mContext) {
        if (isDfuServiceRunning(mContext) && serviceController != null) {
            serviceController.pause();
        }
    }

    //销毁升级
    public void abortDevice(Context mContext) {
        if (isDfuServiceRunning(mContext) && serviceController != null) {
            serviceController.abort();
        }
    }

    /**
     * 判断dfu状态
     *
     * @return
     */
    private boolean isDfuServiceRunning(Context mContext) {
        final ActivityManager manager = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (DfuService.class.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

    //退出 dfu
    public void dispose(Context mContext,DfuProgressListener dfuProgressListener) {
        DfuServiceListenerHelper.unregisterProgressListener(mContext, dfuProgressListener);
        if (isDfuServiceRunning(mContext)) {
            if (serviceController != null) {
                serviceController.abort();
                mContext.stopService(new Intent(mContext, DfuService.class));
            }
        }
        if (starter != null) {
            starter = null;
        }
        if (serviceController != null) {
            serviceController = null;
        }
    }

}

4:到这里主要升级逻辑就完成了,不过还有注意事项!!!
1)权限的添加

    <!-- 在android6.0以后,蓝牙BLE还需要需要获得位置权限 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

有的版本高 升级前需要动态获取

    //检测蓝牙扫描权限
    @Override
    public void checkSelfPermission() {
        if (ContextCompat.checkSelfPermission(Objects.requireNonNull(this), Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            // 申请定位授权
            ActivityCompat.requestPermissions(Objects.requireNonNull(this),
                    new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
        } else {
        	//处理升级逻辑
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                   	//处理升级逻辑
                    }
                } else{
                    ToastUtils.showShort(this,getResources().getString(R.string.scan_no_location));
                }
                break;
        }
    }

2)还有一点别忘记在manifests文件注册dfu服务

<service  android:name=".dfu.DfuService"
            android:exported="true">
            <intent-filter>
                <action android:name="no.nordicsemi.android.action.DFU_UPLOAD" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>
       

5:最后一步 就是简单使用 在你使用的类里面 implements DfuProgressListener

//先注册进度以及升级状态回调
DfuUtils.getInstance().setmDfuProgressListener(mContext,this);//升级状态回调
//开始正式升级
 DfuUtils.getInstance().startUpdate(mContext,mac,deviceName,mDevicePath);
 //实现DfuProgressListener的回调函数
 @Override
    public void onDeviceConnecting(String deviceAddress) {
    }

    @Override
    public void onDeviceConnected(String deviceAddress) {
    }


    @Override
    public void onDfuProcessStarting(String deviceAddress) {
    }

    @Override
    public void onDfuProcessStarted(String deviceAddress) {
  
    }

    @Override
    public void onEnablingDfuMode(String deviceAddress) {
 
    }

    @Override
    public void onProgressChanged(String deviceAddress, int percent, float speed, float avgSpeed, int currentPart, int partsTotal) {
		//percent 是进度 在这里可以展示进度条
    }

    @Override
    public void onFirmwareValidating(String deviceAddress) {

    }

    @Override
    public void onDeviceDisconnecting(String deviceAddress) {

    }

    @Override
    public void onDeviceDisconnected(String deviceAddress) {

    }

    @Override
    public void onDfuCompleted(String deviceAddress) {
    	//升级成功
    }

    @Override
    public void onDfuAborted(String deviceAddress) {
        //升级流产,失败
        // let's wait a bit until we cancel the notification. When canceled immediately it will be recreated by service again.
    }

    @Override
    public void onError(String deviceAddress, int error, int errorType, String message) {
    	//升级错误
    }

6.end 有问题可以留言 看见了回复。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值