11

I'm trying to start my kivy app's service on bootup.

I'm sure that my service is ok because it works when I start my app. But on bootup I have a problem.

I've read this article and tried to make it:

package net.saband.myapp;

import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Context;
import org.kivy.android.PythonActivity;

public class MyBroadcastReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        Intent ix = new Intent(context, PythonActivity.class);
        ix.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(ix);
    }
}

It works but starts the app but not the service. So I've studied some questions on StackOverflow and changed my code for this:

package net.saband.myapp;

import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Context;
import net.saband.myapp.ServiceMyservice;

public class MyBroadcastReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        Intent ix = new Intent(context, ServiceMyservice.class);
        ix.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startService(ix);
    }
}

... and got an error:

10-21 19:16:44.784  1513  1569 I ActivityManager: Start proc 6334:net.saband.myapp:service_myservice/u0a116 for service net.saband.myapp/.ServiceMyservice
10-21 19:16:44.786  6334  6334 I art     : Late-enabling -Xcheck:jni
10-21 19:16:44.885  6334  6334 D AndroidRuntime: Shutting down VM
10-21 19:16:44.888  6334  6334 E AndroidRuntime: FATAL EXCEPTION: main
10-21 19:16:44.888  6334  6334 E AndroidRuntime: Process: net.saband.myapp:service_myservice, PID: 6334
10-21 19:16:44.888  6334  6334 E AndroidRuntime: Theme: themes:{}
10-21 19:16:44.888  6334  6334 E AndroidRuntime: java.lang.RuntimeException: Unable to start service net.saband.myapp.ServiceMyservice@8c96929 with Intent { cmp=net.saband.myapp/.ServiceMyservice }: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference

Can you please explain me what's wrong and what should I do to start the service? Thanks!

UPDATED

By request of @Juggernaut I add my service code:

from time import sleep

if __name__ == '__main__':
    while True:
        print "myapp service"
        sleep(5)

It works when I run app because app calls the service:

def __start_service(self):
    if platform == 'android':
        service = autoclass('net.saband.myapp.ServiceMyservice')
        mActivity = autoclass('org.kivy.android.PythonActivity').mActivity
        argument = ''
        service.start(mActivity, argument)

UPDATED (AndroidManifest)

Here is some strings from my AndroidManifest.xml.

  1. I have the RECEIVE_BOOT_COMPLETED permission:

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

  2. I have the receiver:

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

  3. I have the service registered:

    <service android:name="net.saband.myapp.ServiceMyservice" android:process=":service_myservice" />

By advice of @mariachi I've tried to change android:enabled="true" to android:enabled="false" in the receiver and add android:exported="false" to the service. In this case when the device starts happens nothing: no errors, no service.

Andrzej S.
  • 472
  • 3
  • 19
  • https://stackoverflow.com/a/32033021/6764079 – Amin Etesamian Oct 23 '17 at 05:29
  • 3
    an Activity must be passed to an `Intent` but you are passing a `Service` to it. This is the reason it fails but I got no solution! – Amin Etesamian Oct 23 '17 at 22:01
  • Looks like you're trying to access extras from the intent's bundle and it's crashing. It would be helpful to have more code around your actual service implementation. Also, you're not adding any extras to your intent before your startService call, which is likely why if you're trying to access them it's crashing. – Submersed Oct 31 '17 at 15:24
  • @Submersed thank you for the comment. I've added my AndroidManifest. That's all - I have no more code around the service. What extras should I add in my case? – Andrzej S. Nov 01 '17 at 17:05

3 Answers3

2

OMG! I've found the solution by solving my another issue with kivy service. It's enough just add some extras. Here is work code:

package net.saband.myapp;

import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Context;
import net.saband.myapp.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/main.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);
    }
}
Andrzej S.
  • 472
  • 3
  • 19
1

It seems that Service or Activity that you try to start is not initialized. You didn't paste your AndroidManifest, so I'll write what it's supposed to have.

The first thing is that you should have permission added to run on boot:

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

The second thing is that you should define your receiver in Manifest:

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

The third thing is that you should define your service or activity you try to start, e.g:

    <activity android:name=".PythonActivity" />
    <service android:name=".ServiceMyservice" android:exported="false"/>
mariachi
  • 135
  • 10
  • Thank you for the answer but it didn't help. I've updated my question with my AndroidManifest that I had before and I've tried to change `android:enabled="true"` to `android:enabled="false"` in the receiver and add `android:exported="false"` to the service. But in this case when the device starts happens nothing: no errors, no service. – Andrzej S. Nov 01 '17 at 16:57
  • No errors on bootup is a good sign for your app. Can you put a logger around your activity/sevice start point to check if you receive anything from BroadcastReceiver? – mariachi Nov 02 '17 at 11:01
  • Of course. Looks like BroadcastReceiver is not called or receive nothing because I don't see my Log.d message and if I use my version (with `android:enabled="true"` and without `android:exported="false"`) I can see my Log.d message. – Andrzej S. Nov 02 '17 at 17:03
  • Have you launched your application at least once after installation to activate it? I wonder if your application is in a stopped state, so it won't receive any broadcast. – mariachi Nov 03 '17 at 08:50
  • Yes, I have. I always at first reinstall and run the app, check my service using logcat and than reboot the device. – Andrzej S. Nov 03 '17 at 21:23
  • I wonder if you really need to specify `android:process` for your receiver and service? According to docs: _"Application components are normally run in a single process that is created for the entire application. If the process name begins with a ':' character, a new process private to that application will be created when needed to run that component (allowing you to spread your application across multiple processes)."_ - so your app, receiver and service exists in different processes. I'm not sure if it is the reason of issue, but I'd try to drop `android:process` from both. – mariachi Nov 10 '17 at 09:56
  • I think you're right that is the reason but I can't just drop it because without it I can't even start the service. – Andrzej S. Nov 12 '17 at 01:52
  • Same doc says: "_Specify a specific process that the associated code is to run in. Use with the application tag (to supply a default process for all application components), or with the activity, receiver, service, or provider tag (to supply a specific icon for that component)._" and following: "_If the process name begins with a lower-case character, the component will be run in a global process of that name, provided that you have permission to do so, allowing multiple applications to share one process to reduce resource usage_". I think you should drop ":", and try with application tag – mariachi Nov 13 '17 at 07:32
0

Where Manifest file in kivy project or how you can added this rule in buildozer.spec?:

<receiver android:name=".MyBroadcastReceiver"
          android:enabled="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/32990666) – Daraan Oct 24 '22 at 20:23
  • https://habr.com/ru/post/694906/ – Jessy James Dec 04 '22 at 22:14