Service.startForeground vibrates the device - java

I'm using the startForeground() call for one of my Services:
NotificationCompat.Builder notifBuilder =
new NotificationCompat.Builder(this, "my_channel")
.setContentTitle("Loading");
startForeground(1, notifBuilder.build());
The problem is that since I'm using my unique channel for notifications and it has vibration:
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel mChannel =
new NotificationChannel("my_channel", "Notifications", NotificationManager.IMPORTANCE_DEFAUL);
mChannel.enableLights(true);
mChannel.enableVibration(true);
notificationManager.createNotificationChannel(mChannel);
The startForeground() call generates vibration.
Tried some configs:
Not working:notifBuilder.setVibrate(new long[]{0,0}) nor notifBuilder.setDefaults(~Notification.DEFAULT_VIBRATE)
Working on my device notifBuilder.setVibrate(null) or using a non-registered channel id but I'm not sure if this can cause crashes in other versions or devices.
How can I avoid this vibration without declaring a new channel?

You're creating the NotificationChannel with IMPORTANCE_DEFAULT which the documentation says:
Default notification importance: shows everywhere, makes noise, but does not visually intrude.
You probably want IMPORTANCE_LOW:
Low notification importance: shows everywhere, but is not intrusive.
If you want "my_channel" to stay IMPORTANCE_DEFAULT, you can create a new channel with a different importance for this service.

The vibration pattern is specific to that notification channel, so you'd have to disable it on the notification channel when you post the notification, then reenabled it for notifications you'd like to have vibrate. You could also have separate notification channels for different priorities, as hinted to in the docs:
When you target Android 8.0 (API level 26), you must implement one or more notification channels to display notifications to your users.
So, even if you used setVibrate(null), or some other variation, it'll just be ignored on 26+, since that method has been deprecated and the NotificationChannel's pattern will now be used:
/**
* The pattern with which to vibrate.
*
* <p>
* To vibrate the default pattern, see {#link #defaults}.
* </p>
*
* #see android.os.Vibrator#vibrate(long[],int)
* #deprecated use {#link NotificationChannel#getVibrationPattern()}.
*/
#Deprecated
public long[] vibrate;

Related

Show notifications on lock screen of Xiaomi devices

Push notifications not shows on lock screen of Xiaomi devices.
I've tried to use VISIBILITY_PUBLIC in notification builder and channel but it doesn't work.
The problem is that Xiaomi devices has special permission in apps notifications settings which permits to show notification at lock screen. But this permission is turn off by default. But in some apps like "Telegram" this permission is on by default after installation from google play, I can't find the solution how to do that.
Not sure if this helps, but I had a similar problem an a Huawei Device (API 29).
I wanted to use NotificationManager.IMPORTANCE_LOW on my NotificationChannel, but when I was trying to send Notifications on this Huawei Device, they where not Visible on the Lock Screen.
I figured out that there is an App Notification Option on this Huawei Device to use "gentle notifications". Those Notifications are not shown on the Lock Screen and this Option is turned on by Default if your Channel uses IMPORTANCE_LOW or below.
Changing the Importance of the Channel to IMPORTANCE_DEFAULT was solving my Problem.
Since I wanted IMPORTANCE_LOW because I dont wanted an Notification Sound, I just had to do a little workaround and set setSound(null, null) and setVibrationPattern(null).
NotificationChannel nChannel1 = new NotificationChannel(CHANNEL_1_ID, "Channel Name", NotificationManager.IMPORTANCE_DEFAULT);
nChannel1.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
nChannel1.setSound(null, null);
nChannel1.setVibrationPattern(null);
nChannel1.setDescription("Description");
nManager = context.getSystemService(NotificationManager.class);
nManager.createNotificationChannel(nChannel1);
Notification notification = new NotificationCompat.Builder(applicationContext, CHANNEL_1_ID)
.setContentTitle("title")
.setContentText("text")
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.build();
nManager.notify(1, notification);

notification displayed differently depending on whether app is in foreground or background

