Notification vibrates on each progress update - android

When on Android 8.0 (Oreo), every time there is an update to the progress of the notification, it vibrates. So the phone vibrates 100 times in the process. This only happens on Android 8.0 So i can assume I am having some improper use of their API. I am asking for help in stopping the vibration on each progress update of the notification. Here is my code:
Building Notification
mNotifyManager = (NotificationManager) mActivity.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) createChannel(mNotifyManager);
mBuilder = new NotificationCompat.Builder(mActivity, "FileDownload")
.setSmallIcon(android.R.drawable.stat_sys_download)
.setColor(ContextCompat.getColor(mActivity, R.color.colorNotification))
.setContentTitle(mFile.getName())
.setContentText(mActivity.getResources().getString(R.string.app_name))
.setProgress(0, 0, true);
mNotifyManager.notify(mFile.getId().hashCode(), mBuilder.build());
Create Channel method
#TargetApi(26)
private void createChannel(NotificationManager notificationManager) {
String name = "FileDownload";
String description = "Notifications for download status";
int importance = NotificationManager.IMPORTANCE_MAX;
NotificationChannel mChannel = new NotificationChannel(name, name, importance);
mChannel.setDescription(description);
mChannel.enableLights(true);
mChannel.setLightColor(Color.BLUE);
notificationManager.createNotificationChannel(mChannel);
}
onProgress
#Override
public void onProgress(File file, double progress, long downloadedBytes, long totalBytes) {
mBuilder.setProgress(100, (int) (progress * 100), false);
mNotifyManager.notify(file.getId().hashCode(), mBuilder.build());
}

Using setOnlyAlertOnce(true) on your NotificationCompat.Builder when initially building the notification should do the trick.

Try to disable vibration like this :
notificationBuilder.setDefaults(Notification.DEFAULT_LIGHT | Notification.DEFAULT_SOUND)
.setVibrate(new long[]{0L});

Another option is to set .setNotificationSilent() on your update notifications.

Related

Android push header/heads-up notification doesn't work

I am currently trying to get a header notification on a Nexus S (API 29), but with no success. I've seen some threads with various solutions, but none of them worked. The code is as follows:
Context applicationContext = getApplicationContext();
NotificationCompat.Builder builder = new NotificationCompat.Builder(applicationContext, CHANNEL_ID)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setDefaults(NotificationCompat.DEFAULT_SOUND)
.setSmallIcon(R.drawable.ic_account_circle)
.setContentTitle(notificationTitle)
.setContentText(notificationTextBody)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setLights(Color.RED, 3000, 3000);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(applicationContext);
int notificationId = new Random().nextInt();
//launches the notification on the device
notificationManager.notify(notificationId, builder.build());
I have tried setting sound on, vibrations on, to set the priority as high or max. I have even used the method setFullScreenIntent, separately and all at once, but nothing accomplished, what I seek.
on Android 8+ you have to create notification channel, like in DOC
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 = getString(R.string.channel_name);
String description = getString(R.string.channel_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);
}
}
note that channel also have importance. if you want a heads-up notification you have to set high priority for this channel, DOC
Example conditions that might trigger heads-up notifications include the following:
The notification channel has high importance on devices running Android 8.0 (API level 26) and higher.

Push Notification content text not showing on Lollipop

