解决SharedUserId导致的SecurityException

解决SharedUserId导致的SecurityException

收到一个谷歌报的异常:

java.lang.SecurityException: Package com.xxx.xxx does not belong to 10326
    at android.os.Parcel.createExceptionOrNull(Parcel.java:2373)
    at android.os.Parcel.createException(Parcel.java:2357)
    at android.os.Parcel.readException(Parcel.java:2340)
    at android.os.Parcel.readException(Parcel.java:2282)
    at android.app.INotificationManager$Stub$Proxy.enqueueNotificationWithTag(INotificationManager.java:3207)
    at android.app.NotificationManager.notifyAsUser(NotificationManager.java:581)
    at android.app.NotificationManager.notify(NotificationManager.java:531)
    at android.app.NotificationManager.notify(NotificationManager.java:507)
    at com.termux.app.utils.CrashUtils.sendCrashReportNotification(CrashUtils.java:148)
    at com.termux.app.utils.CrashUtils$1.run(CrashUtils.java:90)
Caused by: android.os.RemoteException: Remote stack trace:
    at android.app.AppOpsManager.checkPackage(AppOpsManager.java:7739)
    at com.android.server.notification.NotificationManagerService.isCallerInstantApp(NotificationManagerService.java:8752)
    at com.android.server.notification.NotificationManagerService.checkDisqualifyingFeatures(NotificationManagerService.java:6131)
    at com.android.server.notification.NotificationManagerService.enqueueNotificationInternal(NotificationManagerService.java:5896)
    at com.android.server.notification.NotificationManagerService.enqueueNotificationInternal(NotificationManagerService.java:5770)

是在显示notification的时候报错的。看意思是当前的包不属于当前的packageId,就很有意思。
因为我们是在原来的包的基础上搞了一个马甲包出来,而我们原来的包使用了SharedUserId,这个玩意儿就很坑,当初不知道为什么引进来的。
关于SharedUserId
具Android developer官网的说法,这玩意会导致不确定性的行为,强烈建议不要使用它。

来追一下这个原因,按照调用栈来看,这种没有头绪的报错可以直接去找报错位置,然后反推出来
Package com.xxx.xxx does not belong to 10326这个在AppOpsManager.checkPackage,调用者是NotificationManagerService#isCallerInstantApp(),我们在这里能发现一丝端倪:

    boolean isCallerInstantApp(int callingUid, int userId) {
...

        try {
            final String[] pkgs = mPackageManager.getPackagesForUid(callingUid);
            if (pkgs == null) {
                throw new SecurityException("Unknown uid " + callingUid);
            }
            final String pkg = pkgs[0];
            mAppOps.checkPackage(callingUid, pkg);

            ApplicationInfo ai = mPackageManager.getApplicationInfo(pkg, 0, userId);
            if (ai == null) {
                throw new SecurityException("Unknown package " + pkg);
            }
            return ai.isInstantApp();
        } catch (RemoteException re) {
            throw new SecurityException("Unknown uid " + callingUid, re);
        }
    }

这里使用了getPackagesForUid返回的package[]数组的第0个package,比较这两个是否相同,如果mAppOps.checkPackage(callingUid, pkg)传入的这两个参数不匹配的话就直接报错。

所以原因可能是mPackageManager.getPackagesForUid(callingUid)返回的包名有多个并且第1个不是自己的包名
所以尝试自己获取比较,如果第0个返回的不是自己的包名,而是其他的包名的话则不去显示Notification。

    /**
     * 使用了getPackagesForUid返回的package[]数组的第0个package,比较这两个是否相同,所以尝试自己获取比较,
     * 如果第0个返回的不是com.mxtech.videoplayer.online,而是com.mxtech.videoplayer.ad则不显示Notification
     *
     * @return 是否需要显示Notification
     */
    private static boolean checkDefaultPackage(final Context context) {
        String pkgName = context.getPackageName();
        PackageManager packageManager = context.getPackageManager();
        try {
            ApplicationInfo ai = packageManager.getApplicationInfo(pkgName, PackageManager.GET_META_DATA);
            String[] packages = packageManager.getPackagesForUid(ai.uid);
            return pkgName.equals(packages[0]);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        return true;
    }

你可能感兴趣的:(解决SharedUserId导致的SecurityException)