Check if Android device has an internal speaker - android

How to check if a device running Android has a speaker on it or not? Meaning is it able to play audio?
Are there any Configuration qualifiers for it? and what about programmatically
EDIT: just bought an Android Wear watch and it does NOT have a speaker so not sure how I would check this

Since API level 21 (most Android Wear based on this level), Android provide a feature, PackageManager.FEATURE_AUDIO_OUTPUT, witch can be used to detect whether there is a way to output the audio.
I tested this feature on my MOTO 360 (no speaker), it don't has this feature, and Ticwatch (with speaker) do have this feature.
But when I connected a Bluetooth headset to the MOTO 360, it still don't have this feature, this confused me.
So I use AudioManager.isBluetoothA2dpOn() for further check.
The detection code can be like this:
public boolean hasAudioOutput() {
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
PackageManager packageManager = getPackageManager();
if (audioManager.isBluetoothA2dpOn()) {
// Adjust output for Bluetooth.
return true;
} else if (audioManager.isBluetoothScoOn()) {
// Adjust output for Bluetooth of sco.
return true;
} else if (audioManager.isWiredHeadsetOn()) {
// Adjust output for headsets
return true;
} else if (audioManager.isSpeakerphoneOn()) {
// Adjust output for Speakerphone.
return true;
} else if (packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
// Has internal speaker or other form of audio output.
return true;
} else {
// No device for audio output.
return false;
}
}

Android API doesn't have any such qualifiers neither there is any library method.
But just a raw idea, try playing some audio and simultaneously record through the mic.
Check if they are same.
This is not a fool proof way, but just a thought!

Probably most android phones have a speaker i guess :P /.. But if you are asking if you can check whether its connected to a speaker or headphones or something like that..then you can use
if (isBluetoothA2dpOn()) {
// Adjust output for Bluetooth.
} else if (isSpeakerphoneOn()) {
// Adjust output for Speakerphone.
} else if (isWiredHeadsetOn()) {
// Adjust output for headsets
} else {
// If audio plays and noone can hear it, is it still playing?
}
SOURCE: http://developer.android.com/training/managing-audio/audio-output.html#CheckHardware

Related

demo player display is too darker

I build out the hdrvivid-debug.apk and installed on a mobile phone with Android 12. when playing one HDR Vivid test stream, the display is very darker compared to the default video player on the phone.
the vivid stream' file name is "hdr_vivid_selftest_dmsync_pq.mp4". it is used to do hdrvivid player test, it simply display a white rectanglular on the middle of screen. I can provide this stream if you want.
Thank you!
Houxiang
Update:
You can check whether the device has the HDR Vivid video decoding capability according the following method, docs link:
// Check the support for MediaCodec on the device.
MediaCodecList mcList = new MediaCodecList(MediaCodecList.ALL_CODECS);
MediaCodecInfo[] mcInfos = mcList.getCodecInfos();
for (MediaCodecInfo mci : mcInfos) {
// Filter out the encoder.
if (mci.isEncoder()) {
continue;
}
String[] types = mci.getSupportedTypes();
String typesArr = Arrays.toString(types);
// Filter out the non-HEVC decoder.
if (!typesArr.contains("hevc")) {
continue;
}
for (String type : types) {
// Check whether 10-bit HEVC decoding is supported.
MediaCodecInfo.CodecCapabilities codecCapabilities = mci.getCapabilitiesForType(type);
for (MediaCodecInfo.CodecProfileLevel codecProfileLevel : codecCapabilities.profileLevels) {
if (codecProfileLevel.profile == HEVCProfileMain10 || codecProfileLevel.profile == HEVCProfileMain10HDR10
|| codecProfileLevel.profile == HEVCProfileMain10HDR10Plus) {
// true means supported.
return true;
}
}
}
}
// false means unsupported.
return false;
If the device has the HDR Vivid video decoding capability, you can adjust the brightness of the video by adjusting the brightness bar of the device..
If the HDR capability is not supported, you need to call the setBrightness() interface to set the video brightness, and this interface takes effect only on devices that do not support HDR.
It seems that the HarmonyOS 2.0.0.268 system of Honor V30 Pro may not support HDR Vivid. The sample code invokes the setBrightness interface, the set value takes effect. But, the phone's default player may have done other processing, so it looks like the brightness may not be the same.
If HDR is not supported, you can set setBrightness() to a moderate brightness value.
What interface is used when you use the HDR Vivid capability? Native interface or Java interface?
About the display is too dark, Have you adjusted the output brightness?
https://developer.huawei.com/consumer/en/doc/development/Media-Guides/android-hdr-0000001276893212
If it's convenient, please provide a comparison video and HDR Vivid resource file for us to check.

