一虐先、Android權(quán)限介紹
應用權(quán)限有助于保護對以下數(shù)據(jù)的訪問和對以下操作的執(zhí)行怨愤,從而為保護用戶隱私提供支持:
- 受限數(shù)據(jù),例如系統(tǒng)狀態(tài)和用戶的聯(lián)系信息赴穗。
- 受限操作憔四,例如連接到已配對的設備并錄制音頻。
1.1 權(quán)限分類
- 安裝時權(quán)限
系統(tǒng)會在應用安裝時自動授予應用相應權(quán)限般眉,包括普通權(quán)限和簽名權(quán)限了赵。 - 運行時權(quán)限
運行時權(quán)限也稱為危險權(quán)限,Android 6.0 開始需要在應用中執(zhí)行權(quán)限申請相關代碼甸赃,系統(tǒng)會彈出授權(quán)框提示框柿汛,需要用戶點擊才可以授權(quán)。 - 特殊權(quán)限
Android 6.0 開始需要用戶在應用設置界面中才能開啟權(quán)限埠对。
基本上每個版本络断,權(quán)限都會有一定的修改,而且系統(tǒng)對這方面的限制是越來越嚴格项玛,所以正確的做法是請求最少數(shù)量的權(quán)限貌笨。
二、權(quán)限申請
Android 6.0 版本開始襟沮,權(quán)限部分有了重大改變锥惋,所以下面以Android 6.0 為分界線昌腰,介紹如何申請權(quán)限。
2.1 Android 6.0 以下
不管是普通權(quán)限還是危險權(quán)限膀跌,只需在 AndroidManifest.xml
清單文件中進行申明即可:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
3.2 android 6.0 以上
安裝時只會給普通權(quán)限授權(quán)遭商,其他權(quán)限需要特殊操作進行申請。
- 危險權(quán)限:
不僅要在清單文件中申明權(quán)限捅伤,還需要代碼中動態(tài)申請權(quán)限劫流,系統(tǒng)會彈出對應的權(quán)限提示框,用戶點擊同意才可以授權(quán)丛忆。 - 特殊權(quán)限
不僅要在清單文件中申明權(quán)限祠汇,還需要在用戶在應用設置界面進行授權(quán)。
權(quán)限等級可以通過 官網(wǎng) 進行查詢蘸际。
動態(tài)申請權(quán)限
主要分為以下幾個步驟:
- 判斷當前是否有權(quán)限
if (PackageManager.PERMISSION_GRANTED == ActivityCompat
.checkSelfPermission(context, permission)) {
//已授權(quán)
} else {
//未授權(quán)
}
- 進行權(quán)限申請
ActivityCompat.requestPermissions(activity, String[] permissions, REQUEST_CODE));
- 用戶授權(quán)后操作
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_CODE) {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
//已授權(quán)
} else {
//未授權(quán)
}
}
}
}
完整參考代碼如下:
private void requestStoragePermission() {
List<String> needRequestList = checkPermission(this, PERMISSION_LIST);
if (needRequestList.isEmpty()) {
//已授權(quán)
} else {
//申請權(quán)限
requestPermission(needRequestList);
}
}
private List<String> checkPermission(Context context, String[] checkList) {
List<String> list = new ArrayList<>();
for (String s : checkList) {
if (PackageManager.PERMISSION_GRANTED != ActivityCompat
.checkSelfPermission(context, s)) {
list.add(s);
}
}
return list;
}
private void requestPermission(List<String> needRequestList) {
ActivityCompat
.requestPermissions(activity, needRequestList.toArray(new String[0]),
REQUEST_CODE));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_CODE_STORAGE) {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
//已授權(quán)
} else {
//未授權(quán)
}
}
}
}
權(quán)限被禁止
如果用戶第一次拒絕權(quán)限后座哩,第二次再申請權(quán)限時徒扶,系統(tǒng)提示框會出現(xiàn)一個不再詢問的按鈕粮彤,如下圖:
如果用戶勾選“不再詢問”,同時點擊拒絕后姜骡,相當于權(quán)限被禁止了导坟。下次再申請權(quán)限,會直接回調(diào)權(quán)限被拒絕圈澈。即 requestPermissions
調(diào)用后不會再彈出系統(tǒng)提示框惫周,只能引導用戶去應用設置界面進行授權(quán)。
這時候可以通過 shouldShowRequestPermissionRationale
方法進行判斷康栈。
該方法的本意是递递,當權(quán)限被拒絕后,你可以提示用戶為什么需要獲取該權(quán)限啥么。有下面幾種場景:
- 沒有申請權(quán)限時登舞,返回false
- 申請權(quán)限,但是被拒絕了悬荣,返回true
- 申請權(quán)限菠秒,但是被用戶禁止了,或者勾選了不再詢問氯迂,返回false
- 申請權(quán)限践叠,用戶允許了,返回false
主要流程如下:
-
onRequestPermissionsResult
權(quán)限申請回調(diào)后嚼蚀,判斷權(quán)限是否被用戶禁止禁灼。 - 引導用戶跳轉(zhuǎn)到應用設置界面授權(quán)。
- 由于授權(quán)后返回應用并沒有任何提示轿曙,所以需要重新再判斷權(quán)限弄捕。
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_CODE) {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
//用戶已授權(quán)
} else {
//判斷用戶是否勾選了不再詢問
if (VERSION.SDK_INT >= VERSION_CODES.M && !shouldShowRequestPermissionRationale(
permission.WRITE_EXTERNAL_STORAGE)) {
//跳轉(zhuǎn)到應用設置界面授權(quán)
goToSetting();
}
}
}
}
}
/**
* 跳轉(zhuǎn)應用設置界面進行授權(quán)
*/
private void goToSetting() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_CODE_SETTING);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_SETTING) {
//從設置界面回來哮独,是不知道用戶是否有授權(quán)的,所以需要重新再判斷
List<String> needRequestList = checkPermission(this, PERMISSION_LIST);
if (needRequestList.isEmpty()) {
//已授權(quán)
}
}
}