Android蓝牙固件升级 DFU-OTA 固件升级
1、添加 依赖包:
implementation 'no.nordicsemi.android:dfu:1.11.0'
2、DfuService类继承 DfuBaseService
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.example.ycblesdkdemo.dfu; import android.app.Activity; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import no.nordicsemi.android.dfu.DfuBaseService; /** * @author Finn_ZENGYUAN * Blog:https://www.cnblogs.com/finn21/ * @date :2021/9/23 11:49 * @description: */ 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(); } } 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、添加工具类 DfuUtils
package com.example.ycblesdkdemo.dfu; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.os.Build; import android.util.Log; import no.nordicsemi.android.dfu.DfuProgressListener; import no.nordicsemi.android.dfu.DfuServiceController; import no.nordicsemi.android.dfu.DfuServiceInitiator; import no.nordicsemi.android.dfu.DfuServiceListenerHelper; import static android.content.Context.ACTIVITY_SERVICE; /** * @author Finn_ZENGYUAN * Blog:https://www.cnblogs.com/finn21/ * @date :2021/9/23 11:45 * @description: */ 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); //监听升级进度 } //开始升级 /** * * @param mContext * @param deviceMac 蓝牙mAC地址 * @param deviceName 蓝牙名称 * @param mDeviceZipFilePath 要升级的固件的地址 */ 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)); Log.e("升级","开始升级"); 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 */ @SuppressLint("NewApi") 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、当前Activity 继承 DfuProgressListener 实现方法如下
//实现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 是进度 在这里可以展示进度条 Log.e("升级",deviceAddress+"升级进度 "+percent+"===="+speed+"===="+avgSpeed+"===="+currentPart+"===="+partsTotal); } @Override public void onFirmwareValidating(String deviceAddress) { } @Override public void onDeviceDisconnecting(String deviceAddress) { } @Override public void onDeviceDisconnected(String deviceAddress) { } @Override public void onDfuCompleted(String deviceAddress) { //升级成功 Log.e("升级",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. //升级错误 Log.e("升级",deviceAddress+"升级失败"); } @Override public void onError(String deviceAddress, int error, int errorType, String message) { //升级错误 Log.e("升级",deviceAddress+"升级错误"+error+"===="+errorType+"===="+message); }
5、开始,退出升级调用:
private void DfuLoad(){//开始升级 //先注册进度以及升级状态回调 DfuUtils.getInstance().setmDfuProgressListener(mContext,this);//升级状态回调 //开始正式升级 DfuUtils.getInstance().startUpdate(mContext,macVal,localName,filepathval); } private void OutDfuLoad(){//退出升级 DfuUtils.getInstance().dispose(mContext,this);//升级状态回调 }
加油!
一个成功的人,会不但的学习,不但的提升自己!一个成功的程序猿也是如此!