How to configure Android Media player to never play over speaker

I am creating Media Player, but it should never play on Speaker. If head phone jack or bluetooth is not available, still Audio should not be played over speaker.
I used below Android API but it still plays over speaker:
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
am.setSpeakerphoneOn(false);
You can check the whether Bluetooth and headphone connected or not by using Broadcast receiver using this link http://blog.urvatechlabs.com/detect-programatically-if-headphone-or-bluetooth-headsets-attached-with-android-phone/ . If it is not connected/removed pause/stop the Android Media Player.
From AudioManager official documentation
audioManager.setSpeakerphoneOn(boolean)
Sets the speakerphone on or off.
It means if you set the false it will disable the speaker sound i.e playing out from the speaker and if you set true it will play from the speaker.
In your case, you don't want to play your music from the outer speaker but still your using the am.setSpeakerphoneOn(true); which is actually enables the outer speaker.
So set am.setSpeakerphoneOn(false); so that it won't play the music from outer speaker
You can also set the Mode ( Call / Voice Communication / Music etc) for your AudioManager
audioManager.setMode(AudioManager.STREAM_MUSIC);
Note:: For changing the audio manager settings you need to set Permission: MODIFY_AUDIO_SETTINGS in manifest
add this line in manifest
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
In additional, this is the code to check which type of audio conncection
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
PackageManager packageManager = getPackageManager();
if (audioManager.isBluetoothA2dpOn()) {
// Adjust output for Bluetooth.
Log.d("debug","BluetoothA2dpOn");
} else if (audioManager.isBluetoothScoOn()) {
// Adjust output for Bluetooth of sco.
Log.d("debug","BluetoothScoOn");
} else if (audioManager.isWiredHeadsetOn()) {
// Adjust output for headsets
Log.d("debug","WiredHeadsetOn");
} else if (audioManager.isSpeakerphoneOn()) {
// Adjust output for Speakerphone.
Log.d("debug","SpeakerphoneOn");
} else if (packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
// Has internal speaker or other form of audio output.
Log.d("debug","Internal Speaker On");
} else {
// No device for audio output.
Log.d("debug","No Audio Device");
}

Speaker Volume (Alarm) decreases when Headphones are plugged in

I'm trying to play an alarm sound through the speakers via the alarm channel at max volume. For that I'm using the AudioManager and a MediaPlayer. If I plug in headphones, the alarm is still played through the speakers, however the volume of the alarm played through the speakers decreases drastically making it useless for my purpose.
Is there a way to prevent this decrease in volume?
The code I'm using is this:
public void startAlarmSound() {
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.setSpeakerphoneOn(false);
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM), 0);
if (!alreadyPlaying)
playAlarmSound();
alreadyPlaying = true;
}
private void playAlarmSound() {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
try {
mediaPlayer.setDataSource(this, Uri.parse("android.resource://com.mystuff.mine/" + R.raw.alarm_sound));
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
To ensure that the volume has not been lowered, I'm calling the following every 5 seconds.
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM), 0);
I'm located within the EU, so it could be caused by that regulation that deals with max volume when plugging in headphones. Since I only care about speaker output I need a workaround even if that is the case.
Edit:
This problem occurs both with my app as well as with system apps (like the alarm clock), and with both Nexus 5 and 6. As I've also read reports of that issue from other phone manufacturers, so I don't think the problem is exclusive to the nexus line of phones. I need a workaround.
I just checked the result of both getStreamMaxVolume(AudioManager.STREAM_ALARM) and getStreamVolume(AudioManager.STREAM_ALARM). Both display 7, regardless of if the headphones are plugged in or not.
I did notice that with headphones plugged in, while the volume indicator is set to max, if I reduce it and quickly increase it again, it will increase to the volume that it has without headphones. However as this requires user interaction, it's not the solution I'm looking for.
According to john saying,
This is built in feature of devices, you cannot set volume so high until user will not allow it by himself as it can hurt ears, and the problem is that speaker and headphone volume is not separated
I think that you may not be able to make your volume full. I'dd suggest you trying to look if you can disable headphones (even if plugged in) then play the alarm (full volume as headphones are disabled), then re-enable headphone after alarm is shut down.
Take a look at this or this in order to disable headphones.

ACTION_HEADSET_PLUG not documented extra strange "state"?

I'm doing some test with Intent.ACTION_HEADSET_PLUG.
Giving the fact that the following code should be the one who give the responses (From com.android.server.HeadsetObserver class 2.2.1 r1):
private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) {
if ((headsetState & headset) != (prevHeadsetState & headset)) {
// Pack up the values and broadcast them to everyone
Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
int state = 0;
int microphone = 0;
if ((headset & HEADSETS_WITH_MIC) != 0) {
microphone = 1;
}
if ((headsetState & headset) != 0) {
state = 1;
}
intent.putExtra("state", state);
intent.putExtra("name", headsetName);
intent.putExtra("microphone", microphone);
if (LOG) Slog.v(TAG, "Intent.ACTION_HEADSET_PLUG: state: "+state+" name: "+headsetName+" mic: "+microphone);
// TODO: Should we require a permission?
ActivityManagerNative.broadcastStickyIntent(intent, null);
}
}
And in the documentation they say: state - 0 for unplugged, 1 for plugged.
I strangely get two different state by plugging two different headsets:
0 = unplugged
1 = Headset with microphone
2 = Headset without microphone
The question is: where the State 2 (two) come from? Can someone enlighten me?
Thanks
I am using that extra state myself in one of my applications. One of your headsets has a mic the other doesn't. Also make sure you a plugging it in all the way, but don't break anything :)
0 - unplugged as in no headset attached to the device
1 - headset with microphone as in wired headset that had a mic so you can talk and the device uses it as a input as you talk
2 - a headset with no microphone as in your regular old stereo headset that you would normally hook up to your stereo system to listen to music with
This is extremely good info to verify that what was just connected is a wired headset that you expect to be able to talk in to and be heard correctly.

How to shut off the sound MediaRecorder plays when the state changes

