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?
Related
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();
}
Basically I have a service running to check my location every 30 minutes and when the location changes, pop up a basic notification. I only need this service when my app is closed (on stop/pause too). So im asking where should I start my service in my activity?
I want something similar as Facebook,Instagram and most of apps have... a service running from the background and when a notification pops up just open de app. While the app is open the service shouldnt do anything.
I tried onDestroy() method (in my MainActivity) but didnt work out, and onStop() method neither.
Do i explain myself?
Thanks!!
Recurring tasks should be scheduled using AlarmManager (or JobScheduler).
This is usually done in a BroadcastReceiver which reacts to BOOT_COMPLETED.
If you want to cancel such a job while your activity is active, call the respective methods on AlarmManager in onResume and onPause.
If you want your service to be running in the background at all times event after closing the app, you need to make your service STICKY and you can do that in the OnStartCommand
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
Note that it returns START_SICKY which tells the OS to recreate the service after it has enough memory and call onStartCommand() again with a null intent.
Read also about application:persistent which is "Whether or not the application should remain running at all times". This is more troublesome - System will try not to kill your app which will effect others in the system, you should be careful using it.
I have an application which works like a framework - other apps can register a PendingIntent with my app which triggers them at some point in the future. I am keeping the PendingIntents in an array list in a service and then iterating over them to trigger. To register an intent the application calls "startService()" with a PendingIntent set within the intent bundle.
At some point, my service is being closed - or more specifically my array list is being emptied (which can only happen by Android killing the service) and as such I loose my PendingIntents for the registered apps.
How can I keep my service alive, or more specifically keep my PendingItents from being lost? I don't want to go against the Android system mechanisms and create a hacky effort, I would like to know the way in which Google think this should be done.
When a service is killed, it's onDestroy() method is called. You could probably over-ride the onDestroy() method and do something like:
public void onDestroy(){
Intent intent = new Intent();
intent.setAction("SERVICESTOPPED");
sendBroadcast(intent);
super.onDestroy();
}
Have a BroadcastReceiver that listens to this intent and handle the situation as and when it happens.
Alternatively, in the onstartCommand(), if you specify the return value as START_STICKY, the OS will restart your service if it gets killed by OS. Generally this happens with long running serices
Have you tried with START_STICKY?
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Put your code here
return START_STICKY;
}
You can try START_REDELIVER_INTENT
I made a remote service, this service is started by my activity the first time that boot, after that, the activity always look if the service is started to avoid start it again.
The service run some methods in the onCreate function. This service is running always and started on boot time also.
The problem (is not a big problem but I want to know why) is that once the service is created if I stop my activity the onTaskRemoved is called, this is correct, but after few seconds the oncreate method is called again and the service starts again.
Any idea why? And how can I control this?
<service
android:name=".Service"
android:icon="#drawable/ic_launcher"
android:label="#string/service_name"
android:process=":update_process" >
</service>
AndroidManifest.xml
if (!isRunning()) {
Intent service = new Intent(this, UpdateService.class);
startService(service);
} else {
//Just to debug, comment it later
Toast.makeText(this, "Service was running", Toast.LENGTH_SHORT).show();
}
When the service is started if it was not running
The problems is that you service is sticky per default, this means that it will be restarted when killed, until you explicitly ask for it to be stopped.
Override the onStartCommand() method in your service, and have it return START_NOT_STICKY. Then you service will not be restarted when killed.
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_NOT_STICKY;
}
Although Bjarke's solution is valid, I would like to propose an alternate solution which covers cases where it might be necessary to perform any recovery in the Service.
Android is invoking onStartCommand() once again after restarting your service to inform you that the Service process crashed unexpectedly (because its task stack was removed), and is now being restarted.
If you look at the intent argument of onCreate(), it will be null (only for such restarts), which indicates that Android is re-creating your previously sticky service which crashed unexpectedly.
In some cases it would be wise to return NON_STICKY ONLY for such restarts, perform any needed cleanup/recovery and stop the service so that you exit gracefully.
When the service is started normally, you should still be returning STICKY otherwise your service would never be restarted to let you perform any recovery.
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// intent is null only when the Service crashed previously
if (intent == null) {
cleanupAndStopServiceRightAway();
return START_NOT_STICKY;
}
return START_STICKY;
}
private void cleanupAndStopServiceRightAway() {
// Add your code here to cleanup the service
// Add your code to perform any recovery required
// for recovering from your previous crash
// Request to stop the service right away at the end
stopSelf();
}
Another option would be to request your service be stopped (using stopSelf()) as part of onTaskRemoved() so that Android does not even have to kill the service in the first place.
I see this example with programs like Advance Task killer, Watch Dog, eBay, battery widgets, ect. There is a background service running that monitors device activity, a broadcastreceiver, but there is an option to disable the notification icon displayed. Currently my application works flawlessly by calling:
Context context = getApplicationContext();
Intent intent = new Intent(context, SomeBackGroundService.class);
context.startService(intent)
and then in my service I am calling:
startForeground(NOTIFICATION_ID, notification);
Now how is it that these other applications can have a long running broadcastreceiver running without a notification icon? What do I need to do in order to disable/set ect as to hide the icon and add this feature to my application?
Thanks in advance
I'm not expert on this, but I disagree with the accepted answer.
Your startForeground is key to ensuring that your service continues running.
Without that, it might keep running, but it has a much lower priority so it is much more likely to be killed by the system.
Your service is entirely independent of whether or not a notification exists for it. If you removed the line, startForeground, the service would continue to run. The only time a service stops is if you call context.stopService() or stopSelf(). Throw some logs into your service, and you'll see that it continues to run.
Override the onStartCommand to determine behavior of your service after garbage collection:
#Override
public int onStartCommand(Intent intent, int flags, int startId() {
super.onStartCommand(intent, flags, startId);
doWork();
return START_STICKY;
}
START_STICKY recreates your service after garbage collection. START_REDELIVER_INTENT will recreate your service after garbage collection using the original intent, use this only if you need extra intent data.
Create a notification that contains an icon made with a png and is only 1 pixel in height and width and make that pixel transparent.