According to android documentation,
A notification remains visible in the notification drawer until dismissed by the app or the user.
But why my notification is getting cleared by itself? My code is something like this
public class Worker extends Service{
private final int notification_id=((int)(Calendar.getInstance().getTimeInMillis())%Integer.MAX_VALUE);
private final String channel_id="STORAGE_ORGANIZER_DUPLICATE_CONTENT_EXTRACTOR_SERVICE_NOTIFICATION";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
final NotificationCompat.Builder notification_builder=
new NotificationCompat.Builder(this, channel_id)
.setSmallIcon(R.drawable.storage_icon)
.setContentTitle(getString(R.string.duplicate_content_extractor_notification_msg1))
.setProgress(1,0,true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setOngoing(true);
startForeground(notification_id,notification_builder.build());
new Thread(new Runnable() {
#Override
public void run() {
// some long running work
Intent remover_intent=new Intent(
DuplicateContentExtractorService.this,
DuplicateContentExtractorServiceStopperService.class
);
PendingIntent remover_pendingIntent=PendingIntent.getService(
DuplicateContentExtractorService.this,
(int)Calendar.getInstance().getTimeInMillis() % 9999,
remover_intent,
PendingIntent.FLAG_ONE_SHOT
);
stopForeground(false);
notification_builder.setOngoing(false);
notification_builder.setDeleteIntent(remover_pendingIntent);
notificationManager.notify(notification_id,notification_builder.build());
}
}).start();
}
you need to set notification_builder.setOngoing(true); to true like
public class Worker extends Service{
private final int notification_id=((int)(Calendar.getInstance().getTimeInMillis())%Integer.MAX_VALUE);
private final String channel_id="STORAGE_ORGANIZER_DUPLICATE_CONTENT_EXTRACTOR_SERVICE_NOTIFICATION";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
final NotificationCompat.Builder notification_builder=
new NotificationCompat.Builder(this, channel_id)
.setSmallIcon(R.drawable.storage_icon)
.setContentTitle(getString(R.string.duplicate_content_extractor_notification_msg1))
.setProgress(1,0,true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setOngoing(true);
startForeground(notification_id,notification_builder.build());
new Thread(new Runnable() {
#Override
public void run() {
// some long running work
Intent remover_intent=new Intent(
DuplicateContentExtractorService.this,
DuplicateContentExtractorServiceStopperService.class
);
PendingIntent remover_pendingIntent=PendingIntent.getService(
DuplicateContentExtractorService.this,
(int)Calendar.getInstance().getTimeInMillis() % 9999,
remover_intent,
PendingIntent.FLAG_ONE_SHOT
);
stopForeground(false);
notification_builder.setOngoing(true);
notification_builder.setDeleteIntent(remover_pendingIntent);
notificationManager.notify(notification_id,notification_builder.build());
}
}).start();
}
Related
Instead of
stopForeground(true)
calling,
stopForeground(false)
should retain the notification as it is (without ongoing state) unless it is dismissed by user/removed programmatically.
This also should prevents notification flashing since I am not recreating the notification.
But it does not work. stopForeground(false) has the same behavior of stopForeground(true).
This is a sample project:
public class AudioTestService extends Service {
private static final String CHANNEL_ID = "TestChannel";
private static final int NOTIFICATION_ID = 14;
Notification mBuilder;
public AudioTestService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
stopForeground(true);
super.onTaskRemoved(rootIntent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent intentA = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intentA, 0);
Notification mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Titolo")
.setContentText("Descrizione")
.setContentIntent(pendingIntent)
.setOngoing(false)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.build();
this.mBuilder = mBuilder;
createNotificationChannel();
startForeground(NOTIFICATION_ID, mBuilder);
return START_STICKY;
}
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = CHANNEL_ID;
String description = CHANNEL_ID + "Description ";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
#Override
public void onDestroy() {
stopForeground(false);
//NotificationManagerCompat.from(this).notify(NOTIFICATION_ID, mBuilder);
super.onDestroy();
} }
The activity, easily handle the button click event:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startService = findViewById(R.id.startService);
Button stopService = findViewById(R.id.stopService);
Button stopNotification = findViewById(R.id.stopWithNotification);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
stopNotification.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.startService:
ContextCompat.startForegroundService(this, new Intent(this, AudioTestService.class));
break;
case R.id.stopService:
finish();
break;
case R.id.stopWithNotification:
stopService(new Intent(this, AudioTestService.class));
break;
}
}}
If you look at the Service's onDestroy() method I set
stopForeground(false);
instead of the method onTaskRemoved() that should remove the notification when the app is cleaned from the task list.
What am I doing wrong?
Please do not mark this as duplicated, I am looking for a solution for days...
Instead of calling stopForeground(false); from onDestroy(), send a broadcast from activity (with action) for stop service. Change your onStartCommand code to check action in intent and do startForeground or stopForeground(false);
I'm continuing in the Android studies and i've a questions.
I'have this intentService:
public class SystemService extends IntentService{
public SystemService() {
super("SystemService");
}
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, startId, startId);
return(START_NOT_STICKY);
}
#Override
public void onCreate(){
super.onCreate();
startForeground();
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void startForeground(){
Intent notificationIntent = new Intent(this, DashboardActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification noti = new Notification.Builder(getApplicationContext())
.setContentTitle("Foregroundservice")
.setContentText("foreground is active")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent).build();
startForeground(1337, noti);
}
}
Why, in onCreate() function, if I put the function startForeground() so, ne initializing foregroundservice before the super.onCreate(), the foreground notify disappear But if a put after seem work?
There seems to be other questions regarding cancelling ongoing notification.
However, i really look into quite a number of them and still have no solution.
SettingFragment
public class SettingFragment extends Fragment {
private Switch mSwitchNotific;
mSwitchNotific.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(isChecked){
Log.v(LOGTAG, "step notification on");
getContext().startService(new Intent(getContext(), UpdateStepNotificationService.class));
}else{
Log.v(LOGTAG, "step notification off");
NotificationManager notificationManager = (NotificationManager)
getContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(StickyUpdateStepNotification.NOTIFICATION_ID);
}
}
}
}
UpdateStepNotificationService
public class UpdateStepNotificationService extends Service {
static NotificationManager notificationManger;
StepsDBHandler stepsDBHandler;
public UpdateStepNotificationService() {}
#Override
public void onCreate() {
super.onCreate();
stepsDBHandler = new StepsDBHandler(getApplicationContext(), null, null, 0);
notificationManger = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
StickyUpdateStepNotification.NOTIFICATION_ID,
new Intent(getApplicationContext(), MainActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT);
final Notification notification = new Notification.Builder(
getApplicationContext())
.setSmallIcon(R.drawable.ic_notice)
.setContentTitle("Walksapp")
.setContentText("Now: " +Integer.toString(stepsDBHandler.getCurrentStepToday()) + " steps")
.setContentIntent(pendingIntent)
.build();
notification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
new Timer().schedule(new TimerTask() {
#Override
public void run() {
notificationManger.notify(StickyUpdateStepNotification.NOTIFICATION_ID, notification);
}
}, 0, 1000);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onDestroy() {
notificationManger.cancel(StickyUpdateStepNotification.NOTIFICATION_ID);
super.onDestroy();
}
}
UpdateStepNotificationService for repeating issue new notification with latest step count.
The notification is with FLAG_NO_CLEAR and FLAG_ONGOING_EVENT.
The only way turn on and off the notification is by switch button in SettingFragment.
Attempt:
notificationManger.cancel(StickyUpdateStepNotification.NOTIFICATION_ID);
Not working
Hope to see any input
Thanks
You will need to kill the timer otherwise it will continue updating the notification.
I have a service to show notification at a specific time and one broadcastreceiver for starting this service. When the app is started, the service is started and shows notification and shows the service in app running on the device, but sometimes in the running app service is a Restarting and the message does not display.
my service code is:
public class NotificationService extends Service {
private boolean flag=false;
public static NotificationCompat.Builder mBuilder;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Timer timer=new Timer();
final Context context=getApplicationContext();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if(CheckTime()){
//Intent intent = new Intent(context, NotificationReciver.class);
//sendBroadcast(intent);
showNotification();
}
}
},0,(1000*60));
return START_NOT_STICKY;
}
private boolean CheckTime(){
final Context context=getBaseContext();
Calendar calendar=Calendar.getInstance();
int hour=calendar.get(Calendar.HOUR_OF_DAY);
int minute=calendar.get(Calendar.MINUTE);
if(hour==16 && minute==11){
return true;
}else {
return false;
}
}
private void showNotification() {
Context context=getApplicationContext();
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Intent intent=new Intent(context, QuestionActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(context,0,intent,0);
mBuilder = new NotificationCompat.Builder(context).
setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Feelinger")
.setContentText("How are you feeling today?")
.setSound(alarmSound)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setVibrate(new long[]{300, 200, 200, 200});
android.app.NotificationManager mNotificationManager = (android.app.NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(100, mBuilder.build());
}
and BroadcastReceiver code is:
public class NotificationManager extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context,NotificationService.class));
}
How to solve this problem?
Write inside service
#Override
public int onStartCommand (Intent intent, int flags, int startId)
{
return START_NOT_STICKY;
}
I have a notification in my service which I cancel in my onDestroy. The notification immediately reappears after cancel code executes. Any clues?. I have tried all the flags combinations. No joy. Code edited for brevity is here.
public class downservice extends Service{
Notification notification;
RemoteViews contentView;
private static final int notifyid = 1;
Context context;
NotificationManager mNM;
PendingIntent cintent;
#Override
public void onCreate() {
String ns = Context.NOTIFICATION_SERVICE;
mNM = (NotificationManager)getSystemService(ns);
Intent noteintent = new Intent(this, configact.class);
cintent = PendingIntent.getActivity(this, 0, noteintent, 0);
contentView= new RemoteViews(getPackageName(), R.layout.notify);
Message msgtx=Message.obtain();
handler.sendMessage(msgtx);
}
private void showNotification(long[] data) {
notification= new Notification();
notification.contentIntent = cintent;
notification.icon=R.drawable.notify;
notification.iconLevel=x;
notification.flags|=Notification.FLAG_AUTO_CANCEL;
contentView.setImageViewResource(R.id.notifyimage, R.drawable.notifyimage);
contentView.setTextViewText(R.id.notifytext,text);
notification.contentView = contentView;
// We use a layout id because it is a unique number. We use it later to cancel.
mNM.notify(notifyid, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
mNM.cancel(notifyid);
}
private Handler handler=new Handler(){
#Override
public void handleMessage(Message msg){
Message msgtx=Message.obtain();
msgtx.arg1=1;
long [] data=getdata();
showNotification(data);
handler.sendMessageDelayed(msgtx, updaterate*1000);
}
};
The handler continues to execute even after service is destroyed and hence the notification which is in the handler loop reappears. I modified the code so that the handler loop does not continue after onDestroy(). I also implemented Handler.Callback since it is cleaner rather than the inline code.
#Override
public boolean handleMessage(Message arg0) {
switch(arg0.arg1){
case 1:
Message msgtx=Message.obtain();
msgtx.arg1=loopstatus;
long [] data=getdata();
showNotification(data);
handler.sendMessageDelayed(msgtx, updaterate*1000);
break;
case 2:
mNM.cancel(notifyid);
break;
default:
break;
}
return true;
}