【问题标题】:Rewrite Methodreference in particular package only using dexlib2仅使用 dexlib2 重写特定包中的方法引用
【发布时间】:2017-03-26 14:37:08
【问题描述】:

我正在使用 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);

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

【问题讨论】:

    标签: android dex smali


    【解决方案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;
                }
            };
        }
    });
    

    【讨论】:

    • 再次感谢您的快速回复!我已经用过了。更新 dex 文件后我遇到了问题。为了验证,我尝试使用 dex2jar 将其转换为 jar 并且在转换时出现错误(d2j fail translate: java.lang.RuntimeException: \r\n\tat com.googlecode.dex2jar.ir.ts.NewTransformer.transform (NewTransformer.java:134))
    • 不知道。听起来像是 dex2jar 的问题 :)
    • 我可以使用它。但是在使用 getTypeRewriter 替换一个类名后,我的 apk 崩溃了。说 NoSuchMethodError。基本上我已经创建了一个库,它被添加为 aar,它具有我已经更改类型的实际类。
    • 那么,它抛出错误的方法是否存在? :)
    • 我有一个类说 IDate,它扩展了日期,我用 IDate 替换了类型日期。当代码具有 simpleDateFormat.format(IDate); 时出现错误。我已经手动尝试过代码。允许,但在 dex 文件中使用时。它正在抛出错误。
    猜你喜欢
    • 1970-01-01
    • 2023-03-07
    • 2019-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多