无法设置音量,音量控制未转发到系统

2023-12-14

我尝试使用安卓MediaPlayer框架来发挥mp3 file (看到这个问题).

在我设法使其工作后,我很快意识到,音量增大/减小事件被类捕获javafxports.android.KeyEventProcessor并且永远不会被转发。我试图规避这一点,但没有成功。

是否有任何方法可以将事件分派到发生该事件的系统not被抓住?

感谢致敬, 丹尼尔


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

我的解决方案部分基于 @josé-pereda 就该主题给出的答案《javafxports如何调用android原生媒体播放器》.

我为任务创建了一个界面“volumeUp", "音量减小" and "mute":

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

然后,根据以下关于如何设置的答案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是一个类变量。

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

@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:如果您想将此解决方案集成为魅力下降插件等,请随意,但如果您这样做,那么很高兴被提及和通知。

问候, 丹尼尔

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法设置音量,音量控制未转发到系统 的相关文章

  • 如何在 Android 中更改 Drawable 的颜色?

    我正在开发一个 Android 应用程序 并且我有一个从源图像加载的可绘制对象 在此图像上 我想将所有白色像素转换为不同的颜色 例如蓝色 然后缓存生成的 Drawable 对象 以便稍后使用它 举例来说 假设我有一个 20x20 PNG 文
  • 如何替换 Android 中已弃用的 Bundle/Argument get(key) 调用

    我有以下扩展函数 允许我在应用程序活动和片段之间传递捆绑数据项 inline fun
  • Android 中的列表(特别是 RecyclerView 和 CardView)如何工作

    请原谅我问这个问题 但我是 Android 开发新手 尽管我正在尝试了解developer android com 网站上的基础知识 但大多数示例 即使他们说它们是为 Android Studio 构建的 尚未设置为使用 Gradle 因此
  • 当路径的点超出视野时,Android Canvas 不会绘制路径

    我在绘制路径时遇到了 Android Canvas 的一些问题 我的情况是 我有一个相对布局工作 如地图视图 不使用 google api 或类似的东西 我必须在该视图上绘制一条路径 canvas drawPath polyPath bor
  • 退出设备上的 system.img

    我正在为我们部署给客户的设备 LG p509 Optimus 1 开发自动应用程序更新解决方案 我们可以控制这些设备 并且目前在它们上安装自定义内核 但不是完整的自定义 ROM 由于我们试图在设备上自动更新我们的应用程序 因此我们需要由我们
  • ADB TCPIP 连接问题

    我有两台 Galaxy S3 其中一个已扎根 另一个则未扎根 因此 当我尝试通过本地网络连接它们时 计算机可以看到已root的计算机 但是正常的就卡在tcpip这一步了 所以 我写 adb tcpip 5555 It says restar
  • HMS 核心地图套件在我的 Android 应用程序上根本无法工作

    我正在尝试在我的应用程序中使用华为 HMS 地图套件 我对整体地图很陌生 无论是来自谷歌还是华为 我按照文档中的教程以及华为提供的代码实验室中的说明进行操作 并将我的代码在一起 但是当我运行地图活动时 什么也没有出现 我得到的只是一个空白活
  • Android 中 localTime 和 localDate 的替代类有哪些? [复制]

    这个问题在这里已经有答案了 我想使用从 android API 获得的长值 该值将日期返回为长值 表示为自纪元以来的毫秒数 我需要使用像 isBefore plusDays isAfter 这样的方法 Cursor managedCurso
  • 选项卡主机内的 Android Fragment 视图状态 [重复]

    这个问题在这里已经有答案了 可能的重复 使用 Fragment 为 Android 中的每个选项卡单独的返回堆栈 https stackoverflow com questions 6987334 separate back stack f
  • 在新的 intel x86 android 模拟器中访问 google api

    我只是尝试在新的 x86 android 模拟器中运行我公司的应用程序 但是我们的应用程序依赖于 google 地图 API 而这在 google 随 android sdk 版本 17 提供的 x86 系统映像中不可用 我的直觉告诉我答案
  • MIUI 权限被拒绝活动 KeyguardLocked

    当应用程序处于后台且屏幕被锁定时 我无法启动活动 没有异常或警告 只是不调用 onCreate 我一直在与这个问题作斗争 我想我终于找到了它的根源 日志中有一行 D com android server am ExtraActivityMa
  • 在android中,将相机预览流到视图上

    我想将 Android 相机的相机预览流式传输到视图上 目的是随后使用 onDraw 将各种内容添加到视图中 我不需要随时实际捕捉图像 它不必是最高质量或每秒最大数量的帧 有谁知道如何做到这一点 将其添加到您的 xml 中
  • Android 上的 MIDI:Java 和/或 AIR 库

    一段时间以来 我一直在考虑在 iPad 上 重新 构建一个应用程序 其中我将使用 Objective C 和DSMI http dsmi tobw net 将 MIDI 信号发送到主机 这还不错 我的意思是 除了实际编写应用程序之外 现在我
  • Android NDK 代码中的 SIGILL

    我在市场上有一个 NDK 应用程序 并获得了有关以下内容的本机崩溃报告 SIGILL信号 我使用 Google Breakpad 生成本机崩溃报告 以下是详细信息 我的应用程序是为armeabi v7a with霓虹灯支持 它在 NVIDI
  • 安卓。 CalendarView...一次仅显示一个月的日历

    我正在使用 CalendarView 其中我想一次仅查看一个月的日历并滚动查看下个月 但 CalendarView 一次显示所有月份 下面是我的代码
  • 如何在android中通过蓝牙向配对设备发送短信?

    在我的应用程序中 我想通过蓝牙发送和接收短信 我可以在列表视图中看到配对设备名称和地址的列表 但是当我尝试向配对设备发送文本时 什么也没有发生 在其他设备中没有收到文本 这是我向配对设备发送消息的代码 private void sendDa
  • Android 标记如何实现拖放?

    你好 我正在 Android 中开发 MapView 应用程序 我有三个标记 我希望稍后能够使用 Google Map API getlocation function 为了尝试一下 我想使用拖放功能移动标记 然后检查位置 任何人都可以通过
  • 禁用 Android 菜单组

    我尝试使用以下代码禁用菜单组 但它不起作用 菜单项仍然启用 你能告诉我出了什么问题吗 资源 菜单 menu xml menu menu
  • Android-dispatchTouchEvent 给了我一个 StackOverflowError

    这里我有一个带有 setOnTouchListener 的 ViewFlipper 它工作得很好 然后我膨胀 ReLayNewsItem 然后将其添加到 ViewFlipper 现在我希望 WebView web 监听触摸事件并将它们传递给
  • 从文件路径显示图像视图?

    我需要仅使用文件名而不是资源 ID 来显示图像 ImageView imgView new ImageView this imgView setBackgroundResource R drawable img1 我在可绘制文件夹中有图像

