Android權限禁止及友好提示用戶開通必要權限


Android權限
Android安全架構規定:默認情況下,任何應用都沒有權限執行對其他應用、操作系統或用戶有不利影響的任何操作。這包括讀寫用戶的私有數據(聯系人,短信,相冊,位置)、讀寫其他應用的文件、執行網絡訪問、使設備保持喚醒狀態等等。

如果是一些正常的權限(非高危權限),比如網絡訪問等在應用清單文件(AndroidManifest.xml)中配置,系統會自動授予,
但是如果有一些高危權限,位置,文件存儲,短信等這個時候系統會要求用戶授予權限,Android 發出權限請求的方式取決於系統版本:
1、如果設備運行的是Android 6.0(Marshmallow,API 23)或更高版本,並且應用的targetSdkVersion是23或更高版本,則應用將在運行時向用戶請求權限(Runtime Permissions)。用戶可隨時撤銷權限,因此應用每次運行時都應該檢查自身是否具備所需的權限。
2、如果設備運行的是Android 5.1(LOLLIPOP_MR1,API 22)或更低版本,並且應用的targetSdkVersion是22或更低版本,則系統在用戶安裝應用時就要求用戶授予權限。如果更新應用時又新增了權限,系統會在用戶更新應用時要求授予該權限。用戶一旦安裝應用,他們撤銷權限的唯一方式是卸載應用。

如果我們程序中某些功能,發布一些圖片等操作,這個時候避免不了要訪問用戶設備的圖片,但是用戶開始的時候禁止了,用戶並不知道,這個時候訪問就會有問題了,那么怎樣去提示用戶並且引導用戶去授予這些權限呢,看下面的效果(說的再多都不如圖來的實際)

下面就開始擼碼了

private void getpermission() {
        //兩個日歷權限和一個數據讀寫權限
        String[] permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.READ_PHONE_STATE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}; //
        PermissionsUtils.showSystemSetting = true;//是否支持顯示系統設置權限設置窗口跳轉
        //這里的this不是上下文,是Activity對象!
        PermissionsUtils.getInstance().chekPermissions(this, permissions, permissionsResult);
    }

首先在頁面Activity啟動之后調用這個方法(注意:數組中的權限可以自己配置,這里我寫了四個)

權限監聽接口對象

  //創建監聽權限的接口對象
    PermissionsUtils.IPermissionsResult permissionsResult = new PermissionsUtils.IPermissionsResult() {
        @Override
        public void passPermissons() {
//權限通過執行的方法
            //權限通過驗證
        }

        @Override
        public void forbitPermissons() {
//這是沒有通過權限的時候提示的內容,自定義即可
            Toast.makeText(mContext, "您沒有允許部分權限,可能會導致部分功能不能正常使用,如需正常使用  請允許權限", Toast.LENGTH_SHORT).show();
            finish();
//            Tool.exitApp();
        }
    };

還需要在activity中重寫一個方法

  @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //就多一個參數this
        PermissionsUtils.getInstance().onRequestPermissionsResult(this, requestCode, permissions, grantResults);
    }

權限以及彈窗設置權限工具類PermissionsUtils.java

/**
 * 權限工具類
 */
public class PermissionsUtils {

    private final int mRequestCode = 100;//權限請求碼
    public static boolean showSystemSetting = true;

    private PermissionsUtils() {
    }

    private static PermissionsUtils permissionsUtils;
    private IPermissionsResult mPermissionsResult;

    public static PermissionsUtils getInstance() {
        if (permissionsUtils == null) {
            permissionsUtils = new PermissionsUtils();
        }
        return permissionsUtils;
    }

    public void chekPermissions(Activity context, String[] permissions, @NonNull IPermissionsResult permissionsResult) {
        mPermissionsResult = permissionsResult;
        if (Build.VERSION.SDK_INT < 23) {
            //6.0才用動態權限
            permissionsResult.passPermissons();
            return;
        }

        //創建一個mPermissionList,逐個判斷哪些權限未授予,未授予的權限存儲到mPerrrmissionList中
        List<String> mPermissionList = new ArrayList<>();
        //逐個判斷你要的權限是否已經通過
        for (int i = 0; i < permissions.length; i++) {
            if (ContextCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
                mPermissionList.add(permissions[i]);//添加還未授予的權限
            }
        }
        //申請權限
        if (mPermissionList.size() > 0) {//有權限沒有通過,需要申請
            ActivityCompat.requestPermissions(context, permissions, mRequestCode);
        } else {
            //說明權限都已經通過,可以做你想做的事情去
            permissionsResult.passPermissons();
            return;
        }
    }

    //請求權限后回調的方法 //參數: requestCode  是我們自己定義的權限請求碼
    // 參數: permissions  是我們請求的權限名稱數組
    // 參數: grantResults 是我們在彈出頁面后是否允許權限的標識數組,數組的長度對應的是權限名稱數組的長度,數組的數據0表示允許權限,-1表示我們點擊了禁止權限
    public void onRequestPermissionsResult(Activity context, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        boolean hasPermissionDismiss = false;
        //有權限沒有通過
        if (mRequestCode == requestCode) {
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] == -1) {
                    hasPermissionDismiss = true;
                }
            }
            //如果有權限沒有被允許
            if (hasPermissionDismiss) {
                if (showSystemSetting) {
                    showSystemPermissionsSettingDialog(context);//跳轉到系統設置權限頁面,或者直接關閉頁面,不讓他繼續訪問
                } else {
                    mPermissionsResult.forbitPermissons();
                }
            } else {
                //全部權限通過,可以進行下一步操作。。。
                mPermissionsResult.passPermissons();
            }
        }
    }

    /**
     * 不再提示權限時的展示對話框
     */
    AlertDialog mPermissionDialog;

    private void showSystemPermissionsSettingDialog(final Activity context) {
        final String mPackName = context.getPackageName();
        if (mPermissionDialog == null) {
            mPermissionDialog = new AlertDialog.Builder(context).setMessage("已禁用權限,請手動授予").setPositiveButton("設置", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    cancelPermissionDialog();
                    Uri packageURI = Uri.parse("package:" + mPackName);
                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
                    context.startActivity(intent);
                    context.finish();
                }
            }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    //關閉頁面或者做其他操作
                    cancelPermissionDialog();
                    //mContext.finish();
                    mPermissionsResult.forbitPermissons();
                }
            }).create();
        }
        mPermissionDialog.show();
        //放在show()之后,不然有些屬性是沒有效果的,比如height和width
        //以下代碼設置解決彈窗不居中問題,一側有邊距,一側沒有
        Window dialogWindow = mPermissionDialog.getWindow();
        WindowManager m = context.getWindowManager();
        Display d = m.getDefaultDisplay(); // 獲取屏幕寬、高
        WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 獲取對話框當前的參數值
        // 設置寬度
        p.width = (int) (d.getWidth() * 0.95); // 寬度設置為屏幕的0.95
        p.gravity = Gravity.CENTER;//設置位置
        //p.alpha = 0.8f;//設置透明度
        dialogWindow.setAttributes(p);

    }

    //關閉對話框
    private void cancelPermissionDialog() {
        if (mPermissionDialog != null) {
            mPermissionDialog.cancel();
            mPermissionDialog = null;
        }
    }

    public interface IPermissionsResult {
        void passPermissons();

        void forbitPermissons();
    }
}

以上這些代碼就可以實現gif圖的效果,當然可以自定義任意效果
如果有問題請請聯系dingchao7323@qq.com,一起交流,共同進步

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM