Skip to content

Commit 469c19f

Browse files
committed
Adding support for including XML elements within <manifest><application>
1 parent 4cc1267 commit 469c19f

File tree

6 files changed

+123
-0
lines changed

6 files changed

+123
-0
lines changed

doc/source/services.rst

+108
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,111 @@ The call to this method should be done within the service code::
138138
from jnius import autoclass
139139
PythonService = autoclass('org.kivy.android.PythonService')
140140
PythonService.mService.setAutoRestartService(True)
141+
142+
Service auto-start
143+
~~~~~~~~~~~~~~~~~~
144+
145+
To automatically start the service on boot, you need to add signals inside ``AndroidManifest.xml`` that Android sends to applications on boot.
146+
Create file ``receivers.xml`` and write this code::
147+
148+
<receiver android:name=".MyBroadcastReceiver" android:enabled="true" android:exported="true">
149+
<intent-filter>
150+
<action android:name="android.intent.action.BOOT_COMPLETED" />
151+
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
152+
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
153+
</intent-filter>
154+
</receiver>
155+
156+
157+
Next step set path to this file in ``buildozer.spec``, set setting ``android.extra_manifest_application_xml`` code::
158+
159+
android.extra_manifest_application_xml = %(source.dir)s/xml/receivers.xml
160+
161+
Then need create ``MyBroadcastReceiver.java``, code::
162+
163+
package com.heattheatr.kivy_service_test;
164+
165+
import android.content.BroadcastReceiver;
166+
import android.content.Intent;
167+
import android.content.Context;
168+
import org.kivy.android.PythonActivity;
169+
170+
import java.lang.reflect.Method;
171+
172+
import com.heattheatr.kivy_service_test.ServiceTest;
173+
174+
public class MyBroadcastReceiver extends BroadcastReceiver {
175+
176+
public MyBroadcastReceiver() {
177+
178+
}
179+
180+
// Start app.
181+
public void start_app(Context context, Intent intent) {
182+
Intent ix = new Intent(context, PythonActivity.class);
183+
ix.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
184+
context.startActivity(ix);
185+
}
186+
187+
// Start service.
188+
public void service_start(Context context, Intent intent) {
189+
String package_root = context.getFilesDir().getAbsolutePath();
190+
String app_root = package_root + "/app";
191+
Intent ix = new Intent(context, ServiceTest.class);
192+
ix.putExtra("androidPrivate", package_root);
193+
ix.putExtra("androidArgument", app_root);
194+
ix.putExtra("serviceEntrypoint", "service.py");
195+
ix.putExtra("pythonName", "test");
196+
ix.putExtra("pythonHome", app_root);
197+
ix.putExtra("pythonPath", package_root);
198+
ix.putExtra("serviceStartAsForeground", "true");
199+
ix.putExtra("serviceTitle", "ServiceTest");
200+
ix.putExtra("serviceDescription", "ServiceTest");
201+
ix.putExtra("pythonServiceArgument", app_root + ":" + app_root + "/lib");
202+
ix.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
203+
context.startService(ix);
204+
}
205+
206+
// Stop service.
207+
public void service_stop(Context context, Intent intent) {
208+
Intent intent_stop = new Intent(context, ServiceTest.class);
209+
210+
context.stopService(intent_stop);
211+
}
212+
213+
// Sinals reciver.
214+
public void onReceive(Context context, Intent intent) {
215+
switch (intent.getAction()) {
216+
case Intent.ACTION_BOOT_COMPLETED:
217+
System.out.println("python MyBroadcastReceiver.java
218+
MyBroadcastReceiver.class onReceive.method: ACTION_BOOT_COMPLETED");
219+
this.service_start(context, intent);
220+
break;
221+
default:
222+
break;
223+
}
224+
}
225+
}
226+
227+
This code start ``service.py`` from ``buildozer.spec`` when get signal ``ACTION_BOOT_COMPLETED``::
228+
229+
services = Test:./service.py:foreground
230+
231+
For example ``service.py``::
232+
233+
import os
234+
from time import sleep
235+
236+
from jnius import cast
237+
from jnius import autoclass
238+
239+
PythonService = autoclass('org.kivy.android.PythonService')
240+
CurrentActivityService = cast("android.app.Service", PythonService.mService)
241+
242+
while True:
243+
print("python service running.....", CurrentActivityService.getPackageName(), os.getpid())
244+
sleep(10)
245+
246+
Name out service will be ``ServiceTest``, prefix ``Service`` + ``Test`` from ``services = Test:./service.py:foreground``.
247+
248+
You can see how it work in test `project <https://github.com/dvjdjvu/kivy_service_test>`__.

pythonforandroid/bootstraps/common/build/build.py

+3
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,9 @@ def create_argument_parser():
944944
ap.add_argument('--extra-manifest-xml', default='',
945945
help=('Extra xml to write directly inside the <manifest> element of'
946946
'AndroidManifest.xml'))
947+
ap.add_argument('--extra-manifest-application-xml', default='',
948+
help='Extra xml to write directly inside the <application> element of'
949+
'AndroidManifest.xml')
947950
ap.add_argument('--extra-manifest-application-arguments', default='',
948951
help='Extra arguments to be added to the <manifest><application> tag of'
949952
'AndroidManifest.xml')

pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@
5858
android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}"
5959
android:hardwareAccelerated="true"
6060
android:extractNativeLibs="true" >
61+
62+
{{ args.extra_manifest_application_xml }}
63+
6164
{% for l in args.android_used_libs %}
6265
<uses-library android:name="{{ l }}" />
6366
{% endfor %}

pythonforandroid/bootstraps/service_library/build/templates/AndroidManifest.tmpl.xml

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
<uses-sdk android:minSdkVersion="{{ args.min_sdk_version }}" android:targetSdkVersion="{{ android_api }}" />
99

1010
<application {% if debug %}android:debuggable="true"{% endif %} >
11+
12+
{{ args.extra_manifest_application_xml }}
13+
1114
{% for name in service_names %}
1215
<service android:name="{{ args.package }}.Service{{ name|capitalize }}"
1316
android:process=":service_{{ name }}"

pythonforandroid/bootstraps/service_only/build/templates/AndroidManifest.tmpl.xml

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}"
4949
android:hardwareAccelerated="true"
5050
android:extractNativeLibs="true" >
51+
52+
{{ args.extra_manifest_application_xml }}
53+
5154
{% for l in args.android_used_libs %}
5255
<uses-library android:name="{{ l }}" />
5356
{% endfor %}

pythonforandroid/bootstraps/webview/build/templates/AndroidManifest.tmpl.xml

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
android:extractNativeLibs="true"
5252
{% if debug %}android:debuggable="true"{% endif %}
5353
>
54+
55+
{{ args.extra_manifest_application_xml }}
56+
5457
{% for l in args.android_used_libs %}
5558
<uses-library android:name="{{ l }}" />
5659
{% endfor %}

0 commit comments

Comments
 (0)