Android 6.0 權(quán)限機(jī)制等新特性

1、電源管理

App Standby(應(yīng)用待機(jī))

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

Doze

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

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

  • 全稱為 應(yīng)用程序鏈接
  • 技術(shù)點(diǎn): 就是隱式啟動(dòng)Intent
  • android更加鼓勵(lì)應(yīng)用程序間的關(guān)聯(lián)而不再是單一的應(yīng)用同瀏覽器的交互

指紋識(shí)別

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

3、應(yīng)用程序權(quán)限管理

權(quán)限機(jī)制

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

運(yùn)行時(shí)權(quán)限的優(yōu)勢(shì)

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

運(yùn)行時(shí)權(quán)限的分類

  • Normal Premission

一些不涉及隱私的權(quán)限,不需要單獨(dú)去申請(qǐng),只需要在manifest申請(qǐng)就可以

  • Dangerous Permission & Dangerous Premission Group

涉及隱私的權(quán)限,會(huì)在運(yùn)行時(shí)向用戶申請(qǐng)。并且會(huì)分單獨(dú)的權(quán)限和權(quán)限組的形式。例如:讀sd卡和寫(xiě)sd卡可以合并成操作sd卡的組形式的權(quán)限組

權(quán)限組的概念

  • 如果你申請(qǐng)某個(gè)危險(xiǎn)的權(quán)限,假設(shè)你的app早已被用戶授權(quán)了同一個(gè)組的某個(gè)危險(xiǎn)權(quán)限,那么系統(tǒng)會(huì)立即授權(quán),而不需要用戶去點(diǎn)擊授權(quán)

新權(quán)限使用實(shí)例

新增API

  • ContextCompact.checkSelfPermission()

    檢測(cè)app是否擁有此權(quán)限

  • ActivityCompat.requestPermissions()

    申請(qǐng)某個(gè)權(quán)限

  • onRequestPermissionsResult()

    申請(qǐng)權(quán)限的回調(diào),處理申請(qǐng)權(quán)限成功失敗

  • ActivityCompat.shouldShowRequestPermissionRationale

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

使用流程

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

  • 檢查權(quán)限

      shell命令:
      adb shell pm list permissions -d -g
    
  • 申請(qǐng)授權(quán)

  • 處理申請(qǐng)回調(diào)

代碼實(shí)戰(zhàn)

  • 運(yùn)用上述流程實(shí)現(xiàn)一個(gè)撥打電話的權(quán)限請(qǐng)求過(guò)程

    1、先在AndroidManifest.xml中注冊(cè)權(quán)限

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

    2、在MainActivity中檢查權(quán)限,如果有直接執(zhí)行撥打電話。如果沒(méi)有權(quán)限,請(qǐng)求權(quán)限

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

    3、處理onRequestPermissionsResult回調(diào)

      @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{
                      // 請(qǐng)求被拒絕,提示用戶
                      Snackbar.make(fabCall, "撥打電話權(quán)限被拒絕", Snackbar.LENGTH_SHORT).show();
                  }
                  break;
          }
      }
    
  • 當(dāng)前我們只添加了一個(gè)權(quán)限,代碼就很臃腫了,所以可以考慮封裝我們請(qǐng)求權(quán)限的代碼到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,實(shí)現(xiàn)在download目錄下新建一個(gè)文件

    判斷是否有權(quán)限。有,直接操作,沒(méi)有,請(qǐng)求權(quán)限。

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

    復(fù)寫(xiě)成功失敗方法

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

    這樣雖然沒(méi)有一個(gè)權(quán)限申請(qǐng)都需要復(fù)寫(xiě)一套成功失敗的回調(diào),但已經(jīng)簡(jiǎn)潔了很多,而且加上注釋邏輯也很清晰

  • 第三方庫(kù)實(shí)現(xiàn) 錄音權(quán)限申請(qǐng)

    也可以借用第三方的庫(kù)來(lái)實(shí)現(xiàn),這里采用的是一個(gè)注解庫(kù)

  • 使用方法

    加入引用

      compile 'com.lovedise:permissiongen:0.0.6'
    

    請(qǐng)求權(quán)限

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

    在onRequestPermissionsResult注冊(cè)該庫(kù)的方法。

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

    成功回調(diào)

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

    失敗回調(diào)

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

    最后,第三方庫(kù)雖然使用方便,但注解時(shí)反射會(huì)影響運(yùn)行時(shí)的速度。使用時(shí)需要考慮。

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;
}

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

然后你們最愛(ài)的源碼###

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容