Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DfuInstallation.Start() throws Bad notification for startForeground thrown on .Net MAUI (Android) #28

Open
juniorsaraviao opened this issue Dec 8, 2023 · 10 comments

Comments

@juniorsaraviao
Copy link

juniorsaraviao commented Dec 8, 2023

Describe the bug
I'm implementing the functionality to upgrade a firmware using DFU but it throws an exception when executing DfuInstallation.Start().

I've declared the Foreground Service permission on AndroidManifest.xml and a Foreground service link but it's still throwing the error.

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

To Reproduce
Steps to reproduce the behavior:

  1. Create a MAUI project (NET 8)
  2. Install the Laerdal.Dfu 1.27.8 NuGet package
  3. Include the Foreground Service permission on AndroidManifest.xml.
  4. Implement a Foreground service.
  5. Create a method to download or retrieve your firmware update file.
  6. Scan for the desired device to DFU.
  7. Create the DfuInstallation object and call Start().

Expected behavior
Start and complete the DFU process with the BLE device.

Desktop:

  • OS: Mac 14.1.1 (23B81)
  • IDE: VS Mac 17.6.7 (build 417)
  • NuGet package Laerdal.Dfu version 1.27.8
  • NET Maui v8.0.100

Smartphone:

  • Device: Samsung A53
  • OS: Android v13

Additional context
Logs:

[DfuBaseService] DFU service destroyed
[AndroidRuntime] Shutting down VM
[AndroidRuntime] FATAL EXCEPTION: main
[AndroidRuntime] Process: com.company, PID: 11852
[AndroidRuntime] android.app.RemoteServiceException$CannotPostForegroundServiceNotificationException: Bad notification for startForeground
[AndroidRuntime] 	at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:2222)
[AndroidRuntime] 	at android.app.ActivityThread.-$$Nest$mthrowRemoteServiceException(Unknown Source:0)
[AndroidRuntime] 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2508)
[AndroidRuntime] 	at android.os.Handler.dispatchMessage(Handler.java:106)
[AndroidRuntime] 	at android.os.Looper.loopOnce(Looper.java:226)
[AndroidRuntime] 	at android.os.Looper.loop(Looper.java:313)
[AndroidRuntime] 	at android.app.ActivityThread.main(ActivityThread.java:8762)
[AndroidRuntime] 	at java.lang.reflect.Method.invoke(Native Method)
[AndroidRuntime] 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
[AndroidRuntime] 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
@ISSPRO-Eng
Copy link

Yeah I have been running into multiple issues with this repo in .NET Maui currently as well

@mattalanskas
Copy link

@juniorsaraviao Any updates on this issue? I am seeing this issue as well while migrating from Xamarin Forms to MAUI

@juniorsaraviao
Copy link
Author

@mattalanskas not really, I was also thinking that this was related to the PostNotification permission but even declaring and allowing it the app still throws the exception.

<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

I remember while the firmware was upgrading, it appeared a notification to show the progress (Xamarin Android version).

@schneifa
Copy link

schneifa commented Dec 21, 2023

I had the same issue on Android. If you do not need the foreground notification, you can disable it in the DfuConfiguration. This worked for me:

_output = new DfuInstallation(address, file);   
_output.DfuErrorReceived += OnDfuErrorOccured;
_output.DfuStateChanged += OnDfuStateChanged;
_output.DfuProgressChanged += OnDfuProgressChanged;
var config = new DfuConfiguration() { DisableNotification = true };
_output.Start(config);

@juniorsaraviao
Copy link
Author

The workaround to use DfuConfiguration worked for me too.

@ISSPRO-Eng
Copy link

Got the foreground issue done with the above workaround. I am now running into an invalid BT Address. I had been using this address in my Xamarin app but now it seems to be an issue.
[AndroidRuntime] java.lang.IllegalArgumentException: 00000000-0000-0000-0000-cd196234d6e5 is not a valid Bluetooth address

I get this from here.
string deviceID = _connection.LastConnectedDevice.Id.ToString();
vm.ConnectionInfoString = deviceInfo;
DfuInstallationConfigurationPageViewModel.Instance.DeviceID = deviceID;

