Why does my Android service restart when the process was killed, although I used START_NOT_STICKY?

My application uses a template in which I start the service with Context # startService () , and also bind to it using Context # bindService () . This means that I can control the lifetime of the service, regardless of whether any clients are attached to it. However, I recently noticed that whenever my application kills the system, it will soon restart any running services. At this point, the service will never be told to stop, and this will leak the battery whenever this happens. Here is a minimal example:

I found someone with a similar problem here , but it was never diagnosed or resolved.

Services:

@Override public void onCreate() { Toast.makeText(this, "onCreate", Toast.LENGTH_LONG).show(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_NOT_STICKY; } @Override public IBinder onBind(Intent intent) { return new Binder(); } 

Activity:

 @Override protected void onStart() { super.onStart(); Intent service = new Intent(this, BoundService.class); startService(service); bindService(service, mServiceConnection, 0); } @Override protected void onStop() { unbindService(mServiceConnection); Toast.makeText(this, "unbindService", Toast.LENGTH_SHORT).show(); super.onStop(); } 

To test this, I launched an application that launched the service and attached to it. Then I stepped back from an application that unties (but does not work). Then i did

 $ adb shell am kill com.tavianator.servicerestart 

and, of course, after 5 seconds, β€œonCreate” will appear, indicating that the service has started again. Logcat shows this:

 $ adb logcat | grep BoundService W/ActivityManager( 306): Scheduling restart of crashed service com.tavianator.servicerestart/.BoundService in 5000ms I/ActivityManager( 306): Start proc com.tavianator.servicerestart for service com.tavianator.servicerestart/.BoundService: pid=20900 uid=10096 gids={1028} 

If you replace the startService () template with BIND_AUTO_CREATE, the problem does not occur (even if I crash the application while it is still connected to the service). It also works if I never contact the service. But the combination of start, bind, and unbind never seems to let my ministry die.

Using dumpsys before killing an application shows this:

 $ adb shell dumpsys activity services com.tavianator.servicerestart ACTIVITY MANAGER SERVICES (dumpsys activity services) Active services: * ServiceRecord{43099410 com.tavianator.servicerestart/.BoundService} intent={cmp=com.tavianator.servicerestart/.BoundService} packageName=com.tavianator.servicerestart processName=com.tavianator.servicerestart baseDir=/data/app/com.tavianator.servicerestart-2.apk dataDir=/data/data/com.tavianator.servicerestart app=ProcessRecord{424fb5c8 20473:com.tavianator.servicerestart/u0a96} createTime=-20s825ms lastActivity=-20s825ms executingStart=-5s0ms restartTime=-20s825ms startRequested=true stopIfKilled=true callStart=true lastStartId=1 Bindings: * IntentBindRecord{42e5e7c0}: intent={cmp=com.tavianator.servicerestart/.BoundService} binder=android.os.BinderProxy@42aee778 requested=true received=true hasBound=false doRebind=false 
+49
android android-service
Sep 28 '12 at 23:06
source share
3 answers

Take a look at this section: Service Lifecycle Changes (since version 1.6)

updated

after some research (created a project, run the described command step by step, etc.), I found that the code works exactly as described in "Changing the service life cycle"

what i found:
adb shell am kill com.tavianator.servicerestart kills nothing
(try adb shell , then in am kill com.tavianator.servicerestart
You will come across a message Error: Unknown command: kill )

so, run the application,
run adb shell
at the ps command prompt
find the PID number of your application
on the command line command line kill <app_xx_PID>
where is your PID number Repeat killing for maintenance (if it works in its own process)
check if the service is working (should not), restart after 5-7 seconds
update One solution (not good enough, but applicable in some cases) stopSelf() for example:

 @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 does a service become restricted when a process is killed?

According to this :

When a service starts, it has a life cycle that is independent of the component that launched it, and the service can work in the background indefinitely, even if the component that started it is destroyed. Thus, a service must stop when it is running by calling stopSelf () , or another component can stop its call to stopService () .
Attention It is important that your application terminates its services when it is running, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService (). Even if you enable service binding, you should always stop the service if it ever received a call to onStartCommand ()

from another document it says:

* START_NOT_STICKY * - If the system kills the service after returning onStartCommand (), do not recreate the service unless waiting for delivery intentions. This is the safest option to avoid starting the service when it’s not necessary, and when your application can simply restart any incomplete tasks.

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


stopSelf () or stopService () - no reboot , why not get the job done?

+26
Oct 2
source share

I believe the problem is that for the service that was started when startService() called, the internal accounting for the bindings (affected by the bindService() / unbindService() calls) somehow prevents the service from being knocked down correctly after of how it is scheduled to restart when the process is killed.

Depending on your preferences, it seems that there are three alternatives to avoid this problem (you mentioned the first two already in your question):

  • Use only startService() / stopService() , do not use bindService() / unbindService() at all.

  • Use only bindService() / unbindService() (with BIND_AUTO_CREATE ), do not use startService() / stopService() at all.

  • If you need startService() / stopService() and bindService() / unbindService() , override onUnbind() in your service and call stopSelf() from it:

     @Override public boolean onUnbind(Intent intent) { stopSelf(); return super.onUnbind(intent); } 

From my testing:

  • Using the first option will print this line in the log:

    W / ActivityManager (nnn): Planning to restart xxxx emergency service in 5000 ms

    but after that the service will not be restarted.

  • The second alternative will lead to the destruction of your service after you untie it (in Activity onStop() in your example).

  • The third alternative will basically make your code behave like the second alternative (without having to change a lot).

Hope this helps!

+9
04 Oct
source share

How to revise your template ?

The START_NOT_STICKY flag appeared at some point during the evolution of Android (after 1.6?). Most likely, you are faced with some subtle regression in the service life cycle that was introduced at that time. Thus, even if at the moment a no less subtle solution is found - and magically verified to work on all possible devices - this will not necessarily work in new versions of Android.

In any case, this life cycle pattern looks unusual, and this may be the very reason for your encounter with this exotic problem.

We consider two cases.

  • Normal (?). Some actions begin the service. Soon after, it becomes attached, used, disconnected - then what? Did you stop somehow? Why is there no significant battery drain in this case?

  • Abnormal. The service is killed at some (random?) Point. When restarting, it implements some incorrect assumptions and remains active, doing something that drains the battery?

Everything looks pretty weird.

I would analyze the parallel processes in your product. All significant cases. Some charts, etc. Most likely, as a result, the very need for such a template will be eliminated.

Otherwise, it seems like any workaround would be a fragile hack.

+2
Oct 07 '12 at 20:22
source share



All Articles