java.lang.IllegalArgumentException: android.content.pm.PackageManager$NameNotFoundException

原因:

当插件化hook跳转Activity成功,还需要去检查activity信息是否存在。如果不处理就会报错。

10-25 19:32:30.867  8754  8754 E AndroidRuntime: Caused by: java.lang.IllegalArgumentException: android.content.pm.PackageManager$NameNotFoundException: ComponentInfo{me.linjw.plugindemo/me.linjw.plugindemo.HideActivity}
10-25 19:32:30.867  8754  8754 E AndroidRuntime:        at android.support.v4.app.NavUtils.getParentActivityName(NavUtils.java:285)
10-25 19:32:30.867  8754  8754 E AndroidRuntime:        at android.support.v7.app.AppCompatDelegateImplV9.onCreate(AppCompatDelegateImplV9.java:158)
10-25 19:32:30.867  8754  8754 E AndroidRuntime:        at android.support.v7.app.AppCompatDelegateImplV14.onCreate(AppCompatDelegateImplV14.java:58)
10-25 19:32:30.867  8754  8754 E AndroidRuntime:        at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:72)
10-25 19:32:30.867  8754  8754 E AndroidRuntime:        at com.cvte.tv.speech.TestActivity.onCreate(TestActivity.java:14)
10-25 19:32:30.867  8754  8754 E AndroidRuntime:        at android.app.Activity.performCreate(Activity.java:6664)
10-25 19:32:30.867  8754  8754 E AndroidRuntime:        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
10-25 19:32:30.867  8754  8754 E AndroidRuntime:        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)

分析:

context.getPackageManager();因为这个packageManager获取不到,因为它是插件,所以要伪造一个。

    public static String getParentActivityName(Activity sourceActivity) {
        try {
            return getParentActivityName(sourceActivity, sourceActivity.getComponentName());
        } catch (NameNotFoundException e) {
            // Component name of supplied activity does not exist...?
            throw new IllegalArgumentException(e);
        }
    }


  @Nullable
    public static String getParentActivityName(Context context, ComponentName componentName)
            throws NameNotFoundException {
        PackageManager pm = context.getPackageManager();
        ActivityInfo info = pm.getActivityInfo(componentName, PackageManager.GET_META_DATA);
        String parentActivity = IMPL.getParentActivityName(context, info);
        return parentActivity;
    }

class ContextImpl extends Context {
    ...
    @Override
    public PackageManager getPackageManager() {
        if (mPackageManager != null) {
            return mPackageManager;
        }

        IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }

        return null;
    }
    ...
}


public final class ActivityThread {
    ...
    static volatile IPackageManager sPackageManager;
    ...
    public static IPackageManager getPackageManager() {
        if (sPackageManager != null) {
            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
            return sPackageManager;
        }
        IBinder b = ServiceManager.getService("package");
        //Slog.v("PackageManager", "default service binder = " + b);
        sPackageManager = IPackageManager.Stub.asInterface(b);
        //Slog.v("PackageManager", "default service = " + sPackageManager);
        return sPackageManager;
    }
    ...
}

所以就从sPackageManager下手处理。

 private static void hookPackageManager() throws Exception {
 
        try {
            // 兼容AppCompatActivity报错问题
            Class<?> forName = Class.forName("android.app.ActivityThread");
            Field field = forName.getDeclaredField("sCurrentActivityThread");
            field.setAccessible(true);
            Object activityThread = field.get(null);
            Method getPackageManager = activityThread.getClass().getDeclaredMethod("getPackageManager");
            Object iPackageManager = getPackageManager.invoke(activityThread);

            Class<?> iPackageManagerIntercept = Class.forName("android.content.pm.IPackageManager");
            Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                    new Class<?>[]{iPackageManagerIntercept}, new MockClass3(iPackageManager));

            // 获取 sPackageManager 属性
            Field iPackageManagerField = activityThread.getClass().getDeclaredField("sPackageManager");
            iPackageManagerField.setAccessible(true);
            iPackageManagerField.set(activityThread, proxy);
        }catch (Exception e){
            Log.e(TAG,"onHookIPackageManager:"+e.toString());
        }
    }


public class MockClass3 implements InvocationHandler {
    private static final String TAG = "MockClass3";
    public Object iPackageManager;
    public MockClass3(Object iPackageManager) {
        this.iPackageManager = iPackageManager;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Log.e(TAG, "invoke: "+method.getName());
        if ("getActivityInfo".equals(method.getName())){
            for (int i=0;i<args.length;i++){
                if (args[i] instanceof ComponentName){
                    ComponentName componentName = new ComponentName(UPFApplication.getContext().getPackageName(),
                            StubActivity.class.getName());
                    args[i] = componentName;
                }
            }
        }
        return method.invoke(iPackageManager,args);
    }
}
发布了118 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chentaishan/article/details/105188703
今日推荐