My Android application uses MediaRecorder on a SurfaceHolder to show a live preview of what the camera is capturing. Every time the user presses the REC button on the app, the app starts to record.
Every time the state of the MediaRecorder switches to/from 'start', Android automatically (?) fires off a beep. This beep sounds different from phone to phone, which makes me think that this beep is natively attached to the state change of MediaRecorder.
The beep is not played if the volume of the phone is set to silent.
I google it and did some research but I couldn't find a way to turn this beep off. Is it possible? If so, how?
The app was tested on: Nexus One 2.3.4, Desire HD 2.3.3
Ok the accepted answer did not work for me. On a Galaxy Nexus Running 4.2.1 (Jelly Bean) when recording via MediaRecorder I needed to use AudioManager.STREAM_RING because AudiManager.STREAM_SYSTEM did not work. It would always play a "chime" sound at beginning of each recording.
Here is my solution using "STREAM_RING" and others.
// disable sound when recording.
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_ALARM,true);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_DTMF,true);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_MUSIC,true);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_RING,true);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_SYSTEM,true);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_VOICE_CALL,true);
// re-enable sound after recording.
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_ALARM,false);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_DTMF,false);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_MUSIC,false);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_RING,false);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_SYSTEM,false);
((AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_VOICE_CALL,false);
Also as the documentation states be sure to re-enable audio in the onPause() method.
I hope this helps someone tearing their hair out over this problem. This disables all sound streams. You can go through and work out which ones you specifically need. I found that different versions of android use different streams for the chime when mediarecorder runs. ie, STREAM_RING works for android 4.2.1 but for ICS it doesn't work.
Edit: As my comment below mentions, I can't get the sound disabled for Android OS 2.3.3 on a Samsung Galaxy S1. Anyone have luck with this?
Darrenp's solution helps to tidy up code but in a recent update to my phone (galaxy nexus android 4.3) the volume / recording beep started up again! The solution by user1944526 definitely helps. In an effort to make it easier to understand...
Use something like ,
// class variables.
Integer oldStreamVolume;
AudioManager audioMgr;
enableSound() {
setMuteAll(false);
if (audioMgr != null && oldStreamVolume != null) {
audioMgr.setStreamVolume(AudioManager.STREAM_RING, oldStreamVolume, 0);
}
}
disableSound() {
audioMgr = (AudioManager)activity.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
oldStreamVolume = audioMgr.getStreamVolume(AudioManager.STREAM_RING);
audioMgr.setStreamVolume(AudioManager.STREAM_RING, 0, 0);
}
For completeness each of those functions you could also call either darrenp's solution in a function or include all of the above STREAM_ lines. but for me now, these combined are working. Hope this helps someone...
try
((AudioManager)context.getSystemService(Context.AUDIO_SERVICE)).setStreamMute(AudioManager.STREAM_SYSTEM,true);
That mute all sounds.
Following on from #wired00's answer, the code can be simplified as follows:
private void setMuteAll(boolean mute) {
AudioManager manager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int[] streams = new int[] { AudioManager.STREAM_ALARM,
AudioManager.STREAM_DTMF, AudioManager.STREAM_MUSIC,
AudioManager.STREAM_RING, AudioManager.STREAM_SYSTEM,
AudioManager.STREAM_VOICE_CALL };
for (int stream : streams)
manager.setStreamMute(stream, mute);
}
This works fine for now but if more streams are introduced in the future, this method may need updating. A more robust approach (though perhaps overkill) is to use reflection to get all the STREAM_* static fields:
List<Integer> streams = new ArrayList<Integer>();
Field[] fields = AudioManager.class.getFields();
for (Field field : fields) {
if (field.getName().startsWith("STREAM_")
&& Modifier.isStatic(field.getModifiers())
&& field.getType() == int.class) {
try {
Integer stream = (Integer) field.get(null);
streams.add(stream);
} catch (IllegalArgumentException e) {
// do nothing
} catch (IllegalAccessException e) {
// do nothing
}
}
}
Interestingly, there seem to be some streams that are not documented, namely STREAM_BLUETOOTH_SCO, STREAM_SYSTEM_ENFORCED and STREAM_TTS. I'm guessing/hoping there's no harm in muting these too!
I just had this problem on a Lenovo K900 running Android 4.2.1.
setStreamMute doesn't seem to do anything for me, but setStreamVolume works...
AudioManager audioMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
int oldStreamVolume = audioMgr.getStreamVolume(AudioManager.STREAM_RING);
audioMgr.setStreamVolume(AudioManager.STREAM_RING, 0, 0);
... do recording ...
audioMgr.setStreamVolume(AudioManager.STREAM_RING, oldStreamVolume, 0);
Add this code before the start:
AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true);
audioManager.setStreamMute(AudioManager.STREAM_MUSIC,true);
And add this code after the stop:
AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, false);
audioManager.setStreamMute(AudioManager.STREAM_MUSIC,false);
There are countries/firmwares that use STREAM_SYSTEM and others using STREAM_MUSIC. There are also countries where this is illegal but use a different channel.

Categories

Resources