我正在尝试以编程方式启动 DFU 模式,以更新使用北欧硬件的 ble 设备的固件。这是我的完整代码:
package fr.digitalblend.dfu
import android.annotation.SuppressLint
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanSettings
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.telecom.Call
import android.view.View
import androidx.annotation.RequiresApi
import androidx.core.net.toUri
import no.nordicsemi.android.dfu.DfuProgressListenerAdapter
import no.nordicsemi.android.dfu.DfuServiceController
import no.nordicsemi.android.dfu.DfuServiceInitiator
import no.nordicsemi.android.dfu.DfuServiceListenerHelper
import no.nordicsemi.android.dfu.DfuBaseService
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.json.JSONObject
import java.io.*
import java.io.FileOutputStream
import java.io.File
class MainActivity : AppCompatActivity() {
private val mDfuProgressListener = object : DfuProgressListenerAdapter() {
override fun onDeviceConnecting(deviceAddress: String) {
println("CONNECTING")
}
override fun onDfuProcessStarting(deviceAddress: String) {
println("WE START")
}
override fun onProgressChanged (
deviceAddress: String,
percent: Int,
speed: Float,
avgSpeed: Float,
currentPart: Int,
partsTotal: Int
) {
super.onProgressChanged (
deviceAddress,
percent,
speed,
avgSpeed,
currentPart,
partsTotal
)
}
override fun onDfuCompleted(deviceAddress: String) {
println("UPDATE COMPLETE")
super.onDfuCompleted(deviceAddress)
}
override fun onDfuAborted(deviceAddress: String) {
println("!!!! onDfuAborted !!!!!")
}
override fun onError(deviceAddress: String, error: Int, errorType: Int, message: String?) {
println("!!!! onError !!!!! ==> " + message)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DfuServiceListenerHelper.registerProgressListener(this, mDfuProgressListener)
getFlowKeyVersion()
}
private fun getFlowKeyVersion(){
val request = Request
.Builder()
.url("https://xxxxxx/api/firmware/27/")
.addHeader("Authorization", "Token xxxxx")
.addHeader("Content-Type", "application/json")
.build()
val client = OkHttpClient()
client.newCall(request).enqueue(object : Callback {
@SuppressLint("UseCompatLoadingForDrawables")
override fun onFailure(call: okhttp3.Call, e: IOException) {
runOnUiThread {
}
}
@SuppressLint("UseCompatLoadingForDrawables")
override fun onResponse(call: okhttp3.Call, response: Response) {
// Handle this
if (response.code == 200) {
val rep = response.body?.string()
val jsonResponse = JSONObject(rep!!)
val version = jsonResponse.getString("version")
val jsonFile = jsonResponse.getJSONObject("file")
val url = jsonFile.getString("url")
val name = jsonFile.getString("name")
val size = jsonFile.getInt("size")
println(url)
println(name)
println(size)
println(version)
if(version != "1") {
runOnUiThread {
getFlowKeyFile(url, name, size)
}
}
} else {
runOnUiThread {
}
}
}
})
}
private fun getFlowKeyFile(url: String, name: String, size: Int) {
val request = Request
.Builder()
.url(url)
.addHeader("Authorization", "Token xxxxxxxx")
.build()
val client = OkHttpClient()
client.newCall(request).enqueue(object : Callback {
@SuppressLint("UseCompatLoadingForDrawables")
override fun onFailure(call: okhttp3.Call, e: IOException) {
runOnUiThread {
}
}
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("UseCompatLoadingForDrawables")
override fun onResponse(call: okhttp3.Call, response: Response) {
// Handle this
if (response.code == 200) {
var inputStream: InputStream? = null
try {
inputStream = response.body?.byteStream()
val buff = ByteArray(1024 * 4)
var downloaded: Long = 0
val target: Long = response.body?.contentLength()!!
val file = File(this@MainActivity.cacheDir, name)
val output: OutputStream = FileOutputStream(file)
while (true) {
val readed: Int = inputStream?.read(buff)!!
if (readed == -1) {
break
}
output.write(buff, 0, readed)
//write buff
downloaded += readed.toLong()
}
output.flush()
output.close()
if(size.toLong() == target){
if (file.exists()) {
println(file.absoluteFile)
dfuFlowKey(file)
} else {
println( "le fichier zip n'est pas disponible")
}
}
} catch (ignore: IOException) {
} finally {
inputStream?.close()
}
} else {
runOnUiThread {
}
}
}
})
}
@RequiresApi(Build.VERSION_CODES.O)
fun dfuFlowKey(file: File) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
DfuServiceInitiator.createDfuNotificationChannel(this)
}
var starter : DfuServiceInitiator? = null
starter = DfuServiceInitiator("DF:27:D8:15:EE:42")
.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true)
.setKeepBond(false)
.setZip(
file.toUri()
)
starter.start(this, DfuBaseService::class.java)
}
}
我阅读了许多示例,当然还有官方文档,但都没有成功。开始后DfuServiceInitiator
没有附加任何内容,我从不输入DfuProgressListenerAdapter
函数......我的项目只有这个活动,没有别的。
任何想法 ?
谢谢你的帮助!