Android全局监听音量按键事件

Hi,I'm Shendi

最近在编写Android自动化之类的东西,对于触发器我选用了音量键,在这里记录一下


Android全局监听音量按键事件


Android全局监听音量按键事件

有多种方式,但效果和兼容性都不太理想,最终我选择了无障碍+音量广播二合一的方式

无障碍监听按键事件

用户体验

  • 需要手动打开无障碍
  • 在某些手机上有熔断问题(小米实测,按几下后就监听不到了,得重启手机才能继续监听)

实现

在 res/xml 中新建无障碍配置文件 accessibility_service_config.xml,如下

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/accessibility_service_description"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:notificationTimeout="50"
    android:canRetrieveWindowContent="true"
    android:accessibilityFlags="flagDefault"
    android:canRequestFilterKeyEvents="true"
    android:canRequestTouchExplorationMode="true"
    android:accessibilityFeedbackType="feedbackAllMask"
/>

上方的 android:canRequestFilterKeyEvents="true" 是必须的,允许无障碍服务接收并过滤按键事件(包括音量键)

新建无障碍服务类,如下

java 复制代码
public class VolumeKeyAccessibilityService extends AccessibilityService {

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();

        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
        info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
        info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
        // 监听按键事件的flags,必须要代码加才能监听到
        info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS;
        info.notificationTimeout = 50;

        setServiceInfo(info);
    }

    @Override
    public boolean onKeyEvent(KeyEvent event) {

        int keyCode = event.getKeyCode();

        if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
            if (event.getAction() == KeyEvent.ACTION_DOWN) {
                Log.i("VolumeKey", "音量 + 按下");
            } else if (event.getAction() == KeyEvent.ACTION_UP) {
                Log.i("VolumeKey", "音量 + 抬起");
            }
            return true; // 拦截按键(不让系统调音量)
        }

        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            if (event.getAction() == KeyEvent.ACTION_DOWN) {
                Log.i("VolumeKey", "音量 - 按下");
            } else if (event.getAction() == KeyEvent.ACTION_UP) {
                Log.i("VolumeKey", "音量 - 抬起");
            }
            return true;
        }

        // 返回 false 表示按键传递给系统
        return false;
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        // 不需要处理无障碍事件
    }

    @Override
    public void onInterrupt() {

    }
}

清单文件中配置服务

xml 复制代码
<service
    android:name=".VolumeKeyAccessibilityService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
    android:exported="false">

    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>

    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibility_service_config" />
</service>

广播监听音量变化

我将其作为无障碍无法正确监听的备用选项。

监听的是音量变化,所以当音量为0,按下音量下键不会触发,音量100按下音量上键不会触发。

实现

注册广播接收器

java 复制代码
// 注册广播接收器
IntentFilter filter = new IntentFilter();
// 音量修改事件
filter.addAction("android.media.VOLUME_CHANGED_ACTION");

registerReceiver(receiver, filter);

广播接收器

java 复制代码
/** 最后一次手机的音量 */
private int lastVolume = -1;

private final BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        switch (intent.getAction()) {
            // 音量变动
            case "android.media.VOLUME_CHANGED_ACTION": {
                int newVolume = intent.getIntExtra("android.media.EXTRA_VOLUME_STREAM_VALUE", -1);

                if (lastVolume == -1) {
                    lastVolume = newVolume;
                    return;
                }

                if (newVolume > lastVolume) {
                    // 等价于音量上键
                    onVolumeUp();
                } else if (newVolume < lastVolume) {
                    // 等价于音量下键
                    onVolumeDown();
                }

                lastVolume = newVolume;
                break;
            }
        }
    }
};
                

END

相关推荐
提子拌饭1331 小时前
番茄时间管理:鸿蒙Flutter 实现的高效时间管理工具
android·flutter·华为·架构·开源·harmonyos·鸿蒙
4311媒体网1 小时前
帝国CMS二次开发实战:精准实现“最新资讯”标识与高亮判断
android
BLUcoding2 小时前
Android 轻量级本地存储 SharedPreferences
android
冬奇Lab2 小时前
Camera HAL3 接口:Android 相机的真正底牌
android·音视频开发·源码阅读
sensen_kiss2 小时前
CAN302 Technologies for E-Commerce 电子商务技术 Pt.6 市场营销与SEO(搜索引擎优化)
android·学习·搜索引擎
菜鸟国国3 小时前
Compose + Koin ViewModel 实战完全手册
android
小羊子说3 小时前
Android 音频系统深度解析:从 App 到内核的完整链路
android·人工智能·性能优化·车载系统
fengci.3 小时前
php反序列化(复习)(第三章)
android·开发语言·学习·php
D4c-lovetrain3 小时前
linux个人心得24 (mysql③,AI排版尝试)
android·adb
csj503 小时前
安卓基础之《(25)—竖屏与横屏切换》
android