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

Android Service does not start if process name is specified in Service attribute #9132

Open
jfichtner opened this issue Jul 12, 2024 · 12 comments
Assignees
Labels
Area: App+Library Build Issues when building Library projects or Application projects.

Comments

@jfichtner
Copy link

jfichtner commented Jul 12, 2024

Description

In a .NET 8 MAUI app, when I attempt to create an Android service that starts in a private process using the Service attribute, and specifying a process name with a colong as the first character as such:
[Service(Process = ":test")] public class TestService : Service

The service simply does not start when attempting to start by calling:
context.StartService(new Intent(context, typeof(TestService)));

In addition, if I remove the colon from the process string I get the following error when attempting to deploy the project:
ADB0010: Mono.AndroidTools.InstallFailedException: Unexpected install output: Failure [INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION: Failed parse during installPackageLI: Failed to read manifest from /data/app/vmdl699026415.tmp/base.apk: com.android.server.pm.pkg.component.ParsedServiceImpl cannot be cast to java.lang.String]

Steps to Reproduce

Create a new .NET MAUI application from the template in VS2022 and add the following class to the MauiApplication file:

    [Service(Process = ":test")]
    public class TestService : Service
    {
        public override IBinder? OnBind(Intent? intent)
        {
            return null;
        }


        public static void start(Context context)
        {
            context.StartService(new Intent(context, typeof(TestService)));
        }

        public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags startCommandFlags, int startId)
        {
            return StartCommandResult.Sticky;
        }
    }

Then in the MainApplication constructor add:

TestService.start(this);

I deployed this to a Pixel 5 emulator for my testing.

When attempting to deploy and run this application, note the following:

  • If a breakpoint is placed in the OnStartCommand, it will never be hit.
  • If the colon is removed from the string in the Process parameter of the Service attribute, then attempting to deploy will result in the deployment error mentioned above.
  • Removing the Process parameter altogether and rerunning results in the breakpoint being hit as expected.

Link to public reproduction project repository

No response

Version with bug

8.0.3 GA

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

No response

Did you find any workaround?

No response

Relevant log output

No response

@jfichtner
Copy link
Author

I assume the version specified above is close enough, but here is the exact output from the dotnet workload list command:

Welcome to .NET 8.0!

SDK Version: 8.0.303

@ninachen03
Copy link

ninachen03 commented Jul 17, 2024

This issue has been verified using Visual Studio 17.11.0 Preview 3 (8.0.70 & 8.0.3). Can repro it.
MauiApp24.zip

@jfichtner
Copy link
Author

Any chance for a workaround here? If not I'll have to split my service out to a separate, native Java/Kotlin apk, which I'd really rather not do.

@PureWeen PureWeen transferred this issue from dotnet/maui Jul 23, 2024
@dotnet-policy-service dotnet-policy-service bot added the needs-triage Issues that need to be assigned. label Jul 23, 2024
@jpobst jpobst added Area: App+Library Build Issues when building Library projects or Application projects. and removed needs-triage Issues that need to be assigned. labels Jul 29, 2024
@dellis1972
Copy link
Contributor

I'm not sure we can support this. Running a service in a seperate process would require the runtime to be initialised I think, I'm not sure we have the hooks in place for that? @jonpryor am I mis remembering this? I seem to remember seperate processes for services was a no go at this time?

@jfichtner
Copy link
Author

@dellis1972, @jonpryor thank you for looking into this. Would you have any advice on how to move forward? Is my only option to create and install a separate apk for the service to run in? Thanks...

@jfichtner
Copy link
Author

Sorry to be a nuisance, @dellis1972 and @jonpryor, but getting an answer on this would help me tremendously in moving forward with my project. Thanks...

@jonpryor
Copy link
Member

@jfichtner: it works for me?

Start with MauiApp24.zip, and apply this patch:

diff --git a/Platforms/Android/MainApplication.cs b/Platforms/Android/MainApplication.cs
index 0fee904..de5faf1 100644
--- a/Platforms/Android/MainApplication.cs
+++ b/Platforms/Android/MainApplication.cs
@@ -21,8 +21,14 @@ namespace MauiApp24
     [Service(Process = ":test")]
     public class TestService : Service
     {
+        public TestService ()
+        {
+            Console.WriteLine ("# jonp: TestService is created!");
+        }
+
         public override IBinder? OnBind(Intent? intent)
         {
+            Console.WriteLine ($"# jonp: TestService.OnBind! intent={intent}");
             return null;
         }
 
@@ -33,6 +39,7 @@ namespace MauiApp24
 
         public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags startCommandFlags, int startId)
         {
+            Console.WriteLine ($"# jonp: TestService.OnStartCommand! intent={intent} startCommandFlags={startCommandFlags} startId={startId}");
             return StartCommandResult.Sticky;
         }
     }

