Это мини статья является дополнением к статье Android. Starting Kivy App and Service on bootup, в которой запускал сервисом kivy приложение на API 22 Android 5. Теперь будем запускать на последних версиях Android. C API 26 Android 8 и по текущий API 35 Android 15 который есть у меня, постигли изменения, которые необходимо внести для автостарта сервиса. Проверял работу на API 22…35, телефоны: Highscreen power five, Nokia 8, Xiaomi Redmi Note 14.
C Android 8 претерпело изменение в запуске сервиса:
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); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(ix); } else { context.startService(ix); } }
Теперь он запускается методом startForegroundService.
Начиная с Android 14 действует ограничение на запуск служб из приёмника BOOT_COMPLETED. Поэтому придется править AndroidManifest.xml, в kivy они задаются файлами шаблонами AndroidManifest.tmpl.xml. Нас будет интересовать два таких файла. Изменением оба, т.к. они идентичны и один из них берется как основа другого.
./kivy_service_test/.buildozer/android/platform/python-for-android/pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml
./kivy_service_test/.buildozer/android/platform/build-arm64-v8a/dists/kivy_service_test/templates/AndroidManifest.tmpl.xml
Здесь мы идем по неправильному пути исходной статьи, так как он самый простой.
Во всех секциях service дописываем android:foregroundServiceType, т.к. теперь требуется указать тип сервиса. Не особо углублялся в эти типы, выбрал первый подходящий который решал мою задачу: location. Он разрешает запуск при сигнале BOOT_COMPLETED. Заодно прописываю android:exported, он вроде как запрещает запускать сервис из другого приложения.
{% if service or args.launcher %} <service android:name="{{ args.service_class_name }}" android:process=":pythonservice" android:foregroundServiceType="location" android:exported="false"/> {% endif %} {% for name in service_names %} <service android:name="{{ args.package }}.Service{{ name|capitalize }}" android:process=":service_{{ name }}" android:foregroundServiceType="location" android:exported="false" /> {% endfor %} {% for name in native_services %} <service android:name="{{ name }}" android:foregroundServiceType="location" android:exported="false" /> {% endfor %} {% if args.billing_pubkey %} <service android:name="org.kivy.android.billing.BillingReceiver" android:process=":pythonbilling" android:foregroundServiceType="location" android:exported="false"/>
После открытия тега application дописываем внутри него:
receiver android:name=".MyBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" /> <action android:name="com.htc.intent.action.QUICKBOOT_POWERON" /> <action android:name="service_start" /> <action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.DELETE" /> </intent-filter> </receiver>
service_start мой сигнал для запуска сервиса при старте приложения, если сервис уже запущен то ни чего не произойдет.
В каждом новом проекте, эти действия придется производить руками. И возможно после команды очистки, придется заново прописывать тип сервиса.
Так же переделал запуск сервиса на старте приложения через свой сигнал:
def service_send_start(*args): """ Отправка сообщения MyBroadcastReceiver. В recivers.xml нужно прописать разрешение. """ intent = Intent('service_start') intent.setPackage(Context.getPackageName()) Context.sendBroadcast(intent)
В buildozer.spec добавляем разрешение FOREGROUND_SERVICE_LOCATION
android.permissions = FOREGROUND_SERVICE, RECEIVE_BOOT_COMPLETED, QUICKBOOT_POWERON, ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, FOREGROUND_SERVICE_LOCATION
Список всех разрешений который мне в итоге потребовался.
Подключаем телефон к ПК. Собираем проект и устанавливаем на телефон:
buildozer android debug && adb install -r -d `ls ./bin/kivy_service_*.apk | tail -1`
Запускам:


