應用權限有助於保護對如下數據的訪問和對如下操做的執行,從而爲保護用戶隱私提供支持:java
系統會在應用安裝時自動授予應用相應權限,包括普通權限和簽名權限。android
運行時權限也稱爲危險權限,Android 6.0 開始須要在應用中執行權限申請相關代碼,系統會彈出受權框提示框,須要用戶點擊才能夠受權。markdown
Android 6.0 開始須要用戶在應用設置界面中才能開啓權限。ide
基本上每一個版本,權限都會有必定的修改,並且系統對這方面的限制是愈來愈嚴格,因此正確的作法是請求最少數量的權限。oop
官網地址ui
Android 6.0 版本開始,權限部分有了重大改變,因此下面以Android 6.0 爲分界線,介紹如何申請權限。this
無論是普通權限仍是危險權限,只需在 AndroidManifest.xml
清單文件中進行申明便可:spa
<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" />
複製代碼
安裝時只會給普通權限受權,其餘權限須要特殊操做進行申請。code
不只要在清單文件中申明權限,還須要代碼中動態申請權限,系統會彈出對應的權限提示框,用戶點擊贊成才能夠受權。orm
不只要在清單文件中申明權限,還須要在用戶在應用設置界面進行受權。
權限等級能夠經過 官網 進行查詢。
主要分爲如下幾個步驟:
if (PackageManager.PERMISSION_GRANTED == ActivityCompat
.checkSelfPermission(context, permission)) {
//已受權
} else {
//未受權
}
複製代碼
ActivityCompat.requestPermissions(activity, String[] permissions, REQUEST_CODE));
複製代碼
@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) {
//已受權
} else {
//未受權
}
}
}
}
複製代碼
完整參考代碼以下:
private void requestStoragePermission() {
List<String> needRequestList = checkPermission(this, PERMISSION_LIST);
if (needRequestList.isEmpty()) {
//已受權
} else {
//申請權限
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) {
//已受權
} else {
//未受權
}
}
}
}
複製代碼
若是用戶第一次拒絕權限後,第二次再申請權限時,系統提示框會出現一個再也不詢問的按鈕,以下圖:
若是用戶勾選「再也不詢問」,同時點擊拒絕後,至關於權限被禁止了。下次再申請權限,會直接回調權限被拒絕。即 requestPermissions
調用後不會再彈出系統提示框,只能引導用戶去應用設置界面進行受權。 這時候能夠經過 shouldShowRequestPermissionRationale
方法進行判斷。
該方法的本意是,當權限被拒絕後,你能夠提示用戶爲何須要獲取該權限。有下面幾種場景:
- 沒有申請權限時,返回false
- 申請權限,可是被拒絕了,返回true
- 申請權限,可是被用戶禁止了,或者勾選了再也不詢問,返回false
- 申請權限,用戶容許了,返回false
主要流程以下:
onRequestPermissionsResult
權限申請回調後,判斷權限是否被用戶禁止。@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) {
//用戶已受權
} else {
//判斷用戶是否勾選了再也不詢問
if (VERSION.SDK_INT >= VERSION_CODES.M && !shouldShowRequestPermissionRationale(
permission.WRITE_EXTERNAL_STORAGE)) {
//跳轉到應用設置界面受權
goToSetting();
}
}
}
}
}
/** * 跳轉應用設置界面進行受權 */
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) {
//從設置界面回來,是不知道用戶是否有受權的,因此須要從新再判斷
List<String> needRequestList = checkPermission(this, PERMISSION_LIST);
if (needRequestList.isEmpty()) {
//已受權
}
}
}
複製代碼