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