i am developing an app which listen volume events whenever hardware volume button is pressed. app can be in foreground or background. i have followed [this] (Is there a broadcast action for volume changes?) but its not working correctly. following issues i am facing
1) If I press the volume button once - the event is triggered 4-6 times.
2) If current volume is maximum and i increase the volume then event doesn't fire..
Please help me.
Try to use following code -
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)){
//Do something
}
return true;
}
for background - any way to detect volume key presses or volume changes with android service?
On a rooted device, you can use the Xposed framework to hook yourself into PhoneWindowManager. A good example is the Xposed Torch Module. Just decompile it and see how they do things.
You can detect this by polling AudioManager for current volume, it's not nice solution, but i don't know better.
private Handler handler;
public int volume;
private Runnable volumeUpdater = new Runnable() {
private int updatesInterval = 100;
#Override
public void run() {
if(volume != audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)){
//volume changed put logic here
}
handler.postDelayed(volumeUpdater, updatesInterval);
}
};
Related
I know selfie stick take picture using volume button . I have a screen recording application . While recording if i open device's existing camera application i want to take picture from camera application automatically . I can press volume button automatically by using below code :
#Override
public void run() {
try {
Instrumentation inst = new Instrumentation();
inst.sendKeyDownUpSync(KeyEvent.KEYCODE_VOLUME_UP);
} catch (Exception e) {
}
}
}).start()
It presses volume button while the camera app is not open . But when the camera app is open it shows :
java.lang.SecurityException: Injecting to another application requires INJECT_EVENTS permission
I know INJECT_EVENTS permission is only work with system apps and without system app it can be used in only rooted device . But while recording i can take picture with selfie stick . Is there any way to act as selfie stick while camera open from my application (Like press volume button ) . Or any other way ?
Thanks in advance
Implement OnTouchListener with your activity
public class YourActivity extends Activity implements OnTouchListener {
.....
Override onKeyDown and write your action inside it
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
|| (keyCode == KeyEvent.KEYCODE_VOLUME_UP)){
//Write your camera capture action
}
return true;
}
I am using Android's MediaPlayer in my RingtoneService (which is a background Service for Ringtone in my application)to ring a ringtone when my Alarm goes on and off!
on the start of Ringtone Service for alarming
MediaPlayer mediaSong;
mediaSong = MediaPlayer.create(this, R.raw.xyz);
mediaSong.start();
on stop after some time
mediaSong.stop();
Its perfect in ringing and stopping the tone.whereas, I would like to make my device silent or say mute when I click on hardware's volume button pressed when an alarm is still ringing.
some stated solutions didn't answer my requirement.Any help is appreciated, please.
Please let me know somewhere if I am unclear!
Thanks in advance!
You need to override onKeyDown method in your Activity.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
mediaSong.stop
return true;
}
return super.onKeyDown(keyCode, event);
}
I've built a small app that mutes/unmute the music stream using the class AudioManager.
In fact, it works until I close the application. i.e. I've muted the sream, I close the app, I restart the app and the button doesn't unmute the stream any more. I've searched in the net but no one seems to have met this problem.
Here's my code:
public class ControlloVolume extends Activity {
ToggleButton tb_mute;
Button btn_mute;
AudioManager mAudioManager;
boolean mute;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_controllo_volume);
tb_mute = (ToggleButton) findViewById(R.id.tb_mute);
btn_mute = (Button) findViewById(R.id.btn_mute);
mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
if(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)==0){
mute = true;
tb_mute.setChecked(mute);
}else{
mute = false;
tb_mute.setChecked(mute);
}
}
public void onButtonClicked(View view){
if(!mute){
mAudioManager.setStreamMute(AudioManager.STREAM_MUSIC, true);
tb_mute.setChecked(true);
mute = true;
}else{
mAudioManager.setStreamMute(AudioManager.STREAM_MUSIC, false);
tb_mute.setChecked(false);
mute = false;
}
}
First, beware it's not recommended
For a better user experience, applications MUST unmute a muted stream
in onPause() and mute it again in onResume() if appropriate.
But I assume you know what you're doing, so here we go.
Note this line from the docs on setStreamMute
The mute command is protected against client process death: if a
process with an active mute request on a stream dies, this stream will
be unmuted automatically.
I've checked on my device and indeed, when I just exit my activity, stream stays muted. But as soon as I kill the process, mute goes away.
Take a look at activity lifecycle.
As your current approach will not work reliably, you could write a foreground service which will trigger the mute - start that service from your activity.
Also you would likely need to setStreamSolo.
Two important things.
Volume==0 and muted are NOT the same thing. I.e. stream can have volume==0 but be not muted. Though if stream is muted, volume will always be 0
mute requests are cumulative. I.e. if you've set mute twice, you must unmute twice as well - your code doesn't handle that
As a side note, for such app you would probably want to use widget instead of activity.
Off topic. It seems surprisingly lot of people don't quite get how booleans work.
And as I see code such as yours regulary, here is a bit streamlined rewrite.
#Override
public void onCreate(Bundle savedInstanceState) {
// ... setup just like you did
// boolean is just like any other type. You can assign not only
// constants, but expressions too
mute = (mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)==0);
tb_mute.setChecked(mute);
}
public void onButtonClicked(View view){
mute = !mute; // invert value
mAudioManager.setStreamMute(AudioManager.STREAM_MUSIC, mute);
tb_mute.setChecked(mute);
}
I have developed a game using andengine
I am facing a problem when using the power Button. If I press the POWER Button while playing the game the screen turns off and the onPause() is called as expected. But when I press the HOME button or POWER button again to turn on the screen, onResume() method is called and but the lockscreen shows up.
In the onResume() method, I resume the music of the game.
So as a result lockscreen shows up , but the game music plays in the background. I do not want to play the music in the lockscreen. Please help me solving this.Thank you
The solution is here: Activity handle when screen unlocked
By registering a BroadcastReceiver filtering the Intent.ACTION_SCREEN_ON, Intent.ACTION_SCREEN_OFF and Intent.ACTION_SCREEN_PRESENT actions, you will be able to handle these 3 cases:
Intent.ACTION_SCREEN_OFF: When the POWER button is pressed and the screen goes black.
Intent.ACTION_SCREEN_ON: When the POWER button is pressed again and lockscreen is showed up.
Intent.ACTION_SCREEN_PRESENT: When you pass the locksreen and are back in your game.
However, in my case (using a Galaxy S GT I9000 with Froyo 2.2) these actions are not called when dealing with the HOME button (and I think it's a general behavior).
One simple and quick (but maybe not the best) way to handle both HOME and POWER buttons to pause and resume your music could be to keep the onPause and onResume methods and use a simple boolean flag like this:
private boolean mPowerButton = false;
#Override
public void onPause() {
super.onPause();
// Pause your music
Log.d("Game activity", "Music paused");
}
#Override
public void onResume() {
super.onResume();
if (!this.mPowerButton) {
// Resume your music
Log.d("Game activity", "[HOME button] Music resumed inside onResume");
}
}
public class receiverScreen extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// This is the lockscreen, onResume has been already called at this
// step but the mPowerButton boolean prevented the resumption of music
}
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
LevelActivity.this.mPowerButton = true;
}
if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
// Resume your music
Log.d("Game activity", "[POWER button] Music resumed inside ACTION_USER_PRESENT action");
LevelActivity.this.mPowerButton = false;
}
}
}
Hope it helps!
I have seen couple of similar problems with solutions, but I couldn't find one that would work in my situation.
I am making VolumePreference (extending DialogPreference) that let's user choose volume level for some alarm.
In other preference user chooses desired ringtone that is played during alarm. It is also played while user is choosing volume in VolumePreference, so he knows how it actually sounds.
In yet another preference user chooses if alarm should "override" phone's media volume level when playing - I do that, so if user wants to have fixed volume level for alarm, then it shouldn't be affected by changes made by volume keys and so on.
If user chooses to do that, before starting to play alarm in AlarmActivity, I set volume to max level with AudioManager and intercept all keyDown events of volume keys, restoring volume level after alarm finishes.
Problem is, I can't block volume keys within my VolumePreference as there is no onKeyDown method.
After some checking, I found registerMediaButtonEventReceiver method of AudioManager that "Register a component to be the sole receiver of MEDIA_BUTTON intents.", which I believe could help in my situation (making some empty receiver), and even make volume locking more universal (register when I want to start lock, unregister after unlock), but it is working from API8, while I am making app for API7 - which still hold over 10% of market from what I read, so I would like to stick to it.
Any ideas on how one could block volume changes in PreferenceDialog?
After some thinking solution proved to be really simple - one can override onKeyDown method of View created in onCreateDialogView of DialogPreference or set onKeyListener of that View.
First example:
LinearLayout layout = new LinearLayout(mContext)
{
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP) return true;
return super.onKeyDown(keyCode, event);
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP) return true;
return super.onKeyUp(keyCode, event);
}
};
Second example (mDialogView is saved reference to layout from first example):
mDialogView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP)
return true;
return false;
}
});
I have chosen second solution, as I think it is more flexible for two reasons at least
I can just remove listener to stop blocking volume keys, while in first method I can't
in first solution I need to decide if I want to block keys input while creating View - not much use if VolumePreference is extending some other Preference that shouldn't block keys input