Start capturing adb logcat:

adb logcat > log.txt &

Build, install, run:

dotnet build -f net8.0-android
dotnet build -f net8.0-android -t:Install
dotnet build -f net8.0-android -t:StartAndroidActivity

log.txt contains:

 1710  1823 I ActivityManager: Start proc 25425:com.companyname.mauiapp24/u0a416 for next-top-activity {com.companyname.mauiapp24/crc64df52bd7414134cd4.MainActivity}
25448 25448 …
 1710  1823 I ActivityManager: Start proc 25448:com.companyname.mauiapp24:test/u0a416 for service {com.companyname.mauiapp24/crc64df52bd7414134cd4.TestService}
25448 25448 …
25448 25448 I .mauiapp24:test: Late-enabling -Xcheck:jni
25448 25448 …
25448 25448 W debug-app-helper: Using runtime path: /data/app/~~iIy8UMzfnGMql_W42HYxzw==/com.companyname.mauiapp24-ZoXFZutkzgyakcaj6FUy8g==/lib/arm64
25448 25448 …
25448 25448 I DOTNET  : JNI_OnLoad: JNI_OnLoad in pal_jni.c
25448 25448 D DOTNET  : GetOptionalClassGRef: optional class com/android/org/conscrypt/OpenSSLEngineImpl was not found
25448 25448 …
25448 25448 I DOTNET  : # jonp: TestService is created!
25448 25448 I DOTNET  : # jonp: TestService.OnStartCommand! intent=Intent { cmp=com.companyname.mauiapp24/crc64df52bd7414134cd4.TestService } startCommandFlags=0 startId=1
25448 25448 I DOTNET  : # jonp: TestService.OnStartCommand! intent=Intent { cmp=com.companyname.mauiapp24/crc64df52bd7414134cd4.TestService } startCommandFlags=0 startId=2

The first line is the initial launch of MainActivity. Note that it's created on PID 25425.

Later, we see Start proc 25448; this is creating the :test process, and please note that 25448 is a different PID from 25425.

Finally, we see the added Console.WriteLine() messages from the Service, showing that TestService is indeed created, and that TestService.OnStartCommand() is invoked. Also note the PID that these messages are coming from: 25448, the PID of the :test service.

Perhaps it's debugging this app which doesn't work as expected? (I have not tried using the debugger.) It certainly appears to work as expected for me

@jonpryor
Copy link
Member

@jfichtner: I would not expect the debugger to work in this scenario, as if I recall correctly, the debugger only wants to deal with one process, and this setup involves two: the process with the Activity, and the process with the Service. Debugging multi-process scenarios is beyond my knowledge.

@jfichtner
Copy link
Author

@jonpryor Ah, I see! So, my test was flawed in that I was expecting the debugger to hit the breakpoint, but since the service is running in a different process the breakpoint won't be hit. I didn't even consider that, so thank you for taking the time!

This does address my issue, because I only need to run in a separate process. However, there still seems to be an issue with specifying a process that does not start with a colon, as this results in a deployment error.

@ne0rrmatrix
Copy link

ne0rrmatrix commented Oct 22, 2024

@jfichtner I have created a service for the maui community toolkit. I use it in MediaElement. Here is an example scenario:

[Service(Exported = false, Enabled = true, Name = "communityToolkit.maui.media.services", ForegroundServiceType = ForegroundService.TypeMediaPlayback)]
class MediaControlsService : Service
{
 // Rest of code
}

Here is link to repo with service: https://github.com/ne0rrmatrix/MauiOld/blob/Media3/src/CommunityToolkit.Maui.MediaElement/Services/MediaControlsService.android.cs

I tested with

[Service(Process = ":test", Exported = false, Enabled = true, Name = "communityToolkit.maui.media.services", ForegroundServiceType = ForegroundService.TypeMediaPlayback)]
class MediaControlsService : Service
{
// Service stuff here
}

and my service worked fine. Maybe it is because I am using a foreground service?

@jfichtner
Copy link
Author

@ne0rrmatrix as I mentioned above, I realized that the service does work, it just doesn't attach the debugger. It still does NOT work if the process name doesn't start with a colon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: App+Library Build Issues when building Library projects or Application projects.
Projects
None yet
Development

No branches or pull requests

6 participants