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

时间:2017-03-26 14:37:08

标签: android dex smali

我正在使用dexlib2来重写dex文件。我需要用我的库类名替换特定的类名,我将包含在aar中。我正在使用下面的代码:

    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);

但是有了这个,它将在所有其他库中替换此类,这将导致问题。我希望它只有在具有某些包的类中才能被替换。我可以在上面添加那种过滤器吗?

1 个答案:

答案 0 :(得分:1)

是。您可以覆盖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;
            }
        };
    }
});