question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

DFU problems on Huawei devices

See original GitHub issue

Hi,

I’m developing an app using the nordic android DFU library, and I try to update the user device’s bootloader + firmware without user interaction.

The issue I’m facing is that it is partially functional: I get many 133 and 129 Bluetooth errors while testing, but also the “DFU CHARACTERISTICS NOT FOUND” one (4102) on Huawei devices. The other devices I’ve tested don’t have that much errors.

Is there a known problem with Huawei devices Bluetooth or did I do something wrong?

My code for both updates below:

Code to start the Bootloader update:

	private fun startBootloaderDFUProcess() {
		Log.i(TAG, "Starting Bootloader DFU update")

		val starter = DfuServiceInitiator(deviceMacAddress!!)
			.setDeviceName(deviceName!!)
			.setKeepBond(true)

		starter.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true)
		starter.setZip(bootloaderPathName!!)
		starter.start(context!!, DfuService::class.java)

		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
			DfuServiceInitiator.createDfuNotificationChannel(context!!)
		}

	}

Code for the DfuProgressListener for the Bootloader:

	private val dfuBootloaderProgressListener = object : DfuProgressListenerAdapter() {
		override fun onEnablingDfuMode(deviceAddress: String) {
			super.onEnablingDfuMode(deviceAddress)
			dfu_description.text = getString(R.string.dfu_initializing_update)
		}

		override fun onProgressChanged(
			deviceAddress: String,
			percent: Int,
			speed: Float,
			avgSpeed: Float,
			currentPart: Int,
			partsTotal: Int
		) {
			super.onProgressChanged(deviceAddress, percent, speed, avgSpeed, currentPart, partsTotal)
			mPercent = percent / 2
			dfu_loading_bar.progress = mPercent
			tv_update_percent.text = getString(R.string.dfu_percent, mPercent)
		}

		override fun onError(deviceAddress: String, error: Int, errorType: Int, message: String?) {
			super.onError(deviceAddress, error, errorType, message)
			Log.v(TAG, "onError : $error type : $errorType message : $message")
			when (error) {
				BOOTLOADER_FW_VERSION_FAILURE -> {
					viewModel.launchScanForDfuTarg()
				}
				DFU_DISCONNECTED -> {
					startBootloaderDFUProcess()
				}
				else -> {
					PrefEnovap.saveIsBackBlockedToPref(false)
					displayErrorOnSnackbarLong(dfu_base, getString(R.string.dfu_error_disconnection))
					(activity as MainActivity).onBackPressed()
				}
			}
		}

		override fun onDfuAborted(deviceAddress: String) {
			super.onDfuAborted(deviceAddress)
			Log.v(TAG, "dfu aborted")
		}

		override fun onFirmwareValidating(deviceAddress: String) {
			super.onFirmwareValidating(deviceAddress)
			Log.v(TAG, "onFirmwareValidating")
		}

		override fun onDeviceDisconnected(deviceAddress: String) {
			super.onDeviceDisconnected(deviceAddress)
			Log.v(TAG, "onDeviceDisconnected")
		}

		override fun onDeviceConnected(deviceAddress: String) {
			super.onDeviceConnected(deviceAddress)
			Log.v(TAG, "onDeviceConnected")
		}

		override fun onDfuProcessStarting(deviceAddress: String) {
			super.onDfuProcessStarting(deviceAddress)
			Log.v(TAG, "onDfuProcessStartingBootloader")
			if (!enovap_button_dfu.isAnimating) {
				enovap_button_dfu.startAnimation()
			}
			dfu_description.text = getString(R.string.dfu_updating)
			mPercent = 0
			dfu_loading_bar.progress = mPercent
			tv_update_percent.text = getString(R.string.dfu_percent, mPercent)
		}

		override fun onDfuProcessStarted(deviceAddress: String) {
			super.onDfuProcessStarted(deviceAddress)
			Log.v(TAG, "onDfuProcessStarted")
		}

		override fun onDeviceConnecting(deviceAddress: String) {
			super.onDeviceConnecting(deviceAddress)
			Log.v(TAG, "onDeviceConnecting")
		}

		override fun onDfuCompleted(deviceAddress: String) {
			super.onDfuCompleted(deviceAddress)
			Log.v(TAG, "onDfuCompleted")
			startFirmwareDFUProcess()
		}
	}

Code to start the Firmware update:

	private fun startFirmwareDFUProcess() {
		Log.i(TAG, "Starting Firmware DFU update")
		DfuServiceListenerHelper.registerProgressListener(context!!, dfuFirmwareProgressListener)

		val starter = DfuServiceInitiator(deviceMacAddress!!)
			.setDeviceName(deviceName!!)
			.setKeepBond(true)

		starter.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true)
		starter.setZip(firmwarePathName!!)
		starter.start(context!!, DfuService::class.java)

		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
			DfuServiceInitiator.createDfuNotificationChannel(context!!)
		}
	}

