仅使用 dexlib2 重写特定包中的 Methodreference

Rewrite Methodreference in particular package only using dexlib2

我正在使用 dexlib2 重写 dex 文件。我需要用我将包含在 aar 中的库 class 名称替换特定的 class 名称。我为此使用以下代码:

    DexFile dexFile = DexFileFactory.loadDexFile(filePath, Opcodes.forApi(apiLevel));
        DexRewriter dexRewriter = new DexRewriter(new RewriterModule() {

            @Override
            public Rewriter<MethodReference> getMethodReferenceRewriter(Rewriters rewriters) {
                return new Rewriter<MethodReference>() {
                    @Override
                    public MethodReference rewrite(MethodReference value) {

                        if (value.getDefiningClass().equals("Ljava/util/Calendar;")
                                && value.getName().equals("getInstance")) {
                            System.out.println("method Ref class:" + value.getDefiningClass());

                            ImmutableMethodReference methodRef = new ImmutableMethodReference(
                                    "Lcom/mylib/ICalendar;", value.getName(),
                                    value.getParameterTypes(), value.getReturnType());
                            return methodRef;
                        }
                        return value;
                    }
                };
            }

        });
        DexFile rewrittenDexFile = dexRewriter.rewriteDexFile(dexFile);
        DexFileFactory.writeDexFile(filePath, rewrittenDexFile);

但是有了这个,它会在所有其他库中替换这个 class,这也会导致问题。我希望它只有在 classes 中包含某些软件包时才被替换。我可以在上面添加那种过滤器吗?

是的。您可以覆盖 getClassDefRewriter 并在那里添加您的过滤器。

DexRewriter dexRewriter = new DexRewriter(new RewriterModule() {

    @Nonnull @Override public Rewriter<ClassDef> getClassDefRewriter(@Nonnull Rewriters rewriters) {
        return new ClassDefRewriter(rewriters) {
            @Nonnull @Override public ClassDef rewrite(@Nonnull ClassDef classDef) {
                if (classDef.getType().startsWith("Lcom/my/package/")) {
                    return super.rewrite(classDef);
                }
                return classDef;
            }
        };
    }

    @Override
    public Rewriter<MethodReference> getMethodReferenceRewriter(Rewriters rewriters) {
        return new Rewriter<MethodReference>() {
            @Override
            public MethodReference rewrite(MethodReference value) {

                if (value.getDefiningClass().equals("Ljava/util/Calendar;")
                        && value.getName().equals("getInstance")) {
                    System.out.println("method Ref class:" + value.getDefiningClass());

                    ImmutableMethodReference methodRef = new ImmutableMethodReference(
                            "Lcom/mylib/ICalendar;", value.getName(),
                            value.getParameterTypes(), value.getReturnType());
                    return methodRef;
                }
                return value;
            }
        };
    }
});