I'm having trouble with notifications on Android. I use the code below to generate a notification on the device whenever a GCM message is received by my app. However, it's producing unexpected results.
public class MyGcmListenerService extends GcmListenerService implements Constants {
private static final String TAG = "MyGcmListenerService";
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("msg");
sendNotification(message);
}
private void sendNotification(String message) {
NotificationManager notificationManager =
(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.gcm_notification_channel_name);
String description = getString(R.string.gcm_notification_channel_description);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(GCM_NOTIFICATION_CHANNEL_ID, name,
importance);
channel.setDescription(description);
channel.setLockscreenVisibility(NotificationCompat.VISIBILITY_PUBLIC);
channel.enableVibration(true);
channel.setSound(defaultSoundUri,
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
.build());
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this,
GCM_NOTIFICATION_CHANNEL_ID)
.setContentText(message)
.setContentTitle("My Title")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_notification);
notificationManager.notify(0, notificationBuilder.build());
}
}
If a GCM message is received whilst the app is open (not just running, but actually open on the screen), then the resulting notification has only a title, and doesn't show the message. This screenshot demonstrates this case. Further, if I send multiple GCM messages to the device whilst the app is in the foreground, only one is displayed.
If a message is received whilst the app is either closed or running in the background, the resulting notification shows only the message, and has no title. This screenshot shows the two messages side-by-side - the bottom one was received with the app in the foreground, the top was received with the app in the background. If multiple messages are received whilst the app is in the background, all are displayed (in contrast to what happens when the app is in the foreground). This screenshot shows that multiple messages are displayed when they're received with the app in the background.
Also, the notification only appears as heads-up when the app is in the foreground.
Finally, if received in the foreground, the resulting notification does nothing when tapped. However, if received in the background, the notification opens the app when tapped. Not really bothered by this, just thought it might be indicative of the problem.
FYI: when testing, I tried both keeping the GCM message the same every time, as well as varying it. Both scenarios gave the same result.
What I'd like to figure out:
How to get both the title and message to display regardless of whether app is in foreground or not. This is the most important.
How to get the notification to appear as heads-up when the app is in the background.
Just to pre-empt any responses saying not to abuse heads-up, it's the most important feature of the app (the app must notify users of certain events in real-time), according to our users.
Update:
Bas van Stein's answer allowed me to figure out why the either only the title or message was displayed.
As he correctly pointed out, when the app is in the background, GCM messages are handled by the system. This drove me to inspect the script that is used to send messages by the backend. I realised that the person who wrote this script had sent the message within the title field of the notification field of the GCM message, and there was no body field. So I corrected this issue, and the notifications displayed correctly (for app in background).
This also allowed me to realise that the line String message = data.getString("msg"); in onMessageReceived was returning null. I changed the method as follows:
public void onMessageReceived(String from, Bundle data) {
Bundle notification = data.getBundle("notification");
String title = notification.getString("title");
String message = notification.getString("body");
sendNotification(title, message);
}
Then I added title as a parameter to sendNotification and changed the line that sets the notification title to: .setContentTitle(title). Now notifications are displayed correctly when the app is in the foreground.
Further, I added a static int to the class that I use as the notification ID (incremented every time), so now multiple notifications display correctly.
Still not solved:
I'm still unable to have notifications appear as heads-up when the app is in the background. I tried adding "priority": "high" to the GCM message notification payload, but this had no effect - apparently this is the default for a GCM notification anyway.
This answer will be only a part of the complete solution but here we go:
First issue, the background and foreground notifications seem to be generated by two different functions, you can test this by applying a break point in your code and attach the debugger. You will likely see that the background notification is not triggering the break point in this code. Perhaps you miss a manifest service?
Second issue, that only one notification is being shown is because of this line:
notificationManager.notify(0, notificationBuilder.build());
The 0 here is the notification id, if you create multiple notifications with the same id it will overwrite the notification instead of showing a new one.
Third issue, that the application is not opened on notification tab, is because there is no intent attached to the notification you generate in your code.
You can use something like this for an intent:
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
notificationBuilder.setContentIntent(pIntent);
The intent is being called when you click on the notification, this could be any intent so you can open a special activity for example.
Hope this brings you in the correct direction.

Notifications in Android - App stops after notify() [duplicate]

