I have searched for this, so apologies if this has been answered already (I am happy to be redirected), but specifically our issue is intermittent.
Our clients are complaining that the notification audio is, intermittently, not 'chiming' when an event is sent to their phones from our software. It will work fine for a time, then 'just stop for a few hours' (extrapolating from the complaints of our customers).
We've not been able to reproduce this in house, but the frustration we are getting from our customers is such that we really need to fix it.
Our customers insist they are not making phone calls, playing audio or running other software, and from seeing their phones, I largely believe them.
We have noticed this largely on Jellybean, as this is what most of our clients are running, however it may not be isolated to this case.
Am I doing something wrong, or is there a better way to 'chime' for a notification. At this stage I am happy to try something different
void updateNotification()
{
Notification.Builder builder = new Notification.Builder(_context);
// Set the appearance of the notification:
int icon;
String title;
String description;
// ...
//CODE setting icon, title and description
// ...
builder.setSmallIcon(icon);
builder.setContentTitle(title);
builder.setContentText(description);
builder.setTicker(description);
// Set the sound for the notification:
builder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM));
Intent intent = new Intent(_context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra(MainActivity.EXTRA_TAB, MainActivity.EXTRA_TAB_TASKS);
builder.setContentIntent(PendingIntent.getActivity(_context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
// Update the notification:
NotificationManager manager = (NotificationManager)_context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(_notificationId, builder.build());
}
For some reason, I noticed some devices mute all volumes (including the alarm volume) when they are put on silent or vibrate mode. And in those modes, for these devices, this volume can't be changed unless you change the mode.
I had users complaining of a similar problem and had to handle it by forcing a change of mode to ensure the volume is high enough. I then played the audio and switched the mode back to the original configuration.
Edit: Here is a post from a user complaining about this. Notice on the screenshot there that the volume button for "alarms" is disabled on mute.
Edit 2: In my particular case, I run the following check to see if I need to increase the volume:
if (audioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL
&& audioManager.getStreamVolume(AudioManager.STREAM_ALARM) == 0) {
// Save current state and increase the volume
}
Whilst the answer #Ricardo gave is certainly worth including in your code, and I have left it in ours, my problem was largely due to the phone's power-management (this may have been obvious, but I'm newish to Android development).
Our notifications are required to be delivered when sent, and our user's phones were going into sleep mode, so we added a WakeLock (though, caring for their battery life, we only have it 'on' when the user was 'Signed In' to our app. At the end of their shift, the WakeLock was released).
Related
Context
I am working on an app that uses FCM. The use of this application is to alert a user of an event that is occurring (such as an alarm system). In view of the alarm nature of the notification, it is essential that a sound is played when receiving a notification even if the smartphone is in silent or vibrate mode.
Question
Is there a way to achieve this described behavior for all smartphone modes (silent, vibrate, sound) ?
What I've tried
As I am working with API26> I created a notification channel to have the highest priority which is Max Priority,
I've set the notification channel to bypass Do Not Disturb mode like so:
notificationChannel.SetBypassDnd(true);
Obviously it only affects the Do Not Disturb mode and absolutely not what I want,
In the notification builder, I've set the notification priority to Max and the category to Alarm:
.SetPriority(NotificationCompat.PriorityMax)
.SetCategory(NotificationCompat.CategoryAlarm);
Reading the Android documentation, this feature is also related to Do Not Disturb Mode.
I am actively looking for a solution to this problem, but at this point I'm a bit stuck.
Any suggestions ?
I've read about a full screen intent in the Android documentation but it's not written that a sound will fire if the smartphone is in silent mode.
Maybe there is a way to create a service that rings when the notification arrives? But this service has to be running all the time, which isn't really a good design idea.
If you guys have any idea, any remarks or suggestions, i'd be grateful to read them !
I believe you need to set priority for your notification.
private fun setPriorityForAlarmNotification() {
if (notificationManager.isNotificationPolicyAccessGranted) {
notificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val policy = NotificationManager.Policy(PRIORITY_CATEGORY_ALARMS, 0, 0)
notificationManager.notificationPolicy = policy
}
}
}
As I can see you setCategory for your notification builder is NotificationCompat.CategoryAlarm.
However, in order to set this priority, you need this permission on your manifest
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
And request permission if needed
fun requestNotificationPolicyPermission() {
val notificationManager = activity!!.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (!notificationManager.isNotificationPolicyAccessGranted) {
val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)
startActivityForResult(intent, REQUEST_CODE_NOTIFICATION_POLICY)
}
}
This solution should work absolutely. Hope this can help you :D
I'm an Android app developer, and is developing an instant message app. The app has a notification problem on Android Oreo system, which shows persistent notification "App is running in the background" and cannot be cleared, and it's OK on system before Android Oreo.
Screenshot: The phone shows persistent notification App is running in the background
I find some discussion, such as Nexus Help Forum about this question, but it doesn't work in my phone's settings.
I want to know how to hide this notification programmatically and the app also can receive message instantly because it's an instant message app.
Any help is very appreciated.
The app has a notification problem on Android Oreo system, which shows persistent notification "App is running in the background" and cannot be cleared, and it's OK on system before Android Oreo.
You used startForeground() with a minimum-importance Notification.
I want to know how to hide this notification programmatically
Use startForeground() with a Notification that has higher than minimum importance. Or, do not use startForeground().
I find some install message apps such as WeChat, Facebook doesn't have this problem on Android Oreo
They are not using foreground services, presumably. For example, they might be using Firebase Cloud Messaging (FCM).
Before we talk about how to get rid of it, however, let’s talk about why it’s there in the first place.
Basically, in previous versions of Android, there was no real way of knowing if an app was running in the background doing a bunch of stuff it’s not supposed to be doing. In most scenarios, these misbehaving apps would wreak havoc on the battery by keeping the system awake—these are called “wakelocks.” In laymen’s terms, it was keeping the system from sleeping. That’s bad.
With Oreo, Google is calling out developers that let their apps do this sort of thing with the new notification. Essentially, if an app is running in the background and chewing up battery life, this new notification will tell you.
NOTE: There are a few legitimate scenarios where an app will continuously run in the background, like the VPN service running. Often, however, apps are running in the background unjustifiably.
It’s worth noting, though, removing the notification does not solve the issue. Period. There’s a reason this notification exists, and getting rid of it will do nothing to solve the underlying issue. You’ll either need to change a setting within the app or uninstall it altogether.
As long as you understand that and still want to remove it, let’s do this thing.
Because this is a relatively crucial system setting, there’s no way within Oreo itself to remove it. That makes sense.
But like with most things, the developer community has found a way to remove it, and developer iboalali released an app to do just that. It’s actually just called “Hide ‘running in the background’ Notification,” which is about as straightforward as an app name could ever be. Go ahead and give it an install.
Without root, there is no way to actually prevent Android System from displaying the persistent “app is running in the background” notification in Android 8.0 Oreo. Looking at the source code for the ForegroundServiceController, its implementation, and the ForegroundServiceDialog doesn’t really reveal anything we can take advantage of. Programatically nothing have been found so far.
Here's a Blog post that can help you
First, you must have the NotificationListenerService implementation. Second, in this service (after onListenerConnected callback), check the active ongoing notifications with packageName called 'android'. And check this notification's title is your app name or text value is 'App is running in the background' and snooze it.
public class NLService extends NotificationListenerService {
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {}
#Override
public void onListenerConnected() {
super.onListenerConnected();
checkOngoingNotification();
}
#Override
public void onNotificationPosted(StatusBarNotification sbn){
if(sbn.isOngoing()) {
checkOngoingNotification();
return;
}
}
private void checkOngoingNotification() {
StatusBarNotification[] activeNotifications = getActiveNotifications();
Log.i("NLService", "Active notifications size : " + activeNotifications.length);
for (StatusBarNotification statusBarNotification : activeNotifications) {
Log.i("NLService", "notification package : " + statusBarNotification.getPackageName());
Log.i("NLService", "notification id : " + statusBarNotification.getId());
Log.i("NLService", "notification key : " + statusBarNotification.getKey());
Log.i("NLService", "isOngoing : " + statusBarNotification.isOngoing());
Log.i("NLService", "isClearable : " + statusBarNotification.isClearable());
Log.i("NLService", "groupKey : " + statusBarNotification.getGroupKey());
Notification notification = statusBarNotification.getNotification();
CharSequence title = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
CharSequence text = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
if (title != null && text != null) {
Log.i("NLService", "title : " + title);
Log.i("NLService", "text : " + text);
if (statusBarNotification.getPackageName().equals("android") &&
(title.toString().contains("Your App Name") || text.toString().contains("App is running"))) {
long snoozLong = 60000L * 60L * 24L * 20L;
this.snoozeNotification(statusBarNotification.getKey(), snoozLong);
Log.i("NLService", "Snoozed notification : " + title);
}
}
}
}
It turns out startForeground() with channel's IMPORTANCE_MIN is not only one source of the notification. If you call startForeground() and give it notification without setSmallIcon() result will be the same.
https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/am/ServiceRecord.java#816
Also you could find in logs something like that:
ActivityManager: Attempted to start a foreground service (ComponentInfo{com.example.app/com.example.app.ExampleService}) with a broken notification (no icon: Notification(channel=channel_example pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0x00000000 vis=PRIVATE))
In Lollipop and below, you could easily send a sound only notification by omitting the icon, content title and content text when constructing, like so:
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setSound(Uri.parse(ringtone));
notificationManager.notify(9998, builder.build());
In Marshmallow, I'm forced to include at least an icon, or I get a 'no valid small icon' exception. I want to use the Notification system, but don't always want to display a notification in the notification bar. Is this possible with Marshmallow, or should I change to playing my notification sound with media player, even though sometimes I, or the user, may want to display a notification?
I read somewhere that the docs said icon was required even thought it didn't throw an exception when omitted in Lollipop and below. After looking into using MediaPlayer, I finally decided to use RintoneManager to play it. I am using the notification sounds, so may as well save myself some typing and do a quick
try {
RingtoneManager.getRingtone(getApplicationContext(), Uri.parse(ringtone)).play();
} catch (Exception e) {
e.printStackTrace();
}
to trigger the sound, I'll save the notification for when I need an actual notification. I was already planing on using if, depending on whether or not the notification should appear in the notification bar.
On Android L, I would like show the user a notification on the lock screen only if the user settings is set to "show all notification content", otherwise the content will be pointless and I just prefer not to show the notification at all.
Any idea how to verify in code the user notification settings?
Thanks!
You need to read
Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS = "lock_screen_allow_private_notifications"
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications"
only if both are 1 then you need to show your notifications.
But since these values are not part of public api, these might change in future, or might not work on all devices
int show_all = Settings.Secure.getInt(getContentResolver(),"lock_screen_allow_private_notifications", -1);
int noti_enabled = Settings.Secure.getInt(getContentResolver(),"lock_screen_show_notifications", -1);
if(show_all > 0 && noti_enabled > 0){
//post noti
}
You can't check that setting as far as I know, but your app can control the level of detail visible when its notifications are displayed over the secure lock screen. To control the visibility level, call setVisibility() (Notification.Builder.setVisibility) and specify one of these values:
VISIBILITY_PUBLIC: Shows the notification’s full content.
VISIBILITY_PRIVATE: Shows basic information, such as the notification’s icon, but hides the notification’s full content.
VISIBILITY_SECRET: Shows nothing, excluding even the notification’s icon.
When the visibility level is VISIBILITY_PRIVATE, you can also provide a redacted version of the notification content that hides personal details. For example, an SMS app might display a notification that shows "You have 3 new text messages" but hides the message content and senders. To provide this alternative notification, first create the replacement notification using Notification.Builder. When you create the private notification object, attach the replacement notification to it through the setPublicVersion() method.
Sources
I've implemented red LED light for my notifications for test purposes, but...
Do I have to check if the device has LED (in case that device doesn't have this feature) and if so how to do it? Also, are LED colors predetermined?
I tried to find some docs or thread that would give me an answer for these questions but had no luck...
There is no way of doing this.
According to Can I detect the presence/absence of 'LED notification' on an Android device?
Most hardware features are exposed via the package manager:
PackageManager pm = getActivity ().getPackageManager ();
boolean hasBluetooth = pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
But not this one.
There is a feature request on record as well:
https://code.google.com/p/android/issues/detail?id=38481
You don't have to check the availability of the LED. the code won't crash even if there is no LED. you can set any color as a hexadecimal color code.
Notification notification = new Notification();
notification .ledARGB = 0xFFff0000;
notification .flags = Notification.FLAG_SHOW_LIGHTS;