I want to stop service from activity . It stops when i don't close the app . But when i close the app and run the app again service doesn't stop.
Flow :
--> Click Switch ON
--> Show Notification / Location Listener
--> Kill App
--> Notification still remains (Service is running means)
--> Open app again and
--> Click Switch OFF
--> Service doesn't stop and notification persists
Service Class
public class locationService extends Service {
NotificationCompat.Builder builder;
NotificationManager notificationManager;
public static final String serviceTag = "LocationServiceTag";
#Nullable
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences sharedPref = getSharedPreferences("AppPref",Context.MODE_PRIVATE);
userCurrentRoute= sharedPref.getString("RouteNo","");
mDatabase = FirebaseDatabase.getInstance().getReference();
notificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
Intent repeating_intent =new Intent(this,MainActivity.class);
PendingIntent pendingIntent= PendingIntent.getActivity(this,10,repeating_intent,PendingIntent.FLAG_UPDATE_CURRENT);
builder = new NotificationCompat.Builder(this)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.bus_small)
.setContentTitle("BusBuzz")
.setContentText("Sharing Location to all")
.setAutoCancel(false)
.setOnlyAlertOnce(true)
.setOngoing(true)
;
notificationManager.notify(10,builder.build());
provider = new LocationGooglePlayServicesProvider();
provider.setCheckLocationSettings(true);
return START_NOT_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
notificationManager.cancel(10);
Toast.makeText(this, "App Closed Location Sharing Stopped", Toast.LENGTH_SHORT).show();
SmartLocation.with(this).location().stop();
super.onDestroy();
}
}
Activity
if (isChecked) {
startService(new Intent(MainActivity.this,locationService.class).addCategory(locationService.serviceTag));
}
else
{
stopService(new Intent(MainActivity.this,locationService.class).addCategory(locationService.serviceTag));
}
You wrote:
--> Click Switch ON
--> Show Notification / Location Listener
--> Kill App
--> Notification still remains (Service is running means)
Just because the notification exists, does not mean that the Service is still running. Actually, it is dead. You killed the App, which kills the Service, and since you return START_NOT_STICKY from onStartCommand(), Android will not restart the Service until your App makes another explicit call to startService(). Since the App was killed, onDestroy() was never called, so the notification was never removed.
You can verify this by using adb shell dumpsys activity services to see if your Service is running after you kill your App.
Related
I have a Service that downloads a database and displays a notification that contains a progress bar indicating download progress. I want to update that notification when the service stops abruptly like when user kills the app, or app gets killed in the background by the OS. The problem is that the service's onDestroy method never called, so I cannot update the notification and remove its progress bar.
I have tried overriding onTaskRemoved method of the Service and added stopWithTask=true in manifest but that didn't helped. I also overrided onDestroy method of the Activity, and put the code that updates the notification, but that also didn't work.
Here's my service:
public class DatabaseDownloadService extends IntentService {
public static final int DOWNLOAD_NOTIFICATION_ID = 1;
private NotificationManagerCompat mNotificationManager;
private NotificationCompat.Builder mNotificationBuilder;
// For updating the UI on download progress.
private ResultReceiver mResultReceiver;
// If the service is stopped before download process is finished,
// updates the notification.
private boolean mCompleted;
public DatabaseDownloadService() {
super("DatabaseDownloadService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
Log.print(getClass().getName(), "onHandleIntent");
if (intent == null || intent.getAction() == null)
return;
mResultReceiver = intent.getParcelableExtra("receiver");
// Some code that downloads the file...
}
private void shutdown() {
if (!mCompleted) {
mNotificationBuilder.setContentText("Download did not complete.")
.setColor(getResources().getColor(R.color.error_color_red))
.setSmallIcon(R.drawable.ic_stat_pause)
.setOngoing(false)
.setProgress(0, 0, false);
mNotificationManager.notify(DOWNLOAD_NOTIFICATION_ID, mNotificationBuilder.build());
}
}
#Override
public void onCreate() {
Log.print(getClass().getName(), "onCreate");
super.onCreate();
startForeground(DOWNLOAD_NOTIFICATION_ID, mNotificationBuilder.build());
}
#Override
public int onStartCommand(#Nullable Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onDestroy() {
Log.print(getClass().getName(), "onDestroy");
super.onDestroy();
// This is the code that updates the notification but onDestroy never gets called.
shutdown();
}
}
It should update the notification when the app is killed by Android, or the user. But it doesn't.
How can I solve this issue? I have been searching for a solution for days, and didn't find one, so my only hope is StackOverflow.
Description of Truecaller/Whatsapp service
**Note: Here force close means killing the app by pressing and holding back button not just stopping the service from service manager/app manager (see Kill app back button).
After killing the truecaller app when I make a call it restarts automatically, same for whatsapp also, After killing it when a message is received it still shows the notification and restarts the service. These services also restarts after a few delay
What I have done so far to achieve this
I want to make a service like this so called my backgroundservice from onDestroy() of my backgroundservice class. Code for this: ServiceDemo 0.1
public class BackgroundService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(BackgroundService.this, "Service Started...", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
#Override
public void onDestroy() {
Intent intentService = new Intent(this,BackgroundService.class);
startService(intentService);
Toast.makeText(BackgroundService.this, "Service Will Be Restarted...", Toast.LENGTH_SHORT).show();
}
}
The service is restarting if I stop it from my service manager. But if I force close/kill it , it's gone.
After this I implemented Broadcast receiver which doesn't make any difference. Code for this: ServiceDemo 0.2
BackgroundService.java
public class BackgroundService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(BackgroundService.this, "Service Started...", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
#Override
public void onDestroy() {
Toast.makeText(BackgroundService.this, "Service Will Be Restarted...", Toast.LENGTH_SHORT).show();
sendBroadcast(new Intent("RestartMe"));
}
}
RestartBackgroundService.java
public class RestartBackgroundService extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// I have also used AlarmManager , but it doesn't make any difference for me
// AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// PendingIntent pi = PendingIntent.getService(context, 0, new Intent(context, BackgroundService.class), PendingIntent.FLAG_UPDATE_CURRENT);
// int interval = 5000;
// am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + interval, interval, pi);
context.startService(new Intent(context.getApplicationContext(),BackgroundService.class));
}
}
As whatsapp is using gcm so I thought if I implement that it would help.
Then I implemented firebase cloud messaging (fcm) to receive push notification and I removed the code to restart background service from onDestroy().
Now if I stops the service from service manager it remains stopped then I sends a notification from my firebase console it receives the notification as google's gcm service is running. If I click the notification it restarts my service again.
But if I force close/kill my app no notifications are received though gcm service is running. Code for this: (I posted a link to make the description a bit short)
ServiceDemo 0.3
What I want
I want my service to be persistent like whatsapp/truecaller even if I force close it. They keep on starting after a few delays. And I want to achieve it without using third parties like fcm.
If someone can give any hints/solution about how to start my service when a particular system service/app (like dialer) starts that would be a great help.
My Android audio player app sets up a bound service while playing to ensure that it won't be killed by the system. The app uses the system media player. The service creates a notification icon in the system bar.
When I swipe the app from the recent apps list, the app disappers. BUT: the media player keeps on playing and the notification stays in the system bar.
When I select the notification or the app icon, it starts a new instance of the app, the running instance is not reachable. It can only be stopped by selecting force stop in the system settings for apps. If I don't swipe the app from the list, I allways get back to the playing instance.
If only my app could detect when it is swiped from the list, it could stop everything correctly. But onDestroy() isn't guaranteed to be called - and won't e.g. in CM12. onStop() or onPause() is not vadlid for me, because the audio should not stop when the app just is going into background.
So, how is it possible to detect when the app is swiped from the list?
This it the service. Can anything be done here?
public class myService extends Service {
...
#Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
showNotification();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
mNM.cancel(NOTIFICATION);
stopForeground(true);
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
...
private void showNotification() {
Notification notification = new Notification(R.drawable.icon, "Hello", 0);
Intent intent = new Intent(this, myActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendIntent = PendingIntent.getActivity(this, 0, intent, 0);
notification.setLatestEventInfo(this, "AppName", "Hello", pendIntent);
notification.flags |= Notification.FLAG_NO_CLEAR;
startForeground(FOREGROUNDID, notification);
}
}
This is how my service is bound:
private static ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// Not used
}
public void onServiceDisconnected(ComponentName className) {
// Not used
}
};
private static void doBindService() {
context.bindService(
new Intent(context, myService.class),
mConnection, Context.BIND_AUTO_CREATE);
}
Thanks for any help.
The Service has an onTaskRemoved() method which is triggered in this scenario. You can stop the service there:
/**
* This is called if the service is currently running and the user has
* removed a task that comes from the service's application. If you have
* set ServiceInfo#FLAG_STOP_WITH_TASK ServiceInfo.FLAG_STOP_WITH_TASK}
* then you will not receive this callback; instead, the service will simply
* be stopped.
*
* #param rootIntent The original root Intent that was used to launch
* the task that is being removed.
*/
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
stopSelf();
}
And remember to unbind the Service from the Activity in onStop() or onDestroy(). (Whatever is in line with your binding strategy.)
I'm calling a service every three minutes using the following function:
public void RunBackgroundService() {
final Handler service_handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
service_handler.post(new Runnable() {
public void run() {
context.startService(new Intent(context,BackgroundService.class));
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 180 * 1000);
}
And this is my service in which I'm launching a notification:
public class BackgroundService extends Service {
Helper helper;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
//Toast.makeText(this, "Service created!", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
//Toast.makeText(this, "Service stopped", Toast.LENGTH_LONG).show();
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onStart(Intent intent, int startid)
{
helper=new Helper(this);
// Log.d("Service started at:", helper.getdatetime());
Intent n_intent = new Intent(this, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, n_intent, 0);
// build notification
// the addAction re-use the same intent to keep the example short
long[] vibrate = { 0, 100, 200, 300 };
Notification n = new Notification.Builder(this)
.setContentTitle("Application")
.setContentText("This is a test")
.setSmallIcon(R.drawable.notification_icon)
.setContentIntent(pIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setVibrate(vibrate)
.setAutoCancel(true)
.build();
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, n);
}
}
It's very important to me to remain the service running at all time, when the app crashes the service stops. How can I prevent the service from stopping ?
When an app crashes, the entire process goes down with it. This includes all Services and other threads in that process. You can't stop that from happening.
The best you can do is to configure your app to run in a different process from the main app process, but then you have to know how that affects the rest of your app.
Be sure to read the docs for how to define a service to run in another process. You use the android:process attribute for that.
You cna not stop system killing your service. But what you can do is to restart the service when it is crashed. Take a look at detailed sof post How to restart service after the app is killed from recent. This solution works not only when app is killed through recent taks by user but also when system kills app.
Use android:process tag to start process in different process.
Then use it as bind to service from your application, this way you can communicate with service via ipc and service runs indefinitely even if your app crashes.
I am trying to put a notification in the status bar when a service starts and keep it there until I stop the service but is disappears after a few seconds(about 10). Any suggestions as to what I am missing? This worked before I tried to re write using notification.builder for compatibility with api 15. The log entry shows onDestroy is not called until I stop the service so it is still running.
public class MyService extends Service {
private NotificationManager mNM;
private int NOTIFICATION = R.string.service_started;
public void onCreate() {
super.onCreate();
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
showNotification();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("MyService", "Service Started");
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mNM.cancel(NOTIFICATION);
Log.e("MyService", "Service Ended");
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IBinder mBinder = new LocalBinder();
private void showNotification() {
Notification.Builder builder = new Notification.Builder(getApplicationContext());
builder.setAutoCancel(false)
.setOngoing(true)
.setSmallIcon(R.drawable.myicon)
.setTicker(getText(R.string.service_label))
.setWhen(System.currentTimeMillis())
.setContentTitle(getText(R.string.service_started))
.setContentText(getText(R.string.service_label));
Notification notification = builder.getNotification();
mNM.notify(NOTIFICATION, notification);
}
I had the same problem with an ongoing notification disappearing in ICS on a new phone. The app and notification had worked perfectly in every version of Android I had tested it on previously, and it even works on an ICS emulator. Needless to say this has been driving me crazy for a couple months now, but I finally found the answer.
http://code.google.com/p/android/issues/detail?id=21635
I am using a BroadcastReceiver to monitor incoming calls on the handset and I programmatically enable the receiver when a button is toggled in addition to setting the notification. So I wrote a small test app with the same BroadcastReceiver hooked up and was able to reproduced the problem. I commented out the setComponentEnabledSetting call and the notification no longer disappears.