Here is the code for showing push notification:
// receiverUid = unique uid for a receiver
// notificationUid = unique notification_uid
// receiverName, title, body are String variables.
NotificationCompat.Builder groupBuilder =
new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL")
.setSmallIcon(R.drawable.ic_app_icon_24)
.setColor(ColorUtils.getColor(getApplicationContext(), R.color.blue_700))
.setGroupSummary(true)
.setGroup(receiverUid)
.setAutoCancel(true)
.setSubText(receiverName)
.setContentIntent(pendingIntentGroup);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL")
.setSmallIcon(R.drawable.ic_app_icon_24)
.setColor(ColorUtils.getColor(getApplicationContext(), R.color.blue_700))
.setContentTitle(title)
.setContentText(body)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntentNotification)
.setGroup(receiverUid)
.setSubText(receiverName)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
// group notification is based on receiverUid, so the notifications are grouped under different receipients
notificationManager.notify(receiverUid, 0, groupBuilder.build());
notificationManager.notify(receiverUid + "_" + notificationUid, 0, builder.build());
This works fine on higher android versions, but the notification text is not shown for Lollipop versions. Here is screenshot on a Lollipop device:
I debugged and verified that the text is passed here. Please suggest. Thanks in Advance.
From official doc :
Set a group summary
On Android 7.0 (API level 24) and higher, the system automatically
builds a summary for your group using snippets of text from each
notification. The user can expand this notification to see each
separate notification, as shown in figure 1. To support older
versions, which cannot show a nested group of notifications, you must
create an extra notification that acts as the summary. This appears as
the only notification and the system hides all the others. So this
summary should include a snippet from all the other notifications,
which the user can tap to open your app
The text is not displayed because the groupBuilder is the one that is displayed and it does not contain any text so for the lesser version of API 27 add your text to the groupBuilder or create a style to summarize the contents of the other notification for example :
NotificationCompat.Builder groupBuilder =
new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL")
.setSmallIcon(R.drawable.ic_app_icon_24)
.setColor(ColorUtils.getColor(getApplicationContext(), R.color.blue_700))
.setGroupSummary(true)
.setGroup(receiverUid)
.setAutoCancel(true)
.setSubText(receiverName)
.setContentIntent(pendingIntentGroup)
.setStyle(new NotificationCompat.InboxStyle()
.addLine("Alex Faarborg Check this out")
.setBigContentTitle("2 new messages")
.setSummaryText("janedoe#example.com"));
Update :
implement the notification count and the messages summary in the Style
public class MainActivity extends AppCompatActivity {
private int notificationCount = 0;
private NotificationCompat.InboxStyle style;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// also you can Save the Notification count on the sharePreference
// for simulate the notification with multiple message
String[][] person = {{"Bill", "Jones"}, {"Janet", "Kline"}, {"George", "Bailey"},
{"Ellan", "Sanches"}, {"Tom", "Nguyen"}, {"William", "Walters"}, {"Author", "James"},
{"Henry", "Daniels"}, {"Mike", "Franklin"}, {"Julie", "Andrews"}};
// i have just testing with the TimeDownCount to add notifications every 20 seconds
CountDownTimer countDownTimer = new CountDownTimer(2000, 10) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
// get random person from the array person
Random random = new Random();
int randomInt = random.nextInt(person.length - 1);
// show notification
showNotification(person[randomInt][0] + " " + person[randomInt][1]);
if (notificationCount < 10) {
this.start();
}
}
};
countDownTimer.start();
style = new NotificationCompat.InboxStyle();
}
private void showNotification(String message) {
notificationCount++;
style.addLine(message); // add person to the style
style.setBigContentTitle(notificationCount + " new messages"); // show Notification count in the Title
NotificationCompat.Builder groupBuilder =
new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL")
.setSmallIcon(R.drawable.ic_baseline_mic_24)
.setColor(Color.BLUE)
.setGroupSummary(true)
.setGroup("receiverUid")
.setAutoCancel(true)
.setStyle(style)
.setSubText("Your Action");
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL")
.setSmallIcon(R.drawable.ic_baseline_mic_24)
.setColor(Color.BLUE)
.setContentTitle("title")
.setContentText("body")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setGroup("receiverUid")
.setSubText("receiverName")
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify("receiverUid", 0, groupBuilder.build());
notificationManager.notify("receiverUid" + "_" + "notificationUid", 0, builder.build());
}
}
overview of how the code works :

How to play different sound files on local notifications

