Android 后台服务监听按键(home,back,音量键)

0.启动1x1大小服务窗口进行监听变化,音量按键下按

不接受触摸屏事件。
public static final int FLAG_NOT_TOUCHABLE = 0x00000010;

当窗口可以获得焦点(没有设置FLAG_NOT_FOCUSALBE选项)时,仍然将窗口范围之外的点设备事件(鼠标、触摸屏)发送给后面的窗口处理。否则它将独占所有的点设备事件,而不管它们是不是发生在窗口范围之内。
public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020;

    public class MonitorView extends View {

        public MonitorView(Context context) {
            super(context);
        }

        @Override
        public boolean dispatchKeyEvent(KeyEvent event) {
            Log.d("suhuazhi", "keyCode " + event.getKeyCode());
            switch (event.getKeyCode()) {
                case KeyEvent.KEYCODE_BACK:
                case KeyEvent.KEYCODE_MENU:
                    // 处理自己的逻辑break;
                case KeyEvent.KEYCODE_VOLUME_DOWN:
                    Log.d("suhuazhi", "KEYCODE_VOLUME_DOWN");
                    if (mAudioUtil != null && isMediaVolumePowerSaveSettings) {
                        int currAudioVolume = mAudioUtil.getMediaVolume();

                        Log.d(TAG, "currMediaVolume = " + currAudioVolume);

                        if (AUDIO_ADJ == currAudioVolume) {
                            Log.d(TAG, "Down volume key resume");
                            mAudioUtil.setMediaVolume(AUDIO_ADJ);
                            isMediaVolumePowerSaveSettings = false;
                        }

                    }
                    break;
                case KeyEvent.KEYCODE_VOLUME_UP:
                    Log.d("suhuazhi", "KEYCODE_VOLUME_UP");
                    break;
                default:
                    break;
            }
            return super.dispatchKeyEvent(event);
        }
    }

Window 窗口显示

    private void showWindow() {
        if (mWindowManager == null) {
            mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
            mMonitorView = new MonitorView(mContext);
        }

        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                1, 1, //Must be at least 1x1
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                //Don't know if this is a safe default
                PixelFormat.TRANSLUCENT);

        //Don't set the preview visibility to GONE or INVISIBLE
        mWindowManager.addView(mMonitorView, params);
    }

    private void hideWindow() {
        if(null != mWindowManager) {
            mWindowManager.removeView(mMonitorView);
        }
    }

运行结果

03-23 17:00:23.910: D/suhuazhi(8340): KEYCODE_VOLUME_UP
03-23 17:00:23.935: D/suhuazhi(8340): keyCode 24

1.使用ContentProvide 监听数据库变化,来监听音量键变化

    private void registerVolumeChangeReceiver() {
        mSettingsContentObserver = new SettingsContentObserver(mContext, null);
        mContext.getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver);
    }

    private void unregisterVolumeChangeReceiver(){
        mContext.getContentResolver().unregisterContentObserver(mSettingsContentObserver);
    }

    public class SettingsContentObserver extends ContentObserver {
        private int oldMediaVolume;


        public SettingsContentObserver(Context c, Handler handler) {
            super(handler);
        }

        @Override
        public boolean deliverSelfNotifications() {
            return super.deliverSelfNotifications();
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);

            if (mAudioUtil != null && isMediaVolumePowerSaveSettings) {
                int currAudioVolume = mAudioUtil.getMediaVolume();

                if (oldMediaVolume == currAudioVolume) {
                    return;
                }

                oldMediaVolume = currAudioVolume;
                Log.d(TAG, "onChange currMediaVolume = " + currAudioVolume);

                if (currAudioVolume == mAudioUtil.getMaxMediaVolume()) {
                    return;
                }

                if (AUDIO_ADJ - currAudioVolume > 0) {
                    Log.d(TAG, "Down volume key resume");
                    mAudioUtil.setMediaVolume(AUDIO_ADJ);
                    isMediaVolumePowerSaveSettings = false;
                }

            }
        }
    }

运行结果
缺点是设置过去需要等待约1.5秒才触发

03-23 15:03:17.490: D/LavaDisplayHelp(2903):  setMediaVolume = 141.5秒后才触发)
03-23 15:03:18.005: D/LavaDisplayHelp(2903): onChange currMediaVolume = 14

