I've got an app which displays a speakerphone toggle button when used on a phone. The toggle switches audio routing between the phone's earpiece and the speakerphone. However, when the app is run on a tablet (or any device which lacks an earpiece), I'd like to remove the toggle, since all audio is routed through the speakerphone.
Ideally, I'd like to use some kind of isEarpiecePresent()
call, or maybe check a flag on some configuration object to find this information, but I can't find anything of the sort in the API.
I attempted to work around the issue by calling AudioManager.setSpeakerphoneOn(false)
, then checking AudioManager.isSpeakerphoneOn()
, hoping that it would still return true and I could key off of that. The system returned false
, even though audio is still routing through the speaker.
I'm currently thinking of checking for telephony capability, even though that doesn't exactly fit. Any other ideas?
Method 1: Turn your Volume up Now, this might come as a shock, but most of the time, you can't hear phone calls unless on speaker Android only because of a low call volume. And in some cases, zero volume! Before doing anything drastic, this should be the first thing that you should do –– increase your phone's volume.
Check the call and media volume on your Android phone . If it is low or mute, increase the call and media volume and retry. Also, check for dirt particles in your phone's microphone and clean it if it is clogged.
So the ugly part is - Google is ignoring the problem. The pretty part is that I managed to actually do the check for earpiece, and on 5/5 devices it worked fine (tested on 5.0, 5.1, 6.0). And again, the ugly part is that this is just bad, unstable code and that it's hacky, but until they publish a better API, I couldn't do much..
Here is the hack:
private Boolean mHasEarpiece = null; // intentionally 'B' instead of 'b'
public boolean hasEarpiece() {
if (mHasEarpiece != null) {
return mHasEarpiece;
}
// not calculated yet, do it now
try {
Method method = AudioManager.class.getMethod("getDevicesForStream", Integer.TYPE);
Field field = AudioManager.class.getField("DEVICE_OUT_EARPIECE");
int earpieceFlag = field.getInt(null);
int bitmaskResult = (int) method.invoke(mAudioManager, AudioManager.STREAM_VOICE_CALL);
// check if masked by the earpiece flag
if ((bitmaskResult & earpieceFlag) == earpieceFlag) {
mHasEarpiece = Boolean.TRUE;
} else {
mHasEarpiece = Boolean.FALSE;
}
} catch (Throwable error) {
Log.e(TAG, "Error while checking earpiece! ", error);
mHasEarpiece = Boolean.FALSE;
}
return mHasEarpiece;
}
I'm open for improvement edits if you have something better :)
I've researched this and unfortunately I can't find any API support for detecting whether an earpiece exists.
I've now raised this with Google as a feature request:
http://code.google.com/p/android/issues/detail?id=37623
If you agree with the feature, click on the star at the bottom of the Google issue page to vote for it!
Lots of users have raised the issue that Google Talk doesn't offer a speaker/earpiece toggle option, which perhaps suggests the absence of a suitable API...
http://code.google.com/p/android/issues/detail?id=19221
As a workaround you may wish to hide the feature on devices approximated by (all of these approaches have drawbacks):
FTR, if you use this answer to route audio to the earpiece, there don't seem to be any negative side affects running that code on the Xoom (OS 3.1) or the Samsung Galaxy Tab (OS 2.2) - the audio just continues to play through the external speaker. I haven't had a chance to test if there are any interactions with Bluetooth headsets yet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With