From 188c666178263b0c9c356cb5ae4e60232f29d987 Mon Sep 17 00:00:00 2001 From: Kenechukwu Akubue Date: Thu, 4 Dec 2025 14:17:04 +0100 Subject: [PATCH 1/4] Add foregroundServiceType support to AndroidManifest templates This commit introduces support for the 'foregroundServiceType' attribute in the AndroidManifest templates across all bootstraps. This change allows specifying the service type for foreground services, which is a mandatory requirement for apps targeting Android 14 (API level 34) and above to prevent runtime crashes. --- .../build/templates/AndroidManifest.tmpl.xml | 5 ++++- .../bootstraps/common/build/build.py | 20 +++++++++++++++---- .../build/templates/AndroidManifest.tmpl.xml | 5 ++++- .../build/templates/AndroidManifest.tmpl.xml | 5 ++++- .../build/templates/AndroidManifest.tmpl.xml | 5 ++++- .../build/templates/AndroidManifest.tmpl.xml | 5 ++++- 6 files changed, 36 insertions(+), 9 deletions(-) diff --git a/pythonforandroid/bootstraps/_sdl_common/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/_sdl_common/build/templates/AndroidManifest.tmpl.xml index c31bb3f747..4aba5fc40c 100644 --- a/pythonforandroid/bootstraps/_sdl_common/build/templates/AndroidManifest.tmpl.xml +++ b/pythonforandroid/bootstraps/_sdl_common/build/templates/AndroidManifest.tmpl.xml @@ -115,8 +115,11 @@ {% endif %} - {% for name in service_names %} + {% for name, foreground_type in service_data %} {% endfor %} {% for name in native_services %} diff --git a/pythonforandroid/bootstraps/common/build/build.py b/pythonforandroid/bootstraps/common/build/build.py index 99c4ea24ab..06d085a972 100644 --- a/pythonforandroid/bootstraps/common/build/build.py +++ b/pythonforandroid/bootstraps/common/build/build.py @@ -466,7 +466,7 @@ def make_package(args): if exists(service_main) or exists(service_main + 'o'): service = True - service_names = [] + service_data = [] base_service_class = args.service_class_name.split('.')[-1] for sid, spec in enumerate(args.services): spec = spec.split(':') @@ -476,8 +476,20 @@ def make_package(args): foreground = 'foreground' in options sticky = 'sticky' in options + foreground_type_option = next((s for s in options if s.startswith('foregroundServiceType')), None) + if foreground_type_option: + try: + foreground_type = foreground_type_option.split('=')[1] + if not foreground_type: + raise ValueError('Missing value for `foregroundServiceType` option. ' + 'Expected format: foregroundServiceType=location') + except IndexError: + raise ValueError('Missing value for `foregroundServiceType` option. ' + 'Expected format: foregroundServiceType=location') + else: + foreground_type = None - service_names.append(name) + service_data.append((name, foreground_type)) service_target_path =\ 'src/main/java/{}/Service{}.java'.format( args.package.replace(".", "/"), @@ -541,10 +553,10 @@ def make_package(args): render_args = { "args": args, "service": service, - "service_names": service_names, + "service_data": service_data, "android_api": android_api, "debug": "debug" in args.build_mode, - "native_services": args.native_services + "native_services": args.native_services, } if is_sdl_bootstrap(): render_args["url_scheme"] = url_scheme diff --git a/pythonforandroid/bootstraps/qt/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/qt/build/templates/AndroidManifest.tmpl.xml index 8ccff2027a..1385bdbd03 100644 --- a/pythonforandroid/bootstraps/qt/build/templates/AndroidManifest.tmpl.xml +++ b/pythonforandroid/bootstraps/qt/build/templates/AndroidManifest.tmpl.xml @@ -91,8 +91,11 @@ {% endif %} - {% for name in service_names %} + {% for name, foreground_type in service_data %} {% endfor %} {% for name in native_services %} diff --git a/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml index 017a1588ec..2add7e7bf2 100644 --- a/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml +++ b/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml @@ -7,8 +7,11 @@ - {% for name in service_names %} + {% for name, foreground_type in service_data %} {% endfor %} diff --git a/pythonforandroid/bootstraps/service_only/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/service_only/build/templates/AndroidManifest.tmpl.xml index f0034d7e73..651a70aea6 100644 --- a/pythonforandroid/bootstraps/service_only/build/templates/AndroidManifest.tmpl.xml +++ b/pythonforandroid/bootstraps/service_only/build/templates/AndroidManifest.tmpl.xml @@ -72,8 +72,11 @@ android:process=":pythonservice" android:exported="true"/> {% endif %} - {% for name in service_names %} + {% for name, foreground_type in service_data %} {% endfor %} diff --git a/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml index 9b436b1fa4..3a99e87470 100644 --- a/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml +++ b/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml @@ -81,8 +81,11 @@ {% endif %} - {% for name in service_names %} + {% for name, foreground_type in service_data %} {% endfor %} From 6f3ae311e214b96ece0e31994b6f9d4f54c5045b Mon Sep 17 00:00:00 2001 From: Kenechukwu Akubue Date: Thu, 4 Dec 2025 14:39:10 +0100 Subject: [PATCH 2/4] Refactor foregroundServiceType option parsing in build.py --- .../bootstraps/common/build/build.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/pythonforandroid/bootstraps/common/build/build.py b/pythonforandroid/bootstraps/common/build/build.py index 06d085a972..e2aacc7ac8 100644 --- a/pythonforandroid/bootstraps/common/build/build.py +++ b/pythonforandroid/bootstraps/common/build/build.py @@ -477,17 +477,15 @@ def make_package(args): foreground = 'foreground' in options sticky = 'sticky' in options foreground_type_option = next((s for s in options if s.startswith('foregroundServiceType')), None) + foreground_type = None if foreground_type_option: - try: - foreground_type = foreground_type_option.split('=')[1] - if not foreground_type: - raise ValueError('Missing value for `foregroundServiceType` option. ' - 'Expected format: foregroundServiceType=location') - except IndexError: - raise ValueError('Missing value for `foregroundServiceType` option. ' - 'Expected format: foregroundServiceType=location') - else: - foreground_type = None + parts = foreground_type_option.split('=', 1) + if len(parts) != 2 or not parts[1]: + raise ValueError( + 'Missing value for `foregroundServiceType` option. ' + 'Expected format: foregroundServiceType=location' + ) + foreground_type = parts[1] service_data.append((name, foreground_type)) service_target_path =\ From 32b689e093e760cf367441047291e90b97b3a8c2 Mon Sep 17 00:00:00 2001 From: Kenechukwu Akubue Date: Thu, 4 Dec 2025 15:02:26 +0100 Subject: [PATCH 3/4] Document foregroundServiceType parameter for Android foreground services --- doc/source/services.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/source/services.rst b/doc/source/services.rst index 99abdba561..6bfcfcd5c3 100644 --- a/doc/source/services.rst +++ b/doc/source/services.rst @@ -64,9 +64,15 @@ The ``PATH_TO_SERVICE_PY`` is the relative path to the service entry point (like You can optionally specify the following parameters: - :code:`:foreground` for launching a service as an Android foreground service - :code:`:sticky` for launching a service that gets restarted by the Android OS on exit/error + - :code:`:foregroundServiceType=TYPE` to specify the type of foreground service, + where TYPE is one of the valid Android foreground service types + (see `Android documentation `__ + for more details). You can specify multiple types separated by a pipe + character "|", e.g. :code:`:foregroundServiceType=location|mediaPlayback`. Mandatory + if :code:`:foreground` is used on Android 14+. Full command with all the optional parameters included would be: -:code:`--service=myservice:services/myservice.py:foreground:sticky` +:code:`--service=myservice:services/myservice.py:foreground:sticky:foregroundServiceType=location` You can add multiple :code:`--service` arguments to include multiple services, or separate From 1b157082217ed1c6e6d4af6676abe0a20951c318 Mon Sep 17 00:00:00 2001 From: Kenechukwu Akubue Date: Thu, 4 Dec 2025 15:05:47 +0100 Subject: [PATCH 4/4] Update foreground service type documentation link in services.rst --- doc/source/services.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/services.rst b/doc/source/services.rst index 6bfcfcd5c3..53a9403885 100644 --- a/doc/source/services.rst +++ b/doc/source/services.rst @@ -66,7 +66,7 @@ You can optionally specify the following parameters: - :code:`:sticky` for launching a service that gets restarted by the Android OS on exit/error - :code:`:foregroundServiceType=TYPE` to specify the type of foreground service, where TYPE is one of the valid Android foreground service types - (see `Android documentation `__ + (see `Android documentation `__ for more details). You can specify multiple types separated by a pipe character "|", e.g. :code:`:foregroundServiceType=location|mediaPlayback`. Mandatory if :code:`:foreground` is used on Android 14+.