欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android屏幕鎖屏彈窗的正確姿勢(shì)DEMO詳解

 更新時(shí)間:2016年09月04日 09:22:15   作者:小馬的編程之旅  
本文給大家分享android屏幕鎖屏彈窗的正確姿勢(shì)DEMO詳解,本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧

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

最近在做一個(gè)關(guān)于屏幕鎖屏懸浮窗的功能,于是在網(wǎng)上搜索了很多安卓屏幕鎖屏的相關(guān)資料,鑒于網(wǎng)上的資料比較零碎,所以我在這里進(jìn)行整理總結(jié)。本文將從以下兩點(diǎn)對(duì)屏幕鎖屏進(jìn)行解析:

1. 如何監(jiān)聽(tīng)系統(tǒng)屏幕鎖屏

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

如何監(jiān)聽(tīng)系統(tǒng)屏幕鎖屏

經(jīng)過(guò)總結(jié),監(jiān)聽(tīng)系統(tǒng)的鎖屏可以通過(guò)以下兩種方式:

1) 代碼直接判定

2) 接收廣播

1) 代碼直接判定

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

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

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

這里需要解釋一下:

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

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

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

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

對(duì)flag進(jìn)行一下說(shuō)明,經(jīng)過(guò)試驗(yàn),總結(jié)為:

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

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

注明:上面的兩種方法,也可以通過(guò)反射機(jī)制來(lái)調(diào)用。

反射代碼如下:

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) 接收廣播

當(dāng)安卓系統(tǒng)鎖屏或者屏幕亮起,或是屏幕解鎖的時(shí)候,系統(tǒng)內(nèi)部都會(huì)發(fā)送相應(yīng)的廣播,我們只需要對(duì)廣播進(jìn)行監(jiān)聽(tīng)就可以了
注冊(cè)廣播的偽代碼如下:

private ScreenBroadcastReceiver mScreenReceiver;
private class ScreenBroadcastReceiver extends BroadcastReceiver {
private String action = null;
@Override
public void onReceive(Context context, Intent intent) {
action = intent.getAction();
if (Intent.ACTION_SCREEN_ON.equals(action)) { 
// 開(kāi)屏
} 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);
}

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

竟然知道了對(duì)于系統(tǒng)屏幕監(jiān)聽(tīng)的方法,那么接下來(lái)就是要在屏幕鎖屏的時(shí)候,彈出懸浮框了,這個(gè)的實(shí)現(xiàn)方式有兩種:

1) 使用WindowManager

2) 使用Activity

目前情況是,使用這兩種方式在真機(jī)上都可以實(shí)現(xiàn),如果網(wǎng)友們發(fā)現(xiàn)有問(wèn)題,可以在博客中留言

1) 使用WindowManager

代碼如下:

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

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

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

如果想讓?xiě)腋〈霸谒枣i屏之上,使用TYPE_SYSTEM_ERROR,因?yàn)樗@示在所有內(nèi)容之上。

2) 使用Activity

Activity的設(shè)置

Activity需要進(jìn)行以下設(shè)置,才可以在鎖屏狀態(tài)下彈窗。
首先是onCreate方法,需要添加4個(gè)標(biāo)志,如下:

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); 
// 自己的代碼 
} 

四個(gè)標(biāo)志位顧名思義,分別是鎖屏狀態(tài)下顯示,解鎖,保持屏幕長(zhǎng)亮,打開(kāi)屏幕。這樣當(dāng)Activity啟動(dòng)的時(shí)候,它會(huì)解鎖并亮屏顯示。
然后在AndroidManifest.xml文件當(dāng)中,對(duì)該activity的聲明需要加上以下屬性:

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

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

在廣播中啟動(dòng)鎖屏彈窗

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

@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類,用來(lái)管理鎖屏的,4.1之后該類的API新增了一個(gè)isKeyguardLocked()的方法判斷是否鎖屏,但在4.1之前,我們只能用inKeyguardRestrictedInputMode()方法,如果為true,即為鎖屏狀態(tài)。需要注意的是,在廣播中啟動(dòng)Activity的context可能不是Activity對(duì)象,所以需要添加NEW_TASK的標(biāo)志,否則啟動(dòng)時(shí)可能會(huì)報(bào)錯(cuò)。我們就可以結(jié)合之前的系統(tǒng)發(fā)送廣播后進(jìn)行相應(yīng)的懸浮窗的彈出處理。

復(fù)寫(xiě)onNewIntent方法

再次亮起屏幕,如果該Activity并未退出,但是被手動(dòng)按了鎖屏鍵,當(dāng)前面的廣播接收器再次去啟動(dòng)它的時(shí)候,屏幕并不會(huì)被喚起,所以我們需要在activity當(dāng)中添加喚醒屏幕的代碼,這里用的是電源鎖??梢蕴砑釉趏nNewIntent(Intent intent),因?yàn)樗鼤?huì)被調(diào)用。也可以添加在其他合適的生命周期方法。添加代碼如下:

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(); 
} 

最后,是添加如下權(quán)限

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

第一條是解鎖屏幕需要的,第二條是申請(qǐng)電源鎖需要的。

以上所說(shuō)是小編給大家介紹的Android屏幕鎖屏彈窗的正確姿勢(shì)DEMO詳解,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的,在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

最新評(píng)論