国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android屏幕鎖屏彈窗的正確姿勢DEMO詳解

2019-12-12 05:25:44
字體:
來源:轉載
供稿:網友

在上篇文章給大家介紹了Android程序開發仿新版QQ鎖屏下彈窗功能。今天通過本文給大家分享android鎖屏彈窗的正確姿勢。

最近在做一個關于屏幕鎖屏懸浮窗的功能,于是在網上搜索了很多安卓屏幕鎖屏的相關資料,鑒于網上的資料比較零碎,所以我在這里進行整理總結。本文將從以下兩點對屏幕鎖屏進行解析:

1. 如何監聽系統屏幕鎖屏

2. 如何在鎖屏界面彈出懸浮窗

如何監聽系統屏幕鎖屏

經過總結,監聽系統的鎖屏可以通過以下兩種方式:

1) 代碼直接判定

2) 接收廣播

1) 代碼直接判定

代碼判斷方式,也有兩種方法:

a) 通過PowerManager的isScreenOn方法,代碼如下:

PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);//如果為true,則表示屏幕“亮”了,否則屏幕“暗”了。boolean isScreenOn = pm.isScreenOn();

這里需要解釋一下:

屏幕“亮”,表示有兩種狀態:a、未鎖屏 b、目前正處于解鎖狀態 。這兩種狀態屏幕都是亮的;

屏幕“暗”,表示目前屏幕是黑的 。

b) 通過KeyguardManager的inKeyguardRestrictedInputMode方法,代碼如下:

KeyguardManager mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);boolean flag = mKeyguardManager.inKeyguardRestrictedInputMode();

對flag進行一下說明,經過試驗,總結為:

如果flag為true,表示有兩種狀態:a、屏幕是黑的 b、目前正處于鎖屏狀態 。

如果flag為false,表示目前未鎖屏

注明:上面的兩種方法,也可以通過反射機制來調用。

反射代碼如下:

private static Method mReflectScreenState;try {mReflectScreenState = PowerManager.class.getMethod(isScreenOn, new Class[] {});PowerManager pm = (PowerManager) context.getSystemService(Activity.POWER_SERVICE);boolean isScreenOn= (Boolean) mReflectScreenState.invoke(pm);} catch (Exception e) {e.printStackTrace()}

2) 接收廣播

當安卓系統鎖屏或者屏幕亮起,或是屏幕解鎖的時候,系統內部都會發送相應的廣播,我們只需要對廣播進行監聽就可以了
注冊廣播的偽代碼如下:

private ScreenBroadcastReceiver mScreenReceiver;private class ScreenBroadcastReceiver extends BroadcastReceiver {private String action = null;@Overridepublic void onReceive(Context context, Intent intent) {action = intent.getAction();if (Intent.ACTION_SCREEN_ON.equals(action)) { // 開屏} else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 鎖屏} else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解鎖}}}private void startScreenBroadcastReceiver() {IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON);filter.addAction(Intent.ACTION_SCREEN_OFF);filter.addAction(Intent.ACTION_USER_PRESENT);context.registerReceiver(mScreenReceiver, filter);}

如何在鎖屏界面彈出懸浮窗

竟然知道了對于系統屏幕監聽的方法,那么接下來就是要在屏幕鎖屏的時候,彈出懸浮框了,這個的實現方式有兩種:

1) 使用WindowManager

2) 使用Activity

目前情況是,使用這兩種方式在真機上都可以實現,如果網友們發現有問題,可以在博客中留言

1) 使用WindowManager

代碼如下:

