Android 6.0 權限機制等新特性

1、電源管理

App Standby(應用待機)

  • 檢測:當設備未充電,且在這段時間內用戶沒有直接或者間接的啟動該應用。
  • 退出:當應用激活時,或者設備充電時,系統(tǒng)將應用移除此狀態(tài)。

Doze

  • 檢測:當設備未充電,且當設備靜止或滅屏一段時間
  • 周期:平臺嘗試讓系統(tǒng)處于休眠狀態(tài),周期性地進入在一個維持窗口恢復正常操作,然后進入更長的休眠狀態(tài)
    (理解:如果用戶不操作手機,android先進入一個休眠狀態(tài),過段時間再檢測還是未操作,就進入下一級休眠狀態(tài),以此類推,知道進入最高級別的休眠狀態(tài),以達到省電)

2、App Link(非新,加強力度)

  • 全稱為 應用程序鏈接
  • 技術點: 就是隱式啟動Intent
  • android更加鼓勵應用程序間的關聯(lián)而不再是單一的應用同瀏覽器的交互

指紋識別

  • 6.0以前一直由各手機制造廠商去研發(fā),導致指紋識別不同的手機差異巨大
  • 6.0以后將由android系統(tǒng)提供api,硬件廠商只需提供相應的硬件支持即可

3、應用程序權限管理

權限機制

  • 5.0以前,只需要manifest.xml中注冊聲明即可
  • 5.0以后,用戶可以在安裝的時候關閉某些權限
  • 6.0及以后,對于一些用戶隱私權限總是會在第一次提示用戶是否授予權限(類似iPhone)

運行時權限的優(yōu)勢

  • 新的權限機制更好的保護了用戶的隱私
  • 給了程序向用戶說明權限的作用
  • 可以防止一些惡意程序盜取用戶或者手機信息,增強了android系統(tǒng)的安全性

運行時權限的分類

  • Normal Premission

一些不涉及隱私的權限,不需要單獨去申請,只需要在manifest申請就可以

  • Dangerous Permission & Dangerous Premission Group

涉及隱私的權限,會在運行時向用戶申請。并且會分單獨的權限和權限組的形式。例如:讀sd卡和寫sd卡可以合并成操作sd卡的組形式的權限組

權限組的概念

  • 如果你申請某個危險的權限,假設你的app早已被用戶授權了同一個組的某個危險權限,那么系統(tǒng)會立即授權,而不需要用戶去點擊授權

新權限使用實例

新增API

  • ContextCompact.checkSelfPermission()

    檢測app是否擁有此權限

  • ActivityCompat.requestPermissions()

    申請某個權限

  • onRequestPermissionsResult()

    申請權限的回調,處理申請權限成功失敗

  • ActivityCompat.shouldShowRequestPermissionRationale

    用于給用戶解釋申請改權限是用于做什么的。用戶拒絕我們的申請之后才會出現(xiàn)

使用流程

  • 在AndroidManifest中添加需要的權限(不可省)

  • 檢查權限

      shell命令:
      adb shell pm list permissions -d -g
    
  • 申請授權

  • 處理申請回調