I need a program that will add a notification on Android. And when someone clicks on the notification, it should lead them to my second activity.
I have established code. The notification should be working, but for some reason it is not working. The Notification isn't showing at all. I don't know what am I missing.
Code of those files:
Notification n = new Notification.Builder(this)
.setContentTitle("New mail from " + "test#gmail.com")
.setContentText("Subject")
.setContentIntent(pIntent).setAutoCancel(true)
.setStyle(new Notification.BigTextStyle().bigText(longText))
.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Hide the notification after it's selected
notificationManager.notify(0, n);
The code won't work without an icon. So, add the setSmallIcon call to the builder chain like this for it to work:
.setSmallIcon(R.drawable.icon)
Android Oreo (8.0) and above
Android 8 introduced a new requirement of setting the channelId property by using a NotificationChannel.
NotificationManager mNotificationManager;
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(mContext.getApplicationContext(), "notify_001");
Intent ii = new Intent(mContext.getApplicationContext(), RootActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, ii, 0);
NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();
bigText.bigText(verseurl);
bigText.setBigContentTitle("Today's Bible Verse");
bigText.setSummaryText("Text in detail");
mBuilder.setContentIntent(pendingIntent);
mBuilder.setSmallIcon(R.mipmap.ic_launcher_round);
mBuilder.setContentTitle("Your Title");
mBuilder.setContentText("Your text");
mBuilder.setPriority(Notification.PRIORITY_MAX);
mBuilder.setStyle(bigText);
mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
// === Removed some obsoletes
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
String channelId = "Your_channel_id";
NotificationChannel channel = new NotificationChannel(
channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_HIGH);
mNotificationManager.createNotificationChannel(channel);
mBuilder.setChannelId(channelId);
}
mNotificationManager.notify(0, mBuilder.build());
Actually the answer by Ć’ernando Valle doesn't seem to be correct. Then again, your question is overly vague because you fail to mention what is wrong or isn't working.
Looking at your code I am assuming the Notification simply isn't showing.
Your notification is not showing, because you didn't provide an icon. Even though the SDK documentation doesn't mention it being required, it is in fact very much so and your Notification will not show without one.
addAction is only available since 4.1. Prior to that you would use the PendingIntent to launch an Activity. You seem to specify a PendingIntent, so your problem lies elsewhere. Logically, one must conclude it's the missing icon.
You were missing the small icon.
I did the same mistake and the above step resolved it.
As per the official documentation:
A Notification object must contain the following:
A small icon, set by setSmallIcon()
A title, set by setContentTitle()
Detail text, set by setContentText()
On Android 8.0 (API level 26) and higher, a valid notification channel ID, set by setChannelId() or provided in the NotificationCompat.Builder constructor when creating a channel.
See http://developer.android.com/guide/topics/ui/notifiers/notifications.html
This tripped me up today, but I realized it was because on Android 9.0 (Pie), Do Not Disturb by default also hides all notifications, rather than just silencing them like in Android 8.1 (Oreo) and before. This doesn't apply to notifications.
I like having DND on for my development device, so going into the DND settings and changing the setting to simply silence the notifications (but not hide them) fixed it for me.
Creation of notification channels are compulsory for Android versions after Android 8.1 (Oreo) for making notifications visible. If notifications are not visible in your app for Oreo+ Androids, you need to call the following function when your app starts -
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 behaviours after this
NotificationManager notificationManager =
getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
You also need to change the build.gradle file, and add the used Android SDK version into it:
implementation 'com.android.support:appcompat-v7:28.0.0'
This worked like a charm in my case.
I think that you forget the
addAction(int icon, CharSequence title, PendingIntent intent)
Look here: Add Action
I had the same issue with my Android app. I was trying out notifications and found that notifications were showing on my Android emulator which ran a Android 7.0 (Nougat) system, whereas it wasn't running on my phone which had Android 8.1 (Oreo).
After reading the documentation, I found that Android had a feature called notification channel, without which notifications won't show up on Oreo devices. Below is the link to official Android documentation on notification channels.
Notifications Overview, Notification anatomy
Create and Manage Notification Channels
For me it was an issue with deviceToken. Please check if the receiver and sender device token is properly updated in your database or wherever you are accessing it to send notifications.
For instance, use the following to update the device token on app launch. Therefore it will be always updated properly.
// Device token for push notifications
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(
new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult instanceIdResult) {
deviceToken = instanceIdResult.getToken();
// Insert device token into Firebase database
fbDbRefRoot.child("user_detail_profile").child(currentUserId).child("device_token")).setValue(deviceToken)
.addOnSuccessListener(
new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
}
});
}
});
I encountered a similar problem to yours and while searching for a solution I found these answers but they weren't as direct as I hoped they would be but it gives an Idea; Your notifications may not be showing because for versions >=8 notifications are done relatively differently there is a NotificationChannel which aids in managing notifications this helped me. Happy coding.
void Note(){
//Creating a notification channel
NotificationChannel channel=new NotificationChannel("channel1",
"hello",
NotificationManager.IMPORTANCE_HIGH);
NotificationManager manager=(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.createNotificationChannel(channel);
//Creating the notification object
NotificationCompat.Builder notification=new NotificationCompat.Builder(this,"channel1");
//notification.setAutoCancel(true);
notification.setContentTitle("Hi this is a notification");
notification.setContentText("Hello you");
notification.setSmallIcon(R.drawable.ic_launcher_foreground);
//make the notification manager to issue a notification on the notification's channel
manager.notify(121,notification.build());
}
Make sure your notificationId is unique. I couldn't figure out why my test pushes weren't showing up, but it's because the notification ids were generated based on the push content, and since I was pushing the same notification over and over again, the notification id remained the same.
Notifications may not be shown if you show the notifications rapidly one after the other or cancel an existing one, then right away show it again (e.g. to trigger a heads-up-notification to notify the user about a change in an ongoing notification). In these cases the system may decide to just block the notification when it feels they might become too overwhelming/spammy for the user.
Please note, that at least on stock Android (tested with 10) from the outside this behavior looks a bit random: it just sometimes happens and sometimes it doesn't. My guess is, there is a very short time threshold during which you are not allowed to send too many notifications. Calling NotificationManager.cancel() and then NotificationManager.notify() might then sometimes cause this behavior.
If you have the option, when updating a notification don't cancel it before, but just call NotificationManager.notify() with the updated notification. This doesn't seem to trigger the aforementioned blocking by the system.
If you are on version >= Android 8.1 (Oreo) while using a Notification channel, set its importance to high:
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
val pendingIntent = PendingIntent.getActivity(applicationContext, 0, Intent(), 0)
var notification = NotificationCompat.Builder(applicationContext, CHANNEL_ID)
.setContentTitle("Title")
.setContentText("Text")
.setSmallIcon(R.drawable.icon)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.build()
val mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mNotificationManager.notify(sameId, notification)

Can I use NotificationCompat.BigTextStyle without crashing on older devices?

I don't have any device older than 4.1 to test on. I'm trying to test out pushing my notifications with the code below. It's mostly all taken from the Notification documentation. Would my code crash or does the NotificationCompat class handle all of this for me gracefully?
Under the "Handling Compatability" section it reads:
Handling compatibility
Not all notification features are available for a particular version,
even though the methods to set them are in the support library class
NotificationCompat.Builder. For example, action buttons, which depend
on expanded notifications, only appear on Android 4.1 and higher,
because expanded notifications themselves are only available on
Android 4.1 and higher.
To ensure the best compatibility, create notifications with
NotificationCompat and its subclasses, particularly
NotificationCompat.Builder. In addition, follow this process when you
implement a notification:
...
So does this mean that if I use the NotificationCompat class it will handle all of the compatibility for me?
My code that I'm worried about (because it uses BigTextStyle):
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mContext).setSmallIcon(R.drawable.ic_launcher).setContentTitle("Title")
.setContentText(String.format("%s", message));
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(mContext, ActivityMain.class);
// The stack builder object will contain an artificial back stack for
// the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
// Add max priority
mBuilder.setPriority(NotificationCompat.PRIORITY_MAX);
// Add bigTextStyle
NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
bigTextStyle.bigText(String.format("%s", message));
mBuilder.setStyle(bigTextStyle);
mBuilder.setAutoCancel(true);
// mId allows you to update the notification later on.
mNotificationManager.notify(1, mBuilder.build());
You have nothing to worry about.
Helper class for generating large-format notifications that include a lot of text.
If the platform does not provide large-format notifications, this method has no effect. The user will always see the normal notification view.
(NotificationCompat.BigTextStyle)

how many notifications can an android app have?

I have thought that any android app can have only one alive notification.
But I now read in the documentation that:
You call cancelAll(), which removes all of the notifications you previously issued.
meaning there can be multiple notification living at the same time?
to my mind , yes. but,
You need to add a unique ID to each of the notifications so that they do not combine with each other.
private static final int NOTIFICATION_ID =1;
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(NOTIFICATION_ID, builder.build());

Categories

Resources