如何模糊我用kotlin编码的sdk(并摆脱元数据)

时间:2017-09-14 12:58:15

标签: android kotlin metadata proguard

我正在开发SDK(Android库),我必须对我的大部分代码进行模糊处理,以便客户不会尝试使用内部代码。 我的lib用kotlin编码,我使用proguard来混淆代码。问题是在编译和混淆之后代码中仍然存在@ kotlin.Metadata(运行时)注释。通过这些注释,可以很容易地检索出源于这个"(不是那样)混淆的Java代码"字节码。

我首先认为这是我的错,我的项目有太多的熵源可能会导致这种行为,所以我做了一个示例项目来证明问题不是来自我的sdk实现。 我用AS创建了一个新项目,然后是一个包含2个文件的lib模块:

  • facade.kt是我的门面类,我不想混淆,所以客户可以使用它:

    package com.example.mylibrary
    
    class MyFacade(val internalClass:InternalClass) {
    
       fun doSomething() {
          internalClass.doSomething(
                 firstArgument=1,
                 secondArgument=2
          )
        }
     }
    
  • 在此示例中,internal.kt保存了我想要混淆的类:

    package com.example.mylibrary
    
    class InternalClass {
        fun doSomething(firstArgument: Int, secondArgument: Int) {
            System.out.println("Arguments are : $firstArgument, $secondArgument")
        }
    }
    

使用此版本闭包将proguard规则注入gradle项目:

buildTypes {
    release {
        minifyEnabled true
        proguardFiles 'proguard-rules.pro'
    }
}

这里是proguard-rules.pro(只有一行,仅此而已):

-keep class com.example.mylibrary.MyFacade {*;}

结果:当我./gradlew clean myLib:assembleRelease时,我确实获得了一个保留我的立面的aar,并且我的内部课程已经用一种方法重命名为' a' a',除了该类仍然使用kotlin @Metadata注释,它保存有助于反编译器检索原始类名,方法,属性和参数名称等的所有信息...... 所以我的代码根本没有被混淆......

@Metadata(
   mv = {1, 1, 7},
   bv = {1, 0, 2},
   k = 1,
   d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\b\n\u0002\b\u0002\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u0016\u0010\u0003\u001a\u00020\u00042\u0006\u0010\u0005\u001a\u00020\u00062\u0006\u0010\u0007\u001a\u00020\u0006¨\u0006\b"},
   d2 = {"Lcom/example/mylibrary/InternalClass;", "", "()V", "doSomething", "", "firstArgument", "", "secondArgument", "mylibrary_release"}
)
public final class a {
    ...
}

所以我的问题是:是否有可能摆脱这些注释,我是唯一面临这个问题的人,还是我错过了什么?

2 个答案:

答案 0 :(得分:3)

如果您要创建供其他人使用的库项目,不要混淆和缩小项目,而是为您的用户提供消费者ProGuard文件通过实施以下几行:

android {
    defaultConfig {
        consumerProguardFiles 'consumer-proguard-rules.pro'
    }
}

Source

在您随库提供的consumer-proguard-rules.pro中,您应该记得相应更新,但始终要记住至少要声明要保留的枚举和注释,否则请让消费者getDefaultProguardFile('proguard-android.txt')采取照顾其他人。

收缩也是如此 - 你应该只关心通过为它们实施keep rules来确保所有必需的(在运行时)资源保持

答案 1 :(得分:1)

最后,我找到了一种删除Kotlin元数据注释的方法。

要隐藏Kotlin元数据注释,您需要启用R8完整模式。

这是有关我的环境的信息。

  

环境

OS: macOS 10.15.1
Android Studio: 3.5.1
Gradle: 5.4.1
Android Gradle Tool: 3.5.2

您要做的就是像下面一样向gradle.properties添加属性

  

gradle.properties

android.enableR8.fullMode=true

这是我的Proguard规则

  

proguard-rules.pro

-dontwarn kotlin.**
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
    static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
}

仅供参考,R8完整模式仍在测试中,因此有时效果不佳。但是,对我来说,它目前可以完美运行。