I am implementing an app kind of an app tracker which requires to run the service all the time in background. So the service is called when application is opened and it stops when stopself() is called. Service also consists of a thread which runs all the time. It used to run perfect. But from last few days it stops after sometime. When coming to my app's ui after some task the service stops!
Can anyone suggest me any solution?
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("SERVICE","started");
if(intent != null && intent.getAction() != null)
{
day=intent.getExtras().getInt("day")+5;
Toast.makeText(this, "day" +day, Toast.LENGTH_LONG).show();
apps=intent.getStringArrayListExtra("apps");
items=apps.size();
timer=intent.getIntegerArrayListExtra("timer");
Run[] a=new Run[items];
t=new Thread[items];
for(int i=0;i<items;i++)
{
int sec=0;
app=apps.get(i).toString();
time=timer.get(i);
a[i]=new Run(app, time,sec);
Log.e("APPTIME",app+ " "+time);
t[i]=new Thread(a[i]);
t[i].start();
}
}
return super.onStartCommand(intent, flags, startId);
}
You should start your service as STICKY_SERVICE
Example for starting as STICKY
Thread for START_STICKY and START_NOT_STICKY
You should consider reading this, if you are working on Android KitKat
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);
Related
I have made a simple example where a toast message will be shown after a time gap. I am using alarmmanager for scheduling a service from where the toast message will be shown. Now the problem is when the app is running it works properly, but when I close the app from task-manager the service is not getting restarted. Below is my service code
public class AlarmService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Alarm Alarm Alarm", Toast.LENGTH_SHORT).show();
return Service.START_STICKY;
}
}
and below is my alarmmanager code :
alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmService.class);
pendingIntent = PendingIntent.getService(this, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 10, pendingIntent);
Now, what is the solution for this? I need to keep the alarm even I close the app.
You can actually implement BroadcastReceiver at onDestroy to restart the service once the app/service is close by the system/user.
You can check the post here, and a tutorial for you, check here.
Hope it helps!
Try with below :-
return Service.START_CONTINUATION_MASK;
I'm beginner android programmer. While experimenting with background Services and background data download I came across this particular problem:
I'm using an AlarmManager to schedule repeating background data download.
public void setBackgroundDataService(Context context, long time_in_millis) {
Intent background_service_intent = new Intent(context, BackgroundDataService.class);
background_service_intent.putExtra("value", val);
PendingIntent pending_intent = PendingIntent.getService(context, BACKGROUND_DATA_SERVICE_ID , background_service_intent, PendingIntent.FLAG_UPDATE_CURRENT);
cancelBackgroundServiceAlarmIfExists(context, background_service_intent);
AlarmManager alarm_manager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarm_manager.setRepeating(AlarmManager.RTC, (System.currentTimeMillis() + time_in_millis), time_in_millis, pending_intent);
}
public static void cancelBackgroundServiceAlarmIfExists(Context context, Intent intent) {
// try to cancel Pending Intent if exists
try {
PendingIntent pending_intent = PendingIntent.getService(context, BACKGROUND_DATA_SERVICE_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm_manager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarm_manager.cancel(pending_intent);
Log.d("DEBUG", "Background service terminated");
} catch (Exception e) {
e.printStackTrace();
}
}
Here is onStartCommand() from Service:
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("DEBUG", "Background service invoked");
if (intent == null)
return super.onStartCommand(intent, flags, startId);
Bundle extras = intent.getExtras();
some_value = extras.getString("value");
startDataDownload();
return super.onStartCommand(intent, flags, startId);
}
Data download is performed in AsyncTask
So the problem is:
Why after swiping the app from applications tray Service gets restarted and intent passed in arguments is null. Proper working of the Service relies on extras passed in the intent. At first my application would just crash (usually 2 times, I assume that something was trying to restart it, but crashed while trying to get extras from null intent). After some time Service would start properly and do its job without crashing (probably AlarmManager restarted it with proper intent extras after specified time). Then sporadically it would crash again. I managed to avoid crashes by checking whether intent is null or not. It seems to work. But the question remains.
Why is my Service getting restarted and null intent gets passed to it right after I swipe my app from application tray. Is there anything thet can be done about it? Is there a better way to download data periodically?
In onStartCommand() you are returning START_STICKY because of this:
return super.onStartCommand(intent, flags, startId);
START_STICKY tells Android that it should restart your Service if the Service is killed (for whatever reason). When you swipe your app from the list of recent tasks, Android kills the OS process hosting your app and then, because your Service returned START_STICKY, Android restarts your Service.
After restarting your Service, Android calls onStartCommand() with a null Intent parameter.
It looks like you are also not stopping your Service after the data download completes.
If you only want your Service to be restarted if it is killed while it is working on something, return START_REDELIVER_INTENT from onStartCommand().
The documentation for Service explains this:
For started services, there are two additional major modes of
operation they can decide to run in, depending on the value they
return from onStartCommand(): START_STICKY is used for services that
are explicitly started and stopped as needed, while START_NOT_STICKY
or START_REDELIVER_INTENT are used for services that should only
remain running while processing any commands sent to them.
I've faced this kind of problem recently. So what I did is make my service looks like a foreground task and that'll solve your problem. And to do that the best approach I can think of is using a notification. Here is the required documentation. And here is a sample code for the notification -
private void showNotification() {
String notificationTitle = "Notification Title";
String notificationContent = "Notification Content";
Intent notificationIntent = new Intent(getApplicationContext(), DashboardActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(context, channelId)
.setTicker(AppConstants.App_Name)
.setSmallIcon(R.drawable.logo)
.setContentTitle(notificationTitle)
.setColor(getApplicationContext().getResources().getColor(R.color.colorWhite))
.setStyle(new NotificationCompat.BigTextStyle().bigText(notificationContent))
.setAutoCancel(false)
.setOngoing(true)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
}
If you like to stop this process just call void stopForeground (int flags) where ever you like. It won't kill your service but your process will no longer be a foreground task.
I want to keep running one service which reads incoming messages even after app is closed [clicking on recent apps button and then close it]. I have tried using START_STICKY, isolated process but nothing is working. Is it possible in latest android versions ?
Try startForeground(notitficationId, notificationObject); command in onStartCommand()
Making a sticky service, will ensure you restarting after app is closed, but you need to call your methods in onStartComand().
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// do your job here
// start reading your incoming messages
readMessages();
return START_STICKY;
}
private void startForground(){
Intent notificationIntent = new Intent(this,MainActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(this, 0,
notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
Notification notification=new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText("App Name")
.setContentIntent(pendingIntent)
.build();
startForeground(NOTIFICATION_ID, notification);
}
If you don't want to show notification or icon but still want to run in background try this answer
try
public int onStartCommand(Intent intent, int flags, int startId)
{
..........
return super.onStartCommand(intent, flags, startId);
}
but when you close the application onStartCommand restart from the beginning whether it has finished it's job or not!
I've created a service , And I also created a notification so when my service runs there is a notification for it.
Now , I want users to be able to swipe/dismiss the notification but when trying to do so I've encountered two problems:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
password = intent.getStringExtra("password");
number = intent.getStringExtra("number");
Intent activityIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0,
activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(this).
setContentTitle(getText(R.string.app_name)).
setContentText("Subject").
setContentInfo("Doing stuff in the background...").
setSmallIcon(R.drawable.ic).
setAutoCancel(true).
setContentIntent(pendingIntent).build();
startForeground(1, notification);
return super.onStartCommand(intent, flags, startId);
}
This code worked perfectly , the only problem with this code is that users cannot swipe dismiss the notification , So from searching around I found that I can fix it by replacing 'startForeground' function with
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0,notification);
And then it worked, I can swipe dismiss, But now I get a different problem , Once I close my application (using long press on middle button then close all applications)
My app thrrows a nullpointerexception few moments later pointing to the line :
password = intent.getStringExtra("password");
as if the intent is null. This does not happen when I use the startForeground function
What might be the problem ?
Return START_NOT_STICKY in onStartCommand().
There are three options to what should happen once the proccess in which the service is running on crushes:
START_STICKY , START_NOT_STICKY , START_REDELIVER_INTENT.
I wanted to reload the service and keep the intent once it crushes.
START_REDELIVER_INTENT did the trick, it restarts the service and redelivers the intent.
START_STICKY , Almost did the trick , the problem with START_STICKY for me was that it restarts the service but with a null intent.
AutoCancel does not work when service is still on foreground. Try remove service from foreground first:
startForeground(1, notification);
stopForeground(false); //false - do not remove generated notification
I have an Android Service class the code for which is as follows:
public class LoginService extends Service {
BroadcastReceiver wifiStateChangeReciever;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("AndroidLearning", "Service onStartCommand Started.");
return Service.START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
Log.i("AndroidLearning", "Service Started.");
final IntentFilter intentFilter = new IntentFilter();
// intentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
intentFilter.addAction("android.net.wifi.STATE_CHANGE");
wifiStateChangeReciever = new WifiStateChangeReciever();
this.registerReceiver(wifiStateChangeReciever, intentFilter, null, null);
Log.i("AndroidLearning", "Reciever Registered.");
}
#Override
public void onDestroy() {
Log.i("AndroidLearning", "Service Destroyed.");
this.unregisterReceiver(wifiStateChangeReciever);
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.w("AndroidLearning", "On Task Remove: FLAG_STOP_WITH_TASK - "
+ ServiceInfo.FLAG_STOP_WITH_TASK);
this.unregisterReceiver(wifiStateChangeReciever);
Intent restartServiceIntent = new Intent(getApplicationContext(),
this.getClass()); restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(
getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
alarmService.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent);
Log.w("AndroidLearning", "End on task removed");
super.onTaskRemoved(rootIntent);
}
}
It registers a BroadcastReciever. The Activity which starts this service has the following code:
Intent intent = new Intent(this, LoginService.class);
startService(intent);
However whenever the Activity is swiped out from the task list (recent) the service is also stopped. I over rode the onTaskRemoved to remedy it but it still does not seem to work and the AlarmManager never starts the pendingIntent. I have tries using both method: set and setExact for the AlarmManager.
I also tried adding the following options to <service> tags
android:stopWithTask="false"
android:process=":remote"
but to no avail.
What am I doing wrong here? Thanks for the help.
I finally found the answer to my own problem. It seems this was a problem with the particular flavor of android that I was running on my phone (Mi UI). There was a separate setting regarding each application whether it needed to be allowed to be restarted or not.
Unless this setting is configured no amount of changing permissions and setting Alarms helped me.
This is a different approach from you but I recently fixed this by adding a notification when the service was running
private void showNotification(){
NotificationCompat.Builder builer = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.logo)
.setContentTitle("Service active")
.setContentText("Your service keeps running")
.setOngoing(true);
mNotificationManager.notify(NOTIFICATION_ID, builer.build());
}
The notification is shown in onStartCommand and dismissed in the service ondestroy method.
You need to start service in foreground if you don't want android to shut it down.
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);
http://developer.android.com/guide/components/services.html#Foreground
If you try this on some devices, sadly, it won't work.
Some OEMs decided to change the normal behavior of what happens when you remove an app from the recent tasks, so they become semi-disabled:
https://issuetracker.google.com/issues/122098785
https://dontkillmyapp.com/