Stop a service after MainActivity is closed (EDITE

2019-03-03 19:55发布

问题:

I think im not clear at all, i do want the service to persist even if the main activity is destroyed via user action or android system does it, it does it well, but when the app is reopened at certain point i will want to check if a bg activity exists and stop it using a action button, THX in advance.


I launch a background service, in my MainActivity I can stop it and rerun it, the service persists when the app is closed from the running apps list, the problem is when I relaunch the closed app an try to stop the service with a button I have the app crashes cause it obviously tries to stop a service from which it no longer has a reference.

private void startBg(){

    if (!hasPermissions() || mScanning) {
        return;
    }

    clearLogs();

    BgServiceIntent = new Intent(MainActivity.this, BgScanService.class);
    startService(BgServiceIntent);
}
private void stopBg(){
    stopService(BgServiceIntent);
}

Calling stopBg() after reopening the app fails, because BgServiceIntent no longer points to this service and thus I get this:

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: mobile.link.imbera.apsys.imberalink, PID: 20104
              java.lang.NullPointerException
                  at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1568)
                  at android.app.ContextImpl.stopServiceCommon(ContextImpl.java:1628)
                  at android.app.ContextImpl.stopService(ContextImpl.java:1589)
                  at android.content.ContextWrapper.stopService(ContextWrapper.java:499)
                  at mobile.link.imbera.apsys.imberalink.MainActivity.stopBg(MainActivity.java:180)
                  at mobile.link.imbera.apsys.imberalink.MainActivity.lambda$onCreate$1$MainActivity(MainActivity.java:124)
                  at mobile.link.imbera.apsys.imberalink.MainActivity$$Lambda$1.onClick(Unknown Source)
                  at android.view.View.performClick(View.java:4463)
                  at android.view.View$PerformClick.run(View.java:18770)
                  at android.os.Handler.handleCallback(Handler.java:808)
                  at android.os.Handler.dispatchMessage(Handler.java:103)
                  at android.os.Looper.loop(Looper.java:193)
                  at android.app.ActivityThread.main(ActivityThread.java:5333)
                  at java.lang.reflect.Method.invokeNative(Native Method)
                  at java.lang.reflect.Method.invoke(Method.java:515)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
                  at dalvik.system.NativeStart.main(Native Method)

回答1:

If the service already running in background then you need to call stopSelf() on same instance of that service . Now as per service life Cycle onCreate() only call once in the lifetime of service . WhereAs onStartCommand get called each time you call startService() with new intent. So what you can do is to pass a flag in intent to stop it .

Intent BgServiceIntent = new Intent(MainActivity.this, BgScanService.class);
    BgServiceIntent.putExtra("close",true);
    startService(BgServiceIntent);

And in Service .

 @Override
public int onStartCommand(Intent intent, int flags, int startId) {
    boolean shouldClose=intent.getBooleanExtra("close",false);
    if(shouldClose){
        stopSelf();
    } else {
        // Continue to action here
    }
    return START_STICKY;
}


回答2:

Maybe all you need to do is check to see if it's null before attempting to stop it:

private void stopBg(){
     if(BgServiceIntent != null)
         stopService(BgServiceIntent);
}


回答3:

First of all start a service in START_NOT_STICKY.
Override this method in your Service

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_NOT_STICKY;
}

and add this in your MainActivity.class

@override
private onDestroy() {
    stopService(YourActiveService);
    finishAffinity();
    super.onDestroy()
}