Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multiDexKeepProguard won't work if minSDK >= 21 #1084

Closed
noproxy opened this issue May 5, 2019 · 19 comments
Closed

multiDexKeepProguard won't work if minSDK >= 21 #1084

noproxy opened this issue May 5, 2019 · 19 comments

Comments

@noproxy
Copy link
Contributor

noproxy commented May 5, 2019

异常类型:编译异常
tinker版本:如:1.9.9
gradle版本:如:3.3.2
是否使用热更新SDK:无
系统:Mac

在min sdk >= 21 时,Android Gradle Plugin,会忽视一切指定分包规则的参数,比如multiDexKeepProguard。

Google应该是考虑到:sdk 21开始android原生支持多dex,指定分包规则没有必要,并影响编译速度,所以在代码中显式的对min sdk >= 21的时候屏蔽了分包规则。

目前Tinker仍然要求loader相关类必须在第一个dex中,请问:

Tinker在min sdk >=21的时候是否有必要强行要求loader相关类在第一个dex?

如果没有必要的话,Tinker的Gradle Plugin需要移除相关检查和报错,否则就只能设置ignoreWarnings = true才能编译通过。

如果有必要的话,需要寻找方案解决Android Gradle Plugin忽视分包规则的问题。

另外,在其他issue里面,很多loader classes are found in old secondary dex相关问题是由这个引起的。其中很多都没有引起重视,被直接closed+wontfix了。

如:
#859
#877
#938
#993
#1032

在这些issue里,@NickKJ 提到的通过CLI可以解决,是因为:
他本人项目min sdk < 21,而通过点击Android Studio的按钮执行时,Studio会注入init.gradle,对build type为debug的variant覆写min sdk为很高的版本,从而提高编译速度以及启用更高级的profile功能。所以表现为通过cli执行可以解决。实际上如果项目本来的min sdk >=21, 通过cli也无法解决这个问题。

@tys282000
Copy link
Collaborator

多谢反馈。Tinker的机制决定了在dalvik机器上loader类目前还是必须出现在主dex里,对于minSDK大于等于21的应用只会跑在ART上,理论上暂时可以靠ignoreWarning规避,但是仅限规避这个warning,因此开启这个开关之后要记得留意编译输出的警告信息了。

其实这个坑我最近看AGP源码也发现了,上周有位开发者也反馈了类似的问题,一开始我怀疑是配置问题,后来确认所有配置都正确之后开始怀疑是不是AGP新引入的native multidex忽略了所有关于分包的配置。接着我试了各种hack方法都没法解决,最后得出的结论是只能自己接管AGP的multidex逻辑自行处理分包,或者通过additionalParams的方式给dx或者d8追加maindexlist参数的方式来解决。

虽然Loader类随便分在minSDK大于等于21的机器上应该不会有啥问题,但考虑到新旧apk分包结果的变化会使补丁大小显著增大,因此我还是计划先留着这个检查。后面的版本会考虑根据用户传入的规则文件生成maindexlist传给dx或者d8的方案来规避这个问题。

@noproxy
Copy link
Contributor Author

noproxy commented May 6, 2019

可以先加一个单独屏蔽这个warning的开关,避免其他问题被忽略

@tys282000
Copy link
Collaborator

嗯嗯,对滴。近期我抽时间加一下吧。

@tys282000
Copy link
Collaborator

tys282000 commented May 7, 2019

其实minSDK>=21的时候直接ignoreWarning还是不行,因为loader类里有个校验注入的dex是否生效的TinkerTestDexLoad类,如果被分到了其他dex,在合成新的补丁dex之后会导致合成的产物里这个类出现两次,其中Tinker生成的test.dex里的那个会被另外一个覆盖,导致补丁加载失败。

所以至少要保证com.tencent.tinker.loader.TinkerTestDexLoad这个类出现在主dex才行。

@muxi166
Copy link

muxi166 commented May 15, 2019

什么时候修复发版呢

tys282000 added a commit that referenced this issue May 15, 2019
@awxy
Copy link

awxy commented May 22, 2019

其实minSDK>=21的时候直接ignoreWarning还是不行,因为loader类里有个校验注入的dex是否生效的TinkerTestDexLoad类,如果被分到了其他dex,在合成新的补丁dex之后会导致合成的产物里这个类出现两次,其中Tinker生成的test.dex里的那个会被另外一个覆盖,导致补丁加载失败。

所以至少要保证com.tencent.tinker.loader.TinkerTestDexLoad这个类出现在主dex才行。

在1.9.13的版本修复了?很急

@awxy
Copy link

