具有代码模糊的多模块库



我有一套库,作为3个独立的aar分发。是否有任何方法能够独立地混淆每个库,但保持在内部调用模块之间方法的能力?

例如,如果libA需要从libB调用myMethod,但我不希望myMethod暴露给集成我的库的客户端(但所有库都必须模糊(。

现在,我不得不将myMethod公开,并将其从模糊处理中排除,以便可以从libA调用它对于这个问题,有没有更好的解决方案,既不会向客户端公开myMethod,又不会混淆

我不确定你是否已经找到了问题的解决方案,但我已经玩了一点,找到了一个有效的解决方案。我制作了一个小型HelloWorld应用程序来展示它是如何做到的:https://github.com/jmineraud/multi-module-android-app.

它包含作为git子模块的lib的repo(https://github.com/jmineraud/multi-module-android-lib)

诀窍是独立地混淆库,但不优化它们(我们不想删除任何函数(,并且所有依赖的子模块都必须重用相同的mapping.txt文件。

在我的子模块proguard文件中,我添加了:

-dontshrink
-dontoptimize
#-useuniqueclassmembernames # Option does not work with R8
-repackageclasses "com.your.package"  # I do not want to obfuscate the whole hierarchy to keep my obfuscated library class separate and avoid obfuscation problems when the lib is used in the app project (which will be in turn obfuscated)
-applymapping "../lib-core/build/outputs/mapping/release/mapping.txt"

我想保留的类用androidx.annotation.Keep中的@Keep进行了注释

库只公开接口而不公开对象是一种最佳做法。此外,接口必须遵守接口分离原则。如果你的客户端不需要使用该方法,那么你的库也需要。您的libA是您的LibB的第一个客户。你们的图书馆必须遵守单一责任原则。我认为您必须重新处理库,为类提取接口,并且只公开接口。

我认为这将是一项小任务,一个快速的解决方案是为每个受保护的方法添加proguard规则,如果您使用的是java。

-keep public class mypackage.MyPublicClass {
protected void myProtectedMethod();
}

重构示例:

//libA
class LibA {
lateinit var libB:LibB
fun serviceA(){
libB.checkLicence()
}
}
//libB
class LibB{
fun serviceB(){}
//this method is needed by libA, due to obfuscation visibility is public instead of internal
//internal fun checkLicence(){}
fun checkLicence(){}
}

重构后的代码可能是:

//new library distributed only internally not to customer 
// LibInternal
interface InternalLib {
fun checkLicence()
}
internal class InternalLibImpl : InternalLib {
override fun checkLicence() {
}
}
object InternalLibFactory {
fun create(): InternalLib = InternalLibImpl()
}
//LibB
interface LibB {
fun serviceB()
}
class LibBImpl(private val internalLib: InternalLib) : LibB {
override fun serviceB() {
internalLib.checkLicence()
}
}
object LibBFactory {
fun create(): LibB = LibBImpl(InternalLibFactory.create())
}
//LibA
interface LibA {
fun serviceA()
}
internal class LibAImpl(private val libB: LibB, private val internalLib: InternalLib) {
fun serviceA() {
internalLib.checkLicence()
libB.serviceB()
}
}
object LibAFactory {
fun create(): LibB = LibBImpl(InternalLibFactory.create())
}

最新更新