@schneifa
Copy link

Got the foreground issue done with the above workaround. I am now running into an invalid BT Address. I had been using this address in my Xamarin app but now it seems to be an issue. [AndroidRuntime] java.lang.IllegalArgumentException: 00000000-0000-0000-0000-cd196234d6e5 is not a valid Bluetooth address

I get this from here. string deviceID = _connection.LastConnectedDevice.Id.ToString(); vm.ConnectionInfoString = deviceInfo; DfuInstallationConfigurationPageViewModel.Instance.DeviceID = deviceID;

The package expects the Bluetooth address in the format "XX:XX:XX:XX:XX:XX". I use this method to convert from the Guid:

private string DevIdToBleAddress(Guid id)
{
    var bytes = id.ToByteArray();
    var relevantBytes = new byte[6];
    Array.Copy(bytes, 10, relevantBytes, 0, 6);
    var str = BitConverter.ToString(relevantBytes);
    var result = str.Replace("-", ":");
    return result;
}

It's basically the last part of the Guid (in your case cd196234d6e5) in this format, which would be CD:19:62:34:D6:E5

@WanftMoon
Copy link

Got the foreground issue done with the above workaround. I am now running into an invalid BT Address. I had been using this address in my Xamarin app but now it seems to be an issue. [AndroidRuntime] java.lang.IllegalArgumentException: 00000000-0000-0000-0000-cd196234d6e5 is not a valid Bluetooth address
I get this from here. string deviceID = _connection.LastConnectedDevice.Id.ToString(); vm.ConnectionInfoString = deviceInfo; DfuInstallationConfigurationPageViewModel.Instance.DeviceID = deviceID;

The package expects the Bluetooth address in the format "XX:XX:XX:XX:XX:XX". I use this method to convert from the Guid:

private string DevIdToBleAddress(Guid id)
{
    var bytes = id.ToByteArray();
    var relevantBytes = new byte[6];
    Array.Copy(bytes, 10, relevantBytes, 0, 6);
    var str = BitConverter.ToString(relevantBytes);
    var result = str.Replace("-", ":");
    return result;
}

It's basically the last part of the Guid (in your case cd196234d6e5) in this format, which would be CD:19:62:34:D6:E5

Yeah, confirmed for Android. It needs the Address, while for iOS, it is the GUID

@ISSPRO-Eng
Copy link

Thanks for the help all. Can probably close this issue.

@siki411
Copy link

siki411 commented May 16, 2024

