在開發(fā)過程中,會遇到需要在桌面顯示彈框的需求,這個與app在前臺,在應(yīng)用中彈框還是有寫區(qū)別的。
既然需求中是要彈出一個彈框,那就有兩種方式可以實現(xiàn):一是在桌面上彈出一個真正的Dialog;另外還可以創(chuàng)建一個dialog樣式的Activity。本篇文章主要介紹如何在開發(fā)中彈出系統(tǒng)級的Dialog。
閑話少說,還是切入正題,談一談今天要說的桌面彈框的實現(xiàn)。
這個例子是在app收到推送的時候,如果app在前臺運行,不管是在哪任何一個Activity都可以彈框,如果在后臺運行就在桌面彈框,這就使得開發(fā)者在開發(fā)過程中,不可能在某一個Activity中寫入彈窗的代碼,那樣子只會在某一個Activity可見時彈出。并不能實現(xiàn)需求。
1:在AndroidManifest.xml清單文件中添加懸浮窗權(quán)限
<use-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
2:在接收到推送的時候,不建議直接彈出懸浮框,因為還有可能用戶并沒有授權(quán)該權(quán)限,因為申請該權(quán)限授權(quán)要調(diào)到設(shè)置頁面,并在Activity的OnActivityResult中獲取是否獲得權(quán)限,所以還是發(fā)個廣播,給BasicActivity,在BasicActivity中判斷是否授權(quán)允許,是否可以直接彈框。但是因為是在BasicActivity中申請的權(quán)限,所以每一個Activity都會收到廣播,這就需要在彈出框之后,標(biāo)記一下,以免按返回鍵到上一個Activity時多次彈框。
public void showDialg(Context context) {
HintDialog hintDialog = new HintDialog(context, "在桌面彈框", new String[]{"同意", "同意"});
hintDialog.setCanceledOnTouchOutside(false);
hintDialog.setCallback(new HintDialog.Callback() {
@Override
public void callback() {
}
@Override
public void cancle() {
}
});
//記得這句話不要忘了
hintDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
hintDialog.setTiShiText("審核申請");
hintDialog.show();
}
這種方法就可以實現(xiàn)此功能。

但是要記得這句話,一定要給Dialog加上去,這是讓Dialog,變成系統(tǒng)彈框。
3:不過在安卓6.0發(fā)布以后,權(quán)限機制發(fā)生了一些改變,在6.0以后,當(dāng)app需要我們授予某些權(quán)限時,是需要去詢問用戶是否開啟權(quán)限的。權(quán)限分為兩種,一種是Normal Permissions,這類權(quán)限一般不涉及用戶隱私,不需要用戶授權(quán)。另一種是Dangerous Permission,這些一般都是涉及到用戶隱私,需要用戶授權(quán)。
同樣,在6.0以上,如果想實現(xiàn)這個需求,同樣需要用戶授權(quán)該權(quán)限。
但是申請該權(quán)限和申請其他的如打電話權(quán)限等有些不同,這個權(quán)限需要調(diào)到該應(yīng)用的權(quán)限設(shè)置頁面,讓用戶自己去授權(quán)。
實現(xiàn)方法如下:
if(Build.VERSION.SDK_INT>=23) {
insertDummyContactWrapper();
}
檢查版本是否大于23,如果大于23,就需要申請該權(quán)限
下面代碼是在BasicActivity中檢查申請權(quán)限的。
final private intOVERLAY_PERMISSION_REQ_CODE=1234;//申請懸浮窗權(quán)限碼
/**
* 動態(tài)權(quán)限檢查
*/
@TargetApi(Build.VERSION_CODES.M)
private void insertDummyContactWrapper() {
if (!Settings.canDrawOverlays(MainActivity.this)) {
showMessageOKCancel("請在應(yīng)用權(quán)限中允許\n\t打開懸浮窗權(quán)限",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//申請該權(quán)限時引導(dǎo)用戶跳轉(zhuǎn)到Setting中自己去開啟權(quán)限開關(guān)
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + BasicActivity.this.getPackageName()));
startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
}
});
} else {
// Already hold the SYSTEM_ALERT_WINDOW permission, do addview or something
}
}
/**
*懸浮窗權(quán)限再沒有授權(quán)的情況下,彈框讓用戶選擇是否調(diào)到權(quán)限設(shè)置頁面去申請該權(quán)限
*/
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("確定", okListener)
.setNegativeButton("拒絕", null)
.create()
.show();
}
申請懸浮窗權(quán)限還有一點和申請其他權(quán)限不同,就是申請其他權(quán)限都是onRequestPermissionsResult 在這個里面監(jiān)測是否授權(quán),但是申請懸浮窗權(quán)限,需要在onActivityResult這里判斷用戶是否授權(quán)
@TargetApi(Build.VERSION_CODES.M)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
if (!Settings.canDrawOverlays(this)) {//權(quán)限未被允許
} else {//權(quán)限被允許
//在這里可以彈出懸浮框
}
}
}
到這里為止,申請懸浮窗和彈出懸浮窗就可以實現(xiàn)了。