這里我將介紹:
*1. 動態(tài)權(quán)限的基本使用(包括個人理解)*
*2. 動態(tài)權(quán)限使用時,我們需要去注意什么*
先解釋 再上例子
為了用戶體驗考慮,Android6.0之后,希望當APP運行到需要被授予某項權(quán)限時,才會去提示用戶開啟某項權(quán)限,而不是像以前那樣,直接在啟動頁就全部請求授予,這就要求我們,在需要時提示用戶開啟權(quán)限并對權(quán)限請求結(jié)果進行回調(diào)監(jiān)聽。
-
需要知道的
-
兩個與權(quán)限有關(guān)的變量:
PackageManager.PERMISSION_GRANTED = 0 //表示授予權(quán)限; PackageManager.PERMISSION_DENIED = -1 //表示權(quán)限未開啟; -
運行權(quán)限檢測的三種方式:
方式一: public static int checkSelfPermission(Activity activity,String writeContacts) { return PermissionChecker.checkSelfPermission(activity, writeContacts); } 方式二: public static int checkSelfPermission(Activity activity,String writeContacts) { return ContextCompat.checkSelfPermission(WelcomeActivity.this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED); } 方式三: public static boolean checkSelfPermission() { PackageManager pm = this.getPackageManager(); for (String auth : authBaseArr) { //注意,這里是只要有一個權(quán)限未通過,則返回false,并不能對具體某個權(quán)限做區(qū)分 if (pm.checkPermission(auth, this.getPackageName()) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } -
請求開啟權(quán)限的彈窗顯示:
ActivityCompat.requestPermissions(mactivity, new String[] { CALL_PHONE ,CAMERA },REQUEST_CODE);注意:一次請求多個權(quán)限會有bug,當該次權(quán)限彈窗中有一個未被授予權(quán)限,那么再次執(zhí)行該代碼時,只會一直提示用戶需要獲取第一項權(quán)限,但是此時即使用戶點擊允許,依然會不斷提示請求開啟第一項權(quán)限(實則是需要開啟后邊的某項權(quán)限),所以還是每次都只請求一個權(quán)限穩(wěn)妥?。?! 例如你可以這樣寫:
private void baiduPermission() { boolean canInitBaidu = true; // 申請權(quán)限 if (android.os.Build.VERSION.SDK_INT >= 23) { pm = this.getPackageManager(); if (pm.checkPermission(authBaseArr[0], this.getPackageName()) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, authBaseRequestCode); canInitBaidu = false; } if (pm.checkPermission(authBaseArr[1], this.getPackageName()) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, authBaseRequestCode); canInitBaidu = false; } } if (canInitBaidu) { initLoc(); } } -
權(quán)限請求結(jié)果監(jiān)聽:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == BaiDuRequest && grantResults.length > 0 && grantResults[0]==-1){ UtilsW.showMessageOKCancel(mactivity, "溫馨提示", " 當前操作需要開啟“XXX”權(quán)限,您可到設(shè)置的權(quán)限管理中,修改該應(yīng)用的相關(guān)權(quán)限。", null); } }注意:這里使用了grantResults.length > 0 ,這是為防止同時有兩個requestPermissions(new String[] { XXX},RequestCode);被調(diào)用,而引起的crash問題,grantResults[0]==-1(也就是grantResults[0]==PackageManager.PERMISSION_DENIED),表示用戶拒絕了該項權(quán)限,那如果要申請多個權(quán)限怎么辦?,我們可以在第一個成功后再去申請,如下:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == BaiDuRequest && grantResults.length > 0 && grantResults[0]==-1){ UtilsW.showMessageOKCancel(mactivity, "溫馨提示", " 當前操作需要開啟“定位”和“存儲”權(quán)限,您可到設(shè)置的權(quán)限管理中,修改該應(yīng)用的相關(guān)權(quán)限。", null); } else if (ACCESS_FINE_LOCATION.equalsIgnoreCase(permissions[0]) && grantResults.length > 0 && grantResults[0]== 0) { ActivityCompat.requestPermissions(mactivity, new String[] {WRITE_EXTERNAL_STORAGE },BaiDuRequest); } } 對于非Android6.0版本的手機,我們還是可以在AndroidManifest.xml中,直接設(shè)置權(quán)限的(如:<uses-permission android:name="android.permission.READ_PHONE_STATE"/>),在啟動APP時,就會有彈窗提示用戶給予權(quán)限了,二者雖有重復(fù),但誰讓咱們大Android越來越貼心呢;
-
shouldShowRequestPermissionRationale作用:
- 第一次請求權(quán)限時,用戶拒絕了,下一次:shouldShowRequestPermissionRationale() 返回 true,應(yīng)該顯示一些為什么需要這個權(quán)限的說明;
- 第二次請求權(quán)限時,用戶拒絕了,并選擇了“不在提醒”的選項時:shouldShowRequestPermissionRationale() 返回 false
- 設(shè)備的策略禁止當前應(yīng)用獲取這個權(quán)限的授權(quán):shouldShowRequestPermissionRationale() 返回 false
注意:上面的:第二次請求權(quán)限時,才會有“不在提醒”的選項,如果用戶一直拒絕,并沒有選擇“不在提醒”的選項,下次請求權(quán)限時,會繼續(xù)有“不在提醒”的選項
應(yīng)用方面舉例:
在獲取DeviceID時,我們有很多方法,比如這樣:
/** * 獲取DeviceId (IMEI方式) * 其他獲取DeviceId方式: http://blog.csdn.net/u014651216/article/details/50767326 */ public static String getDeviceID(Activity activity) { return ((TelephonyManager)activity.getSystemService(activity.TELEPHONY_SERVICE)).getDeviceId(); }但是直接這樣調(diào)用會報錯的:
SecurityException: getDeviceId: Neither user 10282 nor current process has android.permission.READ_PHONE_STATE.我們需要先判斷是否有讀取電話狀態(tài)的動態(tài)權(quán)限,然后去申請該權(quán)限,如下:
//電話狀態(tài)讀取的動態(tài)權(quán)限校驗 if (Utils.checkSelfPermission(this,READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { Utils.showMessageOKCancel(this,"提示:\n\n該應(yīng)用權(quán)限已關(guān)閉。\n開啟方式:點擊確定后,您可到“權(quán)限”中,開啟該應(yīng)用的“電話”權(quán)限。", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); //未開啟該權(quán)限,引導(dǎo)用戶到開啟該項權(quán)限的頁面 intent.setData(Uri.parse("package:" + getPackageName())); startActivity(intent); } }); return ; -
或者直接再次申請權(quán)限:
int permissionNum = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE); //檢測某項權(quán)限是否開啟
if (permissionNum != PackageManager.PERMISSION_GRANTED) { //若該權(quán)限未開啟
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, REQUEST_READ_PHONE_STATE);
} //但這種若用戶在第一次彈窗時,勾選了不再提醒,將不會再次有該項提示了
.