setRingerMode() mutes MediaPlayer on tablet? - android

Android 4.2.2. On my Nexus 7 tablet, setting the ringer mode to RINGER_MODE_SILENT effectively mutes any active MediaPlayer of my activity:
audioManager = (AudioManager)getSystemService(Service.AUDIO_SERVICE);
audioManager.setRingerMode(RINGER_MODE_SILENT);
I'm convinced this is a bug. Has anybody seen this before? And more importantly, is there a workaround?

I'm convinced this is a bug
That could be intentional and I think you can check if the device supports voice calls before changing the ringer mode (after all, ringer modes are to be used for calls only?). Hence,
if (isVoiceCapable(context)) {
audioManager = (AudioManager)context.getSystemService(Service.AUDIO_SERVICE);
audioManager.setRingerMode(RINGER_MODE_SILENT);
}
...
private boolean isVoiceCapable(Context context) {
TelephonyManager telephony =
(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
return telephony != null && (telephony.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE);
}
Hope this helps.

Related

Android - some devices not playing audio through earpiece

There seems to be an issue while trying to play audio files on earpiece in some android devices. Expected behaviour is it should play the audio file in earpiece but in some devices like Samsung galaxy note 2 ( Android version 4.4.2) and Sony Xperia XA ( Android version 6.0) it plays them through speakers.
However in devices like Motorola moto g (android version 6.0) and nexus 5X (android version 7.0) it works fine.
The app also has the android.permission.MODIFY_AUDIO_SETTINGS permission.
Please find the details of this issue below.
Before playing an audio I set the following properties:
audioManager = (AudioManager)configService.getContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setSpeakerphoneOn(isEnabled);
player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
player.setDataSource(path);
I have tried setting mode to MODE_IN_CALL, but that didn't work either:
audioManager.setMode(android.media.AudioManager.MODE_IN_CALL);
I have also tried solutions from other posts asking similar questions but they didn't help much.
It would be helpful to know whether this issue is device specific and how to fix the same.
Thanks for the help.
Finally i found the solution. When registering for intent ACTION_HEADSET_PLUG in BroadcastReceiver, it was broadcasting sticky intent for the headset unplugged event which was saved from the past event. This was causing the callback to fire which played the audio through speaker only.
Refer to the following stack overflow post for further details: link
To fix the issue i used isInitialStickyBroadcast() method to filter out the past events.
public void onReceive(Context context, Intent intent) {
switch (intent.getIntExtra("state", -1)) {
case 0:
if (!isInitialStickyBroadcast()) {
// headset unplugged
}
break;
case 1:
// headset plugged in
break;
default:
break;
}
}
I've been using ACTION_HEADSET_PLUG but had the same problem with playing sound through earpiece on some devices 6.0 +. My solution is to use AudioAttributes for devices with version higher then LOLLIPOP :
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes mAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
.build();
mMediaPlayer = MediaPlayer.create(this, R.raw.connection, mAttributes, 1);
} else {
mMediaPlayer = MediaPlayer.create(this, R.raw.connection);
}

AudioManager.setStreamMute not working in android 5 Lollipop

I'm developing a spam call filtering app and I'm trying to silence ringer for incoming (spam) call. The problem is none of AudioManager.setStreamMute nor AudioManager.setRingerMode is working in Lollipop. Here is my code snippet:
public class CallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
AudioManager audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamMute(AudioManager.STREAM_RING, false);
Log.i(TAG, "unmute");
} else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
AudioManager audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamMute(AudioManager.STREAM_RING, true);
Log.i(TAG, "mute");
}
}
When there's an incoming call, the mute part always gets executed but it sometimes succeeds and sometimes fails to mute the ringer. I can't find any rule. And audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT) doesn't work either. This seems work fine when tested on emulators < 5, so I guess it's somehow related to Lollipop not having silent mode but interruptions filter. Commercial spam call filters are woking fine, so can somebody let me know how I could silence incoming calls with Lollipop?
I've got the same issue for android 5. AudioManager.setStreamMute with the value false to unmute is never working.
I tried AudioManager.setStreamSolo and it worked for me.
//to mute ringtone
Global.app().getAudioManager().setStreamSolo(AudioManager.STREAM_MUSIC, true);
//unmute ringtone
Global.app().getAudioManager().setStreamSolo(AudioManager.STREAM_MUSIC, false);
It mutes all other streams except one you want to play. In may case I needed to play my own audio instead of ringtone.
But you can try to play a silence audio to hack if you need absolute silence.

Why changing ringer mode in android does not require permissions?

I wrote a code to change the ringer mode:
private void changeRingerMode() {
AudioManager audMangr;
audMangr = (AudioManager) getBaseContext().getSystemService(
Context.AUDIO_SERVICE);
audMangr.setRingerMode(AudioManager.RINGER_MODE_SILENT);
}
I am surprised that this one does not require any permission, whereas changing the brightness requires one. I tested it on a ginger bread phone.
Any idea why this works this way?

Unmute stream in silent mode

I'm writing app that should play sound notification even in silent mode. I don't want to temporarily turn off Silent and roll it back late. I'm using ALARM stream for that now. Usually it works proper, because by default ALARM stream not muted in silent. But sometimes it is.
How can I understand if stream currently muted (in silent mode)?
How can I unmute it (without switching to normal mode)?
Answering my own question:
The solution was found in Android OS sources (in standard Alarm app).
I had found way to check and set option "Alarm in Silent":
private static final int ALARM_STREAM_TYPE_BIT =
1 << AudioManager.STREAM_ALARM;
public static void setAlarmInSilent(boolean on) {
int ringerModeStreamTypes = Settings.System.getInt(
context.getContentResolver(),
Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
if (on) {
ringerModeStreamTypes &= ~ALARM_STREAM_TYPE_BIT;
} else {
ringerModeStreamTypes |= ALARM_STREAM_TYPE_BIT;
}
Settings.System.putInt(context.getContentResolver(),
Settings.System.MODE_RINGER_STREAMS_AFFECTED,
ringerModeStreamTypes );
}
Link to the Android src: https://android.googlesource.com/platform/packages/apps/AlarmClock/+/donut-release2/src/com/android/alarmclock/SettingsActivity.java

Android: Checking if headphones are plugged in

How can I check if headphones are currently plugged in. I don't want a broadcastreceiver which informs me when they have been connected to the device. I need something like:
if(/*headphone is connected*/)
...
It looks like you'll be interested in the isWiredHeadsetOn() method and isBluetoothA2dpOn() method of the AudioManager class.
However, the isWiredHeadsetOn() method is only available in Android 2.0 or later. (The isBluetoothA2dpOn() method has been available since Android 1.5.)
Use this code snippet
AudioManager am1 = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
Log.i("am1.isWiredHeadsetOn()", am1.isWiredHeadsetOn()+"");
Log.i("am1.isMusicActive()", am1.isMusicActive()+"");
Log.i("am1.isSpeakerphoneOn()", am1.isSpeakerphoneOn()+"");
This seems to do the job at least on 1.6; not sure whether it's supported in later versions (a is an instance of AudioManager)
boolean headphones = (a.getRouting(a.getMode()) & AudioManager.ROUTE_HEADSET) == AudioManager.ROUTE_HEADSET;

Categories

Resources