hi everyone i hope you are doing fine and best of your health actually i am stuck in dfu plus i am new to maui as well as andriod development. i have downloaded 1.27.8 NuGet package and then select file as initiate the dfu but it doesnt work for me and dfu service destroyed after few secondi am sharing the log as well
private async Task StartDfuProcess(string filePath)
{
try
{
//string Device_address = "C2:08:51:5F:5F:C0";
string Device_address = "D8:12:F2:92:46:8B";
var fileExists = File.Exists(filePath);
Debug.WriteLine($"File path exists: {fileExists}");

    if (!fileExists)
    {
        Debug.WriteLine("File does not exist, aborting DFU process.");
        return;
    }
    Debug.WriteLine("DFU process is about to start.");
    var _output = new DfuInstallation(Device_address, filePath);

    _output.Start();
    Debug.WriteLine("DFU process started successfully.");
}
catch (Exception ex)
{
    Debug.WriteLine($"Error during DFU process: {ex.Message}");
}

}
and logs are
DOTNET] File selected: /data/data/com.companyname.bluetoothcourse/cache/2203693cc04e0be7f4f024d5f9499e13/53f9c563f2c64434802f68ded273b562/dfu_application.zip
[0:] File path exists: True
[0:] DFU process is about to start.
[0:] DFU process started successfully.
[ViewRootImpl@ef052e8[IntermediateActivity]] stopped(false) old=true
[DfuBaseService] DFU service created. Version: 2.3.0
[ViewRootImpl@ef052e8[IntermediateActivity]] stopped(false) old=false
[DfuBaseService] Starting DFU service in foreground
[SurfaceControl] assignNativeObject: nativeObject = 0 Surface(name=null)/@0x27983d / android.view.SurfaceControl.readFromParcel:1121 android.view.IWindowSession$Stub$Proxy.relayout:1830 android.view.ViewRootImpl.relayoutWindow:9005 android.view.ViewRootImpl.performTraversals:3360 android.view.ViewRootImpl.doTraversal:2618 android.view.ViewRootImpl$TraversalRunnable.run:9971 android.view.Choreographer$CallbackRecord.run:1010 android.view.Choreographer.doCallbacks:809 android.view.Choreographer.doFrame:744 android.view.Choreographer$FrameDisplayEventReceiver.run:995
[SurfaceControl] assignNativeObject: nativeObject = 0 Surface(name=null)/@0xd062d01 / android.view.SurfaceControl.readFromParcel:1121 android.view.IWindowSession$Stub$Proxy.relayout:1840 android.view.ViewRootImpl.relayoutWindow:9005 android.view.ViewRootImpl.performTraversals:3360 android.view.ViewRootImpl.doTraversal:2618 android.view.ViewRootImpl$TraversalRunnable.run:9971 android.view.Choreographer$CallbackRecord.run:1010 android.view.Choreographer.doCallbacks:809 android.view.Choreographer.doFrame:744 android.view.Choreographer$FrameDisplayEventReceiver.run:995
[ViewRootImpl@ef052e8[IntermediateActivity]] Relayout returned: old=(0,0,1080,2340) new=(0,0,1080,2340) req=(1080,2340)4 dur=10 res=0x1 s={false 0} ch=false fn=-1
Thread started: #26
[ViewRootImpl@2cac53e[MainActivity]] stopped(false) old=true
[ViewRootImpl@2cac53e[MainActivity]] stopped(false) old=false
[SurfaceControl] assignNativeObject: nativeObject = 0 Surface(name=null)/@0x88124b5 / android.view.SurfaceControl.readFromParcel:1121 android.view.IWindowSession$Stub$Proxy.relayout:1840 android.view.ViewRootImpl.relayoutWindow:9005 android.view.ViewRootImpl.performTraversals:3360 android.view.ViewRootImpl.doTraversal:2618 android.view.ViewRootImpl$TraversalRunnable.run:9971 android.view.Choreographer$CallbackRecord.run:1010 android.view.Choreographer.doCallbacks:809 android.view.Choreographer.doFrame:744 android.view.Choreographer$FrameDisplayEventReceiver.run:995
[ViewRootImpl@2cac53e[MainActivity]] Relayout returned: old=(0,0,1080,2340) new=(0,0,1080,2340) req=(1080,2340)0 dur=15 res=0x7 s={true 488279658496} ch=true fn=-1
[DfuArchiveInputStream] Manifest failed to be parsed. Did you add
[DfuArchiveInputStream] -keep class no.nordicsemi.android.dfu.** { *; }
[DfuArchiveInputStream] to your proguard rules?
[DfuBaseService] An exception occurred while calculating file size
[DfuBaseService] java.io.IOException: The ZIP file must contain an Application, a Soft Device and/or a Bootloader.
[DfuBaseService] at no.nordicsemi.android.dfu.internal.ArchiveInputStream.(ArchiveInputStream.java:269)
[DfuBaseService] at no.nordicsemi.android.dfu.DfuBaseService.openInputStream(DfuBaseService.java:1457)
[DfuBaseService] at no.nordicsemi.android.dfu.DfuBaseService.onHandleIntent(DfuBaseService.java:1201)
[DfuBaseService] at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:77)
[DfuBaseService] at android.os.Handler.dispatchMessage(Handler.java:106)
[DfuBaseService] at android.os.Looper.loop(Looper.java:246)
[DfuBaseService] at android.os.HandlerThread.run(HandlerThread.java:67)
Thread finished: #26
[DfuBaseService] DFU service destroyed
[SurfaceControl] assignNativeObject: nativeObject = 0 Surface(name=null)/@0x27983d / android.view.SurfaceControl.readFromParcel:1121 android.view.IWindowSession$Stub$Proxy.relayout:1830

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants