Android Heads-up notification disappears after a few seconds - android

I would that the notification does not disappear after a few seconds.
So i have create the notification like this:
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setSmallIcon(R.drawable.cast_ic_notification_small_icon)
.setDefaults(Notification.FLAG_ONGOING_EVENT)
.setPriority(Notification.PRIORITY_HIGH)
.setContentTitle(notificationDetails.getSubject())
.setContentText(notificationDetails.getMessage())
.setColor(context.getResources().getColor(R.color.colorPrimary))
.setOngoing(true);
and setting the FLAG_ONGOING_EVENT and the method setOngoing(true).
but after a few seconds the notification continues to disappears.
I wish the notification to disappear only when the user clicks on.
Thank you.

It is actually possible to make a heads-up notification persistent. The trick is to use setFullScreenIntent. If you don't want your notification to have a full-screen version, you can use a dummy intent that won't actually launch any activity, like this:
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(), 0);
notificationBuilder.setFullScreenIntent(pendingIntent, true);
It's a hack, but the behavior makes some sense. If an app is trying to show a full-screen notification, then it must be an important event, like an alarm or a phone call. If the phone decides not to show the full-screen notification, it should probably still show something persistent until the user takes action.
This works on the phones I've tested, but the behavior isn't documented, so there are no guarantees.

This issue is observed on Honor and Huawei devices.
You can try to fix it by using setFullScreenIntent and adding permissions to AndroidManifest.
Code:
PendingIntent pIntent = PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setFullScreenIntent(pIntent, true);
AndroidManifest.xml:
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

Duration of heads-up notification can't be changed It is set at OS level Depends on OS how much time it provides for it.

The duration cannot be changed. Otherwise it would intrude with other heads-up notifications that are in the queue to be displayed.

You can do it with:
notificationBuilder.setFullScreenIntent(pendingIntent, true)
You also have to use these:
val tempChannel = NotificationChannel(tempChannelId, "temp channel",
NotificationManager.IMPORTANCE_HIGH) // Setting to high is important
tempChannel.enableVibration(true)
...
notificationBuilder.setAutoCancel(false)
notificationBuilder.setPriority(NotificationCompat.PRIORITY_MAX) // PRIORITY_HIGH works too
notificationBuilder.setVibrate(LongArray(0)) // For older devices we need to add vibration or sound for the Heads-Up notification. This line will not make it vibrate, you can use another pattern, or default, if you want it to vibrate
notificationBuilder.setFullScreenIntent(pendingIntent, true)
IMPORTANT:
On most of the devices, this will show the notification on the top of the screen, overlapping everything, and staying there.
BUT ON SOME DEVICE THIS WILL IMMEDIATELY LAUNCH THE PENDING INTENT THAT IS GIVEN TO THE NOTIFICATION. (Eg. Huawei)
TO SOLVE THIS we can use a dummy pendingIntent for the fullScreenIntent, that shows the notification the same way, just without the notificationBuilder.setFullScreenIntent(pendingIntent, true); This will work as a fallback, so the notification will appear, but will shrink itself to the status bar after like 5 seconds.
val servicePendingIntent = PendingIntent.getService(context, 0, Intent(context, FullScreenIntentService::class.java), 0)
val mainActivityPendingIntent = PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), PendingIntent.FLAG_ONE_SHOT)
...
notificationBuilder.setContentIntent(mainActivityPendingIntent)
notificationBuilder.setFullScreenIntent(servicePendingIntent, true)
Where:
class FullScreenIntentService : Service() {
override fun onCreate() {
super.onCreate()
showNotificationHereTheSameWayJustWithoutSetFullScreenIntent()
stopSelf()
}
override fun onBind(intent: Intent?): IBinder? = null
}
And don't forget to register the service in AndroidManifest.

.setFullScreenIntent(fullScreenPendingIntent, true)
For heads up notification to stay on, you need add a full screen intent

Apart from the same issue with foreground heads-up notifications disappearing after a few seconds, an additional issue I had was that the action buttons were collapsed.
Among other things, what helped me was:
builder.setCategory(NotificationCompat.CATEGORY_CALL);
After adding this line of code, the notification didn't disappeared after a few seconds and the action buttons weren't collapsed.

Related

Stacking notifications from GCM is not working with setGroup

I have the following notification logic inside a class that extends GcmListenerService, and gets called when one notification arrives. Then, when clicked, the app takes you to MainActivity where the notification is displayed properly.
public static void mostrarAvisoBarraEstado(Context context, String alerts)
{
Intent notificationIntent = new Intent(context.getApplicationContext(), MainActivity.class);
notificationIntent.putExtra("alerts", alerts);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, new Random().nextInt(),
notificationIntent, 0);
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.app_name))
.setContentText("Alert received")
.setSmallIcon(R.drawable.nubeazul)
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setGroup(GRUPO_ALERTAS)
.setGroupSummary(true)
.setAutoCancel(true)
.build();
//notificationManager.notify(0, notification);
notificationManager.notify (new Random().nextInt(), notification);
}
So, right now, each one is displayed separately, and if they build up, the result is rather ugly with all the notification bar full of little icons. Can you guys help for an elegant solution since I am kindda new to Android? Thanks a lot!
NEW STUFF ADDED today!
If I take the notify random out, leaving something like notificationManager.notify(0, notification);, I will get just one notification, but nothing else, then when it launches MainActivity (its onResume() method) it will only display one notification and all the "piled up ones" are just discarded when clicked on the one notification. What I want to achieve is that while maintaining a clean display, i.e: one group notification for all GCM, if I click on the group, I will get each and every notification displayed throught the Alerts.class (something like looping through the notifications, and starting the activity Alerts for each one.
#Override
protected void onResume()
{
super.onResume();
if (getIntent().hasExtra("alerts"))
{
Bundle extras = getIntent().getExtras();
Intent intent = new Intent(this, Alerts.class);
intent.putExtra("alerts" , extras.getString("alerts"));
startActivity(intent);
getIntent().removeExtra("alerts");
}
}
Then the Alerts class will nicely display the alert which it does, but one per notification.
So I tried out your code and managed to see reproduce what you were encountering (I just manually created dummy notifications). So the reason that the Notifications were piling up was because the id you are passing in the notificationManager.notify() is different from one another. As to what I have observed on the Notification and NotificationManagers behavior so far, the id indicated in notify() it kinda represents the id location/position (not sure what to call it) of the Notification that is under the NotificationManager, not an id of the Notification itself.
Imagine the NotificationManager as an array or list. If for example, you have 3 visible notifications on the Status Bar:
Notification 1, Notification 2, Notification 3 and their ids are as follows: 0, 1, 2.
If you generate a new Notification 4 then called notify passing it as a parameter, and the id 1, the notifications that will be currently shown in the NotificationManager would result to something like this:
Notification 1, Notification 4, Notification 3 and their ids are as follows: 0, 1, 2.
So the reason that you're notifications are piling up and NOT grouping together is because you end up with different ids when calling notify() while passing new Random().nextInt().
As per the behavior that I think you are aiming for -- Joining the notifications from your app into one -- the implementation is simple when understood, but I think it's still a little bit tricky. It's like you have to check first if there is more than 1 notification already, then if yes, you create a summary notification with the details and you show it alone (mind the id ;)) and all of those other stuff. I found this blog though that I think might help you with it. Or you can simply just check out the official docs on Stacking Notifications.
So bottom line, simply use a single id to pass in notify() when it comes to your apps Notifications. Hope this helps. Cheers! :D

Android service is frequently stopped and restarted

I'm trying to develop an Android application which draws a floating overlay on the screen, as it is done by Facebook messenger with chat heads.
I've created an Android service from which I handle the UI. Everything works well, but on some devices the service is stopped very frequently and sometimes it is started again after more than 60 seconds.
I know this is a behavior defined by the Android System, but I was wondering if there is a way to give my service the maximum priority. Is this possible? Could this behavior be worsened by something in my implementation which is wrong?
One option is to make your Service a "Foreground Service" as briefly explained in Android documentation. This means that it shows an icon and possibly some status data in the status bar. Quoting:
A foreground service is a service that's considered to be something
the user is actively aware of and thus not a candidate for the system
to kill when low on memory. A foreground service must provide a
notification for the status bar, which is placed under the "Ongoing"
heading, which means that the notification cannot be dismissed unless
the service is either stopped or removed from the foreground.
In practice you just need to modify the Service's onStartCommand() method to set up the notification and to call startForeGround(). This example is from the Android documentation:
// Set the icon and the initial text to be shown.
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), System.currentTimeMillis());
// The pending intent is triggered when the notification is tapped.
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
// 2nd parameter is the title, 3rd one is a status message.
notification.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), pendingIntent);
// You can put anything non-zero in place of ONGOING_NOTIFICATION_ID.
startForeground(ONGOING_NOTIFICATION_ID, notification);
That's actually a deprecated way of setting up a notification but the idea is the same anyway even if you use Notification.Builder.

How do I make a Statusbar notification that does nothing and goes nowhere?

I have a working statusbar notification for Android already, but to create it I must set an Activity for it to open. I don't want any activity to open; however, this small project doesn't need an interface at all.
mNotificationManager = (NotificationManager) aContext
.getApplicationContext().getSystemService(
Context.NOTIFICATION_SERVICE);
// Create the pending intent, which is basically NOW.
PendingIntent contentIntent = PendingIntent
.getActivity(aContext, 1, new Intent(aContext, BlankActivity.class),
PendingIntent.FLAG_CANCEL_CURRENT);
// Create notification
notificationBuilder = new NotificationCompat.Builder(aContext)
.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.ic_launcher) // required for launch
.setTicker("Downloading video...") // required for launch
.setWhen(System.currentTimeMillis()) // should be set for now.
.setContent(remoteView);
BlankActivity is what it sounds like -- an activity that has no content and closes upon being opened. But it still shows up on the list of recently opened windows. I cannot set this to null.
Is there a way I can avoid setting an intent for the status notification at all?
You don't need PendingIntent in that case. Just setting it null in setContentIntent() might help.
Another way can be
PendingIntent contentIntent = PendingIntent.getActivity(aContext(),0,new Intent(),PendingIntent.FLAG_CANCEL_CURRENT);
Try this.
Setting it to null does not work for early versions like SDK 2.3 which requires an intent to be set, otherwise android will choke at receiver's start with the exception:java.lang.RuntimeException: Unable to start receiver com.movistar.android.mimovistar.widgets.WidgetIntentReceiver: java.lang.IllegalArgumentException: contentIntent required
see this post

Disable clearing notification for my application

I need to write some application which will do some work in background. This application will be run from autostart and there wont be any start gui. Gui can be call from click on notification which will be showing with autostart. I worried that, when user clear notifications he lost opportunity to call this gui. My question is that is there any way to block clearing my notification by user?
Here's a notification that won't allow the user to clear it.
Notification notification = new NotificationCompat.Builder(this)
.setTicker(r.getString(R.string.app_name))
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(r.getString(R.string.app_name))
.setAutoCancel(false)
.setOngoing(true)
.build();
The setOngoing(true) call achieves this, and setAutoCancel(false) stops the notification from going away when the user taps the notification.
The notification will be cleared if the application is uninstalled or by calling Cancel or CancelAll: http://developer.android.com/reference/android/app/NotificationManager.html#cancel(int)
You might want to look into making a notification in the "running" section of the notifications. These notifications aren't cleared when the user clears them.
Use the Notification.FLAG_NO_CLEAR AND Notification.FLAG_ONGOING_EVENT. This should give you the effect you want
Though #cja answer might be correct though he is missing some few lines of codes(Notification wont show or wont display on your notification tray).
This is the complete working function :
public void createNotification() {
NotificationCompat.Builder notification = new NotificationCompat.Builder(this);
notification.setTicker( "Ticker Text" );
notification.setSmallIcon(R.drawable.ic_launcher);
notification.setContentTitle( "Content Title" );
notification.setContentText( "Content Text" );
notification.setAutoCancel( false );
notification.setOngoing( true );
notification.setNumber( ++NotificationCount );
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
notification.setContentIntent(pIntent);
notification.build();
NotificationManager nManger = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nManger.notify(NotificationID, notification.build());
}
NotificationID is int serve as your notification's ID.
you can clear it by using this :
public void clear() {
NotificationManager oldNoti = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
oldNoti.cancel( NotificationID );
}
make sure that notification.setAutoCancel( false ); is set to false so it wont be cleared when clear button is pressed or when swipe gesture is present.
few lines of codes are originally from #cja post.
cheers / happy codings...
Just add these two flags to the notification, FLAG_AUTO_CANCEL prevent notification automatically dismissed when the user touches it and FLAG_ONGOING_EVENT make it an Ongoing Notification.
notification.flags=Notification.FLAG_AUTO_CANCEL|Notification.FLAG_ONGOING_EVENT;
using this alone works perfectly for me Notification.FLAG_NO_CLEAR
along with
notification.SetOngoing(true);
notification.SetAutoCancel(false);
You want to implement a Foreground Service.

Custom Notification

I would like to know if there is a way of using the notication bar in order to do some operations (onClick), without having an activity being launched/resumed.
for example.. let's say i raise a notifcation, and when the user press on it, then instead of take me to some activity, it invoke some regular method in my current activity/service
Is there any way to implement such a thing?
for example the current notifcation code do a standart behave onClick. running up an activity.. how will channge the code in order to invoke some method instead of an activity?
messagesManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.icon, message,
System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, someActivity.class), 0);
notification.setLatestEventInfo(context, "notification", message,
contentIntent);
messagesManager.notify(R.string.noto, notification);
Is there any way to implement such a
thing?
Use an appropriate PendingIntent. Instead of calling getActivity(), call getService() or getBroadcast().
I don't believe this is possible or, at the very least, best practice. It's possible that Android could kill your activity while the Notification is still waiting in the top bar. For example maybe you get a phone call but Android is low on RAM - it kills your activity, thus there's really not a 'current' activity anymore.

Categories

Resources