Android动态权限申请
從Android 6.0開始,權限不再是在manifest文件中粘貼一下即可,這時候權限也正式走進大家的視野。項目的6.0適配就是我做的,當時沒有仔細總結,最近在另一個項目添加權限的時候發現,同一個功能都沒有添加申請權限的代碼,一個會掛一個不會,花了幾個小時在這個小問題上。因此多花點時間總結一下權限問題。
Android是一個權限分隔的操作系統,每個應用都有獨特的系統標識。一般情況下,應用沒有權限執行對其它應用、系統、用戶可能有不利影響的操作。每個應用都在應用沙盒中運行,因此當應用需要使用沙盒未提供的功能時,需要申請權限,比如讀寫sd卡、訪問網絡、訪問其它應用的數據、讀寫聯系人、調用攝像頭等。
權限在AndroidManifest.xml文件中聲明,Android 6.0以前,有的APP一股腦聲明了各種各樣的權限,用戶可能沒有細看就安裝了,于是這些APP就可以為所欲為,偷雞摸狗,無法無天。Android 6.0把權限分成正常權限和危險權限,AndroidManifest中聲明的正常權限系統會自動授予,而危險權限則需要在使用的時候用戶明確授予。
換句話說,就是Android 6.0以上的系統在第一次使用危險權限的時候,需要向用戶申請,征得用戶的同意。如果還是在沒有權限的情況下執行操作,就會獲得Crash大禮包,錯誤日志為java.lang.SecurityException: Permission Denial。因此,應用對危險權限的申請,需要相應的處理。
危險權限都屬于權限組,應用在向用戶申請危險權限時,系統會彈對話框,描述應用要訪問的權限組,這時候用戶如果同意授權,則權限組包含的所有權限都會被系統授予。比如,應用被授予READ_EXTERNAL_STORAGE權限之后,如果再申請WRITE_EXTERNAL_STORAGE權限,系統會立即授予該權限。
危險權限表格如下
| CALENDAR | READ_CALENDAR WRITE_CALENDAR |
| CAMERA | CAMERA |
| CONTACTS | READ_CONTACTS WRITE_CONTACTS GET_ACCOUNTS |
| LOCATION | ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION |
| MICROPHONE | RECORD_AUDIO |
| PHONE | READ_PHONE_STATE CALL_PHONE READ_CALL_LOG WRITE_CALL_LOG ADD_VOICEMAIL USE_SIP PROCESS_OUTGOING_CALLS |
| SENSORS | BODY_SENSORS |
| SMS | SEND_SMS RECEIVE_SMS READ_SMS RECEIVE_WAP_PUSH RECEIVE_MMS |
| STORAGE | READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE |
3. 申請權限的正確姿勢?
* 需要申請的所有權限在AndroidManifest文件中聲明
- 使用時檢查權限,沒有權限則申請 //使用兼容庫就無需判斷系統版本int hasWriteStoragePermission = ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.WRITE_EXTERNAL_STORAGE);if (hasWriteStoragePermission == PackageManager.PERMISSION_GRANTED) {//擁有權限,執行操作 initScan();}else{//沒有權限,向用戶請求權限ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MyApplication.CODE_FOR_WRITE_PERMISSION);}
- 覆寫onRequestPermissionsResult方法 @Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {//通過requestCode來識別是否同一個請求if (requestCode == CODE_FOR_WRITE_PERMISSION){if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){//用戶同意,執行操作
initScan();}else{//用戶不同意,向用戶展示該權限作用if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {new AlertDialog.Builder(thisActivity).setMessage(R.string.storage_permissions_remind).setPositiveButton("OK", (dialog1, which) ->ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},EventConstConfig.CODE_FOR_CAMERA_PERMISSION)).setNegativeButton("Cancel", null).create().show();}}}}
shouldShowRequestPermissionRationale方法返回值分幾種情況,怎么使用看應用的具體交互需求。?
1. 第一次請求該權限,返回false。?
2. 請求過該權限并被用戶拒絕,返回true。?
3. 請求過該權限,但用戶拒絕的時候勾選不再提醒,返回false。 -
申請權限的幾個小細節
-
使用兼容庫?
checkSelfPermission、requestPermissions等幾個權限相關的方法用v4包里的可以兼容6.0以下版本,否則需要包一層版本判斷。 -
targetSDKVersion的問題?
我遇到的問題就是這個,有個細節沒注意到。Android系統觸發動態申請權限的條件其實有兩個,設備系統版本在Android 6.0以上并且targetSDKVersion>=23。因此其實在targetSDKVersion版本小于23的情況下,即使在6.0以上的設備運行也不會掛,但會在安裝時列出所有權限,同6.0以下的設備。官方建議保持targetSDKVersion在最新的版本。
-
-
使用第三方庫easypermissions?
申請權限的第三方庫有很多,但沒遇到特別簡潔的,也就沒有特地去研究和使用,避免導入太多第三方庫,easypermissions這個庫是其中一個項目用到的,這里簡單的提一下。- 導入easypermissions
compile 'pub.devrel:easypermissions:0.1.9' - 檢查權限,沒有就進行申請 if (!EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA)) {EasyPermissions.requestPermissions(this, getString(R.string.camera_peemission_tip), CAMERA_REQUEST_CODE, Manifest.permission.CAMERA);}
- 覆寫方法 @Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);// Forward results to EasyPermissionsEasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);}@Overridepublic void onPermissionsGranted(int requestCode, List<String> perms) {
// light();
}@Overridepublic void onPermissionsDenied(int requestCode, List<String> perms) {Dialog dialog = new AlertDialog.Builder(this, R.style.MyAlertDialogStyle).setTitle(R.string.tips).setMessage(R.string.camera_peemission_tip).setPositiveButton(R.string.to_open, (dialog2, which) -> {startActivity(new Intent(Settings.ACTION_APPLICATION_SETTINGS));}).setNegativeButton(R.string.cancel, (dialog3, which) -> {dialog3.dismiss();}).create();dialog.show();}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 轉自:http://blog.csdn.net/forevercbb/article/details/79131740?
轉載于:https://www.cnblogs.com/weiqiangwaideshijie/p/9438390.html
總結
以上是生活随笔為你收集整理的Android动态权限申请的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 以太坊solidity编程常见错误(不定
- 下一篇: android sina oauth2.