解决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;
}
网友评论