ANDROID8.0 雙擊POWER鍵啟動(dòng)流程及音量面板調(diào)取需求實(shí)現(xiàn)

ANDROID8.0 雙擊POWER鍵啟動(dòng)流程及音量面板調(diào)取需求實(shí)現(xiàn)

標(biāo)簽: Android 雙擊power鍵啟動(dòng)流程 雙擊power鍵 Android啟動(dòng)音量面板 Android power鍵

之前參考雙擊調(diào)用Camera,添加了一個(gè)雙擊啟動(dòng)音量面板的功能,為啥?因?yàn)檫@手機(jī)只有power鍵!

實(shí)現(xiàn)功能前,先摸清流程對我們的開發(fā)會(huì)更方便。

POWER鍵大概流程

這里寫圖片描述

PhoneWindowManager.java 類是 處理各種 power 鍵流程的地方,

case KeyEvent.KEYCODE_POWER: 
    if (down) {
        interceptPowerKeyDown(event, interactive);
        } else {
        interceptPowerKeyUp(event, interactive, canceled);
    }

power鍵按下在interceptPowerKeyDown()執(zhí)行,松開的操作在interceptPowerKeyUp()中執(zhí)行

interceptPowerKeyDown()方法中會(huì)調(diào)用 GestureLauncherService.java 的 interceptPowerKeyDown() 方法

GestureLauncherService gestureService = LocalServices.getService(
                GestureLauncherService.class);
        boolean gesturedServiceIntercepted = false;
        if (gestureService != null) {
            gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
                    mTmpBoolean);
            if (mTmpBoolean.value && mRequestedOrGoingToSleep) {
                mCameraGestureTriggeredDuringGoingToSleep = true;
            }
        }

跟蹤看看GestureLauncherService.java 中 執(zhí)行 interceptPowerKeyDown()方法如下

public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive,
            MutableBoolean outLaunched) {
        boolean launched = false;
        boolean intercept = false;
        long powerTapInterval;
        synchronized (this) {
            powerTapInterval = event.getEventTime() - mLastPowerDown;
            if (mCameraDoubleTapPowerEnabled
                    && powerTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) {//雙擊事件
                Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DOUBLE_TAP_TAG,1);
                launched = true;
                intercept = interactive;
                mPowerButtonConsecutiveTaps++;
            } else if (powerTapInterval < POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS) {//延遲雙擊事件
                mPowerButtonConsecutiveTaps++;
            } else {//單擊事件
                mPowerButtonConsecutiveTaps = 1;
            }
            mLastPowerDown = event.getEventTime();
        }
        if (DBG && mPowerButtonConsecutiveTaps > 1) {
            Slog.i(TAG, Long.valueOf(mPowerButtonConsecutiveTaps) +
                    " consecutive power button taps detected");
        }
        if (launched) {
            Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval="
                    + powerTapInterval + "ms");
            //調(diào)用開啟相機(jī)        
            launched = handleCameraGesture(false/* useWakelock */,
                    StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
            if (launched) {
                mMetricsLogger.action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
                        (int) powerTapInterval);
            }
        }
        mMetricsLogger.histogram("power_consecutive_short_tap_count", mPowerButtonConsecutiveTaps);
        mMetricsLogger.histogram("power_double_tap_interval", (int) powerTapInterval);
        outLaunched.value = launched;

        return intercept && launched;
    }

系統(tǒng)會(huì)對mCameraDoubleTapPowerEnabled 取值,核心是通過resources.getBoolean(com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled) 來取,
其實(shí)這個(gè)值是配置在/frameworks/base/core/res/res/values/config.xml中,這里是為true的

<!-- Allow the gesture to double tap the power button twice to start the camera while the deviceis non-interactive. -->
    <bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool>12

接下來會(huì)分別對power連續(xù)按2或者1次進(jìn)行判斷,如果mCameraDoubleTapPowerEnabled = true 會(huì)通過比較按鍵的時(shí)間powerTapInterval小于系統(tǒng)默認(rèn)時(shí)間(CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS=300毫秒),
mPowerButtonConsecutiveTaps計(jì)數(shù)加1,說明連續(xù)按power鍵,或者延遲最大500毫秒內(nèi)連續(xù)按鍵,系統(tǒng)預(yù)計(jì)用戶接下來可能會(huì)執(zhí)行一些操作,計(jì)數(shù)也會(huì)加1.

static final long POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS = 500;
static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300;

powerTapInterval = event.getEventTime() - mLastPowerDown;
mLastPowerDown = event.getEventTime();

if (mCameraDoubleTapPowerEnabled && powerTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) 

if (powerTapInterval < POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS)

執(zhí)行完成之后會(huì)調(diào)用 handleCameraGesture()方法調(diào)用開啟攝像機(jī)。

@VisibleForTesting
    boolean handleCameraGesture(boolean useWakelock, int source) {
        boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
        if (!userSetupComplete) {
            if (DBG) Slog.d(TAG, String.format(
                    "userSetupComplete = %s, ignoring camera gesture.",
                    userSetupComplete));
            return false;
        }
        if (DBG) Slog.d(TAG, String.format(
                "userSetupComplete = %s, performing camera gesture.",
                userSetupComplete));
        if (useWakelock) {
            // Make sure we don't sleep too early
            mWakeLock.acquire(500L);
        }

        StatusBarManagerInternal service = LocalServices.getService(
                StatusBarManagerInternal.class);
        //啟動(dòng)相機(jī)
        service.onCameraLaunchGestureDetected(source);

        return true;

    }

原生雙擊啟動(dòng)相機(jī)流程差不多是這樣,后面service不詳細(xì)說,但是我們這里是需要啟動(dòng)音量面板啊~

需求實(shí)現(xiàn)

流程縷清了實(shí)現(xiàn)起來就很方便了,現(xiàn)在雙擊事件那邊記錄下一個(gè)標(biāo)記值

if (mCameraDoubleTapPowerEnabled&& powerTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) {
    //雙擊事件,添加標(biāo)記為1
    Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DOUBLE_TAP_TAG,1);

然后在外層 PhoneWindowManager.java 添加如果在setting那邊選了調(diào)用音量面板模式和雙擊標(biāo)記值符合則調(diào)用音量面板顯示即可完成需求。

case KeyEvent.KEYCODE_POWER: {
                final int powerKeyModeTag = Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0);
                int doubleTapTag =  Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.DOUBLE_TAP_TAG, 0);
                mCameraDoubleTapPowerEnabled = powerKeyModeTag == 2 ? true : false;
                mButtonDoubleTapPowerEnabled = doubleTapTag == 1 ? true : false;
                if (mCameraDoubleTapPowerEnabled
                    && mButtonDoubleTapPowerEnabled) {
                    AudioManager am = (AudioManager)mContext. getSystemService(mContext.AUDIO_SERVICE);
                    am.adjustVolume(AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI) ;
                    Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DOUBLE_TAP_TAG,0);
                    return ACTION_PASS_TO_USER;
                }
                ...
                break;
}

如果大家有更好的辦法歡迎指導(dǎo)交流~~

版權(quán)聲明:本文為ouzhuangzhuang原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/ouzhuangzhuang/article/details/82150180

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容