Tencent / Shadow

零反射全动态Android插件框架
BSD 3-Clause "New" or "Revised" License
7.45k stars 1.3k forks source link

AndroidViewModel混淆问题 #608

Closed jeec closed 3 years ago

jeec commented 3 years ago

配置: 1.宿主未混淆(排除宿主混淆问题); 2.插件已混淆并可独立运行; 3.宿主启动插件activity时报与关联的viewModel不能找到。 4.插件不混淆时一切正常。

所以现在问题定位在混淆上,请大佬帮看下问题,感谢:

E AndroidRuntime: FATAL EXCEPTION: main E AndroidRuntime: Process: com.aaaa.bbbb:plugin, PID: 23305 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.aaaa.bbbb/com.tencent.shadow.sample.runtime.PluginDefaultProxyActivity}: java.lang.RuntimeException: java.lang.RuntimeException: Cannot create an instance of class com.tencent.shadow.sample.plugin.vm.ChangeIconViewModel E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4060) E AndroidRuntime: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4247) E AndroidRuntime: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91) E AndroidRuntime: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149) E AndroidRuntime: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103) E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2613) E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110) E AndroidRuntime: at android.os.Looper.loop(Looper.java:219) E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:8668) E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109) E AndroidRuntime: Caused by: java.lang.RuntimeException: java.lang.RuntimeException: Cannot create an instance of class com.tencent.shadow.sample.plugin.vm.ChangeIconViewModel E AndroidRuntime: at com.tencent.shadow.core.loader.delegates.ShadowActivityDelegate.onCreate(Unknown Source:374) E AndroidRuntime: at com.tencent.shadow.core.runtime.container.PluginContainerActivity.onCreate(Unknown Source:58) E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:8214) E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:8202) E AndroidRuntime: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1320) E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4033) E AndroidRuntime: ... 11 more E AndroidRuntime: Caused by: java.lang.RuntimeException: Cannot create an instance of class com.tencent.shadow.sample.plugin.vm.ChangeIconViewModel E AndroidRuntime: at androidx.lifecycle.u$a.a(Unknown Source:119) E AndroidRuntime: at androidx.lifecycle.u.b(Unknown Source:37) E AndroidRuntime: at androidx.lifecycle.u.a(Unknown Source:23) E AndroidRuntime: at com.kftpay.module.common.plugin.base.c.I(Unknown Source:4) E AndroidRuntime: at com.kftpay.module.common.plugin.base.c.M(Unknown Source:26) E AndroidRuntime: at com.kftpay.module.common.plugin.base.c.onCreate(Unknown Source:134) E AndroidRuntime: at c.c.a.a.a.d.a.onCreate(Unknown Source:19) E AndroidRuntime: at com.tencent.shadow.core.loader.delegates.ShadowActivityDelegate.onCreate(Unknown Source:353) E AndroidRuntime: ... 16 more E AndroidRuntime: Caused by: java.lang.NoSuchMethodException: com.tencent.shadow.sample.plugin.vm.ChangeIconViewModel. [class com.tencent.shadow.core.runtime.ShadowApplication] E AndroidRuntime: at java.lang.Class.getConstructor0(Class.java:2332) E AndroidRuntime: at java.lang.Class.getConstructor(Class.java:1728) E AndroidRuntime: at androidx.lifecycle.u$a.a(Unknown Source:18) E AndroidRuntime: ... 23 more E bms_file: file /sys/class/hw_power/charger/direct_charger_sc/direct_charge_succ is invalid

shifujun commented 3 years ago

官方的构建流程中会自动Keep那些Activity、Application等不能混淆的类。Shadow转换的Activity或者Application类需要我们自己keep下来。有参考到sample里的这两处设置吗?

https://github.com/Tencent/Shadow/blob/a75c81cd644114b22832ab6f411658a9ef5ffd22/projects/sample/maven/plugin-project/plugin-shadow-apk/build.gradle#L11-L15

