天天看點

自定義鎖屏的實作一、引言二、自定義鎖屏的實作方案三、問題與總結

一、引言

1、軟體項目概述

       基于使用者使用app過程中,手機螢幕關閉後,重新點亮手機螢幕,能夠快速看見使用者的所需資訊的需求,來設計app的自定義鎖屏效果。

2、概述

       本文檔就自定義鎖屏的實作進行講解。

二、自定義鎖屏的實作方案

1、方案一

1)、總體實作

       在app需要時開啟一個service,在service中時刻監聽系統息屏(SCREEN_OFF)廣播,當螢幕熄滅時,Service監聽到廣播,開啟鎖屏頁Activity,在螢幕的最上層顯示。并在activity建立時隐藏掉系統鎖屏(有密碼的情況下是禁止不掉的)。

2)、詳細實作

(1)、開啟服務注冊廣播

//開啟服務

startService(this,LockScreenService.class);
           

//注冊螢幕熄滅廣播

IntentFiltermScreenOffFilter = new IntentFilter();
mScreenOffFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenOffReceiver, mScreenOffFilter);
           

(2)、監聽廣播開啟鎖屏

if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {

    Intent mLockIntent = new Intent(context, LockScreenActivity.class);

    mLockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK );

    startActivity(mLockIntent);

}
           

       注意:将鎖屏Activity的啟動模式設定為singleTask,否則鎖屏Activity實質上還是建立在原來的App的task棧中(可以根據需求做修改)。

(3)、去掉系統鎖屏

       在啟動自定義鎖屏的同時,去掉系統鎖屏。當然如果設定了系統鎖屏密碼,系統鎖屏是無法去掉的,具體代碼如下:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
           

       FLAG_DISMISS_KEYGUARD用于去掉系統鎖屏頁。

       FLAG_SHOW_WHEN_LOCKED使Activity在鎖屏時能夠顯示。

       去掉系統鎖屏需要添權重限如下:

<uses-permissionandroid:name="android.permission.DISABLE_KEYGUARD" />
           

(4)、屏蔽Back和Menu鍵

       重寫onKeyDown方法屏蔽,代碼如下:

public boolean onKeyDown(int keyCode,KeyEvent event) {
    int key = event.getKeyCode();
    switch (key) {
    case KeyEvent.KEYCODE_BACK:
         return true;
    case KeyEvent.KEYCODE_MENU:
         return true;
    default:
         break;
    }
    return super.onKeyDown(keyCode,event);
}
           

       當熄滅螢幕後,就可以看到我們的自定義鎖屏頁了。

(5)、滑屏解鎖

       當手指在螢幕上滑動時,攔截并處理滑動事件,使鎖屏頁随着手指運動,當超過一定距離,鎖屏消失,否則重新覆寫螢幕。

       注意:需要給鎖屏Activity設定透明主題,否則滑動看不見背景頁面。

關鍵代碼如下:

publicboolean onTouchEvent(MotionEvent event) {
        mWidth = getWidth();
        int action = event.getAction();
        float nx = event.getX();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mStartX = nx;
                break;
            case MotionEvent.ACTION_MOVE:
                handleMoveView(nx);
                break;
            case MotionEvent.ACTION_UP:
            caseMotionEvent.ACTION_CANCEL:
                doMoveEvent(nx);
                break;
        }
        return true;
    }
           

       mStartX:用來記錄滑動的起始位置。

       handleMoveView():根據滑動的x軸距離,來控制view的移動。

       doMoveEvent():根據結束位置和起始位置的距離,來判斷是否超過門檻值,如果超過了門檻值,view滑出螢幕,銷毀鎖屏;否則重新覆寫螢幕

(6)、近期任務不顯示鎖屏Activity

       在清單檔案中,設定鎖屏Activity屬性:android:excludeFromRecents=”true”,讓鎖屏Activity不顯示在近期任務中。

3)、結論

       這套方案完成鎖屏頁的實作,可以滿足使用者友善檢視運動狀态的需求。

2、方案二

1)、總體實作

       同方案一。

2)、詳細實作

(1)步驟

       詳細實作步驟同方案一,隻是加載布局的方式不同。

(2)加載布局

       方案一調用Activity的setContentView()方法加載布局;

       方案二将布局inflate()成View後設成系統錯誤的view。

       原理:是把這個view當成系統的錯誤的view,sdk文檔解釋說明。

      Window type: internal system error windows, appear on top of everything theycan. In multiuser systems shows only on the owning user's window.

關鍵代碼如下:

mWindowManager = (WindowManager)mContext.getApplicationContext().getSystemService("window");
mParams = new LayoutParams();
mParams.type = LayoutParams.TYPE_SYSTEM_ERROR;
mWindowManager.addView(mLockView, mParams);
           

3)、結論

       這個error的view在所有的view的最上面,可以達到屏蔽home鍵的,Recent鍵以及下拉效果,并且長按power鍵,關機界面也彈不出來。這套方案同樣可以滿足使用者友善檢視詳細資訊的需求。

三、問題與總結

1、禁止Home鍵與Recent鍵

      Home鍵與Recent鍵(調出最近打開應用的按鍵)的點選事件是在Framework層進行處理的,是以onKeyDown與dispatchKeyEvent都捕獲不到點選事件,是以無法屏蔽其點選效果。關于這兩個按鍵的屏蔽方法,網上用到了反射,有的是通過改變Window的标志位和Type等,總的來說,這些方法隻對部分Android版本有效,有的則無法編譯通過。是以無法在應用層屏蔽掉Home鍵以及Recent鍵。

2、總結

      方案二雖然屏蔽掉了按鍵的響應,但也一定程度上影響了使用者體驗,例如:關機操作。是以不建議使用。

      方案一在滿足使用者的需求的同時,并沒有影響到使用者的體驗。并且與市場上qq音樂,keep的鎖屏頁實作了相同的效果(并沒有對home鍵,Recent鍵以及下拉菜單做相應的處理),是以方案一比較合适。

代碼下載下傳

http://download.csdn.net/detail/chendeshan330/9916014