Android權限
Android安全架構規定:默認狀況下,任何應用都沒有權限執行對其餘應用、操做系統或用戶有不利影響的任何操做。這包括讀寫用戶的私有數據(聯繫人,短信,相冊,位置)、讀寫其餘應用的文件、執行網絡訪問、使設備保持喚醒狀態等等。java
若是是一些正常的權限(非高危權限),好比網絡訪問等在應用清單文件(AndroidManifest.xml)中配置,系統會自動授予,
可是若是有一些高危權限,位置,文件存儲,短信等這個時候系統會要求用戶授予權限,Android 發出權限請求的方式取決於系統版本:
一、若是設備運行的是Android 6.0(Marshmallow,API 23)或更高版本,而且應用的targetSdkVersion是23或更高版本,則應用將在運行時向用戶請求權限(Runtime Permissions)。用戶可隨時撤銷權限,所以應用每次運行時都應該檢查自身是否具有所需的權限。
二、若是設備運行的是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啓動以後調用這個方法(注意:數組中的權限能夠本身配置,這裏我寫了四個)架構
權限監聽接口對象ide
//建立監聽權限的接口對象 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.javaui
/** * 權限工具類 */ 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,一塊兒交流,共同進步this