本篇文章已授權微信公眾號 hongyangAndroid (鴻洋)獨家發布 Android6.0權限機制(一):介紹 Android6.0權限機制(二):封裝 Android6.0權限機制(三):6.0以前國產手機權限處理
為何google在6.0加入這個權限機制
android6.0之前其實也有權限機制,很簡單就是開發者在manifest.xml注冊,用戶安裝app時候,當做權限清單列出來告知用戶我需要這些個權限,但是這樣用戶基本不會去看,導致app權限濫用造成安全隱患。
權限分類
Android權限有100多種不可能每種都去運行時授權,因此google把權限分為兩類: 1.普通權限:例如網絡請求等,按照老的權限機制 2.危險權限:9種共24個(電話,短信,sd卡,位置,攝像頭,傳感器,日歷,錄音,聯系人),就是我們要動態申請的。 ? 用adb命令查看危險權限列表:(tip:記住9種24類)
adb shell pm list permissions -d -g
復制代碼
Dangerous Permissions:group:android.permission-group.CONTACTSpermission:android.permission.WRITE_CONTACTSpermission:android.permission.GET_ACCOUNTSpermission:android.permission.READ_CONTACTSgroup:android.permission-group.PHONEpermission:android.permission.READ_CALL_LOGpermission:android.permission.READ_PHONE_STATEpermission:android.permission.CALL_PHONEpermission:android.permission.WRITE_CALL_LOGpermission:android.permission.USE_SIPpermission:android.permission.PROCESS_OUTGOING_CALLSpermission:com.android.voicemail.permission.ADD_VOICEMAILgroup:android.permission-group.CALENDARpermission:android.permission.READ_CALENDARpermission:android.permission.WRITE_CALENDARgroup:android.permission-group.CAMERApermission:android.permission.CAMERAgroup:android.permission-group.SENSORSpermission:android.permission.BODY_SENSORSgroup:android.permission-group.LOCATIONpermission:android.permission.ACCESS_FINE_LOCATIONpermission:android.permission.ACCESS_COARSE_LOCATIONgroup:android.permission-group.STORAGEpermission:android.permission.READ_EXTERNAL_STORAGEpermission:android.permission.WRITE_EXTERNAL_STORAGEgroup:android.permission-group.MICROPHONEpermission:android.permission.RECORD_AUDIOgroup:android.permission-group.SMSpermission:android.permission.READ_SMSpermission:android.permission.RECEIVE_WAP_PUSHpermission:android.permission.RECEIVE_MMSpermission:android.permission.RECEIVE_SMSpermission:android.permission.SEND_SMSpermission:android.permission.READ_CELL_BROADCASTS
復制代碼
看到上面的dangerous permissions,會發現一個問題,好像危險權限都是一組一組的那么有個問題:分組對我們的權限機制有什么影響嗎?的確是有影響的,如果app運行在Android 6.x的機器上,對于授權機制是這樣的。如果你申請某個危險的權限,假設你的app早已被用戶授權了同一組的某個危險權限,那么系統會立即授權,而不需要用戶去點擊授權。比如你的app對READ_CONTACTS已經授權了,當你的app申請WRITE_CONTACTS時,系統會直接授權通過。此外,對于申請時彈出的dialog上面的文本說明也是對整個權限組的說明,而不是單個權限(ps:這個dialog是不能進行定制的)。不過需要注意的是,不要對權限組過多的依賴,盡可能對每個危險權限都進行正常流程的申請,因為在后期的版本中這個權限組可能會產生變化。
怎么兼容
1.假設我們的項目之前沒加這個權限機制,那現在我們怎么處理呢,要不要加這個權限判斷,這個取決與app的版本兼容性也就是你們是否愿意為Android6.0以上的用戶們處理這個問題。targetSdkVersion這個屬性就是控制是否要引入權限機制的開關。
- 項目中targetSdkVersion<23: 按照老的權限機制,只在manifest聲明就可以了,運行不會報錯,但是會有隱患: 比如,我的APP有個撥號功能,把targetSdkVersion=21,安裝到API23(Android6.0)的設備,可以正常撥號,看似正常。 但是用戶可以直接去設置里面關掉權限:
我在模擬器上有這個警告提示,但不保證所有手機都會有這個提示!這時再打開APP就無法撥號了,由于沒有檢查權限,用戶得不到任何提示,一臉懵逼。
- targetSdkVersion>=23: 這時就需要在代碼中檢查權限了,否則打開app去執行需要權限的操作會崩潰。如果關閉權限將會彈出提示框提示你開啟權限。
2.如果app原先的targetSdkVersion低于23,現在升級到targetSdkVersion=23的app,那么里面的權限默認全部開啟!除非用戶卸載重裝這個app,才是默認關閉所有權限
關于讀寫SD卡權限
在6.0之前由于讀寫SD沒有限制,導致sd卡目錄被app濫用,于是google把sd卡續寫權限列為危險權限,如果開發者不想申請sd卡讀寫權限,可以訪問0/Android/data/包名 這個目錄,不需要權限可以隨便訪問,Android也是建議開發者將這個目錄作為app的緩存目錄
使用
- 首先配置build.gradle,targetSdkVersion版本應該>=23,然后導入support-v4包:
apply plugin: 'com.android.application'android {compileSdkVersion 23buildToolsVersion "25.0.2"defaultConfig {applicationId "com.example.carmelo.myapplication"minSdkVersion 19targetSdkVersion 23versionCode 1versionName "1.0"}buildTypes {release {minifyEnabled false}}}
dependencies {compile fileTree(dir: 'libs', include: ['*.jar'])compile 'com.android.support:support-v4:23.2.1'
}
復制代碼
- manifest.xml聲明權限
<uses-permission android:name="android.permission.CALL_PHONE"/>
復制代碼
- 在Activity或者Fragment中判斷是否開啟了這個權限,如果開啟了就撥號,沒有的話就申請權限:
界面彈出框:拒絕或者同意,回調兩種結果:
[圖片上傳中。。。(2)]
public class MyActivity extends Activity {private Button btn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity);btn = (Button) findViewById(R.id.textView);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int check = ContextCompat.checkSelfPermission(MyActivity.this, Manifest.permission.CALL_PHONE);if(check== PackageManager.PERMISSION_GRANTED){call();}else {ActivityCompat.requestPermissions(MyActivity.this,new String[]{Manifest.permission.CALL_PHONE}, 1);}}});}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if(requestCode==1){if(grantResults[0]==PackageManager.PERMISSION_GRANTED){call();}else {Toast.makeText(MyActivity.this,"沒有撥打電話權限",Toast.LENGTH_SHORT).show();}}}private void call(){Intent intent = new Intent();intent.setData(Uri.parse("tel://1212121212"));intent.setAction(Intent.ACTION_CALL);startActivity(intent);}
}
復制代碼
- 不再提示的處理: 如果用戶勾選了不再提示,并且拒絕了權限,那么后面不會再彈框,并且結果一直回調到沒有權限,此時根據產品需求處理,一般2種方法:
- 在回調中彈出Dialog跳到設置界面開啟權限
- 直接彈出提示:沒有權限(這種更好),因為用戶就是拒絕了權限,不要煩他了