Android 權(quán)限申請

一、Android權(quán)限介紹

應(yīng)用權(quán)限有助于保護(hù)對以下數(shù)據(jù)的訪問和對以下操作的執(zhí)行,從而為保護(hù)用戶隱私提供支持:

  • 受限數(shù)據(jù),例如系統(tǒng)狀態(tài)和用戶的聯(lián)系信息。
  • 受限操作,例如連接到已配對的設(shè)備并錄制音頻。

1.1 權(quán)限分類

  • 安裝時權(quán)限
    系統(tǒng)會在應(yīng)用安裝時自動授予應(yīng)用相應(yīng)權(quán)限,包括普通權(quán)限和簽名權(quán)限。
  • 運(yùn)行時權(quán)限
    運(yùn)行時權(quán)限也稱為危險權(quán)限,Android 6.0 開始需要在應(yīng)用中執(zhí)行權(quán)限申請相關(guān)代碼,系統(tǒng)會彈出授權(quán)框提示框,需要用戶點(diǎn)擊才可以授權(quán)。
  • 特殊權(quán)限
    Android 6.0 開始需要用戶在應(yīng)用設(shè)置界面中才能開啟權(quán)限。

基本上每個版本,權(quán)限都會有一定的修改,而且系統(tǒng)對這方面的限制是越來越嚴(yán)格,所以正確的做法是請求最少數(shù)量的權(quán)限。

官網(wǎng)地址

二、權(quán)限申請

Android 6.0 版本開始,權(quán)限部分有了重大改變,所以下面以Android 6.0 為分界線,介紹如何申請權(quán)限。

2.1 Android 6.0 以下

不管是普通權(quán)限還是危險權(quán)限,只需在 AndroidManifest.xml 清單文件中進(jìn)行申明即可:

    <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)限需要特殊操作進(jìn)行申請。

  • 危險權(quán)限:
    不僅要在清單文件中申明權(quán)限,還需要代碼中動態(tài)申請權(quán)限,系統(tǒng)會彈出對應(yīng)的權(quán)限提示框,用戶點(diǎn)擊同意才可以授權(quán)。
  • 特殊權(quán)限
    不僅要在清單文件中申明權(quán)限,還需要在用戶在應(yīng)用設(shè)置界面進(jìn)行授權(quán)。

權(quán)限等級可以通過 官網(wǎng) 進(jìn)行查詢。

動態(tài)申請權(quán)限

主要分為以下幾個步驟:

  1. 判斷當(dāng)前是否有權(quán)限
      if (PackageManager.PERMISSION_GRANTED == ActivityCompat
          .checkSelfPermission(context, permission)) {
        //已授權(quán)
      } else {
        //未授權(quán)
      }
  1. 進(jìn)行權(quán)限申請
ActivityCompat.requestPermissions(activity, String[] permissions, REQUEST_CODE));
  1. 用戶授權(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)限申請1.png

如果用戶勾選“不再詢問”,同時點(diǎn)擊拒絕后,相當(dāng)于權(quán)限被禁止了。下次再申請權(quán)限,會直接回調(diào)權(quán)限被拒絕。即 requestPermissions 調(diào)用后不會再彈出系統(tǒng)提示框,只能引導(dǎo)用戶去應(yīng)用設(shè)置界面進(jìn)行授權(quán)。
這時候可以通過 shouldShowRequestPermissionRationale 方法進(jìn)行判斷。

該方法的本意是,當(dāng)權(quán)限被拒絕后,你可以提示用戶為什么需要獲取該權(quán)限。有下面幾種場景:

  1. 沒有申請權(quán)限時,返回false
  2. 申請權(quán)限,但是被拒絕了,返回true
  3. 申請權(quán)限,但是被用戶禁止了,或者勾選了不再詢問,返回false
  4. 申請權(quán)限,用戶允許了,返回false

主要流程如下:

  1. onRequestPermissionsResult 權(quán)限申請回調(diào)后,判斷權(quán)限是否被用戶禁止。
  2. 引導(dǎo)用戶跳轉(zhuǎn)到應(yīng)用設(shè)置界面授權(quán)。
  3. 由于授權(quán)后返回應(yīng)用并沒有任何提示,所以需要重新再判斷權(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)到應(yīng)用設(shè)置界面授權(quán)
              goToSetting();
            }
          }
      }
    }
  }
  /**
   * 跳轉(zhuǎn)應(yīng)用設(shè)置界面進(jì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) {
      //從設(shè)置界面回來,是不知道用戶是否有授權(quán)的,所以需要重新再判斷
      List<String> needRequestList = checkPermission(this, PERMISSION_LIST);
      if (needRequestList.isEmpty()) {
        //已授權(quán)
      }
    }

  }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容