diff --git a/doc/source/services.rst b/doc/source/services.rst index 8b5d9a7851..d202190056 100644 --- a/doc/source/services.rst +++ b/doc/source/services.rst @@ -138,3 +138,111 @@ The call to this method should be done within the service code:: from jnius import autoclass PythonService = autoclass('org.kivy.android.PythonService') PythonService.mService.setAutoRestartService(True) + +Service auto-start +~~~~~~~~~~~~~~~~~~ + +To automatically start the service on boot, you need to add signals inside ``AndroidManifest.xml`` that Android sends to applications on boot. +Create file ``receivers.xml`` and write this code:: + + + + + + + + + + +Next step set path to this file in ``buildozer.spec``, set setting ``android.extra_manifest_application_xml`` code:: + + android.extra_manifest_application_xml = %(source.dir)s/xml/receivers.xml + +Then need create ``MyBroadcastReceiver.java``, code:: + + package com.heattheatr.kivy_service_test; + + import android.content.BroadcastReceiver; + import android.content.Intent; + import android.content.Context; + import org.kivy.android.PythonActivity; + + import java.lang.reflect.Method; + + import com.heattheatr.kivy_service_test.ServiceTest; + + public class MyBroadcastReceiver extends BroadcastReceiver { + + public MyBroadcastReceiver() { + + } + + // Start app. + public void start_app(Context context, Intent intent) { + Intent ix = new Intent(context, PythonActivity.class); + ix.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(ix); + } + + // Start service. + public void service_start(Context context, Intent intent) { + String package_root = context.getFilesDir().getAbsolutePath(); + String app_root = package_root + "/app"; + Intent ix = new Intent(context, ServiceTest.class); + ix.putExtra("androidPrivate", package_root); + ix.putExtra("androidArgument", app_root); + ix.putExtra("serviceEntrypoint", "service.py"); + ix.putExtra("pythonName", "test"); + ix.putExtra("pythonHome", app_root); + ix.putExtra("pythonPath", package_root); + ix.putExtra("serviceStartAsForeground", "true"); + ix.putExtra("serviceTitle", "ServiceTest"); + ix.putExtra("serviceDescription", "ServiceTest"); + ix.putExtra("pythonServiceArgument", app_root + ":" + app_root + "/lib"); + ix.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startService(ix); + } + + // Stop service. + public void service_stop(Context context, Intent intent) { + Intent intent_stop = new Intent(context, ServiceTest.class); + + context.stopService(intent_stop); + } + + // Sinals reciver. + public void onReceive(Context context, Intent intent) { + switch (intent.getAction()) { + case Intent.ACTION_BOOT_COMPLETED: + System.out.println("python MyBroadcastReceiver.java + MyBroadcastReceiver.class onReceive.method: ACTION_BOOT_COMPLETED"); + this.service_start(context, intent); + break; + default: + break; + } + } + } + +This code start ``service.py`` from ``buildozer.spec`` when get signal ``ACTION_BOOT_COMPLETED``:: + + services = Test:./service.py:foreground + +For example ``service.py``:: + + import os + from time import sleep + + from jnius import cast + from jnius import autoclass + + PythonService = autoclass('org.kivy.android.PythonService') + CurrentActivityService = cast("android.app.Service", PythonService.mService) + + while True: + print("python service running.....", CurrentActivityService.getPackageName(), os.getpid()) + sleep(10) + +Name out service will be ``ServiceTest``, prefix ``Service`` + ``Test`` from ``services = Test:./service.py:foreground``. + +You can see how it work in test `project `__. diff --git a/pythonforandroid/bootstraps/common/build/build.py b/pythonforandroid/bootstraps/common/build/build.py index 0b6b9832f0..93ec611799 100644 --- a/pythonforandroid/bootstraps/common/build/build.py +++ b/pythonforandroid/bootstraps/common/build/build.py @@ -944,6 +944,9 @@ def create_argument_parser(): ap.add_argument('--extra-manifest-xml', default='', help=('Extra xml to write directly inside the element of' 'AndroidManifest.xml')) + ap.add_argument('--extra-manifest-application-xml', default='', + help='Extra xml to write directly inside the element of' + 'AndroidManifest.xml') ap.add_argument('--extra-manifest-application-arguments', default='', help='Extra arguments to be added to the tag of' 'AndroidManifest.xml') diff --git a/pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml index 3353c0a0d5..38115442ce 100644 --- a/pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml +++ b/pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml @@ -58,6 +58,9 @@ android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}" android:hardwareAccelerated="true" android:extractNativeLibs="true" > + + {{ args.extra_manifest_application_xml }} + {% for l in args.android_used_libs %} {% endfor %} diff --git a/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml index f667651780..84f14110b4 100644 --- a/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml +++ b/pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml @@ -8,6 +8,9 @@ + + {{ args.extra_manifest_application_xml }} + {% for name in service_names %} + + {{ args.extra_manifest_application_xml }} + {% for l in args.android_used_libs %} {% endfor %} diff --git a/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml b/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml index 1b83cd83e3..db4296ebe1 100644 --- a/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml +++ b/pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml @@ -51,6 +51,9 @@ android:extractNativeLibs="true" {% if debug %}android:debuggable="true"{% endif %} > + + {{ args.extra_manifest_application_xml }} + {% for l in args.android_used_libs %} {% endfor %}