Adnroid越過用戶授權使用浮窗

GroverHughe 8年前發布 | 27K 次閱讀 Android Android開發 移動開發

上一片篇文章分析了Android窗口系統層次、Ativity的窗口和系統窗口的區別,這篇文章我來說說使用系統窗口來實現浮窗的一些限制,我們如何越過這些限制。

簡單的浮窗實現

final WindowManager windowManager =     getWindowManager(context);
//創建自定義浮窗
 FloatView    hideDialog = new FloatView(context);
WindowManager.LayoutParams  params = new     WindowManager.LayoutParams();
//params.type 窗口類型,主要決定了窗口的層次
params.type = WindowManager.LayoutParams.TYPE_PHONE;
params.format = PixelFormat.RGBA_8888;
//params.flags 描述窗體其他屬性的標記位,
//LayoutParams.FLAG_NOT_FOCUSABLE表示不能獲取輸入法焦點
params.flags = LayoutParams.FLAG_NOT_FOCUSABLE;
params.gravity = Gravity.LEFT | Gravity.TOP;
params.width = LayoutParams.MATCH_PARENT;
params.height = LayoutParams.MATCH_PARENT;
//添加
windowManager.addView(hideDialog, dialogParams);

使用WindowManager.LayoutParams.TYPE_PHONE
或WindowManager.LayoutParams.TYPE_SYS_ALERT窗體類型,然后在別忘了AndroidManifest.xml文件中申明權限<uses-permissionandroid:name="android.permission.SYSTEM_ALERT_WINDOW" />,這是網上關于浮窗實現的帖子千篇一律的做法,很多開發團隊也是這么做的。然而在Android 4.4( api 19 )以后,手機rom就可以把這個權限動態的交給用戶來選擇了,例如華為、小米、oppo等一些機型。例如在華為榮耀6上,關掉《九游》App的浮窗權限,九游的浮窗就顯示不了了。

九游App浮窗


于是很多產品在浮窗功能環節就加入了授權引導(針對不同的機型提示引導用戶去授權),本人最討論這樣的引導了,興致勃勃的要使用某項功能,突然來個提示框,叫我到xxx設置去進行n個步驟操作,對于這樣的功能我一般都是直接放棄使用的。好在這些痛點我們是可以技術策略解決的。

窗實現越過權限使用浮窗

《交易貓》App已經越過浮窗授權,正常使用浮窗功能。

Adnroid越過用戶授權使用浮窗

交易貓App浮窗


類型為TYPE_PHONE、TYPE_PRIORITY_PHONE、TYPE_SYSTEM_ALERT、TYPE_SYSTEM_ERROR、TYPE_SYSTEM_ERROR這些的窗口都是需要用戶授權的,類型為TYPE_TOAST的不需要,然而在Android 4.4 (api 19)以下TYPE_TOAST是無法獲取焦點的,具體源碼分析過程可以參考文章:
《Android懸浮窗TYPE_TOAST小結源碼分析》。于是我們就可以做一個細分流程了:首先獲取系統版本如果大于等于19我們使用TYPE_TOAST,小于19我們使用TYPE_PHONE窗口類型。

Adnroid越過用戶授權使用浮窗

根據系統版本使用浮窗

輸入法的限制

在4.4以上使用TYPE_TOAST還是有些小小的限制,如果浮窗交互中需要輸入框,TYPE_TOAST和TYPE_PHONE兩種類型窗體對輸入法的處理還是有些區別。當我們的浮窗在橫屏環境中(浮窗下面的應用是橫屏的),輸入法默認是全屏的,我們可以通過設置文本屬性android:imeOptions=“flagNoExtractUi”來禁止輸入法的全屏,同時可以設置窗體屬性為adjustResize來適配調整浮窗位置防止輸入法蓋住輸入框。

Adnroid越過用戶授權使用浮窗

type_phone輸入法.png

然而adjustResize這個屬性對TYPE_TOAST類型的窗體是無效的,本人暫時沒找到對應的源碼佐證,如果你找到了請告訴我一下。所以如果你的浮窗交互中是需要輸入文字的,就不能使用半屏幕輸入法的體驗了。

Adnroid越過用戶授權使用浮窗

TYPE_TOAST輸入法.png


為了最大程度的優化體驗,我們使用浮窗的流程可以細化為:

Adnroid越過用戶授權使用浮窗

授權判斷.png


關于浮窗授權,我們可以使用一下方法來判斷是否授權:

/**
 * 判斷是否開啟浮窗權限,api未公開,使用反射調用
 * @return
 */
private static boolean hasAuthorFloatWin(Context context){

    if (Device.getSystemVersion() < 19){
        return false;
    }
    try {
        AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
        Class c = appOps.getClass();
        Class[] cArg = new Class[3];
        cArg[0] = int.class;
        cArg[1] = int.class;
        cArg[2] = String.class;
        Method lMethod = c.getDeclaredMethod("checkOp", cArg);
        //24是浮窗權限的標記
        return (AppOpsManager.MODE_ALLOWED == (Integer) lMethod.invoke(appOps, 24, Binder.getCallingUid(), context.getPackageName())){

    } catch(Exception e) {
       return false;
    }
}

AppOpsManager是api 19以后引入的,第三方rom可以利用它來管理權限,將某些權限交給用戶來定奪,例如浮窗。詳細參考官方文檔:AppOpsManager


 

來源:http://www.jianshu.com/p/50fbec2baeb4
 

 本文由用戶 GroverHughe 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!