欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-12 10:35:20
...

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" />
相关标签: 音量键