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

相关推荐
凛_Lin~~10 分钟前
安卓 面试八股文整理(原理与性能篇)
android·java·面试·安卓
花花鱼1 小时前
android 更新后安装app REQUEST_INSTALL_PACKAGES 权限受限 + FileProvider 元数据异常
android
2501_946233891 小时前
Flutter与OpenHarmony大师详情页面实现
android·javascript·flutter
z9209810232 小时前
ZTE 中兴 高通 安卓手机 一键改串 一键新机 IMEI MEID 写号 硬改 手机修改参数 视频教程演示
android·智能手机
idealzouhu2 小时前
【Android Framework】Intent 运行机制
android
2501_946233892 小时前
Flutter与OpenHarmony Tab切换组件开发详解
android·javascript·flutter
2501_946233892 小时前
Flutter与OpenHarmony订单详情页面实现
android·javascript·flutter
2501_944446002 小时前
Flutter&OpenHarmony拖拽排序功能实现
android·javascript·flutter
2501_944446002 小时前
Flutter&OpenHarmony应用生命周期管理
android·javascript·flutter
驱动探索者3 小时前
[缩略语大全]之[安卓]篇
android