Search code examples
pythonandroidkivyandroid-service

Kivy service not started after reboot in android


I created and Kivy android app and want to create a reminder service to show notification at specific time by follow the link here and here. The service run sucessfully when I start my app, also it can be restarted automatically after clear from the recent app. However there are a few issue which I am unable to solve, wishing if anyone here can help.

  1. My service unable to load after restart my phone. There is error in logcat.
E AndroidRuntime: java.lang.RuntimeException: Unable to start service com.example.test.ServiceMyservice@18ea0a6 with Intent { flg=0x10000000 cmp=com.example.test/.ServiceMyservice (has extras) }: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
  1. Currently I am testing with plyer notification fire every 5 seconds with schedule module, the service stop after 2~3 hours without error. Why is it and will if be killed if I scheduled the service to show notification once a day or every 6 hours?

Here is my code. Service file in /service/myservice.py

import datetime
from plyer import notification
import schedule
import time
def noti():
    notification.notify(title=datetime.datetime.now(), message="test", app_name='test',  timeout=3600, ticker='', toast=False)

class KivyService:
    def __init__(self):
        pass

    def start(self):
        while True:
            schedule.run_pending()
            time.sleep(1)
            runjob = schedule.get_jobs('reminder')
            if not runjob:
                schedule.every(5).seconds.do(noti).tag("reminder")


if __name__ == '__main__':
    service = KivyService()
    service.start()

Following entries added to AndroidManifest.tmpl.xml

 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Also, added below before

<receiver android:name=".MyBroadcastReceiver" android:enabled="true" android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

And MyBroadcastReceiver.java

package com.example.test;

import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Context;
import com.example.test.ServiceMyservice;

public class MyBroadcastReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        String package_root = context.getFilesDir().getAbsolutePath();
        String app_root =  package_root + "/app";
        Intent ix = new Intent(context, ServiceMyservice.class);
        ix.putExtra("androidPrivate", package_root);
        ix.putExtra("androidArgument", app_root);
        ix.putExtra("serviceEntrypoint", "./service/myservice.py");
        ix.putExtra("pythonName", "myservice");
        ix.putExtra("pythonHome", app_root);
        ix.putExtra("pythonPath", package_root);
        ix.putExtra("pythonServiceArgument", app_root+":"+app_root+"/lib");
        ix.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startService(ix);
    }
}

The sample is using ix.putExtra("serviceEntrypoint", "./service/main.py"); whichI am not sure is it should point to my service python file but I am getting same error.

And my buildozer.spec permission parts

android.permissions = INTERNET, ACCESS_NETWORK_STATE, RECEIVE_BOOT_COMPLETED, FOREGROUND_SERVICE

Services

services=myservice:service/myservice.py

Thanks.


Solution

  • Just answering my own question if someone having same issue. Referring to PythonService.java line 77 it require a parameter serviceStartAsForeground but missing in my reference link, may be due to version difference.

    boolean serviceStartAsForeground = (
                extras.getString("serviceStartAsForeground").equals("true")
            );
    

    so I need to add following line in Java with either true or false then service is able to start after reboot.

    ix.putExtra("serviceStartAsForeground", "false");
    

    However, background service will be killed by system after hours to free up resource. Still looking a way to make to it register to android alarm manager for repeating task e.g. call plyer notification and able to re-register again after reboot.