awxy commented May 23, 2019

其实minSDK>=21的时候直接ignoreWarning还是不行,因为loader类里有个校验注入的dex是否生效的TinkerTestDexLoad类,如果被分到了其他dex,在合成新的补丁dex之后会导致合成的产物里这个类出现两次,其中Tinker生成的test.dex里的那个会被另外一个覆盖,导致补丁加载失败。

所以至少要保证com.tencent.tinker.loader.TinkerTestDexLoad这个类出现在主dex才行。

additionalParams添加无效

@noproxy
Copy link
Contributor Author

noproxy commented May 23, 2019

其实minSDK>=21的时候直接ignoreWarning还是不行,因为loader类里有个校验注入的dex是否生效的TinkerTestDexLoad类,如果被分到了其他dex,在合成新的补丁dex之后会导致合成的产物里这个类出现两次,其中Tinker生成的test.dex里的那个会被另外一个覆盖,导致补丁加载失败。
所以至少要保证com.tencent.tinker.loader.TinkerTestDexLoad这个类出现在主dex才行。

在1.9.13的版本修复了?很急

dev分支已经修了,但是没发版,你可以自己fork了发版

@feicien
Copy link

feicien commented May 24, 2019

其实minSDK>=21的时候直接ignoreWarning还是不行,因为loader类里有个校验注入的dex是否生效的TinkerTestDexLoad类,如果被分到了其他dex,在合成新的补丁dex之后会导致合成的产物里这个类出现两次,其中Tinker生成的test.dex里的那个会被另外一个覆盖,导致补丁加载失败。

所以至少要保证com.tencent.tinker.loader.TinkerTestDexLoad这个类出现在主dex才行。

TinkerTestDexLoad 这个类会在 test.dex 中,不需要处理, 只要把 ignoreWarnings 设置为 true 就可以成功打补丁包的,我这边已经验证过了

我们应用线上版本使用的是 Tinker 1.9.8 版本,由于把 Android Gradle Plugin 由 3.2.1 升级到了 3.3.2 ,导致 additionalParams 配置失效,结果线上版本的包 Tinker 相关的类没有打到 main dex 中。我这边把 ignoreWarnings 修改为 true ,结果成功打上了补丁。

另外,我把 Tinker 升级到 1.9.13,并且把 additionalParameters 相关分包的配置都移除掉,也可以成功打补丁。

一句话总结一下:如果 minSDK >= 21 只需要把 ignoreWarnings 设置为 true ,其它什么都不需要配置,即可成功打补丁

@noproxy
Copy link
Contributor Author

noproxy commented May 24, 2019 via email

@zhangwanggit
Copy link

zhangwanggit commented Jul 26, 2019

你好,我看v1.9.13.1 fix了这个问题,但是如果 ignoreWarnings 设置为 false还是会出现这个问题,true没问题,是不是在1.9.13.1以后就可以将ignoreWarnings设为true了呢。

@aa5279aa
Copy link

aa5279aa commented Sep 7, 2019

@noproxy
感谢,看了你的回复,我通过把sdk从22回退到了19解决了这个问题。

@dotcink
Copy link
Contributor

dotcink commented Nov 6, 2019

@noproxy

请问“运行时load还可能有问题的(是否重现跟实际分包结果有关)。这点已经证明过了,不用再讨论了“这里说的讨论在哪里?有没有链接?
意思是打出来的包(我们的补丁超过 3M)可能造成 crash?

@dotcink
Copy link
Contributor

dotcink commented Nov 7, 2019

@noproxy

请问“运行时load还可能有问题的(是否重现跟实际分包结果有关)。这点已经证明过了,不用再讨论了“这里说的讨论在哪里?有没有链接?
意思是打出来的包(我们的补丁超过 3M)可能造成 crash?

噢噢,是指前面 @tomystang 说的 TinkerTestDexLoad 问题?

@noproxy
Copy link
Contributor Author

noproxy commented Nov 7, 2019 via email

@chrisLeeCreate
Copy link

综上,需要设置tinker包下以及application的代码 到 main-dex-list。 并且把ignoreWarning=false。不影响使用。
additionalParameters = [
'--multi-dex',//多dex分包
'--set-max-idx-number=60000',//每个包内方法数上限
'--main-dex-list=' + projectDir + '/main-dex-rule', //打包到主classes.dex的文件列表
'--minimal-main-dex'
]

@consonluo
Copy link

mark一下

@fengdaren
Copy link

最后怎么解决的???

@yninggis
Copy link

请问minSdkVersion>=24,差分包生成失败是怎么回事?能支持吗?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests