Android BLE dfu升級


dfu升級適用於nordic  nRF51  nRF52 的系統,github上提供了相關升級的庫 https://github.com/NordicSemiconductor/Android-DFU-Library 支持 Android 4.3+

gradle配置如下:

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

在使用前請先配置好BLE的相關權限以及動態權限 讀寫權限 定位等可以使用EasyPermission配置

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

第一步 我們創建一個service集成DfuBaseService

public class DfuService extends DfuBaseService {
    public DfuService() {
    }

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

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

第二步 創建一個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, UpdateZipActivity.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();
    }
}

其中UpdateZipActivity即為處理升級業務的界面

在這里要根據你的業務需求來,可以把升級包打包在apk里,也可以做成下載后升級的情況

如果是打包在apk里可以按下面做,如果你是下載的情況只需要改starter.setZip(uri, path); 傳入文件uri和路徑即可  

private DfuServiceInitiator starter; 


starter = new DfuServiceInitiator(mac).setDeviceName("Smart Lock").setKeepBond(false).setPacketsReceiptNotificationsEnabled(true).setPacketsReceiptNotificationsValue(10);
        // If you want to have experimental buttonless DFU feature supported call additionally:
        starter.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true);
        starter.setZip(R.raw.update24); //setDeviceName為設備過濾條件 setzip傳入raw文件的路徑即可



@Override
protected void onResume() {

DfuServiceListenerHelper.registerProgressListener(this, mDfuProgressListener); //監聽升級進度
starter.start(this, DfuService.class); //啟動升級服務

}

/**
* dfu升級監聽
*/
private final DfuProgressListener mDfuProgressListener = new DfuProgressListener() {
@Override
public void onDeviceConnecting(String deviceAddress) {
Log.i("dfu", "onDeviceConnecting");
proBar.setIndeterminate(true);
airUpgradeTv.setText(R.string.dfu_status_connecting);
}

@Override
public void onDeviceConnected(String deviceAddress) {

}


@Override
public void onDfuProcessStarting(String deviceAddress) {
proBar.setIndeterminate(true);
airUpgradeTv.setText(R.string.dfu_status_starting);
}

@Override
public void onDfuProcessStarted(String deviceAddress) {
Log.i("dfu", "onDfuProcessStarted");
}

@Override
public void onEnablingDfuMode(String deviceAddress) {
Log.i("dfu", "onEnablingDfuMode");
proBar.setIndeterminate(true);
airUpgradeTv.setText(R.string.dfu_status_switching_to_dfu);
}

@Override
public void onProgressChanged(String deviceAddress, int percent, float speed, float avgSpeed, int currentPart, int partsTotal) {
Log.i("dfu", "onProgressChanged");
Log.i("dfu", "onProgressChanged" + percent);
proBar.setProgress(percent);
proBar.setIndeterminate(false);
airUpgradeTv.setText(percent + "%");
}

@Override
public void onFirmwareValidating(String deviceAddress) {
Log.i("dfu", "onFirmwareValidating");
proBar.setIndeterminate(true);
airUpgradeTv.setText(R.string.dfu_status_validating);
}

@Override
public void onDeviceDisconnecting(String deviceAddress) {
Log.i("dfu", "onDeviceDisconnecting");
}

@Override
public void onDeviceDisconnected(String deviceAddress) {
Log.i("dfu", "onDeviceDisconnected");
proBar.setIndeterminate(true);
airUpgradeTv.setText(R.string.dfu_status_disconnecting);

}

@Override
public void onDfuCompleted(String deviceAddress) {

airUpgradeTv.setText(R.string.dfu_status_completed);
proBar.setProgress(100);
proBar.setIndeterminate(false);
//升級成功
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);


}

@Override
public void onDfuAborted(String deviceAddress) {
Log.i("dfu", "onDfuAborted");
//升級流產,失敗
airUpgradeTv.setText(R.string.dfu_status_aborted);
// 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() {
Toast.makeText(UpdateZipActivity.this, "升級出錯", Toast.LENGTH_SHORT).show();
// 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 onError(String deviceAddress, int error, int errorType, String message) {
Log.i("dfu", "onError");

airUpgradeTv.setText(getString(R.string.dfu_status_aborted));
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);

}

@Override
protected void onPause() {
  //取消監聽
DfuServiceListenerHelper.unregisterProgressListener(this, mDfuProgressListener);
super.onPause();
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM