How to set notification sound volume programmatically? - android

I have this method in my main activity
private void beep()
{
AudioManager manager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
manager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, 0,
AudioManager.FLAG_SHOW_UI + AudioManager.FLAG_PLAY_SOUND);
Uri notification = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(),
notification);
r.play();
}
As I understand, notification sound volume should be regulated by STREAM_NOTIFICATION. But notification always plays with the same volume despite that volume number in setStreamVolume method. Why is that?

I went another way. It's not exactly answer to my question but appropriate one. When I play notification in STREAM_MUSIC everything is fine. So notification plays exactly with volume I pass as parameter to the function
private void beep(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();
}

First of all, I hope you realize that you are attempting to play two notifications right after each other, so there might be a conflict about that. AudioManager.FLAG_PLAY_SOUND and r.play() will both try playing the sound. It is usually enough to give user one type of information, either by UI or by playing the beep with new volume. I suggest you delete one of the flags. If you don't need any, just give it 0.
Coming to the main question, I am not sure if you can set volume level to 0. Try putting 1, like
manager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, 1, AudioManager.FLAG_SHOW_UI);
If you want to mute the notification, try using setStreamMute, which is equivalent to setting the volume to 0.

For my case eventually this seemed to be working.
It would make your audio volume relative to the stream current volume but it was useful for my need.
MediaPlayer player = MediaPlayer.create(getApplicationContext(), notificationUri);
player.setVolume(toneLevel, toneLevel);
toneLevel is between 0.0 - 1.0 so you don't even need to find the range of your stream..

Write a function as follow, or copy and paste the following,
public void ringtone() {
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
} catch (Exception e) {}
}
and call ringtone() when you want to make a beep notification.

Related

After Unmute phone when call came only vibrate phone, not able to play ringtone

I'm building an Android app that unmute phone when an Incoming call came in phone.
I use BroadcastReceiver to receive incoming call events. I switch phone from mute mode to Ring Mode when BroadcastReceiver receive incoming call events.
And expect Phone will vibrate and Play ringtone.
But Phone only vibrate, can't play ringtone though phone ring set to max sound.
I found many apps on play store those can unmute before call and play ringtone and vibrate both. Example: One App Link
My code Below:
public void onReceive(Context context, Intent intent) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_RING);
if (intent.getAction()!=null && intent.getAction().equals("android.intent.action.PHONE_STATE")){
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
audioManager.setStreamVolume(AudioManager.STREAM_RING, maxVolume/2, AudioManager.FLAG_PLAY_SOUND);
}
}
}
I'm working on something very similar. You actually have to play a ringtone after overriding the audio settings. But you only need to do this on Android 6.0+ Get an instance of the ringtone and play it when phone state is ringing else just stop it.
public void onReceive(Context context, Intent intent) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_RING);
Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
Ringtone r = RingtoneManager.getRingtone(context, uri);
if (intent.getAction()!=null && intent.getAction().equals("android.intent.action.PHONE_STATE")){
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
audioManager.setStreamVolume(AudioManager.STREAM_RING, maxVolume/2, AudioManager.FLAG_PLAY_SOUND);
r.play();
}else {
r.stop();
}
}
}
Problems you'll run into with this implementation. You will get multiple ringtones playing because the onReceive method is called many times during Phone State changes. The provides a different context each time onReceive is called and creates a different instance of Ringtone each time. I launched a background service to fix this issue so I could hold a single reference to a context and thus a single reference to Ringtone.
Some devices may not have volume control and may operate at a fixed volume, and may not enable muting or changing the volume of audio streams.
isVolumeFixed()
This method will return true on such devices.

Notification with sound although phone is muted

I am creating a notification with Android's NotificationManager.
Is it possible to 'override' the phone's volume (mute) settings in such a way, that the notification's sound is ALWAYS played?
The reason I need this is the following:
The notification is so important, that vibration alone may not be enough. The user MUST be alerted. So a sound shall be played, even if the phone is muted or the volume is very low.
yes it is possible,
MediaPlayer mMediaPlayer;
Uri notification = null;
notification = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_ALARM);
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(ctx, notification);
// mMediaPlayer = MediaPlayer.create(ctx, notification);
final AudioManager audioManager = (AudioManager) ctx
.getSystemService(Context.AUDIO_SERVICE);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mMediaPlayer.prepare();
// mMediaPlayer.start();
mMediaPlayer.setLooping(true);
mMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer arg0) {
mMediaPlayer.seekTo(0);
mMediaPlayer.start();
}
});
You can change RINGING mode like this from silent to normal
AudioManager mobilemode = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mobilemode.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
// Turn on all sound
// turn on sound, enable notifications
mobilemode.setStreamMute(AudioManager.STREAM_SYSTEM, false);
//notifications
mobilemode.setStreamMute(AudioManager.STREAM_NOTIFICATION, false);
//alarm
mobilemode.setStreamMute(AudioManager.STREAM_ALARM, false);
//ringer
mobilemode.setStreamMute(AudioManager.STREAM_RING, false);
//media
mobilemode.setStreamMute(AudioManager.STREAM_MUSIC, false);
// Turn off all sound
// turn off sound, disable notifications
mobilemode.setStreamMute(AudioManager.STREAM_SYSTEM, true);
//notifications
mobilemode.setStreamMute(AudioManager.STREAM_NOTIFICATION, true);
//alarm
mobilemode.setStreamMute(AudioManager.STREAM_ALARM, true);
//ringer
mobilemode.setStreamMute(AudioManager.STREAM_RING, true);
//media
mobilemode.setStreamMute(AudioManager.STREAM_MUSIC, true);
FOR YOUR CASE YOU CAN TRY SOMETHING LIKE THIS
int previousNotificationVolume =mobilemode.getStreamVolume(AudioManager.STREAM_NOTIFICATION);
mobilemode.setStreamVolume(AudioManager.STREAM_NOTIFICATION,mobilemode.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION), 0);
// Play notification sound
// Set notification sound to its previous
mobilemode.setStreamVolume(AudioManager.STREAM_NOTIFICATION,previousNotificationVolume, 0);

Play my sound over the default notification sound when needed

On onReceive method when i get a new message, after i do some checkups and see that the address number is the one i want.
Is it possible to play my notification sound instead of the default message sound? And if a normal message comes then the default sound will play.
The thing is that the phone plays the sound first, and then my application, so there is a conflict there.
Ive searched for an answer but i couldnt find anything.
What i do is kind of unefficient. I play my sound 6 seconds after the default notifications plays like this:
private Runnable task = new Runnable() {
public void run() {
Uri alarmSound = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_ALARM);
Ringtone r = RingtoneManager.getRingtone(
getApplicationContext(), alarmSound);
r.play();
}
};
private void delayNotification() {
Handler handler = new Handler();
int millisDelay = 6000;
handler.postDelayed(task, millisDelay);
}
I know its not a good way to do it so thats y i came here:P
notification.sound =Uri.parse("android.resource://"+context.getPackageName()+"/"
+R.raw.tone);

Ringtone plays over and over again (looping infinitely)

