Application thread get close if its killed by task manager. Need to re-invoke application as though its killed by other application or task manager. Any idea?
You have to run background service with START_STICKY command.
Just extends Service and override onCommand like this :
#Override
public int onStartCommand(Intent intent,int flags,int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
Like this your Service is restart when it's close (by system or anything else)
You just have now check on your service (onCreate for example) if application is running or not and launch it again if not. I suppose PackageManager let you check this or simply put a static boolean is_alive to see if your activity is always running.
Regards
Jim
Bug in Android 2.3 with START_STICKY
I needed to keep alive a Service with all my forces. If the service is running anytime you can pop the UI.
onDestroy()
it will re-launch.
Can't be uninstalled the app, because it has a Device Administrator.
It is a kind of parental control, the user knows it is there.
Only way to stop is to remove the Device Admin, and uninstall it, but removing Device Admin will lock the phone as Kaspersky how it does.
There are a loot of braodcast receivers, such as boot finshed, user presen, screen on, screen off... , many other, all starting the service, you can do it with UI too. Or in the service check if your activity alive , visible, if not, than pop it.
I hope you will use with good reason the info!
Edit: Restart service code snippet:
// restart service:
Context context = getApplicationContext();
Intent myService = new Intent(context, MyService.class);
context.startService(myService);
Edit2: add spippet to check if the service is running in ... a load of Broadcasts
public static boolean isMyServiceRunning(Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (MyService.class.getName().equals(service.service.getClassName())) {
Log.d("myTag", "true");
return true;
}
}
Log.d("myTag", "false");
return false;
}
Edit3 other service start:
public static void startTheService(Context context) {
Intent myService = new Intent(context, MyService.class);
context.startService(myService);
}
Dont't forget Android 2.3 bug: do the logic for initialization in
#Override
public void onCreate()
and not in:
#Override
public int onStartCommand(Intent intent, int flags, int startId)
While look at Google IO official product source code I have found the following
((AlarmManager) context.getSystemService(ALARM_SERVICE))
.set(
AlarmManager.RTC,
System.currentTimeMillis() + jitterMillis,
PendingIntent.getBroadcast(
context,
0,
new Intent(context, TriggerSyncReceiver.class),
PendingIntent.FLAG_CANCEL_CURRENT));
URL for code
You can start a sticky service and register an alarm manager that will check again and again that is your application is alive if not then it will run it.
You can also make a receiver and register it for <action android:name="android.intent.action.BOOT_COMPLETED" /> then you can start your service from your receiver. I think there should be some broadcast message when OS or kills some service/application.
Just to give you a rough idea I have done this and its working
1) register receiver
Receiver Code:
#Override
public void onReceive(Context context, Intent intent) {
try {
this.mContext = context;
startService(intent.getAction());
uploadOnWifiConnected(intent);
} catch (Exception ex) {
Logger.logException(ex);
Console.showToastDelegate(mContext, R.string.msg_service_starup_failure, Toast.LENGTH_LONG);
}
}
private void startService(final String action) {
if (action.equalsIgnoreCase(ACTION_BOOT)) {
Util.startServiceSpawnProcessSingelton(mContext, mConnection);
} else if (action.equalsIgnoreCase(ACTION_SHUTDOWN)) {
}
}
Service Code:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logger.logInfo("Service Started onStartCommand");
return Service.START_STICKY;
}
I prefer doing nothing in onStartCommand because it will get called each time you start service but onCreate is only called 1st time service is started, so I do most of the code in onCreate, that way I don't really care about weather service is already running or not.
according to #RetoMeyer from Google, the solution is to make the app "sticky".
for this, you must establisH START_STICKY in your intent service management.
check this reference from developer android
Yes, Once memory low issue comes android os starts killing application to compensate the required memory. Using services you can achieve this, your service should run parallely with your application but see, some of the cases even your service will be also killed at the same time. After killing if memory is sufficient android os itself try to restart the application not in all the cases. Finally there is no hard and fast rule to re-invoke your application once killed by os in all the cases it depends on os and internal behaviours.
Related
I'm targeting sdk version 27 with a minimum version of 19 and trying to get a service that runs continuously in the background. I tried different service start options but it still got killed with the app. I tried using a BroadcastReceiver to start the service when it got killed but that gave me an error saying that the app was in the background and couldn't start a service so I tried using the JobScheduler and that gave me the same error. How is this supposed to be done? For example, if I were making a pedometer app, how could I keep that running in the background?
In oreo release Android defined limits to background services.
To improve the user experience, Android 8.0 (API level 26) imposes
limitations on what apps can do while running in the background.
Still if app need to run its service always, then we can create foreground service.
Background Service Limitations: While an app is idle, there are limits
to its use of background services. This does not apply to foreground
services, which are more noticeable to the user.
So create a foreground service. In which you will put a notification for user while your service is running. See this answer (There are many others)
Now what if you don't want a notification for your service. A solution is for that.
You can create some periodic task that will start your service, service will do its work and stops itself. By this your app will not be considered battery draining.
You can create periodic task with Alarm Manager, Job Scheduler, Evernote-Jobs or Work Manager.
Instead of telling pros & cons of each one. I just tell you best. Work manager is best solution for periodic tasks. Which was introduced with Android Architecture Component.
Unlike Job-Scheduler(only >21 API) it will work for all versions.
Also it starts work after a Doze-Standby mode.
Make a Android Boot Receiver for scheduling service after device boot.
I created forever running service with Work-Manager, that is working perfectly.
Since Android 8.0 many background service limitations have been introduced.
Two solutions:
if you need to get total control of task and execution timing, you have to choose Foreground Service.
Pros: your app will be considered to be alive, then is more unlikely that the os will kill it to free resources.
Cons: your user will always see the Foreground Notification.
if you need to schedule periodically task, then Work Manager (introduced in Google I/O 18) is the best solution. This component choose the best possible scheduler (Jobscheduler, JobDispatcher, AlarmManager..). Keep in mind that work manager APIs are useful only for the tasks that require guaranteed execution and they are deferrable.
Ref: Android Dev Documentation
The only solution I would suggest is using Firebase Cloud Messages.
Or foreground services.
Using BroadcastReciever we can run backgrouund service continuously, but if it will get killed , destroy automatically re-instance the old service instance
When service stops forcefully it will call onDestroy() method, in this case use one receiver and send one broadcast when ever service destroy and restart service again. in thee following method com.android.app is custom action of reciever class which extends BroadcastReciever
public void onDestroy() {
try {
myTimer.cancel();
timerTask.cancel();
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent("com.android.app");
intent.putExtra("valueone", "tostoreagain");
sendBroadcast(intent);
}
and in onReceive Method
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Service Stoped", "call service again");
context.startService(new Intent(context, ServiceCheckWork.class));
}
In case device is restarted then we have onBootCompleted action for receiver to catch
When you are targeting SdkVersion "O"
In MainActivity.java define getPendingIntent()
private PendingIntent getPendingIntent() {
Intent intent = new Intent(this, YourBroadcastReceiver.class);
intent.setAction(YourBroadcastReceiver.ACTION_PROCESS_UPDATES);
return PendingIntent.getBroadcast(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
here we use PendingIntent with BroadcastReceiver and This BroadcastReceiver has already been defined in AndroidManifest.xml.
Now in YourBroadcastReceiver.java class which contains an onReceive() method:
Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_PROCESS_UPDATES.equals(action)) {
NotificationResult result = NotificationResult.extractResult(intent);
if (result != null) {
List<Notification> notifications = result.getNotification();
NotificationResultHelper notificationResultHelper = new
NotificationResultHelper(
context, notifications);
// Save the notification data to SharedPreferences.
notificationResultHelper.saveResults();
// Show notification with the notification data.
notificationResultHelper.showNotification();
Log.i(TAG,
NotificationResultHelper.getSavedNotificationResult(context));
}
}
}
}
as you say:
I tried using a BroadcastReceiver to start the service when it got
killed but that gave me an error saying that the app was in the
background and couldn't start a service
in Oreo when you are in background and you want to start a service that service must be a foreground service use this code:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
if you use this code in Oreo you have a few seconds in onStartCommand to start foreground otherwise your service considered as not responding and may be force close by user (in Android 8 or above)
There is no need to use BroadcastReceiver to start service after it is closed it is enough to just return START_STICKY or START_REDELIVER_INTENT from onStartCommand of your service to restart service after it is closed
A working hack for this is to simply start a foreground service which is only visible for the fraction of a second and starts your background service. In the background service you'd then periodically start the foreground service.
Before I give an example you should really ask yourself if this is the way to go for you, there might be other solutions to given problems (like using JobIntentService etc.); and keep in mind that this is a hack, it might be patched some time around and I'd generally not use it (I tested it with screen off and battery saving enabled though and it stayed alive the whole time - but this might prevent your device from dozing.. again, this is a dirty hack!)
Example:
public class TemporaryForegroundService extends Service {
public static final int NOTIFICATION_ID = 666;
private static Notification notification;
#Override
public void onCreate() {
super.onCreate();
if(notification == null)
notification = new NotificationCompat.Builder(this, NotificationChannels.importantChannel(this)).
setSmallIcon(R.mipmap.ic_launcher).setContentTitle("The unseen blade").setContentText("If you see me, congrats to you.").build();
startForeground(NOTIFICATION_ID, notification);
startService(new Intent(this, PermanentBackgroundService.class));
stopForeground(true);
stopSelf();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class PermanentBackgroundService extends Service {
private Runnable keepAliveRunnable = new Runnable() {
#Override
public void run() {
keepServiceAlive();
if(handler != null) handler.postDelayed(this, 15*1000);
}
};
private Handler handler;
public void onCreate(){
handler = new Handler();
handler.postDelayed(keepAliveRunnable, 30* 1000);
}
public void onDestroy() {
super.onDestroy();
keepServiceAlive();
}
private void keepServiceAlive() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(PermanentBackgroundService.this, TemporaryForegroundService .class));
} else {
startService(new Intent(PermanentBackgroundService.this, TemporaryForegroundService .class));
}
}
}
I am starting a service from my main Android activity as follows:
final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);
When I close the activity page by swiping it out from the recent apps list, the service stops running and restarts after some time. I can't use persistent services with notifications because of my app requirements. How can I make the service NOT restart or shutdown and just keep on running on app exit?
I'm in the same situation, so far I learned when the app is closed the service get closed also because they are in a one thread, so the service should be on another thread in order fot it not to be closed, look into that and look into keeping the service alive with alarm manager here an example http://www.vogella.com/articles/AndroidServices/article.html this way your service won't be shown in notification.
lastly, after all the research I've done I'm coming to realize that the best choice for a long running service is startForeground(), because it is made for that and the system actually deals with your service well.
make you service like this in your Mainifest
<service
android:name=".sys.service.youservice"
android:exported="true"
android:process=":ServiceProcess" />
then your service will run on other process named ServiceProcess
if you want make your service never die :
onStartCommand() return START_STICKY
onDestroy() -> startself
create a Deamon service
jin -> create a Native Deamon process, you can find some open-source projects on github
startForeground() , there is a way to startForeground without Notification ,google it
Services are quite complicated sometimes.
When you start a service from an activity (or your process), the service is essentially on the same process.
quoting from the developer notes
Most confusion about the Service class actually revolves around what it is not:
A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
So, what this means is, if the user swipes the app away from the recent tasks it will delete your process(this includes all your activities etc).
Now, lets take three scenarios.
First where the service does not have a foreground notification.
In this case your process is killed along with your service.
Second where the service has a foreground notification
In this case the service is not killed and neither is the process
Third scenario
If the service does not have a foreground notification, it can still keep running if the app is closed. We can do this by making the service run in a different process.
(However, I've heard some people say that it may not work. left to you to try it out yourself)
you can create a service in a separate process by including the below attribute
in your manifest.
android:process=":yourService"
or
android:process="yourService" process name must begin with lower case.
quoting from developer notes
If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.
this is what I have gathered, if anyone is an expert, please do correct me if I'm wrong :)
This may help you. I may be mistaken but it seems to me that this is related with returning START_STICKY in your onStartCommand() method. You can avoid the service from being called again by returning START_NOT_STICKY instead.
The Main problem is in unable to start the service when app closed, android OS(In Some OS) will kill the service for Resource Optimization, If you are not able to restart the service then call a alarm manger to start the receiver like this,Here is the entire code, This code will keep alive ur service.
Manifest is,
<service
android:name=".BackgroundService"
android:description="#string/app_name"
android:enabled="true"
android:label="Notification" />
<receiver android:name="AlarmReceiver">
<intent-filter>
<action android:name="REFRESH_THIS" />
</intent-filter>
</receiver>
IN Main Activty start alarm manger in this way,
String alarm = Context.ALARM_SERVICE;
AlarmManager am = (AlarmManager) getSystemService(alarm);
Intent intent = new Intent("REFRESH_THIS");
PendingIntent pi = PendingIntent.getBroadcast(this, 123456789, intent, 0);
int type = AlarmManager.RTC_WAKEUP;
long interval = 1000 * 50;
am.setInexactRepeating(type, System.currentTimeMillis(), interval, pi);
this will call reciver and reciver is,
public class AlarmReceiver extends BroadcastReceiver {
Context context;
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
System.out.println("Alarma Reciver Called");
if (isMyServiceRunning(this.context, BackgroundService.class)) {
System.out.println("alredy running no need to start again");
} else {
Intent background = new Intent(context, BackgroundService.class);
context.startService(background);
}
}
public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
if (services != null) {
for (int i = 0; i < services.size(); i++) {
if ((serviceClass.getName()).equals(services.get(i).service.getClassName()) && services.get(i).pid != 0) {
return true;
}
}
}
return false;
}
}
And this Alaram reciver calls once when android app is opened and when app is closed.SO the service is like this,
public class BackgroundService extends Service {
private String LOG_TAG = null;
#Override
public void onCreate() {
super.onCreate();
LOG_TAG = "app_name";
Log.i(LOG_TAG, "service created");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(LOG_TAG, "In onStartCommand");
//ur actual code
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// Wont be called as service is not bound
Log.i(LOG_TAG, "In onBind");
return null;
}
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.i(LOG_TAG, "In onTaskRemoved");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "In onDestroyed");
}
}
From Android O, you cant use the services for the long running background operations due to this, https://developer.android.com/about/versions/oreo/background . Jobservice will be the better option with Jobscheduler implementation.
try this, it will keep the service running in the background.
BackServices.class
public class BackServices extends Service{
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
in your MainActivity onCreate drop this line of code
startService(new Intent(getBaseContext(), BackServices.class));
Now the service will stay running in background.
Using the same process for the service and the activity and START_STICKY or START_REDELIVER_INTENT in the service is the only way to be able to restart the service when the application restarts, which happens when the user closes the application for example, but also when the system decides to close it for optimisations reasons. You CAN NOT have a service that will run permanently without any interruption. This is by design, smartphones are not made to run continuous processes for long period of time. This is due to the fact that battery life is the highest priority. You need to design your service so it handles being stopped at any point.
You must add this code in your Service class so that it handles the case when your process is being killed
#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);
}
Why not use an IntentService?
IntentService opens a new Thread apart from the main Thread and works there, that way closing the app wont effect it
Be advised that IntentService runs the onHandleIntent() and when its done the service closes, see if it fits your needs.
http://developer.android.com/reference/android/app/IntentService.html
Best solution is to use the sync Adapter in android to start the service. Create a Sync Adapter and call start service their.. inside onPerformSync method. to create sync Account please refer this link https://developer.android.com/training/sync-adapters/index.html
Why SyncAdapter? Ans: Because earlier you used to start the service using your App context. so whenever your app process get killed (When u remove it from task manager or OS kill it because of lack of resources ) at that time your service will also be removed. SyncAdapter will not work in application thread.. so if u call inside it.. service will no longer be removed.. unless u write code to remove it.
<service android:name=".Service2"
android:process="#string/app_name"
android:exported="true"
android:isolatedProcess="true"
/>
Declare this in your manifest. Give a custom name to your process and make that process isolated and exported .
Running an intent service will be easier. Service in creating a thread in the application but it's still in the application.
Just override onDestroy method in your first visible activity like after splash you have home page and while redirecting from splash to home page you have already finish splash. so put on destroy in home page. and stop service in that method.
I have two Application A and B.In app B I have a service that I can run it from app A. I want to send data to app B with intent but always my intent is null!
I run app B's service from app A with this Code:
try {
String packageName = "app_B_package";
String appService = packageName + ".activity.InternetService";
Intent start = new Intent();
start.setComponent(new ComponentName(packageName, appService));
start.putExtra("LAUNCHER_COMMAND_CLOSE" , true);
G.context.startService(start);
} catch (Exception e) {
e.printStackTrace();
}
But when service of app B will run the intent is null. This is onStart of the service in app B:
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i("LOGO_OFFICE_IN", "onStart");
if (intent != null) {
if (intent.getExtras().getBoolean("LAUNCHER_COMMAND_CLOSE")) {
Tools.clearApplicationData(InternetService.this);
new AppStatus(InternetService.this).isAppRunning(getPackageName(), true);
}
}
}
Why my intent is null all the time? I can't find it out.
Thank you for your help.
It looks like your service is type fire-and-forget - it does one quick thing and should quit immediately because it's done. Correct?
1. Don't leave your idle service running
Documentation says
If a component starts the service by calling startService() (which results in a call to onStartCommand()), the service continues to run until it stops itself with stopSelf() or another component stops it by calling stopService().
so after your workload is done call stopSelf().
When your service is not running there's nothing to restart.
2. Use correct start mode
Unless you stop it, your service is by default automatically restarted after it's killed by system (because system needed resources). The default mode is called START_STICKY and does this:
This mode makes sense for things that will be explicitly started and stopped to run for arbitrary periods of time, such as a service performing background music playback.
Since your service is a quick one-time job, it makes no sense for it do be restarted later at an arbitrary time.
To let Android know, you should return START_NOT_STICKY from onStartCommand.
3. Use current API
Don't use onStart, it was deprecated 9 years ago. It doesn't support start modes mentioned above. Implement onStartCommand instead. Your service would look like this:
#Override
public void onStartCommand(Intent intent, int flags, int startId) {
// No super call.
Log.i("LOGO_OFFICE_IN", "onStart");
// Intent cannot be null.
if (intent.getExtras().getBoolean("LAUNCHER_COMMAND_CLOSE")) {
Tools.clearApplicationData(InternetService.this);
new AppStatus(InternetService.this).isAppRunning(getPackageName(), true);
}
stopSelf(); // Work is done, stop service.
return START_NOT_STICKY; // Don't restart if killed.
}
Now that I think of it, only step 1 is absolutely necessary. Anyway, get into habit of using current APIs and finding out how things work.
How to execute some code on application exit? I want to delete temp data on application exit. By application exit i mean that app is not running minimized in background and its totally gone.
I tried to make service that runs in separate process, the service is checking if app process is not running it should delete temp folder. With this approach temp folder is not always deleted because process is still running with the lowest priority.
I can't do this in OnDestroy().
Service code:
[Service(Process = "com.lobomonitor")]
[IntentFilter(new string[] { "com.androidgui.ProcessMonitorService" })]
public class ProcessMonitorService : Service
{
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Thread processThread = new Thread(() =>
{
ActivityManager actManager = (ActivityManager) this.GetSystemService(ActivityService);
while (true)
{
Thread.Sleep(1000);
IList<ActivityManager.RunningAppProcessInfo> procList = actManager.RunningAppProcesses;
procList.Any(i => i.ProcessName.Equals("com.androidgui"));
if (!procList.Any(i => i.ProcessName.Equals("com.androidgui")))
{
FolderManager.Singleton.DeleteTempFolder();
break;
}
}
});
processThread.Start();
return StartCommandResult.RedeliverIntent;
}
public override IBinder OnBind(Intent intent)
{
return null;
}
}
I don't know if that help, but if you kill your app, then service that runs in background calls method:
#Override
public void onTaskRemoved(Intent rootIntent){
super.onTaskRemoved(rootIntent);
}
For example I had once app that was running service. When I killed app - service died too, but I wanted it to stay alive. By using onTaskRemoved I was able to schedule restart of service:
#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);
}
Effect was -> I am killing my app -> Service see that tasks are being removed and calls onTaskRemoved -> I am scheduling restart of service in 1 sec -> Service dies -> After one sec it wakes up -> RESULT: App is killed, i executed code that restarted my service so it is still running in background (visible only in preferences -> applications as process)
http://developer.android.com/reference/android/app/Service.html
void onTaskRemoved(Intent rootIntent)
This is called if the service is currently running and the user has removed a task that comes from the service's application.
My experience shows that most apps do not really need an exit-callback of the sort
you are describing.
The Android way, which usually works fine, is of component-level (Activity, Service..)
lifecycle management.
Some apps allow for an 'Exit' functionality (via button, menu etc.) that, when activated
by the user, allows the app to close all open components and basically go down.
But, if exit-callback is really what you want, the closest thing to it would probably
be to create a dedicated service with no logic other than onDestroy() function
and to activate it at app startup without ever closing it!
class ExitListenerService extends Service {
#Override
public void onDestroy() {
super.onDestroy();
// App exit logic here. Not deterministic!
}
}
The odds are such a service will probably be the last component to be reclaimed by the
operating system. This should work in most cases, it worked fine for me. But it is not
100% guaranteed.
But.. if you must have a bullet proof solution the only other way I know is to create a peer application, call it watchdog, that will periodically wake up to check weather or not your main app
is still running and, if not running, will activate the exit logic.
To run this last check you will need to call
List<RunningAppProcessInfo> runningApps = activityManager.getRunningAppProcesses();
and iterate over runningApps looking for your own.
I am starting a service from my main Android activity as follows:
final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);
When I close the activity page by swiping it out from the recent apps list, the service stops running and restarts after some time. I can't use persistent services with notifications because of my app requirements. How can I make the service NOT restart or shutdown and just keep on running on app exit?
I'm in the same situation, so far I learned when the app is closed the service get closed also because they are in a one thread, so the service should be on another thread in order fot it not to be closed, look into that and look into keeping the service alive with alarm manager here an example http://www.vogella.com/articles/AndroidServices/article.html this way your service won't be shown in notification.
lastly, after all the research I've done I'm coming to realize that the best choice for a long running service is startForeground(), because it is made for that and the system actually deals with your service well.
make you service like this in your Mainifest
<service
android:name=".sys.service.youservice"
android:exported="true"
android:process=":ServiceProcess" />
then your service will run on other process named ServiceProcess
if you want make your service never die :
onStartCommand() return START_STICKY
onDestroy() -> startself
create a Deamon service
jin -> create a Native Deamon process, you can find some open-source projects on github
startForeground() , there is a way to startForeground without Notification ,google it
Services are quite complicated sometimes.
When you start a service from an activity (or your process), the service is essentially on the same process.
quoting from the developer notes
Most confusion about the Service class actually revolves around what it is not:
A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
So, what this means is, if the user swipes the app away from the recent tasks it will delete your process(this includes all your activities etc).
Now, lets take three scenarios.
First where the service does not have a foreground notification.
In this case your process is killed along with your service.
Second where the service has a foreground notification
In this case the service is not killed and neither is the process
Third scenario
If the service does not have a foreground notification, it can still keep running if the app is closed. We can do this by making the service run in a different process.
(However, I've heard some people say that it may not work. left to you to try it out yourself)
you can create a service in a separate process by including the below attribute
in your manifest.
android:process=":yourService"
or
android:process="yourService" process name must begin with lower case.
quoting from developer notes
If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.
this is what I have gathered, if anyone is an expert, please do correct me if I'm wrong :)
This may help you. I may be mistaken but it seems to me that this is related with returning START_STICKY in your onStartCommand() method. You can avoid the service from being called again by returning START_NOT_STICKY instead.
The Main problem is in unable to start the service when app closed, android OS(In Some OS) will kill the service for Resource Optimization, If you are not able to restart the service then call a alarm manger to start the receiver like this,Here is the entire code, This code will keep alive ur service.
Manifest is,
<service
android:name=".BackgroundService"
android:description="#string/app_name"
android:enabled="true"
android:label="Notification" />
<receiver android:name="AlarmReceiver">
<intent-filter>
<action android:name="REFRESH_THIS" />
</intent-filter>
</receiver>
IN Main Activty start alarm manger in this way,
String alarm = Context.ALARM_SERVICE;
AlarmManager am = (AlarmManager) getSystemService(alarm);
Intent intent = new Intent("REFRESH_THIS");
PendingIntent pi = PendingIntent.getBroadcast(this, 123456789, intent, 0);
int type = AlarmManager.RTC_WAKEUP;
long interval = 1000 * 50;
am.setInexactRepeating(type, System.currentTimeMillis(), interval, pi);
this will call reciver and reciver is,
public class AlarmReceiver extends BroadcastReceiver {
Context context;
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
System.out.println("Alarma Reciver Called");
if (isMyServiceRunning(this.context, BackgroundService.class)) {
System.out.println("alredy running no need to start again");
} else {
Intent background = new Intent(context, BackgroundService.class);
context.startService(background);
}
}
public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
if (services != null) {
for (int i = 0; i < services.size(); i++) {
if ((serviceClass.getName()).equals(services.get(i).service.getClassName()) && services.get(i).pid != 0) {
return true;
}
}
}
return false;
}
}
And this Alaram reciver calls once when android app is opened and when app is closed.SO the service is like this,
public class BackgroundService extends Service {
private String LOG_TAG = null;
#Override
public void onCreate() {
super.onCreate();
LOG_TAG = "app_name";
Log.i(LOG_TAG, "service created");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(LOG_TAG, "In onStartCommand");
//ur actual code
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// Wont be called as service is not bound
Log.i(LOG_TAG, "In onBind");
return null;
}
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.i(LOG_TAG, "In onTaskRemoved");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "In onDestroyed");
}
}
From Android O, you cant use the services for the long running background operations due to this, https://developer.android.com/about/versions/oreo/background . Jobservice will be the better option with Jobscheduler implementation.
try this, it will keep the service running in the background.
BackServices.class
public class BackServices extends Service{
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
in your MainActivity onCreate drop this line of code
startService(new Intent(getBaseContext(), BackServices.class));
Now the service will stay running in background.
Using the same process for the service and the activity and START_STICKY or START_REDELIVER_INTENT in the service is the only way to be able to restart the service when the application restarts, which happens when the user closes the application for example, but also when the system decides to close it for optimisations reasons. You CAN NOT have a service that will run permanently without any interruption. This is by design, smartphones are not made to run continuous processes for long period of time. This is due to the fact that battery life is the highest priority. You need to design your service so it handles being stopped at any point.
You must add this code in your Service class so that it handles the case when your process is being killed
#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);
}
Why not use an IntentService?
IntentService opens a new Thread apart from the main Thread and works there, that way closing the app wont effect it
Be advised that IntentService runs the onHandleIntent() and when its done the service closes, see if it fits your needs.
http://developer.android.com/reference/android/app/IntentService.html
Best solution is to use the sync Adapter in android to start the service. Create a Sync Adapter and call start service their.. inside onPerformSync method. to create sync Account please refer this link https://developer.android.com/training/sync-adapters/index.html
Why SyncAdapter? Ans: Because earlier you used to start the service using your App context. so whenever your app process get killed (When u remove it from task manager or OS kill it because of lack of resources ) at that time your service will also be removed. SyncAdapter will not work in application thread.. so if u call inside it.. service will no longer be removed.. unless u write code to remove it.
<service android:name=".Service2"
android:process="#string/app_name"
android:exported="true"
android:isolatedProcess="true"
/>
Declare this in your manifest. Give a custom name to your process and make that process isolated and exported .
Running an intent service will be easier. Service in creating a thread in the application but it's still in the application.
Just override onDestroy method in your first visible activity like after splash you have home page and while redirecting from splash to home page you have already finish splash. so put on destroy in home page. and stop service in that method.