2.使用广播进行监听,来监听音量键变化

是的,没差,速度还是一样慢

    private class VolumeReceiver extends BroadcastReceiver {

        private int oldMediaVolume;

        public void init(Context mContext) {
            IntentFilter filter = new IntentFilter();
            filter.addAction("android.media.VOLUME_CHANGED_ACTION");
            mContext.registerReceiver(this, filter);
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("android.media.VOLUME_CHANGED_ACTION")) {
                if (mAudioUtil != null && isMediaVolumePowerSaveSettings) {
                    int currAudioVolume = mAudioUtil.getMediaVolume();

                    if (oldMediaVolume == currAudioVolume) {
                        return;
                    }

                    oldMediaVolume = currAudioVolume;
                    Log.d(TAG, "currMediaVolume = " + currAudioVolume);

                    if (currAudioVolume == mAudioUtil.getMaxMediaVolume()) {
                        return;
                    }

                    if (AUDIO_ADJ - currAudioVolume > 0) {
                        Log.d(TAG, "Down volume key resume");
                        mAudioUtil.setMediaVolume(AUDIO_ADJ);
                        isMediaVolumePowerSaveSettings = false;
                    }

                }
            }
        }
    }

3.使用无障碍,来监听音量键变化

public class PowerSaveMonitorService extends AccessibilityService {

    private static final String TAG = PowerSaveMonitorService.class.getSimpleName();

    @Override
    protected boolean onKeyEvent(KeyEvent event) {
        Log.i(TAG, "onKeyEvent");
        int key = event.getKeyCode();
        switch(key){
            case KeyEvent.KEYCODE_VOLUME_DOWN:
                Log.i(TAG, "KEYCODE_VOLUME_DOWN");
                break;
            case KeyEvent.KEYCODE_VOLUME_UP:
                Log.i(TAG, "KEYCODE_VOLUME_UP");
                break;
        }
        return super.onKeyEvent(event);
    }

    @Override
    public void onInterrupt() {

    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        String pkgName = event.getPackageName().toString();
        String className = event.getClassName().toString();
        int eventType = event.getEventType();

        switch (eventType) {
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                break;
        }
    }
}

AndroidManifest.xml

        <service
            android:name=".service.PowerSaveMonitorService"
            android:enabled="true"
            android:exported="true"
            android:label="@string/app_name"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>
            <meta-data android:name="android.accessibilityservice"
                android:resource="@xml/accessibility_config"></meta-data>
        </service>

accessibility_config.xml

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:canRetrieveWindowContent="true"
    android:description="@string/app_name"
    android:notificationTimeout="100" />
  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
Android 中,你可以通过创建一个 `BroadcastReceiver` 广播接收器来监听音量的变化。下面是一个示例代码: 首先,在你的 AndroidManifest.xml 文件中添加以下权限: ```xml <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> ``` 然后,创建一个新的 Java 类来实现广播接收器: ```java public class VolumeButtonReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action != null && action.equals("android.media.VOLUME_CHANGED_ACTION")) { // 处理音量改变的逻辑 int currentVolume = intent.getIntExtra("android.media.EXTRA_VOLUME_STREAM_VALUE", -1); int previousVolume = intent.getIntExtra("android.media.EXTRA_PREV_VOLUME_STREAM_VALUE", -1); // 在这里执行你的操作,比如发送广播或者调用相应的方法 // ... } } } ``` 接下来,在你的 Activity 或者 Service 中注册广播接收器: ```java public class MainActivity extends AppCompatActivity { private VolumeButtonReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 创建广播接收器实例 receiver = new VolumeButtonReceiver(); // 创建 IntentFilter 并添加音量改变的 action IntentFilter filter = new IntentFilter(); filter.addAction("android.media.VOLUME_CHANGED_ACTION"); // 注册广播接收器 registerReceiver(receiver, filter); } @Override protected void onDestroy() { super.onDestroy(); // 在 Activity 销毁时注销广播接收器 unregisterReceiver(receiver); } } ``` 这样,当用户按下音量时,`VolumeButtonReceiver` 类中的 `onReceive()` 方法将会被调用,你可以在这个方法中执行你想要的操作。注意,在 Android 8.0(API 级别 26)及以上版本中,需要在运行时请求 `MODIFY_AUDIO_SETTINGS` 权限。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值