代碼實戰(zhàn)

  • 運用上述流程實現(xiàn)一個撥打電話的權限請求過程

    1、先在AndroidManifest.xml中注冊權限

      <uses-permission android:name="android.permission.CALL_PHONE"/>
    

    2、在MainActivity中檢查權限,如果有直接執(zhí)行撥打電話。如果沒有權限,請求權限

      if(ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
              != PackageManager.PERMISSION_GRANTED){
          // 做權限申請?zhí)幚?      ActivityCompat.requestPermissions(this, 
              new String[]{Manifest.permission.CALL_PHONE}, Constants.CALL_PHONE);
      }else{
          // 已經(jīng)有改權限
          doCallPhone();// 撥打電話的具體實現(xiàn)
      }
    

    3、處理onRequestPermissionsResult回調

      @Override
      public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
          super.onRequestPermissionsResult(requestCode, permissions, grantResults);
          switch (requestCode){
              case Constants.CALL_PHONE:
                  if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
                      doCallPhone();
                  }else{
                      // 請求被拒絕,提示用戶
                      Snackbar.make(fabCall, "撥打電話權限被拒絕", Snackbar.LENGTH_SHORT).show();
                  }
                  break;
          }
      }
    
  • 當前我們只添加了一個權限,代碼就很臃腫了,所以可以考慮封裝我們請求權限的代碼到BaseActivity中。

    BaseActivity.java

      public class BaseActivity extends AppCompatActivity {
      
          public boolean hasPermission(String... permissions){
              for(String per : permissions){
                  if(ContextCompat.checkSelfPermission(this, per)
                          != PackageManager.PERMISSION_GRANTED){
                      return false;
                  }
              }
              return true;
          }
      
          public void requestPermission(int code, String... permissions){
              ActivityCompat.requestPermissions(this, permissions, code);
          }
      
          @Override
          public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
              super.onRequestPermissionsResult(requestCode, permissions, grantResults);
              switch(requestCode){
                  case Constants.WRITE_EXTERNAL_CODE:
                      if(isAllGranted(grantResults)){
                          onWriteExternalGranted();
                      }else{
                          onWriteExternalDenied();
                      }
                  break;
              }
          }
      
          private boolean isAllGranted(int[] grantResults) {
              for(int result : grantResults){
                  if(result != PackageManager.PERMISSION_GRANTED){
                      return false;
                  }
              }
              return true;
          }
      
          protected void onWriteExternalDenied() {}
      
          protected void onWriteExternalGranted(){};
      }
    
  • MainActivity 繼承 BaseActivity,實現(xiàn)在download目錄下新建一個文件

    判斷是否有權限。有,直接操作,沒有,請求權限。

      if(hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,
              Manifest.permission.READ_EXTERNAL_STORAGE)){
          doCreateFile(); // 新建文件具體實現(xiàn)
      }else{
          requestPermission(Constants.WRITE_EXTERNAL_CODE,
                  Manifest.permission.WRITE_EXTERNAL_STORAGE,
                  Manifest.permission.READ_EXTERNAL_STORAGE);
      }
    

    復寫成功失敗方法

      @Override
      protected void onWriteExternalDenied() {
          Snackbar.make(fabSD, "獲取文件權限失敗", Snackbar.LENGTH_SHORT).show();
      }
    
      @Override
      protected void onWriteExternalGranted() {
          doCreateFile();
      }
    

    這樣雖然沒有一個權限申請都需要復寫一套成功失敗的回調,但已經(jīng)簡潔了很多,而且加上注釋邏輯也很清晰

  • 第三方庫實現(xiàn) 錄音權限申請

    也可以借用第三方的庫來實現(xiàn),這里采用的是一個注解庫

  • 使用方法

    加入引用

      compile 'com.lovedise:permissiongen:0.0.6'
    

    請求權限

      PermissionGen.needPermission(this, Constants.RECORD_AUDIO,
              new String[]{
                      Manifest.permission.RECORD_AUDIO
              });
    

    在onRequestPermissionsResult注冊該庫的方法。

      @Override
      public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
          super.onRequestPermissionsResult(requestCode, permissions, grantResults);
          PermissionGen.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
      }
    

    成功回調

      @PermissionSuccess(requestCode = Constants.RECORD_AUDIO)
      public void doRecordSounds(){
          Snackbar.make(fabMic, "錄音中...", Snackbar.LENGTH_SHORT).show();
      }
    

    失敗回調

      @PermissionFail(requestCode = Constants.RECORD_AUDIO)
      public void onPremissionDenied(){
          Snackbar.make(fabMic, "沒有錄音權限", Snackbar.LENGTH_SHORT).show();
      }
    

    最后,第三方庫雖然使用方便,但注解時反射會影響運行時的速度。使用時需要考慮。

Constants.java

public class Constants {
    public static final int WRITE_EXTERNAL_CODE = 0x000;
    public static final int CALL_PHONE = 0x001;
    public static final int RECORD_AUDIO = 0x002;
}

本文總結自qandroid老師慕課網(wǎng)Android 6.0新特性課程。###

然后你們最愛的源碼###

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容