Android鎖屏實現與總結

Android鎖屏實現與總結(網易云閱讀)

一、自定義鎖屏基本原理

二、重要步驟

1、廣播注冊

2、Activity設置

3、按鍵的屏蔽

4、滑屏解鎖

5、Event bus的使用

三、出現的問題

1、小米和魅族等手機鎖屏權限問題

2、透明欄與沉浸模式

3、手機適配

4、處理黑色閃屏

5、線控耳機

6、Android上的「安全音量」

一、自定義鎖屏基本原理

先上效果圖:

實現鎖屏的方式有多種(鎖屏應用、懸浮窗、普通Activity偽造鎖屏等等)。通過網絡查找資料與反編譯云音樂apk,本項目使用了國內比較主流并且被廣泛應用的Activity偽造鎖屏方式。

Activity實現自定義鎖屏頁的思路很簡單,即在聽書模式開啟時,啟動一個service,在service中監聽系統SCREEN_OFF的廣播。當屏幕熄滅時service監聽到廣播,開啟一個鎖屏頁Activity在屏幕最上層顯示,該Activity創建的同時會去掉系統的鎖屏(如果有密碼是禁不掉的)。示意圖如下:


二、重要步驟

1、廣播注冊

LockScreenService是普通的Service,在應用啟動聽書模式時候startService(ReadBookActivity),與應用同一個進程。


此外,SCREEN_OFF廣播監聽必須是動態注冊的,如果在AndroidManifest.xml中靜態注冊將無法接收到SCREEN_OFF廣播。


標志位FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,是為了避免在最近使用程序列表出現Service所啟動的Activity。


啟動Activity時Intent的Flag,如果不添加FLAG_ACTIVITY_NEW_TASK的標志位,會出現“Calling startActivity() from outside of an Activity”的運行時異常,因為我們是從Service啟動的Activity。Activity要存在于activity的棧中,而Service在啟動activity時必然不存在一個activity的棧,所以要新起一個棧,并裝入啟動的activity。使用該標志位時,也需要在AndroidManifest中聲明taskAffinity,即新task的名稱,否則鎖屏Activity實質上還是在建立在原來App的task棧中。


2、Activity設置

鎖屏的activity內部也要做相應的配置,讓activity在鎖屏時也能夠顯示,同時去掉系統鎖屏。當然如果設置了系統鎖屏密碼,系統鎖屏是沒有辦法去掉的,這里考慮沒有設置密碼的情況。我們在自定義鎖屏Activity的onCreate()方法里設定以下標志位就能完全實現相同的功能:


FLAG_DISMISS_KEYGUARD用于去掉系統鎖屏頁,FLAG_SHOW_WHEN_LOCKED使Activity在鎖屏時仍然能夠顯示。另外需要在Manifest中加入適當的權限:


3、按鍵的屏蔽

當自定義鎖屏頁最終出現在手機上時,我們希望它像系統鎖屏頁那樣屹立不倒,所有的按鍵都不能觸動它,只有通過劃屏或者指紋才能解鎖,因此有必要對按鍵進行一定程度上的屏蔽。針對只有虛擬按鍵的手機,我們可以通過隱藏虛擬按鍵的方式部分解決這個問題。但是當用戶在鎖屏頁底部滑動,隱藏后的虛擬按鍵還是會滑出,而且如果用戶是物理按鍵的話就必須進行屏蔽了。需要重寫Activity的onBackPressed()方法即可。


Home鍵 與Recent鍵的點擊事件是在framework層進行處理的,因此onKeyDown()與dispatchKeyEvent()都捕獲不到點擊事件。關于這兩個按鍵的屏蔽方法,網上相關的資料有很多,有的用到了反射,有的通過改變Window的標志位和Type等,總的來說這些方法只對部分android版本有效,有的則完全無法編譯通過。其實這么做的目的無非是為了實現一個純粹的鎖屏頁,但是這種做法容易造成鎖屏頁的異常崩潰,我們要滿足的是用戶在鎖屏頁的快捷操作,Home鍵和Recent鍵無關痛癢,基本可以不管。

4、滑屏解鎖

做完以上幾步,當屏幕熄滅后,再打開屏幕就能夠看到我們的自定義鎖屏頁了。接下來要實現劃屏解鎖。劃瓶解鎖的基本思路很簡單,當手指在屏幕上滑動時,攔截并處理滑動事件,使鎖屏頁面隨著手指運動,當運動到達一定的閾值時,用戶手指松開手指,鎖屏頁自動滑動到屏幕邊界消失,如果沒有達到運動閥值,就會自動滑動到起始位置,重新覆蓋屏幕。 為了將劃屏邏輯與頁面內容隔離開來,我們在鎖屏頁面布局中添加一個自定義的UnderView,這個UnderView填充整個屏幕,位于鎖屏內容View(將其引用稱之為mMoveView,并傳入到UnderView中)的下方,所有劃屏相關的事件都在這里攔截并處理。


mMoveView是鎖屏頁的顯示內容,除了處理一些簡單的點擊事件,其他非點擊事件序列都由底層的UnderView進行處理。只需要重寫UnderView的onTouchEvent方法就能夠實現


其中,mStartX記錄滑動操作起始的x坐標,handleMoveView方法控制mMoveView隨手指的移動,doTriggerEvent處理手指離開后mMoveView的移動動畫。兩個方法的定義如下:

在handleMoveView()中,首先計算當前觸點x坐標與初始x坐標mStartX的差值movex,然后調用mMoveView的setTranslationX方法移動。此外,我們可以通過getBackground()獲取UnderView的背景,并根據已劃開屏幕占整個屏幕的百分比調用setAlpha方法改變背景的透明度,做出抽屜拉開時的光影變化效果。


