I have a service with a BroadcastReceiver which communicates with the activity through the method "exampleMethod()". This service start and work correctly but after a while it is stopped by Android and I have to restart it. it is possible to make sure that the service is not stopped for a long time?
public class SMS_Service extends Service{
private BroadcastReceiver rec_sms = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
MainActivity.exampleMethod();
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
after a while Service is stopped by Android
The first thing that matters is that why your service is stopped by the android system,
When the user is directly interacting with a component of that process (that is an activity) Android will try very hard to keep that process running, and you won't see it killed except under extraordinary circumstances.
If it is due to low memory, then nothing could be done. When killing something for memory, the entire process (including the application object) is killed and no code executed in it at this point.
If the service is just being destroyed because it no longer needs to run, its onDestroy() will be called and when the service is later needed a new instance is created and onCreate() called.
Is it possible to make sure that the service is not stopped for a long
time?
This is not possible. The closest you can get is via startForeground(), but not even that guarantees that your service will live forever.
Moreover, this is a serious anti-pattern in Android. Users hate applications that try to run forever, which is why we have to contend with task killers and the like.
Related
I'm running a service that's in the foreground and has a constant notification.
One of my users told me that my app is killed by Clean Master (it's integrated into his android system, it's not a user app). If this app frees RAM it kills my service and it won't restart even though it is using START_STICKY and is using startForeground to run in foreground with a constant notification.
I think this only is possible for a system app, because as far as I know, a foreground service can't be killed by a user app.
Is there anything I can do about this? I want that my service restarts itself if it is killed, just like it's doing it in any other case...
My service looks like following:
public class OverlayService extends Service
{
#Override
public void onCreate()
{
super.onCreate();
// prepare notification...
// ...
// start foreground
super.startForeground(id, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_STICKY;
}
}
I am confused right now , about service concept of running and stopping:
what i want to do:
Start Location service at the very start of application.
Keep getting location updates and store them to shared preference
Stop the service in onDestroy of Application scope!
So far i have searched and studied we can only do following things with service(correct me if i'm wrong):
Stop the service automatically by binding it to related activities/fragments/views , when all of them destroyed service unbind itself automatically so we can call stopself method in unbind
return START_NOT_STICKY in onStartCommand to tell OS , don't recreate it , and create intent local service , after completion of some work it will destroy itself.
Stopping the service manually , by declaring it's intent in some kind of static scope and stopping the service in on onActivityDestroyed of Application class [I am not sure what will happen? , maybe service will destroy each time any activity will be destroyed ? or it will be destroyed only when overall application get's destroyed?]
Either way , i am bit confused and beat , been trying to adjust my Location service with given details for 2 days
If you start your Service using START_NOT_STICKY, then your app will kill your service once your entire application is closed from background i.e. you cleaned your app from home screen.
Here START_NOT_STICKY states that you need not recreate service in case it is been killed.
If this is not the case then you have to manually kill it by your self.
Like
Intent lintent = new Intent(context, LocationService.class);
context.stopService(lintent);
You can use this code at point where your application kills.
That's it. You are good to go with this.
First of all, launch the "LocationService" on your app start:
public class MyApp extends Application {
private static final String TAG = "MyApp";
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "App started up");
startService(new Intent(this, MyLocationService.class));
}
}
Second :
As you said, the Service should better run with the "START_NOT_STICKY" flag
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
Thrid:
Once the system kills your app, the Service will automatically be killed, so no problems at all.
There is no onDestroy() method on the Application object, the only similar event is onTerminated() and it is not being launched on production devices.
onTerminate
Added in API level 1 void onTerminate () This method is for use in
emulated process environments. It will never be called on a production
Android device, where processes are removed by simply killing them; no
user code (including this callback) is executed when doing so.
More information:
https://developer.android.com/reference/android/app/Application.html#onTerminate()
Btw, If you want the MyLocationService to send updates of the location to your app (when it is open), you should consider to use Otto or EventBus (I recommend you this last one because of the simplicity to use it). You can even configure the #Suscriber to receive updates of old retrieved locations if you want.
I will try to explain in a easiest way :)
There are two type of service
IntentService and Service
IntentService when started will kill itself once it treated the content of it onHandleIntent method
as for Service well this one will not end until you give it the command to do so even if your start it using the context of an activity. It will also stop when the application is stopped in an extreme case (by system (Settings/application/YourApp/stop app OR an app crash)
Easiest way is First of all start IntentService with AlarmManager at some repeating time (10 mintutes), then in onHandleIntent() get Location and store into preference.
No Need bind to your activity, the IntentService automatically stops itself after saved in preferences.
Yes you can stop the service in onDestroy() of the activity:
#Override
public void onDestroy(){
Log.v("SERVICE","Service killed");
service.stop();
super.onDestroy();
}
I have built an app for running. It runs an Activity with a timer shown in the user interface, a gps listener that collects coordinates and a lot of other things (the activity does a lot of work).
Now the request of my client is to move all the activity logic in a Service. In this way, when you start a running session, the Service would start and the notification (very simple, just with a static text) would appear. The activity should keep track of the work made in the Service (timer should go on, speed should be shown, ecc...). Tapping on the notification should bring up the activity. If the activity is closed or crashes the Service should keep going on and when you tap on the notification a new Activity should be brought up without the user noticing any difference (the timer should keep showing the right time, the average speed should comprehend the speeds relevated before the activity crash, ecc...).
I know there are a lot of ways to do that.
What I am asking is: what is the best way? Are there examples of such behavior from where to start? What are the common errors I should avoid? Are there best practices to follow?
Thank you
I developed an app with similar service behaviour. It also requires a service which collects data and some activities for showing the data.
For these kind of applications you want to keep the service alive until the user stopps it manualy but it is still possible for android that it kills the service if the device is low on memory.
For the service - activity interaction you need to bind to a service. A good documentation is available here: http://developer.android.com/guide/components/bound-services.html
Be sure to return START_STICKY in the onStartCommand function of the service. This will make sure the intent will be null when the service was restored by the system and tell android that you start and stop your service explicit.
When binding to the service from the activity you need to check if the service is ready (was not restored by the system). This can be done by adding a "ready" field inside the service that is false by default and is set to true if the onStartCommand intent is not null. Therefore you can react properly to a restored service and start the app from the beginning.
To keep the service alive with a high priority you need to call startForeground inside the service. This also requires to show a notification so the users knows a service is running in the background.
Inside service you can use local broadcastmanager.
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
broadcaster = LocalBroadcastManager.getInstance(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000);
return START_STICKY;
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo(); //do watever you want to push
handler.postDelayed(this, 1000); // 10 seconds
}
};
I have a service that gets started (not bound) by an activity. If the activity gets destroyed (e.g. by pressing the back button), the service continues to run, this is of course intended.
However, if I swipe the activity out of the 'recent apps' list, the service gets restarted immediately. This is reproducible, every time the activity/app is swiped out of the list, there is a new call to the service's onCreate-method. No call to onDestroy in between!
First I thought the service gets killed by android, even though I saw no reason for the kill (neither the activity nor the service do resource consuming things, in fact they are minimalistic and do nothing). But then I noticed that the service actually crashes.
V/MainActivity(856): onDestroy // swipe out of the list
I/ActivityManager(287): Killing 856:com.example.myapp/u0a10050: remove task
W/ActivityManager(287): Scheduling restart of crashed service com.example.myapp/.TestService in 5000ms
The code is not noteworthy, but here it is
Activity:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG, "onCreate, starting service...");
startService(new Intent(this, TestService.class));
}
#Override
protected void onStart() {
super.onStart();
Log.v(TAG, "onStart");
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.v(TAG, "onDestroy");
}
//[...]
}
Service:
public class TestService extends Service {
private static final String TAG = "Service";
// onBind omitted
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.v(TAG, "onDestroy");
}
}
In short:
My service is independent of the activity's lifecycle, but only as long as I don't swipe out the app of the recent apps list. In that case, the service gets restarted but without a call to onDestroy.
Every time this happens, not only the state of the service, but also the work the service is doing is lost. I just want to know why the swipe is the reason for this.
Swiping the app from the recent tasks list actually kills the operating system process that hosts the app. Since your service is running in the same process as your activities, this effectively kills the service. It does NOT call onDestroy() on the service. It just kills the process. Boom. Dead. Gone. Your service does not crash.
Since your service returned START_STICKY from the call to onStartCommand(), Android recognizes that your service should be restarted and schedules a restart of the killed service. However, when your service is restarted it will be in a newly created process (you can see onCreate() called in the service), so it will have to start the work all over again.
Rule #1: Don't ever swipe apps from the recent tasks list ;-)
Maybe it can be a problem with Broadcast receivers defined in the manifest.
Do you have some receiver / intent-filter defined in your manifest at application level ? I used to have same kind of problem and it was due to receiver declared in the manifest at the application level
By swiping, your process is NOT guaranteed to be killed by the system get killed. No. You only remove the applciation task (or back stack). Application task is NOT equal to the application process.
So if you have any background jobs (threads, services etc) tied to your back stack and you have a good cancellation policy. The system may try to cache your process if it's suitable for later.
If you kill the app process(es) from the Task Manager though, then it means that your process will be removed and so your JVM/sandbox aggressively by the system.
Use *START_NOT_STICKY* as onStartCommand return
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand");
return START_NOT_STICKY;
}
As the title says I am having the following problem. My foreground service is being killed when the activity that started it is swyped away from recent tasks list.
I am starting a service with
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(notificationID, notification);
return START_STICKY;
}
Can someone please tell me why is this happening and how can I make it so the service stays running when user swypes the activity away.
I don't have access to public void onTaskRemoved (Intent rootIntent) for some reason but I don't know what to do in that method anyway...
I am starting the service like this this and it's not a bound service
serviceIntent = new Intent(this, RecordingService.class);
startService(serviceIntent);
If little use case description helps I am trying to control sound recorder from a remote view in the notification bar so restarting a service is not an option since it should continue to record even if activity is destroyed.
BTW.I did tried starting a service in another process by android:process=":recordingProcess" and the service does continue to run then but I am suspecting this is not how you should do it.
Even i had the same issue and i had access to onTaskRemoved() function.Please check this link, "Process life cycle" topic.
Try to return from onStartCommand() START_REDELIVER_INTENT, service will get start again.
From Android Developer Reference
A service can be both started and have connections bound to it. In
such a case, the system will keep the service running as long as
either it is started or there are one or more connections to it with
the Context.BIND_AUTO_CREATE flag. Once neither of these situations
hold, the service's onDestroy() method is called and the service is
effectively terminated.
How are you starting your service?