Android許可權禁止及友好提示使用者開通必要許可權
轉載請註明出處: https://www.jianshu.com/p/9a55f507b23f
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或更低版本,則系統在使用者安裝應用時就要求使用者授予許可權。如果更新應用時又新增了許可權,系統會在使用者更新應用時要求授予該許可權。使用者一旦安裝應用,他們撤銷許可權的唯一方式是解除安裝應用。
如果我們程式中某些功能,釋出一些圖片等操作,這個時候避免不了要訪問使用者裝置的圖片,但是使用者開始的時候禁止了,使用者並不知道,這個時候訪問就會有問題了,那麼怎樣去提示使用者並且引導使用者去授予這些許可權呢,看下面的效果(說的再多都不如圖來的實際)

2018040209493621.jpg

quanxian.gif
下面就開始擼碼了
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圖的效果,當然可以自定義任意效果
如果有問題請請聯絡[email protected],一起交流,共同進步