這篇文章主要介紹了Android4.0開(kāi)發(fā)之Keyguard解鎖屏機(jī)制的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
成都創(chuàng)新互聯(lián)公司主營(yíng)華池網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,APP應(yīng)用開(kāi)發(fā),華池h5小程序開(kāi)發(fā)搭建,華池網(wǎng)站營(yíng)銷(xiāo)推廣歡迎華池等地區(qū)企業(yè)咨詢(xún)
具體如下:
Keyguard解鎖屏是Android系統(tǒng)中必不可少的模塊,用戶(hù)在開(kāi)機(jī)后或者在點(diǎn)擊Power按鈕屏幕變亮后首先看到的畫(huà)面即為解鎖屏模塊對(duì)應(yīng)的界面。Keyguard模塊功能相對(duì)簡(jiǎn)單:
第一:直觀地顯示手機(jī)當(dāng)前的關(guān)鍵信息:比如電池信息、運(yùn)營(yíng)商信息、日期信息以及通話短信信息等。
第二:增強(qiáng)手機(jī)的安全性能:為了安全,用戶(hù)可以在Setting里的Secure選項(xiàng)中設(shè)置password、pattern、account等不同的安全策略,防止非法用戶(hù)訪問(wèn)手機(jī)系統(tǒng)。
但從代碼實(shí)現(xiàn)的角度該模塊邏輯還是比較復(fù)雜,不但需要監(jiān)聽(tīng)系統(tǒng)中的多種event,比如sim、電話、電池以及Carrier等狀態(tài),還要正確反映、顯示屏幕的不同狀態(tài)。為了對(duì)Keyguard模塊的處理邏輯有更清晰的理解,下面首先從系統(tǒng)構(gòu)成的角度概括介紹Keyguard解鎖屏模塊的框架,然后對(duì)解鎖屏模塊中重要的處理邏輯進(jìn)行詳細(xì)介紹。
一、系統(tǒng)介紹
Keyguard解鎖屏模塊的框架類(lèi)圖如下:
圖中僅列出了Keyguard解鎖屏模塊涉及的重要類(lèi),這些類(lèi)實(shí)現(xiàn)了Keyguard模塊的主要功能,它們的作用如下:
PhoneWindowManager是解鎖屏模塊對(duì)外交互的接口,窗口管理Service、電源管理Service等外部模塊都是通過(guò)PhoneWindowManager訪問(wèn)Keyguard內(nèi)部功能。
KeyguardViewMediator類(lèi)為解鎖屏模塊的中介者,以中介的身份處理keyguard狀態(tài)變化,處理event、power管理、PhoneWindowManager通知等請(qǐng)求,并作為回調(diào)對(duì)象供解鎖屏模塊的其它類(lèi)回調(diào)。
KeyguardUpdateMonitor類(lèi)為解鎖屏模塊的監(jiān)聽(tīng)者,它負(fù)責(zé)監(jiān)聽(tīng)時(shí)間、sim卡、運(yùn)營(yíng)商信息、電池信息、電話信息等狀態(tài)的變化,并通知keyguard View模塊更新顯示。
KeyguardViewManager類(lèi)為解鎖屏view模塊的管理者,管理解鎖屏界面的創(chuàng)建、顯示、隱藏以及重置等。
LockPatternKeyguardView類(lèi)為解鎖屏模塊的View界面,為所有解鎖屏界面的host view。根據(jù)設(shè)置的安全策略,顯示不同的解鎖屏界面。Google原生代碼中實(shí)現(xiàn)了6種解鎖屏界面:
1) LockScreen:用于顯示屏幕加鎖狀態(tài)
2) PatternUnlockScreen:實(shí)現(xiàn)圖案解鎖模式
3) SimPukUnlockScreen:屏幕實(shí)現(xiàn)SIM PUK碼解鎖模式
4) SimUnlockScreen:實(shí)現(xiàn)Sim PIN碼解鎖模式
5) AccountUnlockScreen:實(shí)現(xiàn) GOOGLE 帳戶(hù)解鎖
6) PasswordUnlockScreen:實(shí)現(xiàn)自定義密碼解鎖模式
二、主要邏輯
1、Keyguard模塊啟動(dòng)、顯示邏輯
即手機(jī)開(kāi)機(jī)進(jìn)入系統(tǒng)到鎖屏界面顯示的過(guò)程。手機(jī)系統(tǒng)啟動(dòng)過(guò)程中會(huì)自動(dòng)啟動(dòng)Keyguard解鎖屏模塊,該模塊的創(chuàng)建始于WindowManagerService類(lèi),時(shí)序圖如下:
1)WindowManagerService在啟動(dòng)時(shí)會(huì)實(shí)例化PhoneWindowManager對(duì)象mPolicy,并在窗口管理Policy線程PolicyThread中初始化,代碼如下:
public void run() { Looper.prepare(); WindowManagerPolicyThread.set(this, Looper.myLooper()); ...... mPolicy.init(mContext, mService, mService, mPM); ...... Looper.loop(); }
從代碼中可以看到PhoneWindowManager在獨(dú)立的線程和Looper消息隊(duì)列中處理Message事件,該Looper對(duì)象也為解鎖屏模塊使用以處理所有handler消息。
2)mPolicy函數(shù)init中創(chuàng)建解鎖屏模塊的中介者——KeyguardViewMediator對(duì)象。
3)在KeyguardViewMediator的構(gòu)造函數(shù)中創(chuàng)建LockPatternKeyguardViewProperties、KeyguardUpdateMonitor、KeyguardViewManager等重要對(duì)象:
public KeyguardViewMediator(Context context, PhoneWindowManager callback, LocalPowerManager powerManager) { …… mUpdateMonitor = new KeyguardUpdateMonitor(context); mUpdateMonitor.registerInfoCallback(this); mUpdateMonitor.registerSimStateCallback(this); mLockPatternUtils = new LockPatternUtils(mContext); mKeyguardViewProperties = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor); mKeyguardViewManager = new KeyguardViewManager( context, WindowManagerImpl.getDefault(), this, mKeyguardViewProperties, mUpdateMonitor); …… }
KeyguardViewMediator中記錄了PhoneWindowManager、PowerManager等對(duì)象,同時(shí)也保存了LockPatternKeyguardViewProperties、KeyguardUpdateMonitor、KeyguardViewManager等模塊內(nèi)的重要對(duì)象,這樣該類(lèi)以中介者身份在Keyguard模塊對(duì)外交互以及內(nèi)部各對(duì)象間的交互中發(fā)揮了重要作用。
4)KeyguardUpdateMonitor構(gòu)造函數(shù)中創(chuàng)建mHandler,用以響應(yīng)處理該類(lèi)監(jiān)聽(tīng)的各事件狀態(tài)的改變,并在handle處理函數(shù)中通知mInfoCallbacks和mSimStateCallbacks保存的監(jiān)聽(tīng)對(duì)象,監(jiān)聽(tīng)事件有ACTION_TIME_TICK、ACTION_TIME_CHANGED、ACTION_BATTERY_CHANGED、ACTION_TIMEZONE_CHANGED、ACTION_SIM_STATE_CHANGED、 ACTION_PHONE_STATE_CHANGED、RINGER_MODE_CHANGED_ACTION
至此Keyguard解鎖屏模塊中重要的類(lèi)對(duì)象已經(jīng)實(shí)例化,但是還未涉及解鎖屏View界面的創(chuàng)建和顯示。
5)系統(tǒng)啟動(dòng)后解鎖屏界面的首次顯示始于WindowManagerService的systemReady函數(shù),通知PhoneWindowManager系統(tǒng)就緒,代碼如下:
public void systemReady() { mPolicy.systemReady(); }
6)PhoneWindowManager的systemReady函數(shù)中通知解鎖屏模塊的中介者KeyguardViewMediator對(duì)象系統(tǒng)就緒
7)中介者KeyguardViewMediator類(lèi)中處理系統(tǒng)就緒情形:調(diào)用doKeyguardLocked函數(shù)顯示解鎖屏界面:
public void onSystemReady() { synchronized (this) { mSystemReady = true; doKeyguardLocked(); } } private void doKeyguardLocked() { ...... // if the keyguard is already showing, don't bother if (mKeyguardViewManager.isShowing()) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing"); return; } ..... if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen"); showLocked(); }
showLocked函數(shù)中發(fā)送SHOW消息異步處理解鎖屏界面顯示的請(qǐng)求。
8)handleShow中處理界面顯示的消息請(qǐng)求,函數(shù)中調(diào)用KeyguardViewManager的函數(shù)show實(shí)現(xiàn)解鎖屏界面的真正顯示:
public synchronized void show() { ...... if (mKeyguardHost == null) { if (DEBUG) Log.d(TAG, "keyguard host is null, creating it..."); mKeyguardHost = new KeyguardViewHost(mContext, mCallback); ...... mViewManager.addView(mKeyguardHost, lp); } ...... mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams); if (mKeyguardView == null) { mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this); ...... mKeyguardHost.addView(mKeyguardView, lp); ...... } ...... }
該函數(shù)中主要?jiǎng)?chuàng)建了Keyguard顯示View中的兩個(gè)重要的對(duì)象:mKeyguardHost和mKeyguardView,它們都是繼承于FrameLayout,為解鎖屏視圖的根view。
9)在創(chuàng)建對(duì)象mKeyguardView時(shí)根據(jù)解鎖屏mode創(chuàng)建解鎖屏界面:
protected void updateScreen(Mode mode, boolean force) { ...... // Re-create the lock screen if necessary if (mode == Mode.LockScreen || mShowLockBeforeUnlock) { if (force || mLockScreen == null) { recreateLockScreen(); } } // Re-create the unlock screen if necessary. This is primarily required to properly handle // SIM state changes. This typically happens when this method is called by reset() if (mode == Mode.UnlockScreen) { final UnlockMode unlockMode = getUnlockMode(); if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) { recreateUnlockScreen(unlockMode); } } ...... }
10)在函數(shù)createLockScreen或者createUnlockScreenFor中創(chuàng)建具體的Lock或者Unlock View界面,并調(diào)用show函數(shù)進(jìn)行顯示
至此,Keyguard解鎖屏模塊從系統(tǒng)開(kāi)機(jī)啟動(dòng)到界面顯示的處理邏輯已介紹完成。
2、兩次按下Power按鈕屏幕亮->暗->亮過(guò)程中鎖屏模塊處理邏輯
連續(xù)兩次按下Power按鈕屏幕亮->暗->亮過(guò)程中解鎖屏模塊處理邏輯的時(shí)序圖如下:
1)在函數(shù)PowerManagerService:setPowerState中響應(yīng)Power按鈕的按下,代碼如下:
private void setPowerState(int newState, boolean noChangeLights, int reason) { synchronized (mLocks) { …… if (oldScreenOn != newScreenOn) { if (newScreenOn) { // When the user presses the power button, we need to always send out the // notification that it's going to sleep so the keyguard goes on. But // we can't do that until the screen fades out, so we don't show the keyguard // too early. if (mStillNeedSleepNotification) { sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER); } …… if (err == 0) { sendNotificationLocked(true, -1); // Update the lights *after* taking care of turning the // screen on, so we do this after our notifications are // enqueued and thus will delay turning on the screen light // until the windows are correctly displayed. if (stateChanged) { updateLightsLocked(newState, 0); } mPowerState |= SCREEN_ON_BIT; } } else { …… if (!mScreenBrightness.animating) { err = screenOffFinishedAnimatingLocked(reason); } …… } } …… } }
根據(jù)上面的代碼邏輯,屏幕即將變暗時(shí)調(diào)用函數(shù)screenOffFinishedAnimatingLocked,屏幕即將變亮?xí)r調(diào)用函數(shù)sendNotificationLocked。
2)函數(shù)sendNotificationLocked發(fā)送Notification Task線程到handler,并異步執(zhí)行通知解鎖屏模塊進(jìn)行狀態(tài)更新:
private Runnable mNotificationTask = new Runnable() { public void run() { while (true) { ...... if (value == 1) { policy.screenTurningOn(mScreenOnListener); ...... } else if (value == 0) { policy.screenTurnedOff(why); ...... } else { // If we're in this case, then this handler is running for a previous // paired transaction. mBroadcastWakeLock will already have been released. break; } } } };
上面的線程函數(shù)run中分別處理了屏幕變暗和變亮的情形。按下Power按鈕屏幕變暗時(shí)調(diào)用了函數(shù)screenTurnedOff,why為變暗的原因,此處值為OFF_BECAUSE_OF_USER。
3)KeyguardViewMediator中根據(jù)屏幕變暗的原因分別處理屏幕變暗事件:
/** * Called to let us know the screen was turned off. * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER}, * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or * {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}. */ public void onScreenTurnedOff(int why) { synchronized (this) { …… else if (mShowing) { //若是(mShowing)則重置顯示界面,否則重新顯示鎖屏界面 notifyScreenOffLocked(); resetStateLocked(); } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) { // if the screen turned off because of timeout, set an alarm // to enable it a little bit later (i.e, give the user a chance // to turn the screen back on within a certain window without // having to unlock the screen) …… if (timeout <= 0) { // Lock now mSuppressNextLockSound = true; doKeyguardLocked(); } else { // Lock in the future long when = SystemClock.elapsedRealtime() + timeout; Intent intent = new Intent(DELAYED_KEYGUARD_ACTION); intent.putExtra("seq", mDelayedShowingSequence); PendingIntent sender = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender); } } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) { // Do not enable the keyguard if the prox sensor forced the screen off. } else { //顯示鎖屏屏幕 doKeyguardLocked(); } } }
4)調(diào)用doKeyguardLocked重新顯示鎖屏界面,隨后的鎖屏界面顯示邏輯與Keyguard模塊啟動(dòng)顯示中的8~10步相同,不再贅述。
5)按下Power按鈕屏幕即將由暗->亮?xí)r代碼處理邏輯重新執(zhí)行1~2步,第二步中屏幕變亮?xí)r調(diào)用的函數(shù)是PhoneWindowManager:screenTurningOn。
6)函數(shù)screenTurningOn中調(diào)用中介者KeyguardViewMediator的函數(shù)onScreenTurnedOn,該函數(shù)直接調(diào)用屏幕變亮異步通知函數(shù)KeyguardViewMediator:notifyScreenOnLocked,告知解鎖屏模塊屏幕即將變亮。
7)函數(shù)handleNotifyScreenOn響應(yīng)屏幕變亮的通知
8)程序執(zhí)行到LockPatternKeyguardView:onScreenTurnedOn函數(shù),并調(diào)用show函數(shù)進(jìn)行解鎖屏界面的顯示,代碼如下:
public void show() { if (mMode == Mode.LockScreen) { ((KeyguardScreen) mLockScreen).onResume(); } else { ((KeyguardScreen) mUnlockScreen).onResume(); } ...... }
至此,邏輯處理完成。
3、自定義口令解鎖邏輯
自定義口令解鎖始于PasswordUnlockScreen,時(shí)序圖如下:
1)解鎖屏界面輸入密碼點(diǎn)擊確定按鈕后,在函數(shù)onEditorAction中進(jìn)行響應(yīng):
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { // Check if this was the result of hitting the enter key if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_NEXT) { verifyPasswordAndUnlock(); return true; } return false; }
2)在函數(shù)verifyPasswordAndUnlock中對(duì)輸入的密碼進(jìn)行判斷,如果輸入正確,測(cè)調(diào)用keyguardDone響應(yīng)解鎖完成的操作。mCallback.keyguardDone(true)
調(diào)用是所有解鎖屏mode情形在解鎖成功后必須調(diào)用的函數(shù),隨后的處理邏輯對(duì)于不同的解鎖屏界面也是相同的。
3)回調(diào)KeyguardScreenCallback和KeyguardViewMediator的函數(shù)keyguardDone,在后者的keyguardDone函數(shù)中,異步發(fā)送keyDone事件:
public void keyguardDone(boolean authenticated, boolean wakeup) { synchronized (this) { …… Message msg = mHandler.obtainMessage(KEYGUARD_DONE); msg.arg1 = wakeup ? 1 : 0; mHandler.sendMessage(msg); …… } }
4)函數(shù)KeyguardViewMediator:handleKeyguardDone
異步處理keyguardDone事件,調(diào)用handleHide隱藏鎖屏界面。
5)KeyguardViewManager.hide
函數(shù)中調(diào)用鎖屏界面的銷(xiāo)毀函LockPatternKeyguardView:cleanUp
數(shù)隱藏銷(xiāo)毀界面,如下:
public void cleanUp() { if (mLockScreen != null) { ((KeyguardScreen) mLockScreen).onPause(); ((KeyguardScreen) mLockScreen).cleanUp(); this.removeView(mLockScreen); mLockScreen = null; } if (mUnlockScreen != null) { ((KeyguardScreen) mUnlockScreen).onPause(); ((KeyguardScreen) mUnlockScreen).cleanUp(); this.removeView(mUnlockScreen); mUnlockScreen = null; } ...... }
至此,解鎖完成。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Android4.0開(kāi)發(fā)之Keyguard解鎖屏機(jī)制的示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!