1. 程式人生 > >Android M及以上版本系統 懸浮窗許可權 的解決方案

Android M及以上版本系統 懸浮窗許可權 的解決方案

Android M及以上版本系統 懸浮窗許可權 的解決方案

 

Android的視窗體系中,WindowManager佔有非常重要的地位,平時我們使用懸浮窗會遇到一些許可權的問題。
當 Android工程在
targetSdkVersion 23
編譯,Android6.0及其以上版本手機使用懸浮窗功能時候,會發生如下的異常,導致程式崩潰。

java.lang.RuntimeException: Unable to create service
 com.fb.tangyc.fbtools.service.FBService: android.view.WindowManager$BadTokenException:
 Unable to add window 
[email protected]
-- permission denied for this window type


當Android工程在
targetSdkVersion 22
編譯,Android6.0及其以上版本手機使用懸浮窗功能會正常使用
其實原因很簡單,大部分的Android6.0手機(尤其是三星,谷歌原生手機)
在大於等於23版本下編譯,懸浮窗許可權預設是關閉沒有許可權,然在小於23版本下編譯懸浮窗許可權是開啟有許可權的。
所以在大於23版本下編譯時需要去檢測懸浮窗許可權,並且獲取懸浮窗許可權,下面我就羅列下怎麼去檢測懸浮窗許可權並且獲取懸浮窗許可權

if ( Build.VERSION.SDK_INT> = 23 ) {
       if (Settings.canDrawOverlays(this)) {
           //有懸浮窗許可權開啟服務繫結 繫結許可權
           Intent intent = new Intent(MainActivity.this, MyService.class);
           startService(intent);

       } else {
           //沒有懸浮窗許可權m,去開啟懸浮窗許可權
           try {
                   Intent  intent=new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
             startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
} else {
    // 預設有懸浮窗許可權  但是 華為, 小米,oppo 等手機會有自己的一套 Android6.0 以下  
    // 會有自己的一套懸浮窗許可權管理 也需要做適配
    Intent intent = new Intent(MainActivity.this, MyService.class);
    startService(intent);
}    

每次使用懸浮窗的時候都要去檢測許可權,因為懸浮窗許可權是可以手動關閉的。
位置位於 (三星S6為例Android6.0.1版本)設定-- 應用程式--應用程式管理器 -- 更多 --可出現在頂部的應用程式 --- 選擇你的APP -- 執行在其他應用的上層顯示

 

 

下圖所示:

 

當你點選懸浮窗許可權app開關時候 退出 會在activity 有回撥方法。


protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
        if(Build.VERSION.SDK_INT>=23) {
            if (!Settings.canDrawOverlays(this)) {
                Toast.makeText(this, "許可權授予失敗,無法開啟懸浮窗", Toast.LENGTH_SHORT).show();
            } else {
                       Toast.makeText(this, "許可權授予成功!", Toast.LENGTH_SHORT).show();
               //有懸浮窗許可權開啟服務繫結 繫結許可權
                Intent intent = new Intent(MainActivity.this, FBService.class);
                startService(intent);
            }
        }
    }
}

下面就羅列下Service中啟動懸浮的實現
首先 你需要在配置檔案懸浮窗許可權

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

第二需要在服務中開啟懸浮窗


public class FBService extends Service  {

    private WindowManager wManager;// 視窗管理者
    private WindowManager.LayoutParams mParams;// 視窗的屬性

    private FloatButtonLayout windowView;
    private SurfaceHolder holder;
    public static final String *ACTION_ALPHA *= "com.fb.alpha";
    private ServiceReceiver receiver;

    @Override
    public void onCreate() {

        super.onCreate();
        wManager = (WindowManager) getSystemService(Context.*WINDOW_SERVICE*);
        mParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.*TYPE_SYSTEM_ERROR*, WindowManager.LayoutParams.*FLAG_NOT_FOCUSABLE*, PixelFormat.*TRANSPARENT*);
        mParams.type = WindowManager.LayoutParams.*TYPE_SYSTEM_ERROR*;// 系統提示window
        mParams.format = PixelFormat.*TRANSLUCENT*;// 支援透明
        // mParams.format = PixelFormat.RGBA_8888;
        mParams.flags |= WindowManager.LayoutParams.*FLAG_NOT_TOUCH_MODAL *| WindowManager.LayoutParams.*FLAG_NOT_FOCUSABLE*;// 焦點
        mParams.width = WindowManager.LayoutParams.*WRAP_CONTENT*;// 視窗的寬和高
        mParams.height = WindowManager.LayoutParams.*WRAP_CONTENT*;
        mParams.gravity = Gravity.*LEFT *| Gravity.*TOP*;
        mParams.y = SharedPreferencesUtils.*getSharedPreferencesUtils*().getParamsY(getApplicationContext());
        mParams.x = SharedPreferencesUtils.*getSharedPreferencesUtils*().getParamsX(getApplicationContext());
        mParams.windowAnimations = android.R.style.*Animation_Toast*;
        // mParams.alpha = 0.8f;//視窗的透明度

        LayoutInflater layoutInflater = LayoutInflater.*from*(getApplicationContext());
        windowView = (FloatButtonLayout) layoutInflater.inflate(R.layout.*float_button_layout*, null);

        wManager.addView(windowView, mParams);// 新增視窗
      
    }
       

第三,關閉服務時候,關閉懸浮窗

@Override
public void onDestroy() {
    if (wManager!=null&&windowView != null) {
            wManager.removeView(windowView);
    }
    super.onDestroy();
}

這就是在Android下面開啟懸浮窗許可權的全部流程。