在调试安卓系统或打包系统过程中我们经常遇到有些第三方应用需要安装就默认权限或者打包到系统也要默认权限,这样在安装应用或者第一次打开应用时不会弹出权限框,避免给用户使用不好的体验。安卓系统在设计时对用户隐私和系统安全方面设计得挺好,但是站在用户使用端来看有些弹框是没必要的,比如权限弹框或者crash/ANR弹框,这些弹框对用户使用一点都不友好,虽然保护了用户隐私并且能帮助调试问题,产品最后软件定版时是要考虑去掉这些不必要弹框的。那么权限弹框这个主要是第三方应用需要获取一些系统权限来实现功能,如果是系统应用获取系统权限非常方便没太多限制,第三方应用就需要通过弹框来确认获取,那怎样让第三方应用在安装或者打包到系统就默认授权不弹框呢?我在调试系统时主要遇到这几种情况:1,第三方应用安装时会弹权限框;2,第三方应用打包到系统后第一次打开时会弹权限框。下面我们分别讨论对这两种情况如何默认授权:
1,第三方应用安装时默认授权
第三方应用主要通过静态或动态两种方式获取系统权限,对于安卓10系统来说,主要通过packagesappsPermissionController和frameworksbaseservicescorejavacomandroidserverpmPackageManagerService.java来控制应用安装授权。我们现在packagesappsPermissionControllersrccomandroidpackageinstallerpermissionmodelAppPermissionGroup.java中添加如下函数,添加需要默认动态授权的应用白名单:
public boolean areRuntimePermissionsGranted2() {
if(mPackageInfo != null) {
String packageName = mPackageInfo.packageName;
if(packageName != null) {
if("com.android.launcher".equals(packageName)
|| "cn.kuwo.kwmusiccar".equals(packageName)
|| "com.ximalaya.ting.android.car".equals(packageName)
|| "com.txznet.adapter".equals(packageName)
|| "com.txznet.txz".equals(packageName)
|| "net.easyconn".equals(packageName)) {
return true;
}
}
}
return false;
}
然后在packagesappsPermissionControllersrccomandroidpackageinstallerpermissionuiGrantPermissionsActivity.java中的addRequestedPermissions函数switch (getPermissionPolicy())处添加如下调用:
default: {
if (group.areRuntimePermissionsGranted()||group.areRuntimePermissionsGranted2()) {//kaicer add areRuntimePermissionsGranted2 20200225
group.grantRuntimePermissions(false, new String[]{permName});
state.mState = GroupState.STATE_ALLOWED;
skipGroup = true;
reportRequestResult(permName,
PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_GRANTED);
}
} break;
这部分添加后如果第三方应用申请动态授权,那么在第一次打开应用时就不会再弹授权框。那还有些情况第三方应用没有申请动态权限,则可以在frameworksbaseservicescorejavacomandroidserverpmPackageManagerService.java的doHandleMessage中的POST_INSTALL消息处将grantPermissions直接改为true:
//kaicer modify true for third app permission 20200715
final boolean grantPermissions = true;//(args.installFlags
//& PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
这样直接安装第三方应用就能直接获取权限了。
2,第三方应用打包到系统默认授权
第三方应用打包到系统后如果没有默认授权会在第一次打开时弹权限框,那么我们在frameworksbaseservicescorejavacomandroidserverpmpermissionDefaultPermissionGrantPolicy.java添加授权白名单即可:
private void grantPermissionsToSysComponentsAndPrivApps(int userId) {
Log.i(TAG, "Granting permissions to platform components for user " userId);
List<PackageInfo> packages = mContext.getPackageManager().getInstalledPackagesAsUser(
DEFAULT_PACKAGE_INFO_QUERY_FLAGS, UserHandle.USER_SYSTEM);
for (PackageInfo pkg : packages) {
if (pkg == null) {
continue;
}
//kaicer add for permission 20210415
if(pkg.packageName.equals("cn.kuwo.kwmusiccar")
||pkg.packageName.startsWith("com.ximalaya.ting.android.car")
||pkg.packageName.equals("com.txznet.adapter")
||pkg.packageName.equals("com.txznet.txz")
||pkg.packageName.equals("net.easyconn")
)
grantRequestPermissionsForSystemPackage(userId, pkg);
if (!isSysComponentOrPersistentPlatformSignedPrivApp(pkg)
|| !doesPackageSupportRuntimePermissions(pkg)
|| ArrayUtils.isEmpty(pkg.requestedPermissions)) {
if(!pkg.packageName.startsWith("com.ximalaya.ting.android.car")
&&!pkg.packageName.equals("com.yscl.driver"))//kaicer add for permission 20210415
continue;
}
grantRuntimePermissionsForSystemPackage(userId, pkg);
}
}
这样即使没有签名的应用打包到系统也可以默认授权,但有的应用即使默认授权了也会弹权限框,那么我们在frameworksbaseservicescorejavacomandroidserverpmpermissionPermissionManagerService.java再加一下是否需要弹框白名单即可:
private boolean isPermissionsReviewRequired(@NonNull PackageParser.Package pkg,
@UserIdInt int userId) {
// Permission review applies only to apps not supporting the new permission model.
if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) {
return false;
}
//kaicer add for third app 20210415
if(pkg.packageName.equals("cn.kuwo.kwmusiccar")
||pkg.packageName.startsWith("com.ximalaya.ting.android.car")
||pkg.packageName.equals("com.txznet.adapter")
||pkg.packageName.equals("com.txznet.txz")
||pkg.packageName.equals("net.easyconn")
)
return false;
// Legacy apps have the permission and get user consent on launch.
if (pkg.mExtras == null) {
return false;
}
final PackageSetting ps = (PackageSetting) pkg.mExtras;
final PermissionsState permissionsState = ps.getPermissionsState();
return permissionsState.isPermissionReviewRequired(userId);
}
按照上面方法添加后我们打包到系统的第三方应用就不用再担心弹权限框了。