Android DFU doesn't find firmware in assets folder

Hello!

I am in the process of adding OTA DFU support to our existing application. However, I'm having problems starting the DFU process.

For security reasons we want to embed the firmware file in the Android application, but when attempting to start the DFU process I get an error about the file not being found:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
E/DfuBaseService: An exception occurred while opening file
java.io.FileNotFoundException: file:/android_assets/firmware.zip: open failed: ENOENT (No such file or directory)
at libcore.io.IoBridge.open(IoBridge.java:575)
at java.io.FileInputStream.<init>(FileInputStream.java:160)
at java.io.FileInputStream.<init>(FileInputStream.java:115)
at no.nordicsemi.android.dfu.DfuBaseService.openInputStream(DfuBaseService.java:1462)
at no.nordicsemi.android.dfu.DfuBaseService.onHandleIntent(DfuBaseService.java:1201)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:78)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
at libcore.io.Linux.open(Native Method)
at libcore.io.ForwardingOs.open(ForwardingOs.java:567)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:273)
at libcore.io.ForwardingOs.open(ForwardingOs.java:567)
at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8611)
at libcore.io.IoBridge.open(IoBridge.java:561)
at java.io.FileInputStream.<init>(FileInputStream.java:160)·
at java.io.FileInputStream.<init>(FileInputStream.java:115)·
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

I am using DFU version 2.1.0, "targetSDK 31" and "compileSDK 32".

The test device is a Samsung Galaxy S10+ with Android 12.

Here is the code that starts the DFU process:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fun install(context: Context, advertisement: Advertisement): DfuServiceController {
val starter = DfuServiceInitiator(advertisement.address).apply {
setDeviceName(advertisement.name)
setKeepBond(false)
setForceDfu(false)
setForceScanningForNewAddressInLegacyDfu(false)
setPrepareDataObjectDelay(400L)
setRebootTime(0L)
setScanTimeout(2_000L)
setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true)
setPacketsReceiptNotificationsEnabled(false)
setPacketsReceiptNotificationsValue(12)
}
starter.setZip("file:///android_assets/firmware.zip")
return starter.start(context, DFUService::class.java)
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

I have also added DFUService from the GitHub page:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package ***.data
import android.app.Activity
import no.nordicsemi.android.dfu.DfuBaseService
object DFUServiceRunningObserver {
var isRunning: Boolean = false
}
internal class DFUService : DfuBaseService() {
private var runningObserver: DFUServiceRunningObserver = DFUServiceRunningObserver
@Deprecated("Deprecated in Java")
override fun onCreate() {
super.onCreate()
runningObserver.isRunning = true
}
@Deprecated("Deprecated in Java")
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

As well as a NotificationActivity:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package ***.data
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import ***.MainActivity
class NotificationActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
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
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtras(getIntent().extras!!) // 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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

I have also added those to the manifest:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
... />
<application
...>
...
<activity
android:name=".data.NotificationActivity"
android:exported="false">
</activity>
<service android:name=".data.DFUService" />
</application>
</manifest>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Can anyone tell me what I'm doing wrong?

Best regards
Magnus Johansen