gpt4 book ai didi

android - 无法设置音量,音量控制未转发给系统

转载 作者:搜寻专家 更新时间:2023-11-01 09:39:13 25 4
gpt4 key购买 nike

我尝试使用 Android MediaPlayer 框架来播放 mp3 文件(see this question)。

在我设法让它工作之后,我很快意识到,音量增大/减小事件被 javafxports.android.KeyEventProcessor 类捕获并且永远不会被转发。我试图绕过它,但无济于事。

是否有任何方法可以将事件分派(dispatch)到它不会被捕获的系统?

感谢和问候,丹尼尔

最佳答案

虽然我讨厌不断地回答我自己的问题,但在使用 Android API 几个小时、查阅一些文档等之后,我找到了一个解决方案。

我的解决方案部分基于@josé-pereda 就主题 "javafxports how to call android native Media Player" 给出的答案.

我为任务“volumeUp”、“volumeDown”和“mute”创建了一个界面:

public interface NativeVolumeService {
void volumeUp();
void volumeDown();
void mute();
}

然后,根据下面关于如何设置system volume on Android的回答,我想出了以下在 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);
}
}
}

为了集成它,我在我的主类中创建了适当的实例(我需要这个全局 - 你会看到,为什么)

private void instantiateNativeVolumeService() {
String serviceName = NativeVolumeService.class.getName();
if (Platform.isDesktop()) {
serviceName += "Desktop";
} else if (Platform.isAndroid()) {
serviceName += "Android";
}
try {
volumeService = (NativeVolumeService) Class.forName(serviceName).newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
LOG.log(Level.SEVERE, "Could not get an instance of NativeAudioService for platform " + Platform.getCurrent(), e);
}
}

volumeService 是一个类变量。

然后我在我的 StageScene 上注册了一个事件处理程序:

@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();
}
}
}

最后,解决方案尽可能简洁,也不太复杂。只是在它起作用之前的方式有点令人讨厌。

@JoséPereda:如果您想将此解决方案集成为 charm down 插件等,请随意,但如果您愿意,我们很乐意被提及和通知。

问候,丹尼尔

关于android - 无法设置音量,音量控制未转发给系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40912656/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com