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?
Related
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();
}
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);
Hi I have got problems with launching IntentService as a foreground service. Unfortunatelly the official tutorial does not tell me much as some of methods does not exists, some are deprecated and moreover it's not said where to place the code, that they provide.
I created my own IntentService and I have overridden onCreate method. It looks following:
#Override
public void onCreate(){
super.onCreate();
Intent notificationIntent = new Intent(this, Settings.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new Notification.Builder(this)
.setContentTitle(getText(R.string.serviceName))
.setContentText(getText(R.string.serviceDescription))
.setSmallIcon(R.mipmap.ic_launcher)
.setOngoing(true)
.setContentIntent(pendingIntent)
.build();
startForeground(101, notification);
I know it's not debugging site, but surely there is something obvious, that I am missing. Settings class is my Activity class, from which startService was called, I have also set all needed things to the notification and called startForeground with nonzero first argument. Still no notification appears, although I am pretty sure, that service is working in the background.
Any help would be appreciated (btw. I have already searched for different topics on SO woth service in foreground, but with no help.)
If you use a Service instead of IntentService, you can put the code you wrote to build the notification & startForeground() in onStartCommand :
public class SettingsService extends Service {
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
public SettingsService getService() {
return SettingsService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent = new Intent(this, SettingsService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new Notification.Builder(this)
.setContentTitle("myService")
.setContentText("this is an example")
.setSmallIcon(R.mipmap.ic_launcher)
.setOngoing(true)
.setContentIntent(pendingIntent)
.build();
startForeground(101, notification);
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}
Additionnaly, in onStartCommand, return START_NOT_STICKY if you dont want the service to be recreated when it is killed otherwise return START_STICKY
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;
}