Silvering
Silvering

Reputation: 787

Enter in DFU mode issues (firmware update Nordic Android)

I'm trying to start the DFU mode programmatically in order to update the firmware of my ble device which is using nordic hardware. Here is my complete code :

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([email protected], 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)


    }
}

I read many example and of course the official documentation without success. After the DfuServiceInitiator start nothing append I never enter in DfuProgressListenerAdapter functions... My project only have this activity, nothing else.

Any idea ?

Thanks for your help!

Upvotes: 0

Views: 1069

Answers (0)

Related Questions