Android Can';t设置音量,音量控制不会转发到系统
我尝试使用AndroidAndroid Can';t设置音量,音量控制不会转发到系统,android,javafxports,Android,Javafxports,我尝试使用AndroidMediaPlayer框架来播放mp3文件 () 在我设法使它工作之后,我很快意识到,音量上升/下降事件被类javafxports.android.KeyEventProcessor捕获,并且从未被转发。我试图避开那件事,但没有成功 是否有任何方法可以将事件发送到系统,使其不被捕获 感谢和问候, 丹尼尔虽然我讨厌不断回答自己的问题,但在玩了几个小时安卓API、翻阅了一些文档等之后,我找到了一个解决方案 我的解决方案部分基于@josé-pereda给出的答案 我为任务“vo
MediaPlayer
框架来播放mp3
文件
()
在我设法使它工作之后,我很快意识到,音量上升/下降事件被类javafxports.android.KeyEventProcessor
捕获,并且从未被转发。我试图避开那件事,但没有成功
是否有任何方法可以将事件发送到系统,使其不被捕获
感谢和问候,
丹尼尔虽然我讨厌不断回答自己的问题,但在玩了几个小时安卓API、翻阅了一些文档等之后,我找到了一个解决方案 我的解决方案部分基于@josé-pereda给出的答案 我为任务“volumeUp”、“volumeDown”和“静音”创建了一个界面: 然后,基于以下关于如何设置的答案,我在Android上提出了以下实现:
import java.util.ArrayList;
import java.util.logging.Logger;
import android.content.Context;
import android.media.AudioManager;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import my.package.platform.NativeVolumeService;
import javafxports.android.FXActivity;
public class NativeVolumeServiceAndroid implements NativeVolumeService {
private static final Logger LOG = Logger.getLogger(NativeVolumeServiceAndroid.class.getName());
private final AudioManager audioManager;
private final int maxVolume;
private int preMuteVolume = 0;
private int currentVolume = 0;
public NativeVolumeServiceAndroid() {
audioManager = (AudioManager) FXActivity.getInstance().getSystemService(Context.AUDIO_SERVICE);
maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
}
@Override
public void volumeUp() {
LOG.info("dispatch volume up event");
KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_UP);
dispatchEvent(event, true, false);
}
@Override
public void volumeDown() {
LOG.info("dispatch volume down event");
KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_DOWN);
dispatchEvent(event, false, false);
}
@Override
public void mute() {
LOG.info("dispatch volume mute event");
KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_MUTE);
dispatchEvent(event, false, true);
}
private void dispatchEvent(KeyEvent event, boolean up, boolean mute) {
// hardware key events (amongst others) get caught by the JavaFXPorts engine (or better: the Dalvik impl from Oracle)
// to circumvent this, we need to do the volume adjustment the hard way: via the AudioManager
// see: https://developer.android.com/reference/android/media/AudioManager.html
// see: https://stackoverflow.com/questions/9164347/setting-the-android-system-volume?rq=1
// reason:
// FXActivity registers a FXDalvikEntity, which etends the surface view and passing a key processor
// called KeyEventProcessor - this one catches all key events and matches them to JavaFX representations.
// Unfortunately, we cannot bypass this, so we need the AudioManager
currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
if (mute) {
if (currentVolume > 0) {
preMuteVolume = currentVolume;
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_SAME,
AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE | AudioManager.FLAG_SHOW_UI);
} else {
preMuteVolume = 0;
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, preMuteVolume, AudioManager.FLAG_SHOW_UI);
}
} else if (up) {
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
(currentVolume + 1) <= maxVolume ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI);
} else if (!up) {
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
(currentVolume - 1) >= 0 ? AudioManager.ADJUST_LOWER : AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI);
}
}
}
volumeService
是一个类变量
然后我在我的舞台s场景上注册了一个事件处理程序:
@Override
public void start(Stage stage) throws Exception {
// initiate everything
scene.addEventFilter(KeyEvent.ANY, this::handleGlobalKeyEvents);
// do more stuff, if needed
}
最后,方法handleGlobalKeyEvents
如下所示:
private void handleGlobalKeyEvents(KeyEvent event) {
// use a more specific key event type like
// --> KeyEvent.KEY_RELEASED == event.getEventType()
// --> KeyEvent.KEY_PRESSED == event.getEventType()
// without it, we would react on both events, thus doing one operation too much
if (event.getCode().equals(KeyCode.VOLUME_UP) && KeyEvent.KEY_PRESSED == event.getEventType()) {
if (volumeService != null) {
volumeService.volumeUp();
event.consume();
}
}
if (event.getCode().equals(KeyCode.VOLUME_DOWN) && KeyEvent.KEY_PRESSED == event.getEventType()) {
if (volumeService != null) {
volumeService.volumeDown();
event.consume();
}
}
}
最后,解决方案尽可能干净,也不会太复杂。只有这样,直到它的工作是有点讨厌
@若泽·佩雷达:如果你想把这个解决方案作为一个魅力下降插件来集成,请随意,但如果你想的话,被提及和通知会很好
问候,,
丹尼尔,哇!多么好的回应啊!只是提供了两个链接,这似乎表明它没有解决,也没有解决,或者什么?来吧这就是我们正在谈论的安卓系统,它是可以解决的看到我的答案了,我会提供关于这个话题的。我明白了。因为你总是不断地回答自己的问题,所以你对可能提供有关该主题的一些信息的链接不感兴趣。问题是:链接只说明问题,没有任何解决方案。我的意思是,我可以让这个问题没有答案,即使我已经找到了答案。而你的“评论”只是一个链接列表。没有别的了。我很抱歉这么说,但这是没有帮助的(考虑到这些链接背后缺乏有价值的信息)。这非常有效。对于一个应该在较低级别修复的问题,这是一个很好的解决方法。
@Override
public void start(Stage stage) throws Exception {
// initiate everything
scene.addEventFilter(KeyEvent.ANY, this::handleGlobalKeyEvents);
// do more stuff, if needed
}
private void handleGlobalKeyEvents(KeyEvent event) {
// use a more specific key event type like
// --> KeyEvent.KEY_RELEASED == event.getEventType()
// --> KeyEvent.KEY_PRESSED == event.getEventType()
// without it, we would react on both events, thus doing one operation too much
if (event.getCode().equals(KeyCode.VOLUME_UP) && KeyEvent.KEY_PRESSED == event.getEventType()) {
if (volumeService != null) {
volumeService.volumeUp();
event.consume();
}
}
if (event.getCode().equals(KeyCode.VOLUME_DOWN) && KeyEvent.KEY_PRESSED == event.getEventType()) {
if (volumeService != null) {
volumeService.volumeDown();
event.consume();
}
}
}