为保护用户使用华为手机过程中,不受三方应用随意后台弹窗打扰。我们增加了“后台弹窗”权限,该权限关闭时应用在后台弹出界面的能力会受到限制,除非用户手动授予该权限给应用。后台弹窗权限开关默认为拒绝,拒绝时应用无法在后台时弹出界面。 如果您当前的业务有后台弹窗的场景,我们提供了两种适配方案,推荐您使用方案1: 1、推荐您将后台启动activity改为显示通知,参考适配方案: https://developer.android.com/guide/components/activities/background-starts?hl=zh-cn 实现横幅通知的适配方式: https://developer.android.com/training/notify-user/time-sensitive?hl=zh-cn 2、对于业务上必须具有在后台时弹出界面的应用,例如闹钟类、运动类、电话类等类型,您可以提醒用户去权限设置里手动开启后台弹窗权限开关
以上是后台弹窗权限的说明,现在想要分析如何判断后台弹窗权限是否开启
直接导出HwSystemManager.apk,jadx打开
直接搜类,permissionApp
逐个分析,先排除runtime、group相关,后台弹窗权限不是运行时权限,也不是组权限
permissionApp和permissionApps是抽象父类
所以只剩下SingleHwPermissionApps和HwPermissionApp
HwPermissionApp继承自PermissionApp
public abstract class PermissionApp {
public boolean HGa = false;
public final Context mContext;
public Drawable mIcon = null;
public final String mPackageName;
public final String mPermissionName;
public final long mPermissionType;
public List<String> nMa;
代表某个权限类型的单一应用
SingleHwPermissionApps继承自PermissionApps
public abstract class PermissionApps {
public final Context mContext;
public final String mName;
public final long mPermissionType;
public final ArrayList<PermissionApp> rMa = new ArrayList<>(10);
public final HashMap<String, PermissionApp> sMa = new HashMap<>(16);
代表某个权限类型的所有应用,所以SingleHwPermissionApps就是要找的
rMa代表拥有该权限的所有应用,直接在SingleHwPermissionApps中查找rMa的数据添加方法
可以看到两个很重要的boolean值传入到PermissionInfoWrapper中,并生成HwMonitoredPermission
在HwMonitoredPermission中看到granted的值就是xGa,也就是z2
boolean z2 = j != UpdateConfig.UPDATE_FLAG_KingUserPermision ? PermissionUtils.m20646b(j, aVar.mPermissionCode, aVar.mPermissionCfg) == 1 : PermissionUtils.m20636W(aVar.mPkgName, aVar.f12071Be) == 0;
z2的值是m20646b或者m20636W方法得到的值比对得到的
public static int m20636W(String str, int i) {
if (TextUtils.isEmpty(str)) {
C5994c.warn("PermissionUtils", "getPopupBackgroundWindowMode get invalid package name");
return 3;
}
AppOpsManager appOpsManager = (AppOpsManager) ImageShowMemoryUtil.sContext.getSystemService(AppOpsManager.class);
if (appOpsManager == null) {
C5994c.warn("PermissionUtils", "checkHwOp get null AppOpsManager");
return 3;
}
try {
Class<?> cls = Class.forName("com.huawei.android.app.AppOpsManagerEx");
return ((Integer) cls.getDeclaredMethod("checkHwOpNoThrow", AppOpsManager.class, Integer.TYPE, Integer.TYPE, String.class).invoke(cls, appOpsManager, Integer.valueOf((int) HwAlphaIndexResourceManager.f7172c), Integer.valueOf(i), str)).intValue();
} catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
outline.m11090a(e, outline.m11053Va("getPopupBackgroundOpMode failed"), "PermissionUtils");
return 3;
}
}
可以看到这个方法名就是getPopupBackgroundWindowMode,获取的就是后台弹窗权限的状态,修改代码后就能得到
public static boolean getHadPopWindowPermission(Context context){
try {
AppOpsManager appOpsManager = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
appOpsManager = context.getSystemService(AppOpsManager.class);
}
if (appOpsManager == null) {
return true;
}
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_META_DATA);
int uid = packageInfo.applicationInfo.uid;
Class<?> cls = Class.forName("com.huawei.android.app.AppOpsManagerEx");
Method checkHwOpNoThrow = cls.getDeclaredMethod("checkHwOpNoThrow", AppOpsManager.class, Integer.TYPE, Integer.TYPE, String.class);
int checkHwOpResult = (Integer) checkHwOpNoThrow.invoke(cls, appOpsManager,
100000, uid, context.getPackageName());
return checkHwOpResult == 0;
} catch (PackageManager.NameNotFoundException | ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
Log.d(TAG, "");
}
return true;
}