1.给应用添加默认权限,不再弹出授权提示框
如有些应用打开后根本不需要弹出授权添加权限的提示框,而是已经拥有了Calendar、Contact等权限。
一般的做法是:在frameworks/base/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java文件grantDefaultSystemHandlerPermissions方法中添加:
String appPkgStr = "xxx.com.xxx"; //包名
PackageParser.Package appPkg = getPackageLPr(appPkgStr);
if(appPkg != null){
grantRuntimePermissionsLPw(appPkg, PHONE_PERMISSIONS, userId);
grantRuntimePermissionsLPw(appPkg, STORAGE_PERMISSIONS, userId);
grantRuntimePermissionsLPw(appPkg, LOCATION_PERMISSIONS, userId);
grantRuntimePermissionsLPw(appPkg, CONTACTS_PERMISSIONS, userId);
}
2.在应用中判断权限并申请权限
最近遇到一个比较奇怪的问题:Exchange一直提示没有READ_CALENDAR权限,导致Email登录Exchange账号后日历同步失败。但是看代码中已经做了以下权限的判断及申请:
public static void checkPermissionsForXXX(Activity activity, Intent fIntent) {
ArrayList<String> requestList = new ArrayList<>();
requestList.add(android.Manifest.permission.READ_CONTACTS);
requestList.add(android.Manifest.permission.READ_PHONE_STATE);
requestList.add(Manifest.permission.WRITE_CALENDAR);
try {
PackageInfo info = activity.getApplicationContext()
.getPackageManager()
.getPackageInfo("xxx.xxx.xxx", PackageManager.GET_PERMISSIONS); //通过包名获得PackageInfo信息
boolean needsPermission = false;
for (int i = 0; i < info.requestedPermissions.length; i++) {
String requestedPermission = info.requestedPermissions[i];
if (requestList.contains(requestedPermission)) {
int requestedPermissionsFlag = info.requestedPermissionsFlags[i];
boolean granted = (requestedPermissionsFlag & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
if (!granted) {
needsPermission = true;
break;
}
}
}
if (needsPermission) {
final Intent intent = new Intent("com.xxx.xxx.xxxxxx");//new 一个Intent,准备相应的Activity来进行权限申请
intent.putStringArrayListExtra(PermissionUtil.EXTRA_PERMISSIONS_EXCHANGE, requestList);
Intent fromIntent = activity.getIntent();
if (fromIntent != null) {
intent.putExtra(PermissionUtil.EXTRA_INTENT_EXCHANGE, fromIntent);
}
try {
activity.startActivityForResult(intent, PERMISSION_EXCHANGE);
} catch (ActivityNotFoundException e) {
LogUtils.e(LogUtils.TAG, "Activity not found for certificate request in incomming setting");
}
} else {
launchXxxActivity(activity, fIntent);
}
} catch (PackageManager.NameNotFoundException e) {
LogUtils.w(LogUtils.TAG, e, e.getMessage());
}
}
因为(1)权限这一块基本没有改动过,而以前释放的版本没有报出这个问题,最近的版本报出了这个问题后,所以一致认为应该不是应用本身问题。但是又重新安装了以前的版本,发现以前的版本也有同样的问题,这样就不能确定到底是哪里导致了问题。(2)因为一直以来说的关于危险权限的授权都是:
If any permission in a Permission Group is granted. Another permission in the same group will be automatically granted as well. In this case, once WRITE_CONTACTS is granted, application will also grant READ_CONTACTS and GET_ACCOUNTS.
所以默认的是已经申请了WRITE_CALENDAR,应该来说READ_CALENDAR应该也是有的,所以也就没有在这个权限判断及申请上多琢磨。
但是事实证明,确实是这里出现了问题:应用没有获得READ_CALENDAR权限。故,建议在应用中判断权限并申请权限时不管是否属于Permission Group,都还是判断及申请一遍啊~
修改后如下:
ArrayList<String> requestList = new ArrayList<>();
requestList.add(android.Manifest.permission.READ_CONTACTS);
//Fix email Contacts&Calendar sync issue
requestList.add(Manifest.permission.WRITE_CONTACTS);
requestList.add(Manifest.permission.GET_ACCOUNTS);
requestList.add(Manifest.permission.READ_CALENDAR);
//add end
requestList.add(android.Manifest.permission.READ_PHONE_STATE);
requestList.add(Manifest.permission.WRITE_CALENDAR);
另附一段上面提到的Intent来打开的相应的Activity来进行申请权限的代码:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.permission_block_activity);
List<String> permissions = getIntent().getStringArrayListExtra(PermissionUtil.EXTRA_PERMISSIONS_EXCHANGE);
if (permissions == null || permissions.isEmpty()){
this.finish();
return;
}
boolean isSkip = false;
List<String> requestList = new ArrayList<>();
for (String perm : permissions) {
if (PermissionChecker.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
requestList.add(perm);
isSkip = isSkip || ActivityCompat.shouldShowRequestPermissionRationale(this, perm);
}
}
if (!requestList.isEmpty()) {
//not entrance activity
if (savedInstanceState == null) {
final String[] permissons = requestList.toArray(new String[requestList.size()]);
ActivityCompat.requestPermissions(PermissionExchangeActivity.this, permissons, REQ_CODE_CHECK_PERMISSION);
}
} else {
finish();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(REQ_CODE_CHECK_PERMISSION == requestCode){
finish();
}
}