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);
Related
I am trying to stream voice/audio (two way) between two Android devices Tablet and Mobile (over java sockets).
The Tablet can play received audio(voice) clearly, but the Mobile plays received audio as noise.
Then i set this audio mode in the code on tablet:
audioManager.setMode(AudioManager.MODE_IN_CALL);
This now results in Mobile receiving clear voice.
But the tablet goes silent, it does not play the received audio (or rather its not audible).
I am not sure what combination (if any) of AudioManager mode i should use here?
It's possible to handle the sound you want to play as Alarm.
Create a new class named AlarmController and try this code.
This worked for me on Android 4.4.2 (Huawei ascend P7) with each system volume (Media, Ringtone, Alarm) set to 0.
Context context;
MediaPlayer mp;
AudioManager mAudioManager;
int userVolume;
public AlarmController(Context c) { // constructor for my alarm controller class
this.context = c;
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
//remeber what the user's volume was set to before we change it.
userVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
mp = new MediaPlayer();
}
public void playSound(String soundURI){
Uri alarmSound = null;
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
try{
alarmSound = Uri.parse(soundURI);
}catch(Exception e){
alarmSound = ringtoneUri;
}
finally{
if(alarmSound == null){
alarmSound = ringtoneUri;
}
}
try {
if(!mp.isPlaying()){
mp.setDataSource(context, alarmSound);
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.setLooping(true);
mp.prepare();
mp.start();
}
} catch (IOException e) {
Toast.makeText(context, "Your alarm sound was unavailable.", Toast.LENGTH_LONG).show();
}
// set the volume to what we want it to be. In this case it's max volume for the alarm stream.
mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM), AudioManager.FLAG_PLAY_SOUND);
}
public void stopSound(){
// reset the volume to what it was before we changed it.
mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, userVolume, AudioManager.FLAG_PLAY_SOUND);
mp.stop();
mp.reset();
}
public void releasePlayer(){
mp.release();
}
I hope this works for you. :)
sir, is it possible to ring an alarm even when ringer is muted? if yes, how. and also, can i set its volume to something in between and not just maxvolume? thanks in advance
for (SmsMessage msg : messages) {
if (msg.getMessageBody().contains("firealert")) {
Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
if(alert == null){
// alert is null, using backup
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
if(alert == null){
// alert backup is null, using 2nd backup
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
}
}
Ringtone r = RingtoneManager.getRingtone(context.getApplicationContext(), alert);
AudioManager audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
int maxVolumeAlarm = audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM);
int maxVolumeRing = audioManager.getStreamMaxVolume(AudioManager.STREAM_RING);
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, maxVolumeAlarm,AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
audioManager.setStreamVolume(AudioManager.STREAM_RING, maxVolumeRing,AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
r.play();
Toast.makeText(context.getApplicationContext(), "alarm started", Toast.LENGTH_LONG).show();
}//end if
}//end for
Things to look at:
AudioManager.getRingerMode / setRingerMode. Set it to RINGER_MODE_NORMAL to ensure the phone isn't muted or set to vibrate. (Although you might want to check the state first, so you can store it and reset the value after your alarm is cleared.)
if ( aManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL )
aManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
If you want to set volume to 50% then check AudioManager.getStreamMaxVolume and then divide that by 2, for example. It would probably be better to let the user configure it, though. Use a SeekBar to have him set a preferred volume (which, again, you could reset back to normal after your alarm plays).
RingerVolumeBar = (SeekBar) findViewById(R.id.seekBar1);
RingerVolumeBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener()
{
#Override
public void onProgressChanged(SeekBar seekBar,
int progress, boolean fromUser)
{
aManager.setStreamVolume(AudioManager.STREAM_RING,
progress, AudioManager.FLAG_PLAY_SOUND);
// record new setting so you can load it up or reset it back later
...
}
});
I have a working alarm app, but wanted to add a feature where the user gets the choice between "Play alarm continuously till acknowledged" and "play alarm sound once".
I then looked at my alrm ringing code expecting to see some kind of "repeat" flag which I could optionally remove - but there was none. So how do I play the alarm sound just once?
My existing code looks like this:
private void playSound(Context context, Uri alert)
{
mMediaPlayer = new MediaPlayer();
try
{
mMediaPlayer.setDataSource(context, alert);
final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0)
{
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mMediaPlayer.prepare();
mMediaPlayer.start();
}
}
catch (IOException e)
{
// oops!
}
}
Actually in each alarm sound there is a FLAG named ANDROID_LOOP which force your sound to loop. Unfortunatly you can't change that flag even using MediaPlayer.setLooping(false).
But you still can manually stop your player after a certain time. For example getDuration will give you the length of your sound.
int duration = mMediaPlayer.getDuration();
Runnable stopSoundRunnable = new Runnable() {
#Override
public void run() {
mMediaPlayer.stop();
}
};
mSoundHanlder.postDelayed(stopSoundRunnable, duration);
I am writing an application on android 4.0 which will play the current ringtone when I press a button.
But in the ringtone is played only one time. I need it to repeat for a few times.
My current code:
Uri notifi = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
final Ringtone r = RingtoneManager.getRingtone(c, notifi);
r.play();
Try this code I have used this before and able to play Ringtone continuously until you stop
try {
Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(this, alert);
final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (audioManager.getStreamVolume(AudioManager.STREAM_RING) != 0) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
mMediaPlayer.setLooping(true);
mMediaPlayer.prepare();
mMediaPlayer.start();
}
} catch(Exception e) {
}
Tried the above codes on lollipop and only this worked for me
//activating looping ringtone sound
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
player = MediaPlayer.create(this, notification);
player.setLooping(true);
player.start();
You can have a timer regularly check if the ringtone is still playing. For example, every second:
mRingtone.play();
mTimer = new Timer();
mTimer.scheduleAtFixedRate(new TimerTask() {
public void run() {
if (!mRingtone.isPlaying()) {
mRingtone.play();
}
}
}, 1000*1, 1000*1);
I have read that ringtone has to have ANDROID_LOOP tag. Ref: http://xanderx.com/2010/08/25/making-ringtones-loop-on-android/
You can also try to play this file using AudioManager and set it looping. Ref: http://developer.android.com/reference/android/media/MediaPlayer.html#setLooping(boolean)
I achieved this issues by set looping true with Ringtone and ringtone manager.
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.setLooping(true);
r.play();
Here I am starting ringtone and when we want to stop ringtone we can call
r.stop();
method to stop ringtone
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.