private void init(Context mContext) {this.mContext = mContext;mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);// 更新浮動窗口位置參數 靠邊DisplayMetrics dm = new DisplayMetrics();// 獲取屏幕信息mWindowManager.getDefaultDisplay().getMetrics(dm);mScreenWidth = dm.widthPixels;mScreenHeight = dm.heightPixels;this.mWmParams = new WindowManager.LayoutParams();// 設置window typeif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {mWmParams.type = WindowManager.LayoutParams.TYPE_TOAST;} else {mWmParams.type = WindowManager.LayoutParams.TYPE_PHONE;}// 設置圖片格式,效果為背景透明mWmParams.format = PixelFormat.RGBA_8888;// 設置浮動窗口不可聚焦(實現操作除浮動窗口外的其他可見窗口的操作)mWmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;// 調整懸浮窗顯示的停靠位置為左側置�?mWmParams.gravity = Gravity.LEFT | Gravity.TOP;mScreenHeight = mWindowManager.getDefaultDisplay().getHeight();// 以屏幕左上角為原點,設置x、y初始值,相對于gravitymWmParams.x = 0;mWmParams.y = mScreenHeight / 2;// 設置懸浮窗口長寬數據mWmParams.width = LayoutParams.WRAP_CONTENT;mWmParams.height = LayoutParams.WRAP_CONTENT;addView(createView(mContext));mWindowManager.addView(this, mWmParams);mTimer = new Timer();hide();}

WindowManager的主要配置就是上面的那些代碼,這里需要說明一下,type的類型有如下值:

應用程序窗口。public static final int FIRST_APPLICATION_WINDOW = 1; 所有程序窗口的“基地”窗口,其他應用程序窗口都顯示在它上面。 public static final int TYPE_BASE_APPLICATION =1;普通應用功能程序窗口。token必須設置為Activity的token,以指出該窗口屬誰。public static final int TYPE_APPLICATION = 2;用于應用程序啟動時所顯示的窗口。應用本身不要使用這種類型。它用于讓系統顯示些信息,直到應用程序可以開啟自己的窗口。 public static final int TYPE_APPLICATION_STARTING = 3; 應用程序窗口結束。public static final int LAST_APPLICATION_WINDOW = 99;子窗口。子窗口的Z序和坐標空間都依賴于他們的宿主窗口。public static final int FIRST_SUB_WINDOW = 1000;面板窗口,顯示于宿主窗口上層。public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;媒體窗口,例如視頻。顯示于宿主窗口下層。public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1;應用程序窗口的子面板。顯示于所有面板窗口的上層。(GUI的一般規律,越“子”越靠上)public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW +2;對話框。類似于面板窗口,繪制類似于頂層窗口,而不是宿主的子窗口。public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW +3;媒體信息。顯示在媒體層和程序窗口之間,需要實現透明(半透明)效果。(例如顯示字幕)public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW +4;子窗口結束。( End of types of sub-windows )public static final int LAST_SUB_WINDOW = 1999;系統窗口。非應用程序創建。public static final int FIRST_SYSTEM_WINDOW = 2000;狀態欄。只能有一個狀態欄;它位于屏幕頂端,其他窗口都位于它下方。public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW;搜索欄。只能有一個搜索欄;它位于屏幕上方。public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1;電話窗口。它用于電話交互(特別是呼入)。它置于所有應用程序之上,狀態欄之下。public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;系統提示。它總是出現在應用程序窗口之上。public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW +3;鎖屏窗口。public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW +4;信息窗口。用于顯示toast。public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW +5;系統頂層窗口。顯示在其他一切內容之上。此窗口不能獲得輸入焦點,否則影響鎖屏。public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW +6;電話優先,當鎖屏時顯示。此窗口不能獲得輸入焦點,否則影響鎖屏。public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW +7;系統對話框。(例如音量調節框)。public static final int TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW +8;鎖屏時顯示的對話框。public static final int TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW +9;系統內部錯誤提示,顯示于所有內容之上。public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW +10;內部輸入法窗口,顯示于普通UI之上。應用程序可重新布局以免被此窗口覆蓋。public static final int TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW +11;內部輸入法對話框,顯示于當前輸入法窗口之上。public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW +12;墻紙窗口。public static final int TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW +13;狀態欄的滑動面板。public static final int TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW +14;系統窗口結束。public static final int LAST_SYSTEM_WINDOW = 2999;

