androidsdkmaui

Maui Xamarin service problem with android 12,14


I have a problem with the Maui .net 8.0 application.

I'm trying to create a app that partially works. When I test on Android 12, this line StartForeground(1, notification); starts Foreground correctly.

but on Android 14, I still have the error in StartForeground(1, notification, foregroundServiceType); : Java.Lang.IllegalArgumentException: foregroundServiceType 0x00000001 is not a subset of foregroundServiceType attribute 0x00000000 in service element of manifest file ---> Android.OS.RemoteException: Remote stack trace: at com.android.server.am.ActiveServices.setServiceForegroundInnerLocked(ActiveServices.java:2053)

or in StartForeground(1, notification); : Android.App.MissingForegroundServiceTypeException: 'Starting FGS without a type callerApp=ProcessRecord{f13ab95 8713:com.companyname.mazurek/u0a193} targetSDK=34'

thats full code of service :

using Android.App;
using MyContent = Android.Content ;
using Android.Content;
using Android.OS;


namespace Mazurek.Platforms.Android
{
    [Service]
    public class MainQueryBackgroundService : Service
    {
        private CancellationTokenSource _cancellationTokenSource;
        private static bool _isServiceRunning = false;

        public override IBinder OnBind(Intent intent)
        {
            return null;
        }

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

            _isServiceRunning = true;

            var notification = new Notification.Builder(this, "MyNotificationChannel")
                .SetContentTitle("MainQuery CDM")
                .SetContentText("Serwis MainQuery działa w tle...")
                //.SetSmallIcon(Resource.Drawable.ic_notification)
                .Build();
            try
            {
                var foregroundServiceType = MyContent.PM.ForegroundService.TypeDataSync;
                StartForeground(1, notification, foregroundServiceType);
            }
            catch (Exception ex) 
            {
                StartForeground(1, notification);
            }

            _cancellationTokenSource = new CancellationTokenSource();
            Task.Run(async () =>
            {
                try
                {
                    await DoWorkInBackground(_cancellationTokenSource.Token);
                }
                catch
                {

                }
            });
            

            return StartCommandResult.Sticky;
        }

        private async Task DoWorkInBackground(CancellationToken token)
        {
            while (!token.IsCancellationRequested)
            {
                BackgroundWork.MainQueryTasks tasks = new BackgroundWork.MainQueryTasks();
                await tasks.MainQuery();
                await Task.Delay(60 * 1000);
            }
        }

        public override void OnDestroy()
        {
            _isServiceRunning = false;
            _cancellationTokenSource?.Cancel();
            base.OnDestroy();
        }
    }
}

manifest :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application android:usesCleartextTraffic="true" android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true" android:networkSecurityConfig="@xml/network_security_config">
        <service android:name="Platforms.Android.MainQueryBackgroundService" android:exported="false" android:foregroundServiceType="dataSync" />
        <service android:name="Platforms.Android.TopLayoutBackgroundService" android:exported="false" android:foregroundServiceType="dataSync" />
    </application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
</manifest>

and project:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFrameworks>net8.0-android;net8.0-maccatalyst;net8.0-ios</TargetFrameworks>
        <OutputType>Exe</OutputType>
        <RootNamespace>Mazurek</RootNamespace>
        <UseMaui>true</UseMaui>
        <SingleProject>true</SingleProject>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>

        <!-- Display name -->
        <ApplicationTitle>Mazurek</ApplicationTitle>

        <!-- App Identifier -->
        <ApplicationId>com.companyname.mazurek</ApplicationId>

        <!-- Versions -->
        <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
        <ApplicationVersion>1</ApplicationVersion>

        <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">10.0</SupportedOSPlatformVersion>
        <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>
        <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">31.0</SupportedOSPlatformVersion>
        <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
        <TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
        <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
    </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0-android|AnyCPU'">
      <AndroidPackageFormat>apk</AndroidPackageFormat>
    </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-android|AnyCPU'">
      <EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
    </PropertyGroup>

    <PropertyGroup>
      <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
    </PropertyGroup>

    <ItemGroup>
        <!-- App Icon -->
        <MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />

        <!-- Splash Screen -->
        <MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />

        <!-- Images -->
        <MauiImage Include="Resources\Images\*" />
        <MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
        <MauiImage Update="Resources\Images\wifi.png">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </MauiImage>

        <!-- Custom Fonts -->
        <MauiFont Include="Resources\Fonts\*" />

        <!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
        <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
    </ItemGroup>

    <ItemGroup>
        <PackageReference Include="CommunityToolkit.Maui" Version="9.1.0" />
        <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0-rc.1.24431.7" />
        <PackageReference Include="Microsoft.Maui.Controls" Version="9.0.0-rc.1.24453.9" />
        <PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="9.0.0-rc.1.24453.9" />
        <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.0-rc.1.24431.7" />
        <PackageReference Include="Microsoft.Maui.Essentials" Version="9.0.0-rc.1.24453.9" />
        <PackageReference Include="Microsoft.Maui.Graphics.Skia" Version="9.0.0-rc.1.24453.9" />
        <PackageReference Include="Plugin.LocalNotification" Version="11.1.4" />
        <PackageReference Include="System.ServiceModel.Duplex" Version="6.0.*" />
        <PackageReference Include="System.ServiceModel.Federation" Version="8.0.0" />
        <PackageReference Include="System.ServiceModel.Http" Version="8.0.0" />
        <PackageReference Include="System.ServiceModel.NetNamedPipe" Version="8.0.0" />
        <PackageReference Include="System.ServiceModel.NetTcp" Version="8.0.0" />
        <PackageReference Include="System.ServiceModel.Security" Version="6.0.*" />
    </ItemGroup>

    <ProjectExtensions><VisualStudio><UserProperties XamarinHotReloadDebuggerTimeoutExceptionMazurekHideInfoBar="True" /></VisualStudio></ProjectExtensions>

</Project>

Do you have any solution? I would like the application to work on both Android 12 and 14


Solution

  • You can register the ForegroundServiceType by the [Service] attribute:

    [Service(Exported = false, ForegroundServiceType = global::Android.Content.PM.ForegroundService.TypeDataSync)]
    public class MainQueryBackgroundService : Service
    {
    }
    

    And then remove the

    <service android:name="Platforms.Android.MainQueryBackgroundService" android:exported="false" android:foregroundServiceType="dataSync" />
    

    in the AndroidManifest.

    Finally, you can start the service by the following code:

    if(global::Android.OS.Build.VERSION.SdkInt < global::Android.OS.BuildVersionCodes.Tiramisu)
    {
        StartForeground(1, notification);
    }
    else
    {
        StartForeground(1, notification, global::Android.Content.PM.ForegroundService.TypeDataSync);
    }
    

    Fore more information, you can refer to the official document about Foreground service types are required.