Reputation: 2224
I spent hours to get this simple use case working: when I press the volume hardware buttons, I want to open a DialogFragment. The dialog contains a SeekBar, which should set according the button pressed.
I have several problems here.
First, I don't know how to pass the KeyEvents to the fragment. I created a BroadcastReceiver and registered it via AudioManager.registerMediaButtonEventReceiver
. Additionally, I put the Receiver in the AndroidManifest.xml
:
<receiver android:name=".fragment.ActionbarFragment$MediaButtonEventReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON"/>
</intent-filter>
</receiver>
But this receiver does only work if I use the following intent filter:
<intent-filter>
<action android:name="android.media.VOLUME_CHANGED_ACTION"/>
</intent-filter>
When I look into the AudioManager.VOLUME_CHANGED_ACTION, you'll find the following comment:
* @hide Broadcast intent when the volume for a particular stream type changes.
* Includes the stream, the new volume and previous volumes.
* Notes:
* - for internal platform use only, do not make public,
* - never used for "remote" volume changes
So, it's likely to brake some day and I'd like to avoid this intent. What's the alternative? How do I pass the key events from the hardware buttons to the fragment correctly?
Second, when the DialogFragment is open, the default Android VolumePanel is shown though I have overridden onKeyDown
:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return true;
}
As far as I know, fragments don't have their own onKeyDown, so I was wondering why the VolumePanel is shown, when I press the hardware buttons.
Upvotes: 2
Views: 3722
Reputation: 2224
I finally solved both issues. First of all, MEDIA_BUTTON
seems not to respond to volume changes. It's obviously responds only to PLAY
, PAUSE
, STOP
, etc. which is not what I want.
The simplest solution is still to handle the key events in OnKeyDown()
of every Activity
:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
keyCode == KeyEvent.KEYCODE_MENU) {
showSoundSettingsDialog();
}
return true;
}
To write the code once, I moved this part into a BaseActivity from which the Activities inherit.
The second issue was solved by adding a simple OnKeyListener to the Dialog, as they have their own KeyEvents, what I didn't know so far.
builder.setOnKeyListener(new Dialog.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
volumeUp();
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
volumeDown();
} else if (keyCode == KeyEvent.KEYCODE_BACK) {
dialog.dismiss();
}
return true;
}
});
And that's it.
Upvotes: 3