AudioManager Sound Effects Only Working on Some Devices - android

I am developing a soft keyboard in android that extends InputMethodService. Users of the keyboard can enable or disable sound effects while they are typing. I am using the Android AudioManager class
When the service is initialized, I check to see if the preference is set to play sound effects. In here I obtain a reference to an AudioManager object, and after some fiddling call loadSoundEffects().
In my subclass's implementation of onKey(int, int[]) I call this method if the preference is set to play sound effects.
private void playSoundEffect(int keyCode) {
int sound = AudioManager.FX_KEYPRESS_STANDARD;
if (keyCode == 32)
sound = AudioManager.FX_KEYPRESS_SPACEBAR;
else if (keyCode == MyKeyboard.KEYCODE_DELETE)
sound = AudioManager.FX_KEYPRESS_DELETE;
else if (keyCode == MyKeyboard.KEYCODE_DONE || keyCode == 10)
sound = AudioManager.FX_KEYPRESS_RETURN;
Log.i("Lex", "sound=" + sound);
mAudioManager.playSoundEffect(sound);
}
I've tested this code on a Samsung Galaxy S4 (on API 21) and on two models of Alcatel Ideal phones (running API 21 and 24). The sound effects only play on the Samsung phone.
After doing some research it seems that the sound effects simply aren't included on the Alcatel devices.
Is there a way to check to see if the sound effects exist programmatically? If I am using AuidoManager correctly and the sound effects aren't present I'd like to check for their existence, and if they do not exist disable the option for the user to turn on sound effects at all.

Related

Why AudioManager works for Phone, but not for Android TV emulator?

As one can read here, I try to adjust the volume. Here I set the AudioManager:
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
and I react on a onKeyDown() like:
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (event?.keyCode) {
KeyEvent.KEYCODE_VOLUME_UP -> {
adjustVolume()
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE)
return true
}
KeyEvent.KEYCODE_VOLUME_DOWN -> {
adjustVolume()
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE)
return true
}
else -> {
return super.onKeyDown(keyCode, event)
}
}
}
and adjustVolume() displays then the volume value. This works so far on phones. I can adjust the volume with my own UI and I can see log output.
But when I run this app on a Android TV Emulator, linked code does not work and I see stock UI for volume.
According to #I~nigos answer, the kernel "consumes" the keyevent already at TVs hardware level. It was proposed to handles the sound from internal mixer.
However, how can I intercept the sound level. Also by intercepting the internal mixer.. But how?
Android TV does not expose volume_up/volume_down buttons to the application.
The TV controls are shown as a D-Pad: see D-pad minimum controls
This up/down events from the remote / hardware buttons are handled by the TV hardware before they get to Android (makes sense since the TV might have other functions that depend on).
You can control you app volume output, and raise/lower volume and mute the TV from ADB; but you cannot get this events.
How to handle sound on TVs? The TV has internally a mixer. Output an appropiate sound level (not at 100% to avoid distorsion in some equipment).

Android interrupt media player with ringtone manager

I have used ringtonemanager previously in android studio and it seemed to lower the volume of any music that was playing in a different app to play the alert i was trying to play, then once my alert had completed the background music would then come back to normal volume (as the default alarm/notification would do) But now a year or so later im trying to implement this again but my alert cannot be heard over the music playing in Google Play Music.
Is this a change that now requires additional parameters to function as it used to?
Im using:
Uri notification =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
myRM = RingtoneManager.getRingtone(this.getContext(), notification);
myRM.play();
Many Thanks
Handling Changes in Audio Output seems what fits your need.
In short, you need to request audio focus before starting playing.
...
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mAudioManager.requestAudioFocus(null, mStreamType, AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
mRingtone.play();
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
Used to indicate a temporary request of audio focus, anticipated to
last a short amount of time, and where it is acceptable for other
audio applications to keep playing after having lowered their output
level (also referred to as "ducking").
Remember to release audio focus when finishing..
if (mRingtone != null && mRingtone.isPlaying()) {
mRingtone.stop();
}
mRingtone = null;
if (mAudioManager != null) {
mAudioManager.abandonAudioFocus(null);
}

Android - How to change sound output while playing sound?

I have an app that plays a list of soundtracks. It works great, however changing the sound output to internal speakers or vice versa, has no effect. It stops the current one, and then plays the next on the new mode.
I've read in android documentation of MediaPlayer that I can't change the sound output using setAudioStreamType() method. So this is the problem, but can't find a solution!
Here's the code for the toggle when the track is playing:
if (this.audioManager.isSpeakerphoneOn() || this.getCurrent() == 1) {
this.audioManager.setMode(AudioManager.MODE_IN_CALL);
this.audioManager.setSpeakerphoneOn(false);
this.mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
} else if (this.getCurrent() != 0) {
this.audioManager.setMode(AudioManager.MODE_NORMAL);
this.audioManager.setSpeakerphoneOn(true);
this.mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
Thanks in advance!

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.

Control volume keys

In my application I have overridden the onKeyDown() and onKeyUp() functions in order to capture volume keys events. I use such events in order to control my application volume. I use the music stream to play my sounds. When detecting an event like this I also show a custom toast (similar to the one shown by Android). The problems I'm facing with this take are:
Android always plays a sound on volume keys events
That sound is played always at the same intensity.
What I'd like is to control the intensity at which the default sound is played (also the stream on which is played) in the following way: a louder sound for a higher volume and a lower sound for a low volume, if this is possible.
Or a way to disable playing that default sound and play my custom sound at the intensity I just set.
Actually the sound is played on onKeyUp(...), so you can simply overload the method in your activity when it gets called for the volume keys :
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
return true;
}
return super.onKeyUp(keyCode, event);
}
This worked for me :)
It's strange cause I was writing similar functionality and Android seems to play louder sounds when you rise stream volume.
am.setStreamVolume(AudioManager.STREAM_MUSIC, progress,AudioManager.FLAG_PLAY_SOUND);
Thats what I used in my application. am is instance of AudioManager you can get by writing:
AudioManager am = (AlarmManager) getSystemService(AUDIO_SERVICE);
To disable sound you can replace AudioManager.FLAG_PLAY_SOUND with "0" value what should disable it.
I'm not sure if it is possible to replace those sound in AudioManager but you can play those custom sounds with MediaPlayer inside of your onKeyDown methods.
Hope this helps.

Categories

Resources