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.
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.
I need to be able to detect when changes occur in contact data (any type of change to any contact in the address book).
I am using this ContentObserver:
public class ContactsContentObserver extends ContentObserver {
private Context context;
private Handler toastMessageHandler;
public ContactsContentObserver(Handler handler, Context ctx) {
super(handler);
context = ctx;
}
#Override
public void onChange(boolean selfChange) {
this.onChange(selfChange,null);
}
#Override
public void onChange(boolean selfChange, Uri uri) {
// Change Detected! Do something.
}
}
I register this observer in a service like this:
#Override
public int onStartCommand (Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
registerContactsContentObserver();
return START_STICKY;
}
private void registerContactsContentObserver(){
ContactsContentObserver myObserver = new ContactsContentObserver(new Handler(), this);
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, myObserver);
}
I start this service in my main activity.
It works fine as long as the activity is open (even if in the background), and the onChange() method is called every time I change any contact data.
But it doesn't work at all if I manually close the app by clearing it from recent apps in android
Am I doing something wrong? Isn't the service supposed to run even when the app is closed?
I've been able to solve the issue with the help of pskink
Starting the service in the forground like this:
private void runAsForeground(){
Intent notificationIntent = new Intent(this, LauncherActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(this, 0,
notificationIntent, PendingIntent.FLAG_ONE_SHOT);
Notification notification=new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("test")
.setContentIntent(pendingIntent).build();
startForeground(1, notification);
}
#Override
public int onStartCommand (Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
runAsForeground();
registerContactsContentObserver();
return START_STICKY;
}
solved the issue.
Although, I still don't understand why the issue occurred in the first place, since, the service is sticky and supposed to run even if the app is closed. Even if android stopped the service to save memory, it is supposed to restart it.
Can somebody explain to me why starting the service in the foreground is any different than a regular sticky service in the background?
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.
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.
Im creating an application where I can add appointments to a list.
If an appointment is nearby, I want my app to show a notification in the status bar the day of the appointment at a certain hour.
I used the code from http://developer.android.com/guide/topics/ui/notifiers/notifications.html
to create my notification.
However, the "when" parameter in the script is somewhat confusing because a statusbar notification is always triggered when called.
Notification notification = new Notification(icon, tickerText, when);
What is the best way to schedule such notification?
It seems there is no easy way and I have to create a service that starts a listener Activity with a thread to loop my appointmentdates and show a notification when a date fits the current date?
However, the "when" parameter in the script is somewhat confusing
because a statusbar notification is always triggered when called.
Notification notification = new Notification(icon, tickerText, when);
Exactly - notification is triggered when called. If you set when variable to System.currentTimeMilis() as in the example, it means - show the notification now.
As what triggers your notifications, that is up to you to handle. An Activity doesn't seem like a good choice, but a Service does. Initialize your service on application start (and don't forget to stop it on application exit), and let it do the "listening" and triggering of notifications. It might look as:
public class NotifyService extends Service {
private NotificationManager mNM;
#Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
//do some work, listen for change
if (triggerSatisfied) showNotification();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
// Cancel the persistent notification.
mNM.cancelAll();
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
private final IBinder mBinder = new LocalBinder();
private void showNotification() {
//code for notification goes here
}
public class LocalBinder extends Binder {
NotifyService getService() {
return NotifyService.this;
}
}