Android修改原始碼控制永不鎖屏

來源:互聯網
上載者:User

鎖定螢幕對於移動終端來說是非常有必要的,但是對於機頂盒產品就沒有這個必要了。所以本文介紹一下怎樣讓Android裝置永不鎖屏。
Android系統的鎖屏時間存放在Setting資料庫中,欄位為Settings.System.SCREEN_OFF_TIMEOUT。查看SettingsProvider源碼,查看如下檔案的源碼:
frameworks/base/packages/SettingsProvider/src/com/Android/providers/settings/DatabaseHelper.java

查看loadSystemSettings()函數的代碼如下:
private void loadSystemSettings(SQLiteDatabase db) {
        SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
                + " VALUES(?,?);");

        Resources r = mContext.getResources();

        loadBooleanSetting(stmt, Settings.System.DIM_SCREEN,
                R.bool.def_dim_screen);
        loadSetting(stmt, Settings.System.STAY_ON_WHILE_PLUGGED_IN,
                "1".equals(SystemProperties.get("ro.kernel.qemu")) ? 1 : 0);
        loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
                R.integer.def_screen_off_timeout);

        // Set default cdma emergency tone
        loadSetting(stmt, Settings.System.EMERGENCY_TONE, 0);

        // Set default cdma call auto retry
        loadSetting(stmt, Settings.System.CALL_AUTO_RETRY, 0);

        // Set default cdma DTMF type
        loadSetting(stmt, Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, 0);

        // Set default hearing aid
        loadSetting(stmt, Settings.System.HEARING_AID, 0);

        // Set default tty mode
        loadSetting(stmt, Settings.System.TTY_MODE, 0);

        loadBooleanSetting(stmt, Settings.System.AIRPLANE_MODE_ON,
                R.bool.def_airplane_mode_on);

        loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_RADIOS,
                R.string.def_airplane_mode_radios);

        loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
                R.string.airplane_mode_toggleable_radios);

        loadBooleanSetting(stmt, Settings.System.AUTO_TIME,
                R.bool.def_auto_time); // Sync time to NITZ

        loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
                R.integer.def_screen_brightness);

        loadBooleanSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_MODE,
                R.bool.def_screen_brightness_automatic_mode);

        loadDefaultAnimationSettings(stmt);

        loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION,
                R.bool.def_accelerometer_rotation);

        loadDefaultHapticSettings(stmt);

        stmt.close();
    }
從代碼中我們可以看出,假如 Settings.System.SCREEN_OFF_TIMEOUT沒有初始化的話(系統初次開機,這個欄位肯定是沒有初始化的),將會利用資源中的R.integer.def_screen_off_timeout來初始化。我們為了讓系統永不鎖屏,只需要把資源 R.integer.def_screen_off_timeout設為-1即可。查看檔案
frameworks/base/packages/SettingsProvider/res/values/defaults.xml
可以找到R.integer.def_screen_off_timeout的定義。
<integer name="def_screen_off_timeout">60000</integer>
發現預設值為60000ms,也就是60s。我們只需要把這個參數改為-1。然後重新編譯SettingsProvider模組,就OK了。
另外為了防止使用者進入系統後,修改鎖屏時間,在Setting模組中刪除對鎖屏時間的設定。這樣Android裝置就永不鎖屏了。
後來發現我的Android裝置燒錄好之後第一次啟動永遠不會鎖屏,但是裝置重啟之後開機就進入鎖屏狀態,解鎖之後就再也不會鎖屏了(因為永遠不逾時)。看來“革命尚未成功,同志仍需努力”啊。
那麼為什麼啟動之後沒有進入鎖屏狀態呢?是不會系統有把逾時鎖屏的值給修改了呢?我通過sqlite3去查看settings.db的內容,發現逾時鎖屏的值仍然是-1。說明啟動之後,系統並沒有去資料庫中查看螢幕逾時鎖屏的值,就直接鎖屏了。
但是怎樣才能開機之後不進入鎖屏狀態呢?這個是個非常費思量的問題。經過go,我知道鎖屏的代碼在LockScreen.java中,然後順藤摸瓜,終於找到了可以設定鎖屏功能開關的位置。代碼位於:
frameworks/policies/base/phone/com/Android/internal/policy/impl/KeyguardViewMediator.java
該檔案中有一個變數定義如下:
    /**
     * External apps (like the phone app) can tell us to disable the keygaurd.
     */
    private boolean mExternallyEnabled = true;
mExternallyEnabled是用來管理是否開啟螢幕鎖的關鍵。預設值是開啟屏鎖,根據注釋可以知道他是希望應用程式來修改這個值。但是經過加列印資訊發現開機的時候沒有任何應用程式會修改它。修改這個值調用如下函數:
   /**
     * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide
     * a way for external stuff to override normal keyguard behavior. For instance
     * the phone app disables the keyguard when it receives incoming calls.
     */
    public void setKeyguardEnabled(boolean enabled) {
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")");

            mExternallyEnabled = enabled;

            if (!enabled && mShowing) {
                if (mExitSecureCallback != null) {
                    if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring");
                    // we're in the process of handling a request to verify the user
                    // can get past the keyguard. ignore extraneous requests to disable / reenable
                    return;
                }

                // hiding keyguard that is showing, remember to reshow later
                if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
                        + "disabling status bar expansion");
                mNeedToReshowWhenReenabled = true;
                hideLocked();
            } else if (enabled && mNeedToReshowWhenReenabled) {
                // reenabled after previously hidden, reshow
                if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
                        + "status bar expansion");
                mNeedToReshowWhenReenabled = false;

                if (mExitSecureCallback != null) {
                    if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting");
                    mExitSecureCallback.onKeyguardExitResult(false);
                    mExitSecureCallback = null;
                    resetStateLocked();
                } else {
                    showLocked();

                    // block until we know the keygaurd is done drawing (and post a message
                    // to unblock us after a timeout so we don't risk blocking too long
                    // and causing an ANR).
                    mWaitingUntilKeyguardVisible = true;
                    mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS);
                    if (DEBUG) Log.d(TAG, "waiting until mWaitingUntilKeyguardVisible is false");
                    while (mWaitingUntilKeyguardVisible) {
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    if (DEBUG) Log.d(TAG, "done waiting for mWaitingUntilKeyguardVisible");
                }
            }
        }
    }
經過上面的討論我們可以發現我們有兩個解決方案:
1、定義變數的時候,給其初始化為false。
2、在launcher模組啟動的時候,調用setKeyguardEnabled方法,關閉鎖屏功能。
我懶得修改Laucher模組,我的解決方案就是在定義mExternallyEnabled時修改其初始值為false。各位朋友可以根據自己的實際情況選擇解決方案。My Code如下:
   /**
     * External apps (like the phone app) can tell us to disable the keygaurd.
     */
    private boolean mExternallyEnabled = false;
這樣修改之後,Android裝置開機之後,預設不會進入鎖屏狀態,除非你在應用程式中調用setKeyguardEnabled方法顯示開啟這個功能。因為設定的逾時時間為-1,則永遠也不會進入鎖定畫面。完全滿足了我的需求,終於大功告成了。開心啊~!!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.