Local notifications pop up when my Xamarin phone app receives a new event. This works fine, and it also plays a sound. However I want to play different sounds depending on the type of event that my app has received. I thought this would be simple enough, but whatever sound is played first after I rebuild the app, that is the sound that then plays for every notification regardless of the code.
For example, after rebuild, if Priority enum is Priority.Temp then TempNotif.wav will play. But if the code calls this method again to show another notification and Priority enum isn't Priority.Temp, TempNotif.wav still plays, even though I have set it to play StandardNotif.wav. It seems like android takes a copy of the first sound and doesn't bother updating it once there is a sound in place. Whatever is happening, surely I can play different sounds for different notifcations?
Here is code:
public void CreateNotification(string title, string message, Priority priority)
{
Android.Net.Uri sound = null;
if (priority == Priority.Temperature)
{
sound = global::Android.Net.Uri.Parse($!{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.TempNotif}");
}
else
{
sound = global::Android.Net.Uri.Parse($!{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.StandardNotif}");
}
var alarmAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
builder = new NotificationCompat.Builder(context, notificationChannelId);
builder.SetContentTitle(title)
.SetAutoCancel(true)
.SetContentText(message)
.SetPriority((int)NotificationPriority.High)
.SetSmallIcon(Resource.Drawable.MetroIcon)
.SetColor(00255)
.SetVibrate(new long[0])
.SetSound(sound)
.SetVisibility((int)NotificationVisibility.Public);
notificationManager = context.GetSystemService(Context.NotificationService) as
NotificationManager;
if (global::Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
NotificationImportance importance = NotificationImportance.High;
NotificationChannel notificationChannel = new NotificationChannel(notificationChannelId,
title, importance);
notificationChannel.Importance = NotificationImportance.High;
notificationChannel.EnableLights(true);
notificationChannel.EnableVibration(true);
notificationChannel.SetSound(sound, alarmAttributes);
notificationChannel.SetShowBadge(true);
notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });
if (notificationManager != null)
{
builder.SetChannelId(notificationChannelId);
notificationManager.CreateNotificationChannel(notificationChannel);
}
}
notificationManager.Notify(0, builder.Build());
}
Credit to #Mooniean for the answer!
The answer is to provide a different channel ID for each type of notification I want to display.
I set two static values for channel ID's and provide one depending on the type of notification I want to display.
private static string StandardchannelId = "1000";
private static string TempChannelId = "2000";
Here I assign my channelID depending on an enum I made:
if (priority == Priority.Temperature)
{
this.channelId = TempChannelId;
sound = global::Android.Net.Uri.Parse($"{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.TempNotif}");
}
else
{
this.channelId = StandardchannelId;
sound = global::Android.Net.Uri.Parse($"{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.StandardNotif}");
}
And here I assign the channelID:
builder.SetChannelId(this.channelId);

NotificationCompat with API 26

