前言
谷歌在2015年8月份時候,釋出了Android 6.0版本,代號叫做“棉花糖”(Marshmallow ),其中的很大的一部分變化,是在使用者許可權授權上,或許是感覺之前預設授權的不合理,現在6.0出來,使得使用者許可權授權變得合理。這可能也是參考IOS系統的,只有在使用者需要使用許可權的時候,才去授權請求,這樣做的目的是提高使用者體驗,當然,使用者感覺好了,受苦的是我們開發人員,原來的規則不適用了,現在我們去適應新的規則,畢竟是靠谷歌這顆大樹吃飯的嘛。
原來許可權模型
在Android 6.0版本之前,許可權都是一條龍服務的,只要使用者安裝完,AndroidManifest清單上申請的許可權都會被系統預設授權,並且授權後也撤銷不了。這樣的弊端在哪裡呢?有些許可權可能使用者覺得不需要,比如他不想有通知的許可權,不想受到通知的干擾,那麼他就不能遮蔽通知,就是不需要的許可權,他去不掉,自主權不在他那邊。還有一些情況是,一些惡意程式,會利用這個許可權預設授權,進行惡意獲取使用者資料和攻擊。所以Android 6.0版本,一方面讓使用者更加容易的控制自己的隱私,一方面需要重新適配應用許可權。
Android 6.0許可權模型
採用新的許可權模型,只有在需要許可權的時候,才告知使用者是否授權,是在runtime時候授權,而不是在原來安裝的時候 ,同時預設情況下每次在執行時開啟頁面時候,需要先檢查是否有所需要的許可權申請。這樣的使用者的自主性提高很多,比如使用者可以給APP賦予攝像的許可權,但是可以拒絕記錄裝置位置的許可權,就是怕位置資訊上傳等等。
許可權流程
在API 23中,許可權滿足的標準流程:
但這裡有個問題,那就是在系統授權彈窗環節,提醒框會有個不再提示的核取方塊,如果使用者點選不太提示,並拒絕授權,那麼再下次授權的時候,系統授權彈窗的提示框就不會在提示,所以我們很有必要需要自定義許可權彈窗提示框,那麼流程圖就變成如下了。
許可權型別
ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_INSTALL_PACKAGES
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
SET_ALARM
INSTALL_SHORTCUT
UNINSTALL_SHORTCUT
Permission Group | Permissions |
---|---|
CALENDAR |
|
CAMERA |
|
CONTACTS |
|
LOCATION |
|
MICROPHONE |
|
PHONE |
|
SENSORS |
|
SMS |
|
STORAGE |
版本相容
// Assume thisActivity is the current activity int permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR);
// Here, thisActivity is the current activity if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { // Should we show an explanation? if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_CONTACTS)) { // Show an expanation to the user *asynchronously* -- don't block // this thread waiting for the user's response! After the user // sees the explanation, try again to request the permission. } else { // No explanation needed, we can request the permission. ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS); // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an // app-defined int constant. The callback method gets the // result of the request. } }
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! Do the // contacts-related task you need to do. } else { // permission denied, boo! Disable the // functionality that depends on this permission. } return; } // other 'case' lines to check for other // permissions this app might request } }
“android.permission.SYSTEM_ALERT_WINDOW”
“android.permission.WRITE_SETTINGS”這兩個許可權,實現方式跟上之前在工作中,碰到一種情況,如果是執行在6.0的版本上是需要走新的許可權模型,如果是執行在老的版本上,則需要進行一個判斷,此時碰到一個問題是,在谷歌官方推薦中,在判斷app執行的系統是否在Android M上時,它的判斷是如下: Build.VERSION.CODENAME.equals("MNC"); 可是在我實際適配中,發現這句卻無效的,就改用Build.VERSION.SDK_INT >= 23。的,需要另外特殊處理。
ACTION_MANAGE_OVERLAY_PERMISSION
.這樣一個動作,同時可以用Settings.canDrawOverlays() 方法進行判斷之前是否已經授權過了。
ACTION_MANAGE_WRITE_SETTINGS 這樣一個動作,同時可以用Settings.System.canWrite()
.
方法進行判斷之前是否已經授權過了。
具體程式碼:
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + getPackageName())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
注意點
之前在工作中,碰到一種情況,如果是執行在6.0的版本上是需要走新的許可權模型,如果是執行在老的版本上,則需要進行一個判斷,此時碰到一個問題是,在谷歌官方推薦中,在判斷app執行的系統是否在Android M上時,它的判斷是如下: Build.VERSION.CODENAME.equals("MNC"); 可是在我實際適配中,發現這句卻無效的,就改用Build.VERSION.SDK_INT >= 23。
總結
- 首先要知道6.0版本許可權模型跟原來版本是不同的,不再是統一在manifest中預設系統授權,而是有需要的時候,向系統請求授權,提高使用者體驗。
- 瞭解許可權檢測流程,一點注意點是如果系統許可權彈窗提示框被不再提醒了,需要我們自定義提示彈窗,引導使用者去授權。
- 明白許可權型別,分為normal和dangerous型別,同時,在dangerous中還需要注意一點,SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS這兩個特殊授權請求方式,跟一般授權請求方式不同。
- 在判斷APP是否執行在Android M上,可以用版本號來判斷,可以準確點。
參考