I've this IntentService:
public class ServiceUpdateNewResults extends IntentService{
private void setAlarmToCheckUpdates() {
Calendar calendar = Calendar.getInstance();
//calendar.add(Calendar.DAY_OF_YEAR, 1); //dema
//calendar.set(Calendar.HOUR_OF_DAY, 22); //a les 10
calendar.add(Calendar.SECOND, 20);
Intent myIntent = new Intent(this.getApplicationContext(), ReceiverCheckUpdates.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, myIntent,0);
AlarmManager alarmManager = (AlarmManager)this.getApplicationContext().getSystemService(this.getApplicationContext().ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
}
public ServiceUpdateNewResults() {
super("ServiceUpdateNewResults");
}
#Override
protected void onHandleIntent(Intent intent) {
//fem les coses.
//Toast.makeText(this.getApplicationContext(), "holaa", Toast.LENGTH_LONG).show();
setAlarmToCheckUpdates();
Log.d("debugging","hello");
}
}
And this is calling a BroadCastReceiver every 20 seconds, which ends up calling this service, and this is going to happen "forever". (in a future it will be 1 day, not 20 seconds).
This is the Receiver:
public class ReceiverCheckUpdates extends BroadcastReceiver{
Context context;
#Override
public void onReceive(Context context, Intent intent){
this.context = context;
Intent service1 = new Intent(context, ServiceUpdateNewResults.class);
context.startService(service1);
}
}
This is working perfectly, but if I stop the app from Android settings, the service is also stopped. I want to avoid this. I want that if the App is closed, the service should keep working.
Is it possible?
Actually, when is a service killed ?
if I stop the app from Android settings, the service is also stopped
If by "stop the app from Android settings", you mean that you press the Force Stop button, your app will not run again until something manually runs one of your components (e.g., user launches your activity). More specifically in this case, your alarms are unscheduled.
I want to avoid this.
Then do not press the "Force Stop" button.
I want that if the App is closed, the service should keep working.
In any non-"Force Stop" scenario, the alarms will keep firing (at least until the device falls asleep, given your current implementation).
The IntentService is part of your app. If the system destroys your app, it will destroy the IntentService. You can reduce the chances of this happening by putting the IntentService in a separate process, but you can't stop the system from destroying an IntentService. You can make it highly unlikely that the system will destroy a Service; to do that, you use a "foreground" Service. However, you should avoid doing this unless you really really need to. In addition, you can't have a foreground IntentService, so you'll have to add your own background Handler and HandlerThread.
Related
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'm developing an app that need to do some check in the server every certain amount of time. The check consist in verify if there are some notification to display. To reach that goal I implemented Service, Alarm Manager and Broadcast Reciever. This is the code that I'm using so far:
public class MainActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
setRecurringAlarm(this);
}
/**
*
* #param context
*/
private void setRecurringAlarm(Context context) {
Calendar updateTime = Calendar.getInstance();
Intent downloader = new Intent(context, MyStartServiceReceiver.class);
downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, downloader, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 60000, pendingIntent);
}
...
}
Receiver class
public class MyStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent dailyUpdater = new Intent(context, MyService.class);
context.startService(dailyUpdater);
Log.e("AlarmReceiver", "Called context.startService from AlarmReceiver.onReceive");
}
}
Service class
public class MyService extends IntentService {
public MyService() {
super("MyServiceName");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.e("MyService", "Service running!");
// TODO Do the hard work here
this.sendNotification(this);
}
private void sendNotification(Context context) {
// TODO Manage notifications here
}
}
Manifest.xml
<!--SERVICE AND BROADCAST RECEIVER-->
<service
android:name=".MyService"
android:exported="false"/>
<receiver
android:name=".MyStartServiceReceiver"
android:process=":remote"/>
The code works fine, the task in the service will be excecuted periodically. The problem is that the service is destroyed when the app is forced to close. I need to keep alive the service, capable to execute the task, even if the user has closed the app, so the user can be updated via notifications. Thank you for your time!
You can't. If the app is forced closed, that means either its crashed (in which case the service has to be stopped as it may no longer work correctly) or the user force closed it in which case the user wants the app to stop- which means the user doesn't want the service to run. Allowing a service to be automatically restarted even if the user stops it would be basically writing malware into the OS.
In fact, Android went the exact opposite (and correct) way- if the user force stops an app, NOTHING of the app can run until the user runs it again by hand.
You may go through this. I hope this will solve your problem. If you want to keep awake your service it is practically not possible to restart the app which is forced close. So if you disable force stop your problem may be solved.
I want to start an IntentService if the battery level reaches a certain value while charging.
However, I dont want to register a BroadcastReceiver for android.intent.action.BATTERY_CHANGED in the AndroidManifest.xml because i need the service only started at a certain level (e.g. 40%) and only while charging.
Another idea would be starting a service that runs as long as the phone is charged and register a receiver programmatically.
A third idea would be to periodically start a service with AlarmManager and check battery level.
What is the best way?
Solution:
I have implemented the fourth idea from answer below.
final int PI_REQUEST_CODE = 123456;
int pref_BatteryUpdatePeriod = 120000; // 2 minutes
// set repeating alarm manager
Intent monitorIntent = new Intent(this, CheckBatteryReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), PI_REQUEST_CODE, monitorIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().get(Calendar.MILLISECOND), pref_BatteryUpdatePeriod, pendingIntent);
and the broadcast receiver for the alarm:
public class CheckBatteryReceiver extends BroadcastReceiver {
private int targetBatterylevel = 40;
#Override
public void onReceive(Context context, Intent intent) {
// get sticky intent
Intent batteryStatusIntent = context.getApplicationContext()
.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int batteryLevel = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 50);
// evaluate battery level
if(batteryLevel >= targetBatterylevel){
// start service to stop charging
} else {
// continue charging
}
}
}
Note: I had to use context.getApplicationContext() instead of context otherwise the app would crash with an exception that I can't register a receiver within a broadcastreceiver
I dont want to register a BroadcastReceiver for android.intent.action.BATTERY_CHANGED in the AndroidManifest.xml because i need the service only started at a certain level (e.g. 40%) and only while charging.
That does not work anyway, as you cannot register for that broadcast in the manifest.
Another idea would be starting a service that runs as long as the phone is charged and register a receiver programmatically.
Yuck.
A third idea would be to periodically start a service with AlarmManager and check battery level.
A fourth idea is to use AlarmManager, as you suggest, but bypass the service at the outset. Just have AlarmManager invoke a BroadcastReceiver. It can check the battery level by calling context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)) (on the context passed into onReceive()). The Intent returned by registerReceiver() will be the last broadcast of ACTION_BATTERY_CHANGED. If the battery level is at or below your desired threshold, then start your IntentService. You may need to adopt the WakefulBroadcastReceiver or WakefulIntentService pattern if your alarm will wake up the device. Also allow the user to choose the polling period, so they can trade off precision for better device performance.
I would go with the fourth idea.
It doesn't sound too bad to have a service running, reacting to android.intent.action.BATTERY_CHANGED as long as it doesn't do anything when you don't need it to. That is, have a check for the interesting battery level and charging state early and just exit if you have nothing to do.
If you want to complicate things, register a mini service which only has the task of starting your main service when conditions are right. However, I don't see what benefit that would have.
public class Main extends Activity {
private TextView batteryTxt;
private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context ctxt, Intent intent) {
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
batteryTxt.setText(String.valueOf(level) + "%");
}
};
#Override
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.main);
contentTxt = (TextView) this.findViewById(R.id.batteryTxt);
this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
}
I am starting a service (or re-starting the running service) when an activity is launched, using :
Intent intent = new Intent(this, MyService.class);
startService(intent);
Later on based on certain actions, the same activity binds to the service using
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
And when the activity is destroyed, I call
unbindService(mConnection);
Earlier, the service used to restart when I killed the same activity/application from the application tray and showed the "message 1 process 1 service running" under running apps.
Now, the service does not restart on killing the same activity/application.
And I get the message "0 process 1 service running", which means the service is actually not running.
The service does not restart on application being closed. My application consists of one activity. Also the service is successfully started when launched after a system boot.
Why does the process of the service gets killed when I start it using startService() ??
edit
The service used to re-start earlier after i closed the app from the application tray. But now suddenly with the SAME code, it doesn't. It happens with other apps too when i close them. eg.
Here is a workaround I came across and works well for re-starting a service if its process is killed on closing the application. In your service, add the following code.
I came across this workaround in this thread.
#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);
}
Seems to be a bug that the process of the application is killed. There is no point for a service to run if its process is killed.
Please be aware of that: onDestroy is not always called. You should not put code that way.
When activity forced closed or closed by system abnormally, onDestroy is not getting called.
Unfortunately, this is a complicated problem due to the way Android works. There are a number of strategies that each work around different parts of the problem. For best results, combine multiple strategies together.
Note that some of these strategies may no longer be necessary in more recent Android versions.
1. Start an activity
What to do
Taken from Foreground service killed when receiving broadcast after acitivty swiped away in task list:
In the foreground service:
#Override
public void onTaskRemoved( Intent rootIntent ) {
Intent intent = new Intent( this, DummyActivity.class );
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
startActivity( intent );
}
In the manifest:
<activity
android:name=".DummyActivity"
android:theme="#android:style/Theme.NoDisplay"
android:enabled="true"
android:allowTaskReparenting="true"
android:noHistory="true"
android:excludeFromRecents="true"
android:alwaysRetainTaskState="false"
android:stateNotNeeded="true"
android:clearTaskOnLaunch="true"
android:finishOnTaskLaunch="true"
/>
(If your service is in a different process then set this activity's process to the same one.)
In DummyActivity.java:
public class DummyActivity extends Activity {
#Override
public void onCreate( Bundle icicle ) {
super.onCreate( icicle );
finish();
}
}
Side effects
Causes the recents activity to close. Normally, swiping away an app doesn't close the recents activity.
Disadvantages
This only takes effect when the dummy activity starts, which may take half a second or more, so this still leaves the service open to being killed for a bit.
Explanation
When you remove/swipe your app away, a flag called waitingToKill is set. While this flag is set, Android may kill the process at any point in the future, such as when you receive a broadcast. Starting an activity clears this flag.
2. Spam a BroadcastReceiver with foreground broadcasts
What to do
Merge this into your service code:
if (Build.VERSION.SDK_INT >= 16) {
Intent intent = new Intent(this, DummyReceiver.class);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//This seems to be timing-related; the more times we do this,
//the less likely the process gets killed
for (int i = 0; i < 50; ++i)
sendBroadcast(intent);
}
Create a dummy broadcast receiver:
public class DummyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {}
}
Add the receiver to your manifest:
<receiver android:name=".DummyReceiver" />
Side effects
May cause a slight (~250ms) delay/hang when the task is removed from the recents screen.
Disadvantages
This only keeps the process alive while it is receiving the broadcasts. the waitingToKill flag is still set, so the process may still be killed afterwards, such as when a broadcast is received.
Explanation
If your process isn't running in foreground priority, Android will try to kill it immediately. Receiving foreground broadcasts temporarily prevents this, resulting in the waitingToKill flag being set instead.
3. Don't bind to services
Binding to a service seems to increase the likelihood of the service's process being killed immediately when a task is removed.
I know this question is old but I recently encountered this problem and suddenly my service get stopped on closing app. Earlier it was working fine. This problem wasted my lot of time. To others who have similar problem make sure that YOUR BACKGROUND DATA RESTRICTION IS OFF.
This was the problem I had and it actually makes sense as when background data is Restricted background process won't run.
onDestroy is not always called. The Main problem in your case is ur unable to start the service when app closed,that time android OS(In Some OS) will kill the service, If you are not able to restart the service then call a alarm manger to start the reciver like this,
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");
}
}
when there is no binding to a service or well established foreground then android system recognize the service as unused overloading service that should be shut down. Here is the best way to maintain your service even if the app is closed: AlarmManager or Service
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.