Skip to content

Commit c6d39ad

Browse files
committed
Adding support for including XML elements within <manifest><application>
1 parent 7de5d2b commit c6d39ad

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
@@ -130,3 +130,111 @@ The call to this method should be done within the service code::
130130
from jnius import autoclass
131131
PythonService = autoclass('org.kivy.android.PythonService')
132132
PythonService.mService.setAutoRestartService(True)
133+
134+
Service auto-start
135+
~~~~~~~~~~~~~~~~~~
136+
137+
To automatically start the service on boot, you need to add signals inside ``AndroidManifest.xml`` that Android sends to applications on boot.
138+
Create file ``receivers.xml`` and write this code::
139+
140+
<receiver android:name=".MyBroadcastReceiver" android:enabled="true" android:exported="true">
141+
<intent-filter>
142+
<action android:name="android.intent.action.BOOT_COMPLETED" />
143+
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
144+
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
145+
</intent-filter>
146+
</receiver>
147+
148+
149+
Next step set path to this file in ``buildozer.spec``, set setting ``android.extra_manifest_application_xml`` code::
150+
151+
android.extra_manifest_application_xml = %(source.dir)s/xml/receivers.xml
152+
153+
Then need create ``MyBroadcastReceiver.java``, code::
154+
155+
package com.heattheatr.kivy_service_test;
156+
157+
import android.content.BroadcastReceiver;
158+
import android.content.Intent;
159+
import android.content.Context;
160+
import org.kivy.android.PythonActivity;
161+
162+
import java.lang.reflect.Method;
163+
164+
import com.heattheatr.kivy_service_test.ServiceTest;
165+
166+
public class MyBroadcastReceiver extends BroadcastReceiver {
167+
168+
public MyBroadcastReceiver() {
169+
170+
}
171+
172+
// Start app.
173+
public void start_app(Context context, Intent intent) {
174+
Intent ix = new Intent(context, PythonActivity.class);
175+
ix.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
176+
context.startActivity(ix);
177+
}
178+
179+
// Start service.
180+
public void service_start(Context context, Intent intent) {
181+
String package_root = context.getFilesDir().getAbsolutePath();
182+
String app_root = package_root + "/app";
183+
Intent ix = new Intent(context, ServiceTest.class);
184+
ix.putExtra("androidPrivate", package_root);
185+
ix.putExtra("androidArgument", app_root);
186+
ix.putExtra("serviceEntrypoint", "service.py");
187+
ix.putExtra("pythonName", "test");
188+
ix.putExtra("pythonHome", app_root);
189+
ix.putExtra("pythonPath", package_root);
190+
ix.putExtra("serviceStartAsForeground", "true");
191+
ix.putExtra("serviceTitle", "ServiceTest");
192+
ix.putExtra("serviceDescription", "ServiceTest");
193+
ix.putExtra("pythonServiceArgument", app_root + ":" + app_root + "/lib");
194+
ix.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
195+
context.startService(ix);
196+
}
197+
198+
// Stop service.
199+
public void service_stop(Context context, Intent intent) {
200+
Intent intent_stop = new Intent(context, ServiceTest.class);
201+
202+
context.stopService(intent_stop);
203+
}
204+
205+
// Sinals reciver.
206+
public void onReceive(Context context, Intent intent) {
207+
switch (intent.getAction()) {
208+
case Intent.ACTION_BOOT_COMPLETED:
209+
System.out.println("python MyBroadcastReceiver.java
210+
MyBroadcastReceiver.class onReceive.method: ACTION_BOOT_COMPLETED");
211+
this.service_start(context, intent);
212+
break;
213+
default:
214+
break;
215+
}
216+
}
217+
}
218+
219+
This code start ``service.py`` from ``buildozer.spec`` when get signal ``ACTION_BOOT_COMPLETED``::
220+
221+
services = Test:./service.py:foreground
222+
223+
For example ``service.py``::
224+
225+
import os
226+
from time import sleep
227+
228+
from jnius import cast
229+
from jnius import autoclass
230+
231+
PythonService = autoclass('org.kivy.android.PythonService')
232+
CurrentActivityService = cast("android.app.Service", PythonService.mService)
233+
234+
while True:
235+
print("python service running.....", CurrentActivityService.getPackageName(), os.getpid())
236+
sleep(10)
237+
238+
Name out service will be ``ServiceTest``, prefix ``Service`` + ``Test`` from ``services = Test:./service.py:foreground``.
239+
240+
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
@@ -851,6 +851,9 @@ def parse_args_and_make_package(args=None):
851851
ap.add_argument('--extra-manifest-xml', default='',
852852
help=('Extra xml to write directly inside the <manifest> element of'
853853
'AndroidManifest.xml'))
854+
ap.add_argument('--extra-manifest-application-xml', default='',
855+
help='Extra xml to write directly inside the <application> element of'
856+
'AndroidManifest.xml')
854857
ap.add_argument('--extra-manifest-application-arguments', default='',
855858
help='Extra arguments to be added to the <manifest><application> tag of'
856859
'AndroidManifest.xml')

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

+3
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@
6363
android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}"
6464
android:hardwareAccelerated="true"
6565
android:extractNativeLibs="true" >
66+
67+
{{ args.extra_manifest_application_xml }}
68+
6669
{% for l in args.android_used_libs %}
6770
<uses-library android:name="{{ l }}" />
6871
{% 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
@@ -52,6 +52,9 @@
5252
android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}"
5353
android:hardwareAccelerated="true"
5454
android:extractNativeLibs="true" >
55+
56+
{{ args.extra_manifest_application_xml }}
57+
5558
{% for l in args.android_used_libs %}
5659
<uses-library android:name="{{ l }}" />
5760
{% endfor %}

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

+3
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555
android:extractNativeLibs="true"
5656
{% if debug %}android:debuggable="true"{% endif %}
5757
>
58+
59+
{{ args.extra_manifest_application_xml }}
60+
5861
{% for l in args.android_used_libs %}
5962
<uses-library android:name="{{ l }}" />
6063
{% endfor %}

0 commit comments

Comments
 (0)