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/
Related
I am new to android. I have already developed android application which starts service when application starts.
What I have :
Currently when application starts, it creates sticky notification in notification area as shown in screenshot.
Source code for service :
public class InfiniteService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Intent notificationIntent = new Intent();
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getString(R.string.app_name))
.setContentText("Welcome To TestApp")
.setContentIntent(pendingIntent).build();
startForeground(1337, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Log.e("InfiniteService", "Service started");
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
//Log.e("InfiniteService", "onDestroy");
sendBroadcast(new Intent("InfiniteService"));
}
What I want :
I want to get rid of this sticky notification in notification area. Instead I want service that runs in background continuously.
What I have tried :
I tried 'return START_NON_STICKY' in onStartCommand with initial impression that it will remove sticky notification but later learned from here that START_STICKY tells the OS to recreate the service after it has enough memory
I was suspecting PendingIntent is making this but again after reading explanation, come to know that it is not what I am looking for.
Then I searched how to create sticky notification in android hoping to get some clue. After reading this article, got to know flags makes it sticky. I searched "Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT" in my entire code but did not find anything.
What am I missing? Any pointers/help would be great. Thanks.
I want to show notification every minute using Alarm Manager, I have implemented below code, it's working fine but the problem is when I remove app from stack the service is not running.
I want keep alive, I have tried START_STICKY in onStartCommand and also used onTaskRemoved but it's same.
I also tried to implement using WakefulIntentService but the problem is same. My code is below.
In MainActivity
Intent myIntent = new Intent(NotificationDemo.this, MyReceiver.class);
myIntent.putExtra("title", "2 minutes");
Random random = new Random();
int m = random.nextInt(9999 - 1000) + 1000;
Log.d("m::: In Notification", m + "");
myIntent.putExtra("id", m);
pendingIntent = PendingIntent.getBroadcast(NotificationDemo.this, m, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
// alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(),alarmManager.Inte pendingIntent);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
1 * 60 * 1000,
pendingIntent);
MyService
public class MyAlarmService extends Service {
private NotificationManager mManager;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String title = intent.getStringExtra("title");
int id = intent.getIntExtra("id", 0);
mManager = (NotificationManager) this.getApplicationContext().getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(), MainActivity.class);
Notification notification = new Notification(R.mipmap.ic_launcher, title, System.currentTimeMillis());
intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Log.d("id::", id + "");
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this.getApplicationContext(), id, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
// notification.setLatestEventInfo(this.getApplicationContext(), "AlarmManagerDemo", "This is a test message!", pendingNotificationIntent);
NotificationCompat.Builder builder = new NotificationCompat.Builder(MyAlarmService.this);
notification = builder.setContentTitle(title)
.setContentText("Hellooo...")
.setTicker("Good Evening...")
.setSmallIcon(android.R.drawable.ic_btn_speak_now)
.setVibrate(new long[]{1000, 1000, 1000, 100})
.setLights(5, 5, 5)
.setContentIntent(pendingNotificationIntent).build();
mManager.notify(id, notification);
startForeground(1337, notification);
return START_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
// sendBroadcast(new Intent("IWillStartAuto"));
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
// sendBroadcast(new Intent("IWillStartAuto"));
// Intent intent = new Intent(getApplicationContext(),MyReceiver.class);
// sendBroadcast(intent);
}
}
and this is my receiver
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String title = intent.getStringExtra("title");
int id = intent.getIntExtra("id", 0);
Intent service1 = new Intent(context, MyAlarmService.class);
service1.putExtra("title", title);
service1.putExtra("id", id);
context.startService(service1);
}
}
In Manifest
<receiver android:name=".MyReceiver">
<!--<intent-filter>
<action android:name="IWillStartAuto"/>
</intent-filter>-->
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".MyAlarmService"
android:enabled="true"
android:stopWithTask="false" />
You need to start your service in foreground.
You are missing something this in your service OnCreate() method.
startForeground(1337, notification);
return START_STICKY;
And don't stop your service in your activities or fragments onDestroy() methods.
I tested this code on my phone with android 6.0 and on emulator with android 7.0 in both is working fine, even removing the application from the stack. The notification still working even removing the receiver code.
You can try with receiver configuration process=":remote" to keep receiver alive. I faced with this problem and here is my solution.
Did you try the code with any other output statements? Notifications are, off-late, not being fired for me either - I might blame Instant Run, nevertheless could you try replacing the notification-firing code snippet with maybe something like a Toast? Since Toasts don't work in services, maybe you could try creating a file in your external storage directory whenever the service starts to know that maybe it's up and running?
I have the following scheme:
Activity A -which can start Activity B.
Activity B has a background Service it uses which is triggered by an Alarm as follows:
alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
serviceSaveSample = new Intent(getApplicationContext(),
SaveSampleService.class);
alarmSaveSample = PendingIntent.getService(getApplicationContext(),
9988766, serviceSaveSample, PendingIntent.FLAG_UPDATE_CURRENT);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
+ (secondsToSample * 1000), secondsToSample * 1000,
alarmSaveSample);
The service implementation:
public class SaveSampleService extends Service { ...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, RunActivity.class), 0);
Notification notif = new NotificationCompat.Builder(
getApplicationContext()).setAutoCancel(true)
.setContentText("message").setSmallIcon(R.drawable.logo)
.setAutoCancel(true)
.setSmallIcon(R.drawable.logo)
.setContentIntent(contentIntent)
.build();
startForeground(startId, notif);
// some work...
return START_STICKY;
}
the problem is that if i move the app to the background when Activity B is at the top of the stack and the service is running, the service restarts itself after i have closed Activity B explicitly.
i have tried any, if not all flags and still this problem persists.
tried setting the launchMode to any of the values and still not working.
any suggestions?
You need to call the cancel method of AlarmManager, and stopService in your activity onStop.
Check the Services life cycle http://developer.android.com/guide/components/services.html#StartingAService
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);
This is onStartCommand()
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Notification creation code
telMgr = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
telMgr.listen(new PSL(), PhoneStateListener.LISTEN_CALL_STATE);
return super.onStartCommand(intent, flags, startId);
}
and PhoneStateListener class (under service class)
public class PSL extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNum) {
switch(state) {
case TelephonyManager.CALL_STATE_IDLE:
case TelephonyManager.CALL_STATE_OFFHOOK:
//Work1
break;
case TelephonyManager.CALL_STATE_RINGING:
//Work2
break;
}
}
}
both of them are in same .java file
I have these code on one service class.
when I call startService() from main activity, it works well.
but when my app is killed by Task Manager, Killer or automatically by shortage of memory on device, Service does restarts but not working.
when i go to Setting - Application - Running, it shows process 1 and service 1, before/after killed.but after killed, memory share goes 1/10. I have tried startForeground() not to be killed easily with my notification - it didn't work. (doesn't show any notification)
and also tried return of onStartCommand(): START_STICKY, START_REDELIVER_INTENT - shows same result is there any way I can restart completely or make it not killed?
After Spending few Hours I fount that , For Android 2.0 or later you can use the startForeground() method to start your Service in the foreground.
Documentation provided by Android
A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)
Ther are very rare chances of Foreground Service to kill by OS.But It works fine.
public class ServicePhoneState extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Music Player")
.setTicker("Google Music Player")
.setContentText("My Music")
.setSmallIcon(R.drawable.ic_bg_icon)
.setPriority(Notification.PRIORITY_MAX)
.setContentIntent(pendingIntent)
.setOngoing(false)
.build();
startForeground(10, notification);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I solved it by startForeground()
It didn't work because I had not used Notification.FLAG_FOREGROUND_SERVICE on Notification
After Spending few Hours I fount that , For Android 2.0 or later you can use the startForeground() method to start your Service in the foreground.
Documentation provided by Android
A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.) Ther are very rare chances of Foreground Service to kill by OS.But It works fine.
public class ServicePhoneState extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyPhoneStateListener phoneListener = new
MyPhoneStateListener(ServicePhoneState.this);
TelephonyManager telephony = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Music Player")
.setTicker("Google Music Player")
.setContentText("My Music")
.setSmallIcon(R.drawable.ic_bg_icon)
.setPriority(Notification.PRIORITY_MAX)
.setContentIntent(pendingIntent)
.setOngoing(false)
.build();
startForeground(10, notification);
return START_NOT_STICKY;}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
#Override
public IBinder onBind(Intent intent) {
return null;}}