随机推荐

  • 从音频输入捕获原始音频以在 Mac 上进行实时处理的最简单方法

    从内置音频输入捕获音频并能够在请求时实时读取原始采样值 如 wav 中 的最简单方法是什么 就像从套接字读取一样 希望代码使用 Apple 的框架之一 音频队列 文档不是很清楚 我需要的是非常基础的 为此尝试使用 AudioQueue 框架
  • Google API 上未捕获异常“InvalidArgumentException”,带有消息“

    我已复制此网站上他们的文档中的代码 here 我已经更改了下面这些的 JSON 我已经在 Composer 上的 API 上生成了新文件 但仍然遇到一些问题 我不确定我做错了什么 这是否意味着他们的 API 漏洞太多 这是演示链接 demo
  • 使用嵌套视图时 Prism 7 抛出异常

    几个月前我发布了类似的问题使用 Prism 和 IsNavigationTarget 处理嵌套视图 可能返回 false 我仍然不确定正确的方法是什么 假设你有一个视图A 在这个视图A中你声明了一个区域A 然后你在这个区域A中注入了一个视图
  • 如何在窗口外触摸时取消 Activity 等主题的对话框?

    我有一个带有对话框主题的活动 当有人触摸此活动窗口之外的任何位置的屏幕时 我想关闭 完成 此活动 我怎样才能做到这一点 只是要指出的是is一种从以对话框为主题的活动中获得类似对话框的 触摸外部取消 行为的方法 尽管我还没有完全调查它是否有不
  • 正则表达式在多个多行字符串中查找列表值python

    我正在寻找一些帮助 以在具有多行但相似模式的字符串中搜索列表条件 每个子查询都有as and so as space and space 图案 我想搜索每个模式中的子标准并生成输出 sub apple apple event pear st
  • python、selenium 中切换帧的函数

    我正在寻找一个可以更轻松地在两个框架之间切换的功能 现在 每次我需要在帧之间切换时 我都会通过以下代码来完成此操作 driver switch to frame driver find element by css selector fra
  • Protovis 是否应该像 RaphaelJS 一样在 IE 7、8 和 9 上工作?

    我想Protovis可能在 IE 7 和 8 上工作 或者至少在 IE 9 上工作 但令我惊讶的是 我在所有 3 个浏览器上都尝试过它 但它在任何一个上都不起作用 对于那些示例页面 这是一个临时的 JS bug 它应该在 IE 上工作吗 比
  • 使用泛型进行反序列化的重构方法

    这是我要重构的方法 public static List
  • 使用量角器从日历中选择 angular-ui 日期选择器值

    我的日期选择器结构如下所示
  • 如何以编程方式将字段添加到 Delphi 中的表格

    在我的 Delphi 2009 应用程序中 我需要检查某个字段是否存在以及在应用程序执行期间是否未添加该字段 我已经弄清楚了该字段的测试 但无法添加字段 我试过这个 var fld TStringField begin if not ADO
  • 如何在 Laravel 5.6 中正确使用可选路由参数?

    我正在尝试使用 Laravel 5 6 创建一个 API 但是 在我看来 不可能在参数之前 之后使用可选的路由参数 我想实现以下目标 Route get api lists id items as gt api lists items ge
  • 无法使用 VBA .find 查找日期

    tmpArr 1 j 可以是日期或字符串 如果它是一个日期 那么我需要在 Range i4 ck4 中找到它 此范围内的日期被格式化为日期 我下面的代码没有找到我的日期 我究竟做错了什么 Data是 A 列中的代码 由字母数字组成 长度可能
  • 如何知道thrust::partition_copy的结果中有多少个元素

    我正在尝试使用推力库的partition copy函数对数组进行分区 我见过传递指针的示例 但我需要知道每个分区中有多少个元素 我尝试的是将设备向量作为 OutputIterator 参数传递 如下所示 include
  • Kafka 服务器不返回任何内容

    Zookeeper 已在 Windows 环境中启动并运行 现在 当我使用以下命令启动 Kafka 服务器时 bin windows kafka server start bat config server properties 没有显示任
  • 编写 Hyperledger Fabric Chaincode 时应遵循的最佳实践

    为了避免错误并编写高效的 Hyperledger Fabric Chaincode 应该遵循哪些最佳实践 编写 Hyperledger Fabric 链码的一般指南 有关详细说明 请参阅以下链接 https gist github com
  • Mockito - 奇怪的包范围类继承问题

    发现非常有趣的问题 并在调试后找到了重现它的场景 因此 如果我有一个包范围 B 的类 该类具有一些公共方法和扩展它的公共类 A package somepackage class B public void someMethod throw
  • 多处理 AttributeError 模块对象没有属性“__path__”

    我有一个很长的脚本 最后需要对庞大列表的所有项目运行一个函数 这需要很长时间 例如考虑 input a 1 2 3 4 a lengthy computation on some data print test 1 for testing
  • 如何使用Python字典? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我发现在 python 中迭代字典很困难 我已经通过 CodeAcademy 完成了学习并独立学习 但仍然觉得翻字典很困难 除了 Python 官方
  • java.io.IOException:参数无效

    我有一个带有负载均衡器的以集群模式运行的 Web 应用程序 它由两个 Tomcat T1 和 T2 组成 仅寻址一个 DB T2 通过 nfs 安装到 T1 这是两个节点之间唯一的差异 我有一个生成一些文件的java方法 如果请求 在 T1
  • 无法设置音量,音量控制未转发到系统

    我尝试使用安卓MediaPlayer框架来发挥mp3 file 看到这个问题 在我设法使其工作后 我很快意识到 音量增大 减小事件被类捕获javafxports android KeyEventProcessor并且永远不会被转发 我试图规