https://github.com/Tencent/Shadow/blob/a75c81cd644114b22832ab6f411658a9ef5ffd22/projects/sample/maven/plugin-project/sample-runtime/proguard-rules.pro#L26-L28

jeec commented 3 years ago

以上两处已设置,MyApplication也keep住了。我看到上面报的错最终是因为找不到构造方法而不能创建viewModel实例(Caused by: java.lang.NoSuchMethodException: com.tencent.shadow.sample.plugin.vm.ChangeIconViewModel. [class com.tencent.shadow.core.runtime.ShadowApplication]),所以将插件和宿主viewModel都更新到相同版本(2.3.1),此错误并未消除。

shifujun commented 3 years ago

那把代码push上来我看看吧。最好是fork之后做的少量改动。

jeec commented 3 years ago

稍微修改了sample/maven下的代码,复现了遇到的问题:git@github.com:jeec/Shadow.git

shifujun commented 3 years ago

我是这样测试的没能复现crash。我是在API 28的官方虚拟机上测试的。

cd projects/sample/maven

cd plugin-project
./gradlew packageReleasePlugin
adb push build/plugin-release.zip /data/local/tmp

cd ../manager-project
./gradlew assembleRelease
adb push sample-manager/build/outputs/apk/release/sample-manager-release.apk /data/local/tmp

cd ../host-project
./gradlew installDebug

image

shifujun commented 3 years ago

刚看到你把

//方式二viewModel继承AndroidViewModel():
    //private val mViewModel: MainAndroidViewModel by viewModels()

注释掉了。那我再试试。

shifujun commented 3 years ago

因为lifecycle-viewmodel的aar里打包了一个proguard.txt,它会把自己Proguard规则带到最终的apk构建中。它是这样定义的:

-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.ViewModel {
    <init>();
}

-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.AndroidViewModel {
    <init>(android.app.Application);
}

所以我们把其中的android.app.Application换成com.tencent.shadow.core.runtime.ShadowApplication添加到插件构建的Proguard配置中就可以了。

-keepclassmembers,allowobfuscation class * extends androidx.lifecycle.AndroidViewModel {
    <init>(com.tencent.shadow.core.runtime.ShadowApplication);
}

https://github.com/shifujun/Shadow/commit/81f66025ccbe936538e6fc1ac4017218868cbd25 这样就可以了。

jeec commented 3 years ago

这样确实viewModel不再报错。但在几台真机上测试发现LiveData均没有收到点击响应事件:华为P30 : 鸿蒙2.0.0; OPPO Ace2: android 11; 在9.0版本的魅族M10上运行正常。

shifujun commented 3 years ago

LiveData均没有收到点击响应事件

是指这样的代码无法正常工作吗?不是的话,给个例子? https://github.com/Tencent/Shadow/blob/0e5d9d8d935d296bc40555b07d8396ba539de214/projects/test/plugin/androidx-cases/androidx-cases-lib/src/main/java/com/tencent/shadow/test/plugin/androidx_cases/lib/LiveDataWithActivityTestActivity.java#L33-L50

jeec commented 3 years ago

还是之前的demo: git@github.com:jeec/Shadow.git 。 其中com.tencent.shadow.sample.plugin.MainActivity里的LiveData在上述几款真机上不能正常工作,具体操作是:点击页面按钮,LiveData未收到事件响应。

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)

    findViewById<TextView>(R.id.tv).setOnClickListener {
        Toast.makeText(this, "click", Toast.LENGTH_SHORT).show()
        mViewModel.mLiveData.value = "THIS IS PLUGIN"
    }

    mViewModel.mLiveData.observe(this, Observer {
        Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
        findViewById<TextView>(R.id.tv).text = it
    })
}
shifujun commented 3 years ago

LiveData没响应的问题是maven sample引用是较早的版本2.1.0,缺少2.1.1版本包含的 0e5d9d8d935d296bc40555b07d8396ba539de214 提交。

liluyue commented 3 years ago

建议有个统一的混淆注意事项文件,我刚才也遇到这个问题了