Control volume keys - android

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.

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).

AudioManager Sound Effects Only Working on Some Devices

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.

Controlling the volume of forced-to-speaker audio

I'm playing an audio clip using OpenSL ES. In my code I have
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setSpeakerphoneOn(true);
to force audio through the speaker while the headset is plugged in. It works fine, but I can't control the volume. Pressing the volume buttons while the clip is playing makes the volume seekbar appear and move, but the volume doesn't change.
Calling setVolumeControlStream(AudioManager.STREAM_VOICE_CALL) or setVolumeControlStream(AudioManager.STREAM_MUSIC) before playing doesn't seem to help.
Changing any of the volumes outside of my app (e.g. in the Android settings) doesn't affect the playing volume. Volume control works well on both headset and speaker when no routing is applied.
I've also tried routing the audio to the speaker using this code I found in another answer
Class audioSystemClass = Class.forName("android.media.AudioSystem");
Method setForceUse = audioSystemClass.getMethod("setForceUse", int.class, int.class);
// First 1 == FOR_MEDIA, second 1 == FORCE_SPEAKER. To go back to the default
// behavior, use FORCE_NONE (0).
setForceUse.invoke(null, 1, 1);
but it doesn't work on my Android 4.3 Nexus 4. I need the most compatible way to to that anyway.
Any ideas?
Thanks.
Here is a couple ideas:
MODE_IN_CALL sets all sorts of priority/policy on STREAM_VOICE_CALL. During this time, other STREAM may loose volume control focus. See if your audio clip is played over STREAM_VOICE_CALL.
MODE_IN_COMMUNICATION (for VoIP) may be a better fit for you. MODE_IN_CALL is for cellular call and can degrade your audio quality.
You may want to try grab audio focus and see if that helps. http://developer.android.com/training/managing-audio/audio-focus.html

Changing volume for one alarm sound only on Android

I am working on a life saving medical app and if the user is in a life threatening situation, they need to hear the alert.
When I have a notification to the status bar or have a dialog appear for a critical message to the user, I need to get their attention. If the media volume or ringer volume is low or off, I want to override it for my alert only. I would prefer not to change the settings for the phone, just for my one sound that I want to play.
When I try:
AudioManager audioManager = (AudioManager)getSystemService(this.AUDIO_SERVICE);
audioManager.setStreamVolume(AudioManager.STREAM_RING,
audioManager.getStreamMaxVolume(AudioManager.STREAM_RING), 0);
This correctly sets the volume for my stream but has the side effect of changing the stream volume for everyone else.
Is there a way of setting the volume for one song only?
It could be set back after the song is done.
AudioManager audioManager = (AudioManager)getSystemService(this.AUDIO_SERVICE);
int current_volume=audioManager.getStreamVolume(AudioManager.STREAM_RING);
audioManager.setStreamVolume(AudioManager.STREAM_RING,
audioManager.getStreamMaxVolume(AudioManager.STREAM_RING), 0);
// Play here
audioManager.setStreamVolum(AudioManager.STREAM_RING,current_volume,0);

How to play default TICK sound?

I want to connect Android OS default tick sound (for example, the sound you hear when you long click Home button and select previous app to start) with my button click. I know how to play sounds via MediaPlayer, but I do not know where to search for this default tick sound. It had to be in some default resources, but I could not find it.
MediaPlayer mp = MediaPlayer.create(getBaseContext(), sound);
mp.setLooping(false);
mp.start();
Anyone can help?
PS. this sound will be activated inside of onClick method.
PPS. I know I can user /raw dir, but I do not think there's a need for it. Not to say, it's cooler to play this tick sound prepared for user's phone.
You can play the default Android 'tick' sound using the view.playSoundEffect() method on any View - surprisingly enough, all views can play a selection of 'system' sounds:
view.playSoundEffect(SoundEffectConstants.CLICK);
and don't forget to add this to your view :
android:soundEffectsEnabled="true"
This is probably the simplest answer to your problem :)
If you want control over the volume of the sound, use the AudioManager system service. Plus this can be used from a Service if you don't have a view handy.
// get the AudioManager once onCreate or similar
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
...
// Play a System Sound
audioManager.playSoundEffect(SoundEffectConstants.CLICK);
// OR at 50% Volume
audioManager.playSoundEffect(SoundEffectConstants.CLICK, 0.5F);
If you are on Google GLASS you can use the com.google.android.glass.media.Sounds constants
audioManager.playSoundEffect(Sounds.TAP);
The following are included in Sounds
DISALLOWED, ERROR, SUCCESS, TAP, SELECTED, DISMISSED
Roberto Tyley's answer is correct.
You can play a sound from every view just by calling it this way:
Button01.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
v.playSoundEffect(SoundEffectConstants.CLICK);
}
});
Just note that the sound will not play if touch sounds are off by default. This is set in the general device sound preferences (Settings-->Sound-->Audible or on newer OS: Options > Sound > Touch)
Also, if this setting is set, most click events will trigger the click sound anyway!
You can use tick, beep or any kind of inbuilt sound by Tone Generator
ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 100);
toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 200);
NOTE: This is a pretty old answer. Check Roberto Tyley's answer below.
I think the sound that you are looking for is and is in - /system/media/audio/ui/KeypressStandard.ogg
I think you can give that path to the SetDataSource API of the mediaplayer. But I am not really sure if it will have the same name in all android phones.
There might be a better way to query for default click sound..

Categories

Resources