I dont see any information about how to use NotificationCompat with Android O's Notification Channels
I do see a new Constructor that takes a channelId but how to take a Compat notification and use it in a NotificationChannel since createNotificationChannel takes a NotificationChannel object
Create the NotificationChannel only if API >= 26
public void initChannels(Context context) {
if (Build.VERSION.SDK_INT < 26) {
return;
}
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel("default",
"Channel name",
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("Channel description");
notificationManager.createNotificationChannel(channel);
}
And then just use:
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, "default");
So your notifications are working with both API 26 (with channel) and below (without).
Declare Notification Manager:
final NotificationManager mNotific=
(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence name="Ragav";
String desc="this is notific";
int imp=NotificationManager.IMPORTANCE_HIGH;
final String ChannelID="my_channel_01";
Notification Channel
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel mChannel = new NotificationChannel(ChannelID, name,
imp);
mChannel.setDescription(desc);
mChannel.setLightColor(Color.CYAN);
mChannel.canShowBadge();
mChannel.setShowBadge(true);
mNotific.createNotificationChannel(mChannel);
}
final int ncode=101;
String Body="This is testing notific";
Notification Builder
Notification n= new Notification.Builder(this,ChannelID)
.setContentTitle(getPackageName())
.setContentText(Body)
.setBadgeIconType(R.mipmap.ic_launcher)
.setNumber(5)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setAutoCancel(true)
.build();
NotificationManager notify to User:
mNotific.notify(ncode, n);
NotificationChannel actually groups multiple notifications into channels. It basically gives more control of the notification behavior to the user. You can read more about Notification Channel and its implementation at Working with Notification Channel | With Example
Notification Channel is only applicable for Android Oreo.
//Notification channel should only be created for devices running Android 26
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel("unique_channel_id","channel_name",NotificationManager.IMPORTANCE_DEFAULT);
//Boolean value to set if lights are enabled for Notifications from this Channel
notificationChannel.enableLights(true);
//Boolean value to set if vibration is enabled for Notifications from this Channel
notificationChannel.enableVibration(true);
//Sets the color of Notification Light
notificationChannel.setLightColor(Color.GREEN);
//Set the vibration pattern for notifications. Pattern is in milliseconds with the format {delay,play,sleep,play,sleep...}
notificationChannel.setVibrationPattern(new long[]{500,500,500,500,500});
//Sets whether notifications from these Channel should be visible on Lockscreen or not
notificationChannel.setLockscreenVisibility( Notification.VISIBILITY_PUBLIC);
}
Note that Channel ID passed to the constructor acts as the unique identifier for that Notification Channel. Now create the Notification as shown below
// Creating the Channel
NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(notificationChannel);
To add any Notification to this Channel just pass the Channel ID as shown below
//We pass the unique channel id as the second parameter in the constructor
NotificationCompat.Builder notificationCompatBuilder=new NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID);
//Title for your notification
notificationCompatBuilder.setContentTitle("This is title");
//Subtext for your notification
notificationCompatBuilder.setContentText("This is subtext");
//Small Icon for your notificatiom
notificationCompatBuilder.setSmallIcon(R.id.icon);
//Large Icon for your notification
notificationCompatBuilder.setLargeIcon( BitmapFactory.decodeResource(getResources(),R.id.icon));
notificationManager.notify( NOTIFICATION_ID,notificationCompatBuilder.build());
Please be careful if you did all the work and you did not get any results. On some devices, you must set the notification priority.
final NotificationCompat.Builder mBuilder = new
NotificationCompat.Builder(mContext, "default")
.setPriority(Notification.PRIORITY_MAX);
I know this answer is late, but better late then never!
I have just released the notification-channel-compat library which provides Notification Channel support going back to OS 4.0. Since developers anyways have to design for Channels, they can now use the benefits of Channels for all devices, and they don't have to design separately for older devices.
The library uses the built-in channel classes for OS 8.0+ devices, and mimics it for older devices. All it takes, is using our NotificationChannelCompat, NotificationChannelGroupCompat and NotificationChannelManagerHelper classes, and adding one line of code. You can see more at github. Please test it and let me know of any issues.
Thank you,
Lionscribe

Disable vibration for a notification

