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