Code for the DfuProgressListener for the Firmware:

	private val dfuFirmwareProgressListener = object : DfuProgressListenerAdapter() {
		override fun onProgressChanged(
			deviceAddress: String,
			percent: Int,
			speed: Float,
			avgSpeed: Float,
			currentPart: Int,
			partsTotal: Int
		) {
			super.onProgressChanged(deviceAddress, percent, speed, avgSpeed, currentPart, partsTotal)
			enovap_button_dfu.startAnimation()
			mPercent = FIRMWARE_START_PERCENT + percent / 2
			dfu_loading_bar.progress = mPercent
			tv_update_percent.text = getString(R.string.dfu_percent, mPercent)
		}

		override fun onError(deviceAddress: String, error: Int, errorType: Int, message: String?) {
			super.onError(deviceAddress, error, errorType, message)
			Log.v(TAG, "onError : $error message : $message")
			when (error) {
				BOOTLOADER_FW_VERSION_FAILURE -> {
					viewModel.launchScanForDfuTarg()
				}
				else -> {
					DfuServiceListenerHelper.unregisterProgressListener(context!!, this)
					PrefEnovap.saveIsBackBlockedToPref(false)
					displayErrorOnSnackbarLong(dfu_base, getString(R.string.dfu_error_disconnection))
					(activity as MainActivity).onBackPressed()
				}
			}
		}

		override fun onDfuAborted(deviceAddress: String) {
			super.onDfuAborted(deviceAddress)
			Log.v(TAG, "dfu aborted")
		}

		override fun onFirmwareValidating(deviceAddress: String) {
			super.onFirmwareValidating(deviceAddress)
			Log.v(TAG, "onFirmwareValidating")
		}

		override fun onDeviceDisconnected(deviceAddress: String) {
			super.onDeviceDisconnected(deviceAddress)
			Log.v(TAG, "onDeviceDisconnected")
		}

		override fun onDeviceConnected(deviceAddress: String) {
			super.onDeviceConnected(deviceAddress)
			Log.v(TAG, "onDeviceConnected")
		}

		override fun onDfuProcessStarting(deviceAddress: String) {
			super.onDfuProcessStarting(deviceAddress)
			Log.v(TAG, "onDfuProcessStarting")
			dfu_loading_bar.progress = FIRMWARE_START_PERCENT
			tv_update_percent.text = getString(R.string.dfu_percent, FIRMWARE_START_PERCENT)
		}

		override fun onDfuProcessStarted(deviceAddress: String) {
			super.onDfuProcessStarted(deviceAddress)
			Log.v(TAG, "onDfuProcessStarted")
		}

		override fun onDeviceConnecting(deviceAddress: String) {
			super.onDeviceConnecting(deviceAddress)
			Log.v(TAG, "onDeviceConnecting")
		}

		override fun onDfuCompleted(deviceAddress: String) {
			super.onDfuCompleted(deviceAddress)
			DfuServiceListenerHelper.unregisterProgressListener(context!!, this)
			activity?.runOnUiThread {
				PrefEnovap.saveIsBackBlockedToPref(false)
				dfu_description.gone()
				dfu_icon.fadeOut {}
				dfu_icon.gone()
				dfu_title.fadeOut {}
				dfu_title.gone()
				dfu_subtitle.fadeOut {}
				dfu_subtitle.gone()
				tv_update_percent.fadeOut {}
				tv_update_percent.gone()
				dfu_loading_bar.fadeOut {}
				dfu_loading_bar.gone()
				enovap_button_dfu.fadeOut {}
				enovap_button_dfu.gone()
				enovap_button_dfu.revertAnimation()
				dfu_icon.setImageDrawable(getDrawable(context!!, R.drawable.ic_up_to_date))
				dfu_title.text = getString(R.string.enovap_up_to_date)
				dfu_subtitle.text = getString(R.string.dfu_up_to_date_description)
				Handler().postDelayed({
					dfu_icon.visible()
					dfu_icon.fadeIn {}
					dfu_title.visible()
					dfu_title.fadeIn {}
					dfu_subtitle.visible()
					dfu_subtitle.fadeIn {}
					enovap_button_dfu_finish.visible()
					enovap_button_dfu_finish.fadeIn {}
				}, 400)
			}
		}
	}

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
philips77commented, May 20, 2021

The library will do this automatically. Also, if your using non modified DFU bootloader it will send those notifications automatically.

0reactions
mattgraham1commented, May 19, 2021

@philips77 When setting setPacketsReceiptNotificationsEnabled to true, what changes that fixes the issue users reported above? What I’m wondering when setting that to true do you have to ensure a notification is received before doing more work, If so, is this on the controller application to implement the notification is received?

Also, I’m curious is it be common practice to set a retry policy?

Read more comments on GitHub >

github_iconTop Results From Across the Web

DFU problems on Huawei devices to Upload .hex files #298
So you're using DFU from SDK 6.1 or older. By counting number of services, the library assumes that the device is in DFU...
Read more >
Online update failure on my HUAWEI phone/tablet
Learn about 'Online update failure on my HUAWEI phone/tablet'. Find all usage guide, troubleshooting tips and resources for your HUAWEI product.
Read more >
Top 9 Huawei Phone Problems and How to Fix Them - Dr.Fone
In this article, we have broken down for you the top 6 problems of Huawei phones and provided you solutions on how to...
Read more >
Reboot loop! Factory reset didn't work! - Huawei Ascend P6-U06
1) download the firmware by below link http://consumer.huawei.com/en/mobile-phones/support/downloads/p6-u06-en.htm#anchor 2) Copy it to SD ...
Read more >
How to Enter Recovery Mode on Huawei Phone in One Click
It is quite easy and quick to enter Recovery Mode on Huawei devices, but the problem arises when the keys aren't working or...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found