I am using an empty activity to start a sticky service. I start the service using the following code.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent service = new Intent(this, MyService.class);
service.setAction("com.company.test.MyService");
startService(service);
finish();
setContentView(R.layout.activity_transparent);
}
The problem is that if the activity gets killed it will cause the service to restart. Is there a way to avoid this problem?
Note: I am killing the application by swiping it out of the task manager, and not the activity's finish() call.
No, actually. This is a new feature in the Android SDK- killing the app kills all processes connected to the app, and even the app's sticky services will not restart anymore.(EDIT: The service may not restart, depending on the device; apparently sticky services are still a buggy feature on certain versions of android.)
If you want to keep your service perpetually running, you will need to use a ForegroundService, with a persistent notification in the drawer.
Apparently, this is to make sure that no services run without the user's knowledge.
Related
Problem statement:
I want to launch an application which contains a set of services [run in the background]. These services will be communicating
to a client activity [which also is a part of the application].
When the application is killed (manually by swiping out the running application OR through Settings->Apps->Running application->stop the application),
I want the services to be running in the background. When the application is launched back, it will resume the communication with the services running in the background.
Solution:
For the communication between the services and the client activity, I have put all the background services in a separate process and the activity in the application process.
The services and the activity communicate through the Messenger (the IPC provided by android). This works fine, without any issue.
The problem I am having is with the services to be run in the background when the application which launched the services is killed manually.
Killing manually implies: manually by swiping out the running application OR through Settings->Apps->Running application->stop the application.
For this I tried the following
The set of services are running as a global process (by using android:process in the Manifest). But these services are killed when the application is killed.
I include 2 activities in the Manifest file and both have following lines in the Manifest
"android.intent.action.MAIN" and "android.intent.category.LAUNCHER" for both the activities.
Here out of the 2 activities, one activity and all the services are made a part of one process. The other activity (which is the client activity that uses the services) is made a part of the application.
Basically thinking that 2 applications will be launched and one of the application (which holds all the services) will be running irrespective of the other being killed.
However I see that only one application will be running and when I kill it, all the services are made to stop.
So I think that the only way I could possibly achieve this is, if I am able to launch 2 Virtual Machines from a single apk. So that all the services are part of one VM and the
client activity(that uses the services) is part of the other VM. Now if the application holding the client activity is killed, the VM holding the services will be running without any issue.
But is there is a way that one apk can allow for launching 2 applications which run on 2 different VMs. If yes, how can I do that?
OR
Is there any other solution to my problem statement.
Thanks in advance.
You can certainly restart the service when the app is killed. You just have to handle the uncaughtException and fire the alarm that starts the service again. Follow my post to know more around restarting services.
There is a better solution for this.
Yes when user kill application all services will be stopped. So you have to restart the service.
For this there is a simple technique.
Create a receiver which check if service is running or not, if not start the service. and after this create a entry on alarmanager to recall this reciever after 2 sec, so after every 2 sec it check whether your service is running or not.
Please check below code.
public class MyServiceReceiver extends BroadcastReceiver {
Context con;
#Override
public void onReceive(final Context context, final Intent intent) {
this.con = context;
if (!Support.isServiceRunning(context, MyService.class.getName())) {
con.startService(new Intent(con, MyService.class));
}
Intent in = new Intent(con, MyServiceReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(con, 0, in, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmmanager = (AlarmManager) con.getSystemService(Context.ALARM_SERVICE);
alarmmanager.set(AlarmManager.RTC, System.currentTimeMillis() + 2000, pi);
}
}
I have an app that runs as a web server. The app has a service that is START_STICKY I want this service to run the web server all the time (option is given to user in a notification to stop it).
Problem is that the server is restarted (loosing settings etc) when i swipe my app closed. It stays there fine but logcat shows that it is restarting.
I can re- open my app and bind to the new service, this works fine. Although swipe closing again has the same effect.
I need this to NOT restart.
Standard service code
private WebServerService mService;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder binder) {
WebServerService.MyBinder b = (WebServerService.MyBinder) binder;
mService = b.getService();
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
}
};
public serviceStart() {
mIntent = new Intent(mContext.getApplicationContext(), WebServerService.class);
mContext.startService(mIntent);
mContext.bindService(mIntent, mConnection, Context.BIND_AUTO_CREATE);
}
Service on start
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, START_STICKY, startId);
Log.d("SERVICE","Started");
return START_STICKY;
}
Short answer: you can't. Every Android app can be killed by the system or by the user when the system claims memory or the user swipes out the app from the recent apps list. This is an Android design and all apps must adhere to it. The only (small) improvement you can have is setting the service as a Foreground service:
where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)
Use startForeground()
The drawback is that you'll have to provide a notification.
Like Mimmo said: You can't. The system can indeed kill apps/services if low on memory. Also users can do this. Either with the force close button in app settings or swiping the app. Swipe to close is like the force stop. The app/service DOES NOT RESTART when closing an app like this. That is just how the system works. Try it yourself, download advance task killer and kill Facebook for example. If you restart advance task killer a few seconds later, you will see Facebook is running again. Now open Facebook and use the swipe function to kill it. Now start the task killer again. You will see Facebook is not running anymore. Again, that is how the system works.
Setting the service as a Foreground service is not going to help either.
Will the tag android:process="anyname" on your manifest be useful? It makes the service run on a different process of your app.
http://developer.android.com/guide/topics/manifest/service-element.html#proc
As appointed by others it still can be terminated by the system if running low on memory but it won't terminate by closing your app. Hope it helps.
I am developing android application which has background running Service.
When I swap out app from the "Recent app List", it will cause the application to shutdown and stop the service. (The following method has the code for the same.)
#Override
public void onTaskRemoved(Intent rootIntent)
{
//code to be executed
//Stop service
super.onTaskRemoved(rootIntent);
}
Service start up code is in Application class(onCreate()), it will never be executed if app gets resume.
Positive Scenario
1) If I relaunch app after successful execution of service, new instance of app will be
created and service will also start.
Negative Scenario
1) Because there is some code in the above method which is responsible to stop the thread and the service, it causes the app to take some time to stop the service (after swapping from the recent apps).
During this time if I relaunch the application, the application resumes instead off getting recreated.
Now, the service which was running, will stop.
So,in this type situation I have application but without background service.
How can I handle this situation?
1) Application shouldn't be re-launch until service's task is completed.
2) Start service from launcher activity.
Thanks in advance.
in onStartCommand() of Service class , You have to set return as "START_STICKY" that ensure restart service which is terminated by android platform(if app breaks).
You can check the status of the service in OnResume and restart from there using Intent
#Override
protected void onResume()
{
/* This will be called when starting the UI and resume from background
* If the service is not running, then start the service and bind to the service.
* If the service is already running, then just bind with the service. The status
* of the service is determined by the #DetermineServiceStatus function.
*/
}
You have almost no control over service' s lifetime. Background services are prone to be killed by Android, whenever system needs more resources.
The best way to design a background service is return a START_STICKY from your onStartCommand() (which you already did) to ensure that when enough resources become available, your service automatically be restarted, and the job that you perform within the background service should be implemented so that even if it is interrupted, it should succesfully continue its task when restarted by Android OS.
I am developing an application that makes use of a Service. The Service itself works, but the Android systems kills it within 30 seconds of exiting my Activity, sometimes as early as 6 seconds.
I've had a look at a lot of different posts regarding this and know that I can use a foreground service with an icon. At this stage I don't want to go down this path.
I am explicitly starting the service with the following code. The service is controlled by a SwitchPreference.
The service also returns START_STICKY so it does get restarted.
This is the code I am using (not run together like this).
// starting within the activity
Intent intent = new Intent(context, ListenerService.class);
startService(intent);
// stopping within the activity
Intent intent = new Intent(context, ListenerService.class);
stopService(intent);
// Service onStartCommand
return START_STICKY;
When I exit the application the first time, I see the activity being destroyed and then within 30 seconds I see my toast message displayed stating that the service has been restarted.
I understand that the Android system has every right to kill my service when memory is low, but should I expect it to be killed almost immediately after I exit my application?
Is it just garbage collecting my activity references and starting the service "clean"?
I am cleaning up objects in my onStop() method of the activity.
Also, when I return into my application via the activity, is it good practice to bind to the service to get a reference to the service object?
The binding is completed in onStart() method of the activity as follows:
Intent intent = new Intent(this, ListenerService.class);
bindService(intent, serviceConnection, 0);
Unbinding is completed in the onStop() method
unbindService(serviceConnection);
So 2 questions:
1. Should I expect the Android system to kill and restart my service almost immediately?
2. Is my binding methodology acceptable?
Many thanks
From what i understand you are controlling the lifecycle of your service through your activity by calling startService and stopService. Is this correct?
If you want to keep the service running why are you calling stopService on it?
Regarding the rebooting of the service - everything depends on your service configuration, and your code implementation.
I have a service that is defined as:
public class SleepAccelerometerService extends Service implements SensorEventListener
Essentially, I am making an app that monitors accelerometer activity for various reasons while the user sleeps with his or her phone/device on the bed. This is a long-running service that MUST NOT be killed during the night. Depending on how many background apps and periodic processes occur during the night, android sometimes kills off my process, thereby ending my service. Example:
10-04 03:27:41.673: INFO/ActivityManager(1269): Process com.androsz.electricsleep (pid 16223) has died.
10-04 03:27:41.681: INFO/WindowManager(1269): WIN DEATH: Window{45509f98 com.androsz.electricsleep/com.androsz.electricsleep.ui.SleepActivity paused=false}
I do not want to force the user to have 'SleepActivity' or some other activity in my app as the foreground. I can't have my service run periodically, because it is constantly intercepting onSensorChanged.
Any tips? source code is here: http://code.google.com/p/electricsleep/
For Android 2.0 or later you can use the startForeground() method to start your Service in the foreground.
The documentation says the following:
A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)
The is primarily intended for when killing the service would be disruptive to the user, e.g. killing a music player service would stop music playing.
You'll need to supply a Notification to the method which is displayed in the Notifications Bar in the Ongoing section.
When you bind your Service to Activity with BIND_AUTO_CREATE your service is being killed just after your Activity is Destroyed and unbound. It does not depend on how you've implemented your Services unBind method it will be still killed.
The other way is to start your Service with startService method from your Activity. This way even if your Activity is destroyed your service won't be destroyed or even paused but you have to pause/destroy it by yourself with stopSelf/stopService when appropriate.
As Dave already pointed out, you could run your Service with foreground priority. But this practice should only be used when it's absolutely necessary, i.e. when it would cause a bad user experience if the Service got killed by Android. This is what the "foreground" really means: Your app is somehow in the foreground and the user would notice it immediately if it's killed (e.g. because it played a song or a video).
In most cases, requesting foreground priority for your Service is contraproductive!
Why is that? When Android decides to kill a Service, it does so because it's short of resources (usually RAM). Based on the different priority classes, Android decides which running processes, and this included services, to terminate in order to free resources. This is a healthy process that you want to happen so that the user has a smooth experience. If you request foreground priority, without a good reason, just to keep your service from being killed, it will most likely cause a bad user experience. Or can you guarantee that your service stays within a minimal resource consumption and has no memory leaks?1
Android provides sticky services to mark services that should be restarted after some grace period if they got killed. This restart usually happens within a few seconds.
Image you want to write an XMPP client for Android. Should you request foreground priority for the Service which contains your XMPP connection? Definitely no, there is absolutely no reason to do so. But you want to use START_STICKY as return flag for your service's onStartCommand method. So that your service is stopped when there is resource pressure and restarted once the situation is back to normal.
1: I am pretty sure that many Android apps have memory leaks. It something the casual (desktop) programmer doesn't care that much about.
I had a similar issue. On some devices after a while Android kills my service and even startForeground() does not help. And my customer does not like this issue. My solution is to use AlarmManager class to make sure that the service is running when it's necessary. I use AlarmManager to create a kind of watchdog timer. It checks from time to time if the service should be running and restart it.
Also I use SharedPreferences to keep the flag whether the service should be running.
Creating/dismissing my watchdog timer:
void setServiceWatchdogTimer(boolean set, int timeout)
{
Intent intent;
PendingIntent alarmIntent;
intent = new Intent(); // forms and creates appropriate Intent and pass it to AlarmManager
intent.setAction(ACTION_WATCHDOG_OF_SERVICE);
intent.setClass(this, WatchDogServiceReceiver.class);
alarmIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am=(AlarmManager)getSystemService(Context.ALARM_SERVICE);
if(set)
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, alarmIntent);
else
am.cancel(alarmIntent);
}
Receiving and processing the intent from the watchdog timer:
/** this class processes the intent and
* checks whether the service should be running
*/
public static class WatchDogServiceReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
if(intent.getAction().equals(ACTION_WATCHDOG_OF_SERVICE))
{
// check your flag and
// restart your service if it's necessary
setServiceWatchdogTimer(true, 60000*5); // restart the watchdogtimer
}
}
}
Indeed I use WakefulBroadcastReceiver instead of BroadcastReceiver. I gave you the code with BroadcastReceiver just to simplify it.
http://developer.android.com/reference/android/content/Context.html#BIND_ABOVE_CLIENT
public static final int BIND_ABOVE_CLIENT -- Added in API level 14
Flag for bindService(Intent, ServiceConnection, int): indicates that the client application binding to this service considers the service to be more important than the app itself. When set, the platform will try to have the out of memory killer kill the app before it kills the service it is bound to, though this is not guaranteed to be the case.
Other flags of the same group are: BIND_ADJUST_WITH_ACTIVITY, BIND_AUTO_CREATE, BIND_IMPORTANT, BIND_NOT_FOREGROUND, BIND_WAIVE_PRIORITY.
Note that the meaning of BIND_AUTO_CREATE has changed in ICS, and
old applications that don't specify BIND_AUTO_CREATE will automatically have the flags BIND_WAIVE_PRIORITY and BIND_ADJUST_WITH_ACTIVITY set for them.
Keep your service footprint small, this reduces the probability of Android closing your application. You can't prevent it from being killed because if you could then people could easily create persistent spyware
I'm working on an app and face issue of killing my service by on app kill. I researched on google and found that I have to make it foreground. following is the code:
public class UpdateLocationAndPrayerTimes extends Service {
Context context;
#Override
public void onCreate() {
super.onCreate();
context = this;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
StartForground();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void StartForground() {
LocationChangeDetector locationChangeDetector = new LocationChangeDetector(context);
locationChangeDetector.getLatAndLong();
Notification notification = new NotificationCompat.Builder(this)
.setOngoing(false)
.setSmallIcon(android.R.color.transparent)
//.setSmallIcon(R.drawable.picture)
.build();
startForeground(101, notification);
}
}
hops that it may helps!!!!