Отладка
Ждем печати python service running….. com.heattheatr.kivy_service_test
adb logcat | egrep "python |Test "
Результат работы:
08-25 14:54:14.652 21092 21112 I Test : Android kivy bootstrap done. __name__ is __main__ 08-25 14:54:14.652 21092 21112 I python : AND: Ran string 08-25 14:54:14.652 21092 21112 I python : Run user program, change dir and execute entrypoint 08-25 14:54:14.791 21092 21112 I Test : [INFO ] [Logger ] Record log in /data/user/0/com.heattheatr.kivy_service_test/files/app/.kivy/logs/kivy_25-08-25_1.txt 08-25 14:54:14.791 21092 21112 I Test : [INFO ] [Kivy ] v2.3.1 08-25 14:54:14.791 21092 21112 I Test : [INFO ] [Kivy ] Installed at "/data/user/0/com.heattheatr.kivy_service_test/files/app/_python_bundle/site-packages/kivy/__init__.pyc" 08-25 14:54:14.792 21092 21112 I Test : [INFO ] [Python ] v3.11.5 (main, Aug 18 2025, 22:24:06) [Clang 14.0.6 (https://android.googlesource.com/toolchain/llvm-project 4c603efb0 08-25 14:54:14.792 21092 21112 I Test : [INFO ] [Python ] Interpreter at "" 08-25 14:54:14.792 21092 21112 I Test : [INFO ] [Logger ] Purge log fired. Processing... 08-25 14:54:14.792 21092 21112 I Test : [INFO ] [Logger ] Purge finished! 08-25 14:54:15.473 21092 21112 I Test : python service running..... com.heattheatr.kivy_service_test 21092 08-25 14:54:25.474 21092 21112 I Test : python service running..... com.heattheatr.kivy_service_test 21092 08-25 14:54:35.474 21092 21112 I Test : python service running..... com.heattheatr.kivy_service_test 21092 08-25 14:54:45.475 21092 21112 I Test : python service running..... com.heattheatr.kivy_service_test 21092
Перезагружаем телефон, смотрим adb:
08-25 15:17:33.023 12012 12012 I System.out: python Context: android.app.ReceiverRestrictedContext@2829109, Intent: android.intent.action.BOOT_COMPLETED 08-25 15:17:33.023 12012 12012 I System.out: python Build.VERSION.SDK_INT 35 08-25 15:17:33.047 1737 1755 I ActivityManager: Background started FGS: Allowed [callingPackage: com.heattheatr.kivy_service_test; callingUid: 10350; uidState: RCVR; uidBFSL: n/a; intent: Intent { flg=0x10000000 cmp=com.heattheatr.kivy_service_test/.ServiceTest (has extras) }; code:BOOT_COMPLETED; tempAllowListReason:<ad20de6 android.intent.action.BOOT_COMPLETED/u0,reasonCode:BOOT_COMPLETED,duration:20000,callingUid:1000>; targetSdkVersion:31; callerTargetSdkVersion:31; startForegroundCount:0; bindFromPackage:null: isBindService:false] 08-25 15:17:33.333 12281 12281 D ActivityThread: setEmbeddedParam packageName=com.heattheatr.kivy_service_test processName=com.heattheatr.kivy_service_test:service_Test isEmbedded=false isIsolated=false 08-25 15:17:34.028 12281 12435 I python : Initializing Python for Android 08-25 15:17:34.028 12281 12435 I python : Setting additional env vars from p4a_env_vars.txt 08-25 15:17:34.029 12281 12435 I python : Changing directory to the one provided by ANDROID_ARGUMENT 08-25 15:17:34.029 12281 12435 I python : /data/user/0/com.heattheatr.kivy_service_test/files/app 08-25 15:17:34.031 12281 12435 I python : Preparing to initialize python 08-25 15:17:34.032 12281 12435 I python : _python_bundle dir exists 08-25 15:17:34.032 12281 12435 I python : calculated paths to be... 08-25 15:17:34.032 12281 12435 I python : /data/user/0/com.heattheatr.kivy_service_test/files/app/_python_bundle/stdlib.zip:/data/user/0/com.heattheatr.kivy_service_test/files/app/_python_bundle/modules 08-25 15:17:34.032 12281 12435 I python : set wchar paths... 08-25 15:17:34.077 12281 12435 I python : Initialized python 08-25 15:17:34.077 12281 12435 I python : AND: Init threads 08-25 15:17:34.078 12281 12435 I test : testing python print redirection 08-25 15:17:34.079 12281 12435 I python : AND: Ran string 08-25 15:17:34.079 12281 12435 I python : Run user program, change dir and execute entrypoint 08-25 15:17:35.399 12281 12435 I test : python service running..... com.heattheatr.kivy_service_test 12281 08-25 15:17:36.659 12885 12971 I python : Initializing Python for Android 08-25 15:17:36.659 12885 12971 I python : Setting additional env vars from p4a_env_vars.txt 08-25 15:17:36.661 12885 12971 I python : Changing directory to the one provided by ANDROID_ARGUMENT 08-25 15:17:36.661 12885 12971 I python : /data/user/0/com.intercom.intercom/files/app 08-25 15:17:36.662 12885 12971 I python : Preparing to initialize python 08-25 15:17:36.663 12885 12971 I python : _python_bundle dir exists 08-25 15:17:36.663 12885 12971 I python : calculated paths to be... 08-25 15:17:36.663 12885 12971 I python : /data/user/0/com.intercom.intercom/files/app/_python_bundle/stdlib.zip:/data/user/0/com.intercom.intercom/files/app/_python_bundle/modules 08-25 15:17:36.663 12885 12971 I python : set wchar paths... 08-25 15:17:36.826 12885 12971 I python : Initialized python 08-25 15:17:36.826 12885 12971 I python : AND: Init threads 08-25 15:17:36.826 12885 12971 I intercom: testing python print redirection 08-25 15:17:36.827 12885 12971 I python : AND: Ran string 08-25 15:17:36.827 12885 12971 I python : Run user program, change dir and execute entrypoint 08-25 15:17:45.400 12281 12435 I test : python service running..... com.heattheatr.kivy_service_test 12281 08-25 15:17:55.408 12281 12435 I test : python service running..... com.heattheatr.kivy_service_test 12281 08-25 15:18:05.408 12281 12435 I test : python service running..... com.heattheatr.kivy_service_test 12281
Спасибо за внимание.
Ссылки
ссылка на оригинал статьи https://habr.com/ru/articles/940534/
Добавить комментарий