eddieowens / react-native-boundary

Native implementation of geofencing/region monitoring
Apache License 2.0
121 stars 72 forks source link

[Android 8+] Crash when the app is in background #45

Open RustamG opened 5 years ago

RustamG commented 5 years ago

Hi @eddieowens,

In Android 8 and up it's not possible to start services when your app is in background. Proof

If you try to do so, you get an error. Here is a log with stack trace:

I/RNBoundary: Handling geofencing event
I/RNBoundary: Geofence transition: 1
I/RNBoundary: Enter geofence event detected. Sending event.
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
    Process: com.sample.android, PID: 7277
    java.lang.RuntimeException: An error occurred while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:354)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
        at java.util.concurrent.FutureTask.run(FutureTask.java:271)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.sample.android/com.eddieowens.services.BoundaryEventHeadlessTaskService (has extras) }: app is in background uid UidRecord{8a05d06 u0a88 TRNB idle change:uncached procs:1 seq(0,0,0)}
        at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1577)
        at android.app.ContextImpl.startService(ContextImpl.java:1532)
        at android.content.ContextWrapper.startService(ContextWrapper.java:664)
        at com.eddieowens.services.BoundaryEventJobIntentService.sendEvent(BoundaryEventJobIntentService.java:71)
        at com.eddieowens.services.BoundaryEventJobIntentService.onHandleWork(BoundaryEventJobIntentService.java:46)
        at android.support.v4.app.JobIntentService$CommandProcessor.doInBackground(JobIntentService.java:392)
        at android.support.v4.app.JobIntentService$CommandProcessor.doInBackground(JobIntentService.java:383)
        at android.os.AsyncTask$2.call(AsyncTask.java:333)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:764) 

So the cause is this line.

Is this something we might hope to get fixed? And what would be ETA?

Thanks.

EDIT: targetSdkVersion should be 26 or higher

songoten28 commented 5 years ago

same problem: Fix by add this line

   public static final String ON_ENTER = "onEnter";
    public static final String ON_EXIT = "onExit";

    final Handler handler = new Handler();

    public BoundaryEventJobIntentService() {
        super();
    }

    boolean workSuccessful = true;

....

private void sendEvent(final Context context, final String event,final ArrayList<String> params) {
        if(workSuccessful) {
            workSuccessful= false;
            final Intent intent = new Intent(RNBoundaryModule.GEOFENCE_DATA_TO_EMIT);
            intent.putExtra("event", event);
            intent.putExtra("params", params);

            Bundle bundle = new Bundle();
            bundle.putString("event", event);
            bundle.putStringArrayList("ids", intent.getStringArrayListExtra("params"));

            Intent headlessBoundaryIntent = new Intent(context, BoundaryEventHeadlessTaskService.class);
            headlessBoundaryIntent.putExtras(bundle);
            context.startService(headlessBoundaryIntent);
            HeadlessJsTaskService.acquireWakeLockNow(context);

            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        startForeground(1, new Notification());
                    }
                    workSuccessful = true;
                }
            }, 6000);
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        startForeground(1, new Notification());
    }

you should create another file to replace this file using : postinstall: cp BoundaryEventJobIntentService.java /node_modules/...

Workarround: https://stackoverflow.com/questions/44425584/context-startforegroundservice-did-not-then-call-service-startforeground

woffu commented 5 years ago

With the fork: https://github.com/woffu/react-native-boundary And the proposal of pull request (https://github.com/eddieowens/react-native-boundary/pull/46) there is a fix for this issue using the startForegroundService() with a notification

mathiasmoeller commented 4 years ago

Any news on this topic? Will the PR be merged?

mathiasmoeller commented 4 years ago

Hey @woffu. Your fix worked fine for me. Thanks a lot! But I still have issues with the Headless event. It seems like my callback is registered AFTER the Headless event is fired. I tried to explain it more in #55. You seem to have a decent understanding of this project. Could you maybe help me out? It would be very much appreciated!!