Why does my Android service get restarted when the process is killed, even though I used START_NOT_STICKY?

后端 未结 3 1218
忘掉有多难
忘掉有多难 2021-01-29 19:20

My app uses a pattern where I start a service with Context#startService() as well as bind to it with Context#bindService(). This is so that I can control the lifetime of the se

3条回答
  •  青春惊慌失措
    2021-01-29 19:52

    Look to this document section: Service lifecycle changes (since 1.6)

    updated

    after some investigations (have created project, run described command step by step, etc) i found that code is working exactly as described in "Service lifecycle changes"

    what I found:
    adb shell am kill com.tavianator.servicerestart kills nothing
    (try adb shell , then in shell am kill com.tavianator.servicerestart
    You will be faced with error message Error: Unknown command: kill)

    so,
    run your application,
    run adb shell
    in shell run ps command
    find PID number of Your app
    in shell run command kill
    where is Your PID number
    repeat killing steps for service (if it is running in its own process)
    check if service is running (should not), restarted after 5-7 sec
    update
    one solution (not enough good, but usable in some cases) is stopSelf() e.g.:

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "onStartCommand", Toast.LENGTH_LONG).show();
        stopSelf();
        return START_NOT_STICKY;
    }
    


    update
    updated solution

    void writeState(int state) {
        Editor editor = getSharedPreferences("serviceStart", MODE_MULTI_PROCESS)
                .edit();
        editor.clear();
        editor.putInt("normalStart", state);
        editor.commit();
    }
    
    int getState() {
        return getApplicationContext().getSharedPreferences("serviceStart",
                MODE_MULTI_PROCESS).getInt("normalStart", 1);
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (getState() == 0) {
            writeState(1);
            stopSelf();
        } else {
            writeState(0);
            Toast.makeText(this, "onStartCommand", Toast.LENGTH_LONG).show();
        }
        return START_NOT_STICKY;
    }
    

    Why service get restrted when the process is killed?

    According to this document:

    When a service is started, it has a lifecycle that's independent of the component that started it and the service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is done by calling stopSelf(), or another component can stop it by calling stopService().
    Caution: It's important that your application stops its services when it's done working, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call to onStartCommand()

    from other hand document says:

    *START_NOT_STICKY* - If the system kills the service after onStartCommand() returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.

    So, after reading this document and some experiments i think system treats manually killed services as unfinished (crashed: @see W/ActivityManager(306): Scheduling restart of crashed service) and restarts it despite of value returned by onStartCommand.


    stopSelf() or stopService() - no restarts, why not if job done ?

提交回复
热议问题