如果想讓懸浮窗在所以鎖屏之上,使用TYPE_SYSTEM_ERROR,因為它顯示在所有內容之上。

2) 使用Activity

Activity的設置

Activity需要進行以下設置,才可以在鎖屏狀態下彈窗。
首先是onCreate方法,需要添加4個標志,如下:

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Window win = getWindow(); win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); // 自己的代碼 } 

四個標志位顧名思義,分別是鎖屏狀態下顯示,解鎖,保持屏幕長亮,打開屏幕。這樣當Activity啟動的時候,它會解鎖并亮屏顯示。
然后在AndroidManifest.xml文件當中,對該activity的聲明需要加上以下屬性:

<activity android:name=".alarm.AlarmHandlerActivity" android:launchMode="singleInstance" android:excludeFromRecents="true" android:taskAffinity="" android:theme="@android:style/Theme.Wallpaper.NoTitleBar"/> 

而對于布局文件,要顯示的view居中,背景透明。由于上面已經設置了背景為壁紙的背景,所以顯示的是桌面的背景。如果背景設為默認的白色,則導致彈窗后面是一片白色,看起來很丑。如果背景設置為透明,則彈窗后面會顯示出解鎖后的界面(即使有鎖屏密碼,也是會顯示解鎖后的界面的),一樣很影響視覺效果。

在廣播中啟動鎖屏彈窗

我們設置的是鎖屏下才彈窗的,非鎖屏下就不適合彈出這個窗口了(你可以試一下,效果會很怪)。一般是注冊一個廣播接收器,在接收到指定廣播之后判斷是否需要彈窗,所以在BroadcastReceiver的接收代碼中需要先判斷是否為鎖屏狀態下:

@Override public void onReceive(Context context, Intent intent) { Log.d(LOG_TAG, intent.getAction()); KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); if (km.inKeyguardRestrictedInputMode()) { Intent alarmIntent = new Intent(context, AlarmActivity.class); alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(alarmIntent); } } 

這里用到的是KeyguardManager類,用來管理鎖屏的,4.1之后該類的API新增了一個isKeyguardLocked()的方法判斷是否鎖屏,但在4.1之前,我們只能用inKeyguardRestrictedInputMode()方法,如果為true,即為鎖屏狀態。需要注意的是,在廣播中啟動Activity的context可能不是Activity對象,所以需要添加NEW_TASK的標志,否則啟動時可能會報錯。我們就可以結合之前的系統發送廣播后進行相應的懸浮窗的彈出處理。

復寫onNewIntent方法

再次亮起屏幕,如果該Activity并未退出,但是被手動按了鎖屏鍵,當前面的廣播接收器再次去啟動它的時候,屏幕并不會被喚起,所以我們需要在activity當中添加喚醒屏幕的代碼,這里用的是電源鎖。可以添加在onNewIntent(Intent intent),因為它會被調用。也可以添加在其他合適的生命周期方法。添加代碼如下:

PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE); if (!pm.isScreenOn()) { PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright"); wl.acquire(); wl.release(); } 

最后,是添加如下權限

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

第一條是解鎖屏幕需要的,第二條是申請電源鎖需要的。

以上所說是小編給大家介紹的Android屏幕鎖屏彈窗的正確姿勢DEMO詳解,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的,在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 西丰县| 澄城县| 宣恩县| 文山县| 阿鲁科尔沁旗| 宝坻区| 华坪县| 乌拉特中旗| 泗阳县| 延安市| 开原市| 青川县| 冀州市| 盐城市| 原阳县| 南漳县| 丰都县| 台山市| 罗田县| 济南市| 黑山县| 阿瓦提县| 绿春县| 竹山县| 和平区| 姚安县| 沁水县| 开封市| 台北市| 宜章县| 闽侯县| 花垣县| 西乌珠穆沁旗| 青铜峡市| 通道| 渝中区| 托里县| 乳山市| 山东| 沙洋县| 南安市|