I'm developing an app that handles sound and vibration of apps' notifications. I am listening to notifications using NotificationListenerService. I am able to turn on or off notification's sound using AudioManager as follows:
// It turns off notification's sound
myAudioManager.setStreamMute(AudioManager.STREAM_NOTIFICATION, true);
// It turns on notification's sound
myAudioManager.setStreamMute(AudioManager.STREAM_NOTIFICATION, false);
I have also tried to turn on or off notification's vibration with following code but it didn't work on my phone which has Android KitKat 4.4.4
// to turn off notification's vibration
myAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION, AudioManager.VIBRATE_SETTING_OFF);
// to turn on notification's vibration
myAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION, AudioManager.VIBRATE_SETTING_ON);
Here's what I did. In my NotificationListenerService, I cancel the original notification, turn off its vibration, and send it out again. Code like this should work:
Integer key = 1;
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
Notification n = sbn.getNotification();
if (doINeedToDisableVibration(sbn)) {
cancelNotification(sbn.getKey());
n.defaults &= ~Notification.DEFAULT_VIBRATE;
n.vibrate = null;
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
synchronized(key) {
nm.notify(key++, n);
}
}
}
In doINeedToDisableVibration(sbn), either make sure that vibration is on in the notification, or else check that sbn.packageName is NOT the same as your own package name, or you have a danger of generating an endless loop.
I am not sure this will work with all notifications. But it did work with MMS notifications on my HTC One A9 with 6.0.
setVibrateSetting api is deprecated in API 16. As per android developer site,
Applications should maintain their own vibrate policy based on current ringer mode that can be queried via getRingerMode().
So, you try with Ringer mode to enable/disable vibration.
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
for setting silent mode :
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
For normal mode :
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
For ring vibrate mode:
audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
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 am using a NotificationChannel to define my app's notification. I set it's sound with the following code :
AudioAttributes.Builder constructeurAttributsAudio=new AudioAttributes.Builder();
constructeurAttributsAudio.setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT);
canalNotification.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + contexte.getPackageName() + "/raw/cloche"),constructeurAttributsAudio.build());
When the notification appears, the sound is correctly emitted, but it's volume is set at the maximum and doesn't take into account the sound level set for notifications by the user. Does anyone know how I can have my app set the notification sound level to the value choosen by the user?
Edit #1 : if I copy the code to execute it in the app's body (triggered by a Button click) instead of in the onReceive method of my BroadcastReceiver, the notification sound is correctly emitted at the sound level chosen by the user for notifications.
Edit #2 : strangely, the notification sound level is correct when the app is executed on the emulator! Could the reason be a parameter in the phone's configuration? (They both run under Android 9).
Uninstalling and reinstalling the app solved the problem!
I use the following code, hopefully useful for you too:
private void setvolume(int volume)
{
AudioManager manager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
manager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
Uri notification = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
MediaPlayer player = MediaPlayer.create(getApplicationContext(), notification);
player.start();
}
In my app, I have 3 radio button for letting user changing ringer mode of the device. But from android 8 I'm facing one weird issue.
When ringer mode is set from Normal to Silent touch sound is still heard. This is not intended behavior.
But when ringer mode is changed from Normal to Vibrate and then Vibrate to Silent. Touch sound is not heard. This is intended behavior for my app
Now my question why this is happening in Normal to Silent mode.
This are my code for changing ringer mode
Permission for OS 7 and above
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
In my code, I have checked if the user gave me the ACCESS_NOTIFICATION_POLICY permission and if not move him to ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS for giving me the permission and after that I let the user change the setting.
public static void setMannerMode(Context context, int ringerMode) {
try {
AudioManager auManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
auManager.setRingerMode(ringerMode);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I have changed the mode like this according to checked radio button
Util.setMannerMode(getApplicationContext(), AudioManager.RINGER_MODE_NORMAL);
or
Util.setMannerMode(getApplicationContext(), AudioManager.RINGER_MODE_VIBRATE);
or
Util.setMannerMode(getApplicationContext(), AudioManager.RINGER_MODE_SILENT);
Finally i have fixed this touch sound issue while on SILENT mode on OS 8 is by setting NotificationManager.INTERRUPTION_FILTER_NONE in NotificationManager
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);
More info on interruption filter can be found NotificationManager
How can I send a notification with sound and vibration when phone is in do not disturb mode on Android Devices.
I use the following code, and it is working when my application is currently in foreground.
PendingIntent contentIntent = PendingIntent.getActivity(this, NOTIFICATION_ID,
resultIntent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("Notification")
.setStyle(new NotificationCompat.BigTextStyle().bigText("You've received new message."))
.setContentText("You've received new message.");
// FOR SILENT MODE
AudioManager am = (AudioManager) getBaseContext().getSystemService(Context.AUDIO_SERVICE);
// For Normal mode
am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
am.setStreamVolume(AudioManager.STREAM_MUSIC, am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
mBuilder.setVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 });
// Set Vibrate, Sound and Light
int defaults = 0;
defaults = defaults | Notification.DEFAULT_LIGHTS;
// defaults = defaults | Notification.DEFAULT_VIBRATE;
// defaults = defaults | Notification.DEFAULT_SOUND;
mBuilder.setDefaults(defaults);
mBuilder.setSound(Uri.parse("android.resource://" + getPackageName()
+ "/" + R.raw.siren));
// Cancel the notification after its selection
mBuilder.setAutoCancel(true);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
I also want notifications with sound and vibration when my app is in background.
Generally speaking you can't. Even notification with MAX priority wont be shown in DND mode.
The possible workaround that I can imagine is to use android.permission.SYSTEM_ALERT_WINDOW to draw custom notification over system window (FB Messanger works in similar way) : Creating a system overlay window (always on top) .
But this method is suitable only in rare cases and most of the time it's a violation of Android UI/UX best practices.
Ok good news you are half way there.
I achieved this previously by using AudioManager & VIBRATOR_SERVICE (yea I know ;)
The idea is not to use NotificationCompat.Builder because it will rely on system settings and if device is in silent mode, it won't vibrate nor play sound. You have to manually play a sound using AudioManager & vibrate using VIBRATOR_SERVICE.
You are using AudioManager & setting the properties but you are never actually asking it to play the sound. So, in your code its never actually utilized.
Here's an example of how to play a sound using AudioManager, it will also ignore silent mode:
Here's an example of using VIBRATOR_SERVICE:
Combine these 2 approaches and ditch NotificationCompat.Builder
If you can get right permissions to change settings of device, then you could show notifications with sound and vibration at your apps. Also check this out.
My old Nokia phone was flashing hardware buttons when I missed a call. So I was able to understand that I have missed a call just by looking to phone. With my new Android phone I have to reach my phone and wake the screen to see if I have missed a call.
I have searched Android market but could not find exact application to solve my problem. So I have decided to write it. The question is how can I turn on and off back lid of hardware buttons of a android phone?
I have googled it but could not find a clean answer.
Thanks in advance.
Android does have notifications for that purpose, the backlight is not thought to be controlled through the API (you could do it on rooted devices but thats another story).
Personally, I dedinitely do get notifications for missed calls, and my notification LED blinks. However, you can implement your own notifications:
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// create a new notification
CharSequence tickerText = "Missed call";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
// control how the notification led should behave
notification.ledARGB = 0xff00ff00;
// blink for 300ms every 1s
notification.ledOnMS = 300;
notification.ledOffMS = 1000;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
// usually you also want to create a PendingIntent and attach it
// with notification.setLatestEventInfo
// finally, post the notification to the notification manager
notificationManager.notify(HELLO_ID, notification);
There are many other options for notifications, like vibration or FLAG_AUTO_CANCEL, but they are documented very well ;-)
On a rooted device, you could execute the following to control the backlight (however, I would recommend sticking to the intended way, which are notifications):
su
echo 25 > /sys/class/leds/button-backlight-portrait/currents
echo 25 > /sys/class/leds/button-backlight-landscape/currents
where 25 would be the brightness. But admittetly, I don't know for sure if this would even work on all devices.