之前一直没注意,今天有同学跟我说在oppo n1手机上获取apk安装包时会崩溃,看到的崩溃信息是
java.lang.NullPointerException
at android.app.ActivityThread$ResourcesKey.<init>(ActivityThread.java:2200)
at android.app.ActivityThread.getTopLevelResources(ActivityThread.java:187)
at android.app.ActivityThread.getTopLevelResources(ActivityThread.java:246)
at android.app.ContextImpl$ApplicationPackageManager.getResourcesForApplication(ContextImpl.java:2188)
at android.app.ContextImpl$ApplicationPackageManager.getDrawable(ContextImpl.java:2114)
at android.content.pm.PackageItemInfo.loadIcon(PackageItemInfo.java:131)
at android.app.ContextImpl$ApplicationPackageManager.getApplicationIcon(ContextImpl.java:2169)
at com.metago.astro.IconManager.loadPackageIcon(IconManager.java:330)
从异常信息可以看出是在ResourcesKey的构造时崩溃的。找到4.2的该类定义
ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale) {
1516 mResDir = resDir;
1517 mDisplayId = displayId;
1518 if (overrideConfiguration != null) {
1519 if (Configuration.EMPTY.equals(overrideConfiguration)) {
1520 overrideConfiguration = null;
1521 }
1522 }
1523 mOverrideConfiguration = overrideConfiguration;
1524 mScale = scale;
1525 int hash = 17;
1526 hash = 31 * hash + mResDir.hashCode();
1527 hash = 31 * hash + mDisplayId;
1528 hash = 31 * hash + (mOverrideConfiguration != null
1529 ? mOverrideConfiguration.hashCode() : 0);
1530 hash = 31 * hash + Float.floatToIntBits(mScale);
1531 mHash = hash;
可以看到类在构造时没有对resDir进行校验,在第1526行引用时就可能报空指针问题
而我一直使用的note3并未出现此问题,于是再看到4.4上这个类的定义
31 public More ...ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration,
32 float scale, IBinder token) {
33 mResDir = resDir;
34 mDisplayId = displayId;
35 if (overrideConfiguration != null) {
36 mOverrideConfiguration.setTo(overrideConfiguration);
37 }
38 mScale = scale;
39 mToken = token;
40
41 int hash = 17;
42 hash = 31 * hash + (mResDir == null ? 0 : mResDir.hashCode());
43 hash = 31 * hash + mDisplayId;
44 hash = 31 * hash + (mOverrideConfiguration != null
45 ? mOverrideConfiguration.hashCode() : 0);
46 hash = 31 * hash + Float.floatToIntBits(mScale);
47 mHash = hash;
48 }
看到4.4中的42行在引用时进行了判空,所以并没有崩溃。这种情况下获取到的icon都是默认的,也就是安卓那个小绿机器人。
解决这个问题的办法是在获取了apk安装包的applicationInfo后,
applicationInfo.sourceDir = "apkpath";
applicationInfo.publicSourceDir = "apkpath";
把这apk的路径赋予这两个值任意之一就行,因为从activityThread.java可以看到,resDir取的就是sourceDir和publicSourceDir之一。