當手指離開屏幕,doTraiggerEvent方法會對滑動的距離與閥值進行一個比較,此處的閥值為0.4*屏幕寬度,如果低于閥值,則通過ObjectAnimator在0.25s將mMoveView移動到初始位置,同時在ObjectAnimator的AnimatorUpdateListener的onAnimationUpdate方法中更新背景透明度;如果低于閥值,以同樣的方式將mMoveView移出屏幕右邊界,然后將Activity干掉,具體做法是為animator增加一個AnimatorListenerAdapter的監聽器,在該監聽器的onAnimationEnd方法中使用在Activity中定義的mHandler發送finish消息,完成解鎖。

5、Event bus的使用

鎖屏Activity中的Buttun,可以通過EventBus遠程控制ReadBookActivity中的播放、暫停、下一首等操作。


二、出現的問題

1、小米和魅族等手機鎖屏權限問題

例如小米手機(miui 6.8.18開始)有鎖屏權限的問題,權限未開的情況下鎖屏會在系統鎖屏的下方。目前只能手動打開(個別應用在MIUI是默認打開)。

在設置中:


2、透明欄與沉浸模式

透明欄與沉浸模式總共用到了5個Flag,SYSTEM_UI_FLAG_LAYOUT_STABLE保持整個View穩定,使View不會因為SystemUI的變化而做layout。SYSTEM_UI_FLAG_IMMERSIVE_STIKY,能夠在隱藏的bar被呼出時(比如從屏幕下邊緣開始向上做滑動手勢),使bar在無相關操作的情況下自動再次隱藏。對于SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,我們容易被其中的HIDE_NAVIGATION所迷惑,其實這個Flag沒有隱藏導航欄的功能,只是控制導航欄浮在屏幕上層,不占據屏幕布局空間。SYSTEM_UI_FLAG_HIDE_NAVIGATION,才是能夠隱藏導航欄的Flag。SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN也不能隱藏狀態欄,只是使狀態欄浮在屏幕上層。


需要注意的是,這段代碼除了需要加在Activity的OnCreate()方法中,也要加在重寫的onWindowFocusChanged()方法中,在窗口獲取焦點時再將Flag設置一遍,否則可能導致無法達到預想的效果。

在Android 5.0之后狀態欄和導航欄也有更多的特點。除了原有的“半透明”模式以外,還有“全透明”以及“變色”模式,一種會完全隱藏背景,另一種可以取色作為背景顏色等。對于Android 4.4以上5.0以下的版本,設置透明狀態欄的方式如下:


對于Android 5.0及以上版本,設置透明狀態欄的方法如下:


除了要清理掉4.4的FLAG_TRANSLUCENT_STATUS外,還要配合SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN和SYSTEM_UI_FLAG_LAYOUT_STABLE,添加標志位FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,并調用setStatusBarColor設置狀態欄的顏色為透明。

3、手機適配

由于Android手機屏幕高度差異比較大,所以有可能會存在要顯示的控件高度比屏幕還高的問題。所以需要通過代碼對布局中某些控件寬高進行等比例調整。


例如在本項目中通過固定音量鍵以上的高度和最下方滑動解鎖的位置,來動態等比例動態調整中間的專輯封面圖片。mMain.post(new Runnable()。

4、處理黑色閃屏

我們的鎖屏Activity在滑動”解鎖”之后,理論上是直接進入下面的界面,但有時如果下面不是launcher,而是一個app,有可能會閃一下黑屏,這個其實是底下activity的入場動畫導致的,某些Android版本會對頂部activity透明時處理有些奇怪,不能保證其他的應用不閃黑屏,但是對自己的的應用還是可以的,只需要在主體activity的style中加上


5、線控耳機

我們只要定義一個廣播接收者來接收到這個廣播。這個廣播的意圖是android.intent.action.MEDIA_BUTTON。注冊普通的廣播接收器有兩個常見的辦法,一種是在代碼中動態注冊,另一種是在項目Manifest里面注冊。但是這個廣播,要注冊兩遍、兩遍、兩遍,Manifest里一遍(常規辦法),代碼中一遍(借助多媒體服務注冊),否則沒有效果。


因為兩種注冊方式缺一不可,所以解除了一種,它的監聽作用也就失效了。

6、Android上的「安全音量」

當Android設備插上耳機,為了避免音量過高傷害用戶聽力,會觸發其“安全音量”(Safe Media Volume)機制,如果在未經用戶確認允許使用大音量時,且這時設置音量newIndex超過其推薦閾值,則這段代碼執行完你會發現毫無反應,播放的聲音依然不會很大。

解決問題的關鍵在于被忽略的最后一個參數flags。只要在設置音量后,復查一次當前值是否相當,如果比較小,則交由系統來顯示音量提示對話框。而此時因欲設定的值超過推薦值,一般會觸發音量過高警告,提示用戶用戶確認后即可設置成功。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,637評論 25 708
  • ¥開啟¥ 【iAPP實現進入界面執行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,482評論 0 17
  • Android Studio JNI流程首先在java代碼聲明本地方法 用到native關鍵字 本地方法不用去實現...
    MigrationUK閱讀 11,916評論 7 123
  • 日月臥東方, 韜謀斬熾名。 仙幽實復幻, 俊逸雨修屏。 點黛樓軒改, 撥箏殿宇清。 剜心玉侶眷, 隱魄凍思凝。 聲...
    云汐詩怡閱讀 529評論 9 4
  • 培養情商的5個關鍵步驟 情商 情商,就是一種辨別、管理個人以及他人情緒的能力。很多學術研究都證實過,通過科學的情商...
    張耀磊閱讀 242評論 0 0