標籤:create ssi 影響 提醒 一個 1.9 config pil 就會
從Android 6.0開始,許可權不再是在manifest檔案中粘貼一下即可,這時候許可權也正式走進大家的視野。項目的6.0適配就是我做的,當時沒有仔細總結,最近在另一個項目添加許可權的時候發現,同一個功能都沒有添加申請許可權的代碼,一個會掛一個不會,花了幾個小時在這個小問題上。因此多花點時間總結一下許可權問題。
- Android系統許可權的概念
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檔案中聲明
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- 使用時檢查許可權,沒有許可權則申請
//使用相容庫就無需判斷系統版本 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方法
@Override public 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這個庫是其中一個項目用到的,這裡簡單的提一下。
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); }
- 覆寫方法
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); // Forward results to EasyPermissions EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); } @Override public void onPermissionsGranted(int requestCode, List<String> perms) {// light(); } @Override public 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
Android動態許可權申請