I'm writing an app using notification. Google developer guidelines encourages developers to provide settings to customize the notifications (disable vibration, set notification sound...), so I am trying to disable vibration for notifications if the user set it that way.
I am using NotificationCompat.Builder to create the notification, like this:
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(Application.getContext())
.setDefaults(Notification.DEFAULT_ALL)
.setPriority(Notification.PRIORITY_MAX)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(largeIconBitmap)
.setAutoCancel(true)
.setContentIntent(resultPendingIntent)
.setContentTitle(title)
.setContentText(content);
I tried different ways to disable notifications:
notificationBuilder.setVibrate(null);
notificationBuilder.setVibrate(new long[]{0l, 0l});
notificationBuilder.setDefaults(Notification.DEFAULT_ALL | ~Notification.DEFAULT_VIBRATE);
notificationBuilder.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND);`
I also tried to build the notification and change values on the resulting object:
Notification notification = notificationBuilder.build();
notification.vibrate = null;
But the phone still vibrates when the notification appears.
How can I disable vibration for notifications?
After a long trial & error session, I think I finally understood what's wrong.
The problem lies in this instruction notificationBuilder.setDefaults(Notification.DEFAULT_ALL).
No matter what parameter you pass to notificationBuilder.setVibrate() after setting DEFAULT_ALL or DEFAULT_VIBRATE will be silently discarded. Someone at Google must have decided to give a higher precedence to setDefaults than to setVibrate.
This is how I ended up disabling vibration for notifications in my app:
notificationBuilder.setDefaults(Notification.DEFAULT_LIGHT | Notification.DEFAULT_SOUND)
.setVibrate(new long[]{0L}); // Passing null here silently fails
This works but doesn't feel right to initialize a new long[] just to disable the vibration.
In the year 2020:
Setting the importance of the notification channel to NotificationManager.IMPORTANCE_NONE worked for me.
They are not stop because you are use "setDefaults(Notification.DEFAULT_ALL)" so if you need to stop vibration and sound remove this line , or if you need to use the default sound and stop vibration I think you must use setDefaults(Notification.DEFAULT_SOUND) etc ...
You have 2 solutions with the notification channel.
Set a "fake" pattern to disable the vibration.
Set Importance flag, but less flexible (see https://developer.android.com/training/notify-user/channels#importance). Takes care, it will also impact some other stuff like priority...
As a result, you can use
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
// no vibration
channel.setVibrationPattern(new long[]{ 0 });
channel.enableVibration(true);
Or
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
.setVibrate(null) works for me - and a better solution than creating a needless long[].
Result: device doesn't vibrate and no grumbling in LogCat either. :)
notification.vibrate = new long[] { -1 };
this code work for me.
Above solutions didnt work but adding mBuilder.setOnlyAlertOnce(true); to my notification builder solved my problem.
if (mBuilder == null) {
String channelId = "channel-id";
String channelName = "Channel Name";
int importance = NotificationManager.IMPORTANCE_MAX;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(
channelId, channelName, importance);
mChannel.setSound(null, null);
mChannel.enableVibration(false);
notificationManager.createNotificationChannel(mChannel);
}
mBuilder = new NotificationCompat.Builder(Application.context, channelId);
mBuilder.setSmallIcon(R.drawable.ic_ulakbel)
.setContentTitle("YOURTITLE")
.setAutoCancel(true)
.setColor(ContextCompat.getColor(Application.context, R.color.green))
.setColorized(true);
mBuilder.setChannelId(channelId);
mBuilder.setPriority(1);
mBuilder.setCustomContentView(notificationLayout);
mBuilder.setCustomBigContentView(notificationLayout);
mBuilder.setOnlyAlertOnce(true);
notificationManager.notify(1452, mBuilder.build());
}else{
Notification notification = mBuilder.build();
notification.flags = Notification.FLAG_ONGOING_EVENT;
notificationManager.notify(1452,notification);
}
private void removeSoundAndVibration(Notification notification) {
notification.sound = null;
notification.vibrate = null;
notification.defaults &= ~DEFAULT_SOUND;
notification.defaults &= ~DEFAULT_VIBRATE;
This code is from Notification Compat Api Class. This should work, add all these to your builder.
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Example Service Channel",
NotificationManager.IMPORTANCE_MIN
);
serviceChannel.setVibrationPattern(new long[]{ 0 });
serviceChannel.enableVibration(true);
serviceChannel.enableLights(false);
serviceChannel.setSound(null, null);
serviceChannel.setShowBadge(false); //
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
If you make IMPORTANCE_MIN that you can disabled vibration, if you make IMPORTANCE_DEFAULT it happens vibration so you can try IMPORTANCE_MIN
July 2022: I have tried everything in this thread, and the only thing that worked was Zhar's suggestion to set importance to low:
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
I am targeting Android API level 24.
setVibrate(new long[0]) works if you're targetting API 28. I'm working with chinese smartwatches running smartphone android roms so in the rest of the devices should work fine. Hope it helps!

Categories

Resources