1. 程式人生 > >Android6.0(Android M) 懸浮窗被禁用,無許可權開啟懸浮窗的解決方案

Android6.0(Android M) 懸浮窗被禁用,無許可權開啟懸浮窗的解決方案

最近需要在Android6.0的機子上實現一個懸浮窗的功能,發現6.0之前的機子都能使用懸浮窗,但是唯獨6.0版本不行,以下我是查到的相關資料,挺有意思的,順帶說一下:

國內查,所有的新聞統一都說是谷歌有意禁止該功能(預設關閉),且說不會妥協去修改,僅此而已,未找到相關的開發者解決方案。

國外查,尼瑪人家說這個android6.0的bug,在6.0.1之後會修復。。。。

WTF,那麼問題來了,本猿該信誰。。。。。。。。

Whatever,我要的是解決方案,直奔主題

——————————————————————————我是一條一本正經的分割線————————————————————————————

解決方案有兩種:

一是如果你做的是系統應用開發,只要給apk簽名,那麼預設懸浮窗許可權是給予的,顯然這種情況不符合大多數開發者的要求。

二是在開啟懸浮窗之前,引導使用者去開啟許可權,本博文重點介紹這種方法

許可權開啟的UI路徑是 “ 通用 -- 應用管理 -- 更多 -- 配置應用 --- 在其他應用的上層顯示 --- 選擇你的APP -- 執行在其他應用的上層顯示 ”  >_< 藏得也是夠深的!!!

【步驟1】在AndroidManifest.xml中新增懸浮窗的許可權

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
【步驟2】Activity的編寫如下
package test.floatWin;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

import com.cxq.selftestdemo.R;

public class TestFloatWinActivity extends AppCompatActivity {

    private static final String TAG = "TestFloatWinActivity";
    public static int OVERLAY_PERMISSION_REQ_CODE = 1234;
    //開啟懸浮窗的Service
    Intent floatWinIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_floatwin);
        floatWinIntent = new Intent(TestFloatWinActivity.this, FloatWinService.class);
    }

    /**
     * 按下begin按鈕
     *
     * @param v
     */
    public void begin(View v) {
        //開啟懸浮框前先請求許可權
        askForPermission();
    }

    /**
     * 按下end按鈕
     *
     * @param v
     */
    public void end(View v) {
        //關閉懸浮框
        stopService(floatWinIntent);
    }


    /**
     * 請求使用者給予懸浮窗的許可權
     */
    public void askForPermission() {
        if (!Settings.canDrawOverlays(this)) {
            Toast.makeText(TestFloatWinActivity.this, "當前無許可權,請授權!", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
        } else {
            startService(floatWinIntent);
        }
    }

    /**
     * 使用者返回
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
            if (!Settings.canDrawOverlays(this)) {
                Toast.makeText(TestFloatWinActivity.this, "許可權授予失敗,無法開啟懸浮窗", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(TestFloatWinActivity.this, "許可權授予成功!", Toast.LENGTH_SHORT).show();
                //啟動FxService
                startService(floatWinIntent);
            }

        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

大概解釋一下,Activity中有兩個Button,

一個Begin,對應方法是開啟懸浮窗,但是在開啟前回去檢測許可權,許可權有則直接執行懸浮框,沒有則直接跳轉到許可權請求頁面,引導使用者開啟

一個End,對應的方法是關閉懸浮窗

懸浮窗的開啟我是放在Service中的,Service開啟懸浮窗執行,Serive停止懸浮窗關閉,這點大家可以根據自己的需求去改。