I have an Android app that plays a notification ringtone (RingtoneManager.TYPE_NOTIFICATION) when certain events are sent to a BroadcastReceiver.
The code that plays the ringtone basically does:
onReceive(Context context, Intent intent)
{
...
Uri ringtoneUri = someFunctionToLookupAValidNotificationRingtoneUri();
...
Ringtone tone = RingtoneManager.getRingtone(context, uri);
Log.v(TAG, "About to play ringtone");
tone.play();
}
Every so often when this code is run, the ringtone starts playing over and over again infinitely. Sometimes it happens when a large number of events are bunched close together, but it has also happened when only one event came in. The log message (and debugging) verifies that the tone.play() call is happening only once per event, and there isn't an infinite stream of events.
The only way stop the infinite looping is to kill my app.
It's almost as if every so often, Android forgets to flush the sound output buffer and so it keeps looping through playing whatever is inside.
Any ideas how to debug and/or fix this issue?
I had a similar problem. It turned out that when a ringtone is played, it will repeat indefinitely until stopped, whereas when a notification sound is played, it will play only once. So my guess is that the difference in your case lies in whether a ringtone or a notification sound was selected in someFunctionToLookupAValidNotificationRingtoneUri(). As you do not supply the code for someFunctionToLookupAValidNotificationRingtoneUri(), I cannot know what happens there.
Picking a notification sound
If you use a ringtone picker for the user to select a notification sound, this code will start the intent to pick a notification sound as opposed to a ringtone:
private void PickANotificationSound() {
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
// We want a notification sound picked. If we don't add this to the
// intent, a ringtone is picked; this means that when it is played,
// it will keep on playing until it is explicitly stopped. A
// notification sound, however, plays only once.
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE,
RingtoneManager.TYPE_NOTIFICATION);
// Start the intent to pick a notification sound. The result will show
// up later when onActivityResult() is called.
startActivityForResult(intent, REQUESTCODE_NOTIFICATION_SOUND);
}
where REQUESTCODE_NOTIFICATION_SOUND is just a local constant with any name and value, identifying the request:
private static final int REQUESTCODE_NOTIFICATION_SOUND = 1;
An onActivityResult() callback function like this will then pick up the notification sound URI and play it:
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == REQUESTCODE_NOTIFICATION_SOUND) {
try {
if (resultCode == RESULT_OK) {
Uri ringtoneUri = data.getParcelableExtra(
RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
if (ringtoneUri != null) {
PlayRingtoneOrNotificationSoundFromUri(ringtoneUri);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else
super.onActivityResult(requestCode, resultCode, data);
}
private void PlayRingtoneOrNotificationSoundFromUri(Uri ringtoneUri) {
Ringtone ringtone = RingtoneManager.getRingtone(
getApplicationContext(), ringtoneUri);
if (ringtone != null) {
ringtone.play();
}
}
Because we said in the intent that we wanted to pick a notification sound, the resulting sound is a notification sound and is therefore only played once after the call to ringtone.play().
If we had said in the intent that we wanted to pick a ringtone, like this:
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE,
RingtoneManager.TYPE_RINGTONE);
the picker would return a ringtone that would play indefinitely after the ringtone.play() call – until stopped by ringtone.stop() or the application was killed.
Two meanings of 'ringtone'
Note that the terminology in the Android API adds to the confusion, as the word "ringtone" is used with two different meanings (cf. the documentation of RingtoneManager):
Any sound meant to catch the user's attention, such as a sound to play repeatedly when the phone rings, a notification sound, or a similar sound. This meaning is used in the name RingtoneManager.
A sound to play repeatedly when the phone rings, as opposed to a notification sound or a similar sound. This meaning is used in the name TYPE_RINGTONE in RingtoneManager.TYPE_RINGTONE.

setRingerMode during incoming call - RINGING

I have a task - change the ringer volume immediately when phone ringing. For example:
After detecting, that there is incoming call I need to set ringer volume to 0 (mute) and vibrator also should be disabled (if it not disabled already). Then there is delay when I need to perform another code (startComputing();). After that ringer volume should be changed to certain value (f.e.7) and vibrator should be activated. Here is my code:
public class IncomingCallReceiver extends BroadcastReceiver {
private AudioManager amanager;
public void onReceive(Context context, Intent intent) {
if(intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
amanager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
amanager.setRingerMode(0x00000000); // no sound and no vibration
startComputing();
amanager.setRingerMode(0x00000002); // normal
amanager.setStreamVolume(AudioManager.STREAM_RING, 7,
AudioManager.FLAG_SHOW_UI
+ AudioManager.FLAG_PLAY_SOUND);
}
}
private void startComputing() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1)The main problem is that after this: amanager.setStreamVolume(AudioManager.STREAM_RING, 7, AudioManager.FLAG_SHOW_UI + AudioManager.FLAG_PLAY_SOUND);
ringer does not ring at all, only toast message appears that sound level changed but phone does not play any sound. How this can be changed?
2)Also there is problem that amanager.setRingerMode(0x00000000); does not change Volume and vibration immediately but just in about half a sec.
Thank You in Advance.
Jacob
I don't think there is anything you can do to overcome the 1/2 sec delay before you mute the ringer. Sometimes it works (ie very short or no delay), sometimes you will hear the ringer for a short period of time.
I think the problem you are having is with the flags passed to setStreamVolume.
Try this:
amanager.setStreamVolume(AudioManager.STREAM_RING, 7,
AudioManager.FLAG_SHOW_UI|AudioManager.FLAG_PLAY_SOUND);
You should be using the bitwise inclusive or (|), and not simple addition (+).

Categories

Resources