I have some process that I would like to run in the background the whole time.
So I made it a Service.
My question is: is there anyway to prevent from the user from killing this service? (even if he uses third party app)
No, it is not possible. It is also a bad idea.
Maybe this can help you:
final Intent intent = new Intent(context, YourService.class);
final PendingIntent pending = PendingIntent.getService(context, 0, intent, 0);
final AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pending);
long interval = 30000;//milliseconds
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(),interval, pending);
This way your service will be receiving regular onStart events from AlarmManager. If your service is stopped it will be restarted. So you may say it will be running infinitely.
More complete sample can be found in Photostream sample application http://code.google.com/p/apps-for-android/.
•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.)
Send a broadcast in the onDestory method of the service, restart the service in the onReceive method the the broadcast receiver.
But make sure the resources your service are under control
See: http://developer.android.com/reference/android/app/Service.html#ProcessLifecycle
Related
I'm starting a service using
startService(new Intent(this, RelayService.class));
and then the service starts an alarm using
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, SyncAlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + SYNC_EVERY_MS, SYNC_EVERY_MS, pi);
and then BroadcastReceiver SyncAlarmReciver is trying to get the service using
RelayServiceBinder relay = (RelayServiceBinder)
peekService(context, new Intent(context, RelayService.class));
It all works fine until the service is restarted by the system after application gets killed when other applications need more memory. After restart, the service relaunches the alarm using the same code, but peekService() returns null. Through debugging messages, I see that context in the service and in the broadcast receiver is the same, as well as RelayService object, i.e. these objects are the same objects in memory. How can I solve this problem?
If it helps, here are links to the three pieces of the code mentioned: main activity, service, broadcast receiver.
P.S. I know that the service is running continuosly because I'm watching the process closely and see it running fine and not restarting in any way, and also because I see that connection it opens before launching the alarm does not get interrupted.
As suggested by JesusFreke, the problem is that peekService() can only return an existing IBinder object. As the service is restarted by the system and there's no Activity that would bind to the service at this point, the IBinder object does not exist yet. So a null is returned. It's a shame that documentation misses this fact entirely.
As I definitely didn't want to start the service if it wasn't running, using startService() seemed a bad idea, so I resorted to quering a static attribute of the service (which was there anyway).
I want to provide the user with toast notifications every 'x' minutes, I tried to do this with the help of service, but when the application was killed, the service stops.
The same issue occurs with intent Service as well, what should I be doing in order for me to keep a thread/service in memory even after the application is killed?
The terms of your question are a bit confusing :
the application lies in a process. If the process is killed, then everything running in that process is killed.
if you want something to survive that process's death, you should use a second process and run the thing to survive inside it.
a service can be run in its own process, looks like a good choice here. Look at android:process attribute in the service tag : http://developer.android.com/guide/topics/manifest/service-element.html
But what you want to do is maybe simpler : set a repeating task. For this, you could use the alarm manager.
You can, for instance :
provide the alarm manager with a pending intent
the pending intent will trigger a service of your own
the service will we waked up, then run. This has the advantage of not letting your service always run and count time to know when it has to wake up (which would drain battery). Here the alarm manager will wake it up when needed, your service will just execute its task and die.
If you combine this approach with the first part of that answer, running your service in a different process, then you can achieve something that's really light weight for the Android device : only your service (in its own process) will wake up at given interval, and the application's process will not be launched by this alarm, but only the service's process.
And about toast notifications, yes, a service is a good place to do it, but the notification bar may be more appropriate to display notifications and notify the user that some event took place inside a background service.
Try implementing foreground service. foreground service
Foreground service displays notification and is never stopped until you want.
Implement this code snippet in your service's onCreate
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
My Problem Is When I M Pressing Home Button And Close My App At That Time Background Service stoped And After That It Requires To LOgin Again In App Then Background Service Will Start So How Can I Do Like Whatssapp If App Will Close Or Kiiled Then Also Sevice Can Run In Background.....
I had the same problem. When you swipe an application out of the application tray, the process of the background service is killed.
You can add the following code in your service or see this question
#Override
public void onTaskRemoved(Intent rootIntent){
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
What this code does is that it restarts the process of your application once it is killed when your activity is killed.
Its very simple, Just follow the scenarios in below link.
Continue Service even if application is cleared from Recent app
your service and processes (Threads run inside your service) will remain continuous.
Ok, I'm just guessing - really don't want to check all code for your application.
Service can be starter in 2 ways:
Using bindService() what probably you are doing here. It's nice, but means that service will be disposed as soon as the last client unbind it (what you probably doing in some onPause() method.
Using the startService() command. In such case service will run as long as you stop it or system will consider that this service is using to much memory that should be used for some more urgent task (ex: some fat activity)
The quick fix for your issue (if my guesses are right) will be switching service to be run in "startService" mode. If you don't want to play much with your code the best place to put it is onBind() method of your service (just try to start service from itself). Of course this will not start the service but will switch it's mode to the "long running, real background one".
This will not solve all your problems as I mentioned above - service still can be killed by system in order to get more resources. You can prevent it in some ways: if you really want to keep service running, you should consider to use foreground service (google it) that will increase chances of the service to survive. But the best option is just to use service lifecycle, save data if needed and load them on service start, just like you should do with activity. For long running background services there is also option start sticky that will cause service starting after every kill, crash etc.
I have written a service that fetches data from a CRM based web service and puts in a database on the phone. Now this service has to be run every 3 hours, so it can sync data between CRM and the android database.
Now to have this service run itself, I'm using alarm manager and have the web service "start" itself.
Intent intent = new Intent(ServiceClass.this, ServiceClass.class);
PendingIntent pintent = PendingIntent.getService(ServiceClass.this, 0, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 10800*1000, pintent);
This service needs to be started after a reboot, for that purpose I'm using the method outlined here..
I just want to know if I'm going on the right path, or if I'm making a mistake or if there is a better way to do this. I haven't worked with Android much and just need a few pointers. Thanks!
Yes you are on the right path. The Alarm Manager is very reliable and is used specifically for this purpose - to schedule tasks in the future (both repeating and non-repeating).
And I agree with #tyczj, you should definitely define your ServiceClass as an IntentService. An IntentService is a subclass of Service which runs in the background and is specifically designed to perform a specific task, and then kill itself once it's finished. It's perfect for downloading data and background syncing.
It's quite easy to implement as well, you'll most likely just need to override one method - onHandleIntent - which is what is called when the service starts.
To re-schedule the tasks on reboot, the method outlined in that post is what I use. Hope this helps!
public class MyHibernatedService extends Service{
public void onCreate() {
super.onCreate();
//declaring the intents ..
//some codes...
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, IntentServiceToBeRun, 0);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MILLISECOND, 10000);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
I want my Service to launch an IntentService every single day at a certain time. However, I've read somewhere on the internet, StackOverflow, google,etc.. that a Service cannot stay alive forever, this is how Android works. It will have to kill that Service whenever Android needs memory or is using too much memory.
What guarantees for me that this code will run everyday and my Service will not be killed?
EDIT :
I noticed in the Android docs:
The Android system will attempt to keep the process hosting a service around as long as the service has been started or has clients bound to it
what do they actually mean by "clients bound to it"?
Don't use your own service to periodically start another service, but use the AlarmManager service instead (like you are already doing). There is no need for this second service IMHO.
The AlarmManager is a system service and will never be killed by Android, and it already does exactly what your own service would do: start things periodically (or single-shot at a specified time).
On the "clients bound to it": off-topic, but it means other components (like other services, or activities) are connected to it using a call to Context.bindService(). For details, check the dev guide.
You don't actually need to keep your service alive.
Here you are setting the AlarmManager, that is able to wake your IntentService up when it is time, even if the phone is sleeping. This service does the job, not yours.
What guarantees for me that this code will run everyday and my Service
will not be killed?
The code that you provided in MyHibernatedService has to be executed only once, to set the alarm, then you won't need it anymore. If it is the only thing that MyHibernatedService does, then you don't need it at all.
You could for instance create a static method in your intent service that would set the alarm, and call it from anywhere according to what you want (probably the place where you used to start MyHibernatedService).
Also, if you don't really need an incredible accuracy on the time your intent service is started, prefer setInexactRepeating() instead of setRepeating().