android開發中懸浮窗被禁用,無許可權開啟懸浮窗的解決方案
首先,感謝這兩篇博文http://blog.csdn.net/cankingapp/article/details/51569576
http://blog.csdn.net/cool_fuwei/article/details/53070232
瞭解知識:
1.首先要知道6.0版本許可權模型跟原來版本是不同的,不再是統一在manifest中預設系統授權,而是有需要的時候,向系統請求授權,提高使用者體驗。
2.瞭解許可權檢測流程,一點注意點是如果系統許可權彈窗提示框被不再提醒了,需要我們自定義提示彈窗,引導使用者去授權。
3.明白許可權型別,分為normal和dangerous型別,同時,在dangerous中還需要注意一點,SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS這兩個特殊授權請求方式,跟一般授權請求方式不同。
4.在判斷APP是否執行在Android M上,可以用版本號來判斷,可以準確點。
問題一:在安卓開發中處理懸浮窗許可權時,發現魅族和小米手機無論android4.4.4、android5.1.1還是android6.0,許可權manifest中:android.permission.SYSTEM_ALERT_WINDOW許可權也加過了,就是彈不起。這個許可權也不是android 6.0中的敏感許可權,所以android 6.0動態申請許可權也是行不通的,這個問題很難通過diamante開啟懸浮窗,沒轍之後想到,呼叫應用的設定介面引導使用者去手動的開啟。
問題二:在三星6.0或android6.0及android 6.0以上的手機(小米和魅族處理方式另外處理同上),未處理彈窗問題可能會引發以下問題,
android.view.WindowManager$BadTokenException: Unable to add window
android.view.ViewRootImpl[email protected] -- permission denied for this window type
at android.view.ViewRootImpl.setView(ViewRootImpl.java:879)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:337)
at android.view .WindowManagerImpl.addView(WindowManagerImpl.java:91)
at android.app.Dialog.show(Dialog.java:350)
話不多說,直接上程式碼處理以上兩個疑問。
@Override
public void onClick(View view) {
String user = edit_user.getText().toString();
String pwd = edit_pwd.getText().toString();
if (user.equals("123") && pwd.equals("123")) {
editor = pref.edit();
editor.putString("user", user);
editor.putString("pwd", pwd);
editor.commit();
//開啟懸浮窗前先請求許可權
if ("Xiaomi".equals(Build.MANUFACTURER)) {//小米手機
LogUtil.E("小米手機");
requestPermission();
} else if ("Meizu".equals(Build.MANUFACTURER)) {//魅族手機
LogUtil.E("魅族手機");
requestPermission();
} else {//其他手機
LogUtil.E("其他手機");
if (Build.VERSION.SDK_INT >= 23) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivityForResult(intent, 12);
} else {
switchActivity();
}
} else {
switchActivity();
}
}
} else {
ToastUtil.show(this, "這麼簡單都出錯,腦子呢?");
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 11) {
if (isFloatWindowOpAllowed(this)) {//已經開啟
switchActivity();
} else {
ToastUtil.show(this, "開啟懸浮窗失敗");
}
} else if (requestCode == 12) {
if (Build.VERSION.SDK_INT >= 23) {
if (!Settings.canDrawOverlays(LoginActivity.this)) {
ToastUtil.show(this, "許可權授予失敗,無法開啟懸浮窗");
} else {
switchActivity();
}
}
}
}
/**
* 跳轉Activity
*/
private void switchActivity() {
startActivity(new Intent(LoginActivity.this, Main2Activity.class));
ToastUtil.show(LoginActivity.this, "吆,竟然蒙對了!");
finish();
}
/**
* 判斷懸浮窗許可權
*
* @param context
* @return
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public static boolean isFloatWindowOpAllowed(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); // AppOpsManager.OP_SYSTEM_ALERT_WINDOW
} else {
if ((context.getApplicationInfo().flags & 1 << 27) == 1 << 27) {
return true;
} else {
return false;
}
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
public static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class<?> spClazz = Class.forName(manager.getClass().getName());
Method method = manager.getClass().getDeclaredMethod("checkOp", int.class, int.class, String.class);
int property = (Integer) method.invoke(manager, op,
Binder.getCallingUid(), context.getPackageName());
Log.e("399", " property: " + property);
if (AppOpsManager.MODE_ALLOWED == property) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
Log.e("399", "Below API 19 cannot invoke!");
}
return false;
}
/**
* 請求使用者給予懸浮窗的許可權
*/
public void requestPermission() {
if (isFloatWindowOpAllowed(this)) {//已經開啟
switchActivity();
} else {
openSetting();
}
}
/**
* 開啟許可權設定介面
*/
public void openSetting() {
try {
Intent localIntent = new Intent(
"miui.intent.action.APP_PERM_EDITOR");
localIntent.setClassName("com.miui.securitycenter",
"com.miui.permcenter.permissions.AppPermissionsEditorActivity");
localIntent.putExtra("extra_pkgname", getPackageName());
startActivityForResult(localIntent, 11);
LogUtil.E("啟動小米懸浮窗設定介面");
} catch (ActivityNotFoundException localActivityNotFoundException) {
Intent intent1 = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent1.setData(uri);
startActivityForResult(intent1, 11);
LogUtil.E("啟動懸浮窗介面");
}
}
相關推薦
android開發中懸浮窗被禁用,無許可權開啟懸浮窗的解決方案
首先,感謝這兩篇博文http://blog.csdn.net/cankingapp/article/details/51569576 http://blog.csdn.net/cool_fuwei/article/details/53070232 瞭解知識:
Android6.0(Android M) 懸浮窗被禁用,無許可權開啟懸浮窗的解決方案
最近需要在Android6.0的機子上實現一個懸浮窗的功能,發現6.0之前的機子都能使用懸浮窗,但是唯獨6.0版本不行,以下我是查到的相關資料,挺有意思的,順帶說一下: 國內查,所有的新聞統一都說是谷歌有意禁止該功能(預設關閉),且說不會妥協去修改,僅此而已,未找到相關的開
android開發中RadioGroup動態新增元件的時候checkedId自動累加的解決方案
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedCh
Android開發中的SQLite事務處理,即beginTransaction()方法
使用SQLiteDatabase的beginTransaction()方法可以開啟一個事務,程式執行到endTransaction() 方法時會檢查事務的標誌是否為成功,如果程式執行到endTransaction()之前呼叫了setTransactionSuccessful()
關於Android開發中實現錨點技術,也是焦點的改變
今天朋友問了我一個問題,他的需求是點選listview的item跳轉到另一個listview中,由於需要跳轉的操作比較多,他想在一個佈局中實現,我給他一個建議就是做控制元件焦點的切換,
Android開發中資料庫(sqlite)的檢視及一些問題的解決方法
最近在學習Android中的Sqlite遇到一些問題,這裡做一下總結。 一、建立資料庫 首先你要新建一個使用Sqlite的APP,開發工具Ecplise、AndroidStudio都可,這裡以後者AS為例。如果你沒有現成的程式,可以用博主的這個、 檔名
【轉】SQL2008的sa賬戶被禁用,其他賬戶無法連線的解決方法
百度知道上搜來的,不過答案好像也是CSDN的。但我沒有找到地址,先貼出來方法備忘,侵刪。 或者你還有其它的sysadmin許可權的賬號,你可以用此賬號登入,重置SA密碼。 但是在以下情況下,怎麼辦呢? 1. SA密碼丟失或者SA賬號被禁用。 2. 你進行了一些安全操作,把B
Qt 中執行cmd命令失敗,無許可權,需要提升程式以管理員執行 vs2013設定
程式中有些 地方 需要執行windows cmd 命令, 如 taskkill 程序命令 (QString c = "taskkill /im osk.exe /f";m_pProcess->execute(c);) 這種 命令是需要管理員身份的, 因此程式必須以管理員身份執行
Windows7 64位系統中,讀取登錄檔,檔案路勁重定位解決方案
在Windows7 64位系統中,讀取登錄檔,檔案路勁會進行重定位。以下是解決辦法: //第一步:定義巨集 #define KEY_WOW64_64KEY (0x0100) //支援讀寫64位登錄檔
sudoers檔案更改錯誤,root許可權無法使用的解決方案
/etc/sudoers: syntax error near line sudo: parse error in /etc/sudoers near line 25 sudo: no valid sudoers sources found, quitting 終極解決方案
Android開發中,Fragment巢狀Fragments遇到的問題
Fragment,簡稱碎片,是Android 3.0(API11)提出的,為了相容低版本,support-v4庫中也開發了一套Fragment API,最低相容Android 1.6。 Fragment是依賴於Activity的,不能獨立存在的。 一個Acti
Android開發中,使用 EditText 輸入內容,如何進行一鍵清空內容處理
本文僅為個人的處理方式,希望能對您有所幫助,歡迎各位留言指正,抱拳了 1、text.xml示例: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://s
Android開發中,有哪些讓你覺得相見恨晚的方法、類或介面
1、Throwable介面中的getStackTrace()方法(或者Thread類的getStackTrace()方法),根據這個方法可以得到函式的逐層呼叫地址,其返回值為StackTraceElement[]; 2、StackTraceElement類,其中四個方法getClassName(),getFi
啟動虛擬機器會有錯誤報告:二進位制轉換與此平臺上的長模式不相容。此虛擬環境中的長模式將被禁用,因此需要使用長模式的應用程式將無法正常執行
1.先安裝VMware2.常建立虛擬機器3.啟動虛擬機器,啟動會有:二進位制轉換與此平臺上的長模式不相容。此虛擬環境中的長模式將被禁用,因此需要使用長模式的應用程式將無法正常執行 解決辦法:需要開啟BIOS系統把 Intel Virtual Technology 改為e
android開發中遇到的進位制轉換,16進位制資料流轉和字串的相互轉換
最近開發的程式是利用無線網路,收發資料,其中,接收和傳送的格式是16進位制位元組陣列 byte[],而顯示到介面中則不可能把一堆的位元組流顯示出來。因此,需要進行一下轉換。 直接說轉換的演算法吧 一、16進位制位元組陣列轉換成字串 核心的語句就一句getSt
Android開發中,dialog的實現方式
在Android開發中,我們經常會需要在Android介面上彈出一些對話方塊,比如詢問使用者或者讓使用者選擇。這些功能我們叫它Android Dialog對話方塊,在我們使用Android的過程中,我歸納了一下,Android Dialog的型別無非也就7種,下面我分別向
Android開發中佈局與元件(一)—— 螢幕尺寸單位dp,px,sp的探究
在Android開發中,常用的尺寸單位有 dp , px , sp 。當然還有其他的單位如 pt , mm 等,不過這些都是不常用,所以我們重點來探究一下 dp , px , sp 這三個常用的單位。 px 英文 pixel 的縮寫,即畫素。無論螢幕密度為多少,一個畫素單位對應
Android開發中 十進位制,十六進位制的相互轉化
最近的開發 Android專案中要實現使用者自定義顏色,於是就自己利用 SeekBar 和 EditText 實現了一個拾色器。 原理也很簡單,就是用四個SeekBar 分別代表顏色的四個值:R,G,B,Alpha,每個顏色值都用0-255來表示,最終在轉化為十六進位制顏色值。 但是
Android學習筆記 —— Android 開發中,限制 EditText 輸入框不能輸入中文(漢字)
今天在練習開發一個小專案的時候,需要限制 EditText 輸入框不能輸入中文(漢字),在網上找了很多例子, 結合自己的實際,終於完成了這一功能。現在把程式碼記錄下來,方便以後查詢! 首先是xml佈
Android開發中一些被冷落但卻很有用的類和方法
來自:http://luckyandyzhang.github.io/ Resources.getIdentifier : 這個我 用過,記得以前做過一個面板切換功能,可以通過這個方法從面板包 獲取面板資源。 (面板包的資源名稱和 主包的資源名稱id 名是一樣的