如果說5.0是android上的里程碑,那么6.0就是對它的完善與升級。6.0從UI上與5.0沒有任何區別,依舊堅持了好評的md風格,但不僅僅只是內核的升級而已。
6.0首先是刪除了apache的httpclient包,讓一些網絡請求框架需要對6.0進行適配,雖然有補救的方法,但官方刪除了,也讓okhttp更深入人心。然后就是今天我們重點討論的權限管理。
6.0以前的app安裝時,會默認授予清單文件manifest中的權限,雖然安裝時會告知用戶有哪些權限,但一般很少有人會在意這一點。于是各種居心叵測的廠家或者開發者往往都是列一堆的權限,做著用戶所不知道的事情。從6.0開始,情況就不一樣了,一些危險的權限我們不但在寫在manifest中,還需要用戶授予同意才能使用。可以說扼殺了一部分廠家的利益。
那么這些危險的權限有哪些呢?
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
permission:android.permission.CAMERA
permission:android.permission.BODY_SENSORS
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
permission:android.permission.RECORD_AUDIO
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
至于如何適配6.0之后的手機,主要有2種方式
1.app的build.gradle中 targetSdkVersion <23
這種方式簡單粗暴,安裝時依然會默認授予全部的權限,但是用戶可以在app的權限管理中關閉某些權限,可能導致app無法運行。
2.如果targetSdkVersion>=23則需要寫相應的適配代碼
public static boolean hasPermission(@NonNull Context context, @NonNull String... permissions) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
for (String permission : permissions) {
boolean hasPermission = (ContextCompat.checkSelfPermission(context, permission) == PackageManager
.PERMISSION_GRANTED);
if (!hasPermission) return false;
}
return true;
}
我們先判斷android版本,有沒有權限,然后若沒有權限就申請
public static void requestPermission(@NonNull Activity activity, int requestCode, @NonNull String... permissions) {
String [] ps=new String[permissions.length];
for (int i=0;i<permissions.length;i++){
ps[i]=permissions[i];
}
ActivityCompat.requestPermissions(activity, ps, requestCode);
}
然后就是權限授予的回調
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
//這里就可以處理了
}
如果用戶拒絕了授予,則可以使用如下方法給用戶解釋為什么需要該權限,返回true我們就彈出解釋對話框,
public static boolean shouldShowRationalePermissions(Object o, String... permissions) {
for (String permission : permissions) {
if (o instanceof Activity) {
return ActivityCompat.shouldShowRequestPermissionRationale((Activity) o, permission);
} else if (o instanceof android.support.v4.app.Fragment) {
return ((android.support.v4.app.Fragment) o).shouldShowRequestPermissionRationale(permission);
}
}
return false;
}
如果用戶不但拒絕,還點擊了不再提醒,就比較麻煩了,因為不會再有授權框了,我們只能檢測如果權限拒絕了,彈出提示框,要用戶到權限管理中心去開啟權限。
public static boolean hasAlwaysDeniedPermissio(Object o, @NonNull List<String>
deniedPermissions) {
for (String deniedPermission : deniedPermissions) {
if(!shouldShowRationalePermissions(o,deniedPermission))
return true;
}
return false;
}
以上就是處理6.0以上的權限問題,但不一定適配國產等機型,畢竟國內各大Rom修改源碼比較嚴重,有自家的權限管理,需要特殊處理。
目前github上開源的權限管理也有不少
- lovedise的PermissionGen
- PermissionGen的升級版 yanzhenjie的AndPermission
- hotchemi的PermissionsDispatcher,插件地址permissions-dispatcher-plugin
- k0shk0sh的PermissionHelper
- ParkSangGwon的TedPermission
- Google官方googlesamples的easypermissions
- anthonycrd的Grant
- 基于Rx的RxPermissions
- Karumi的Dexter
- 張鴻洋的MPermissions
各有優劣,不過對于國產手機,自帶權限管理可能需要自行適配了哦。