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

如何正确传递ShadowActivity上下文给插件中的第三方SDK? #1369

Open
LuYeCong opened this issue Mar 5, 2025 · 5 comments
Open

Comments

@LuYeCong
Copy link

LuYeCong commented Mar 5, 2025

问题描述:

我们在使用Shadow框架时遇到类转换异常:

Caused by:java.lang.RuntimeException: java.lang.ClassCastException: com.tencent.shadow.test.plugin.general_cases.lib.gallery.TestApplication cannot be cast to com.tencent.shadow.core.runtime.ShadowActivity
com.tencent.shadow.core.loader.delegates.ShadowActivityDelegate.onCreate(ShadowActivityDelegate.kt:159)
com.tencent.shadow.core.runtime.container.PluginContainerActivity.onCreate(PluginContainerActivity.java:84)
android.app.Activity.performCreate(Activity.java:9221)
android.app.Activity.performCreate(Activity.java:9177)
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1538)
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4392)
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4631)
android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:112)
android.app.servertransaction.TransactionExecutor.executeNonLifecycleItem(TransactionExecutor.java:186)
android.app.servertransaction.TransactionExecutor.executeTransactionItems(TransactionExecutor.java:112)
android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:84)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:2873)
android.os.Handler.dispatchMessage(Handler.java:107)
android.os.Looper.loopOnce(Looper.java:249)
android.os.Looper.loop(Looper.java:337)
android.app.ActivityThread.main(ActivityThread.java:9580)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
Caused by:java.lang.ClassCastException: com.tencent.shadow.test.plugin.general_cases.lib.gallery.TestApplication cannot be cast to com.tencent.shadow.core.runtime.ShadowActivity
com.box_suwell.kt.KtSuwellActivity$Companion.startDocAct(KtSuwellActivity.kt:129)

背景

  1. 插件化之前,原宿主中通过jsFuncApi.run()直接调用第三方SDK的接口实现(在宿主中正常)
  2. 现在将该接口实现迁移到插件中,context参数传递宿主Activity或插件Application均失败
  3. 第三方SDK内部会使用传入的context.startActivity()
  4. 第三方SDK的代码我们无法修改

关键代码

// 宿主调用插件接口
jsFuncApi.run(
    context, // 宿主Activity
    parseParamsData,
    getDefaultExtFuncCallBack(callbackId)
)

// 插件中尝试启动Activity
context.startActivity(intent) // 这里触发异常

错误分析
根据框架原理,Shadow通过动态代理机制将插件Activity包装成ShadowActivity。当使用宿主Activity作为context启动插件组件时:

  1. 宿主Activity无法识别插件中的类加载器
  2. 插件组件需要通过Shadow的代理机制与宿主交互

尝试过的方案

  1. 传入宿主Activity -> 无法startActivity
  2. 传入插件Application -> 类转换异常

请求建议
根据框架设计文档,能否指导如何:

  1. 在插件中正确获取有效的ShadowActivity上下文?
  2. 是否需要通过PluginContainerActivity等专用容器传递上下文?
  3. 是否有推荐的上下文传递模式来兼容第三方SDK的startActivity调用?

@shifujun

@zhuqichao
Copy link

如果第三方SDK是打包到插件里的,那么传入SDK的context应该是插件的activity

@LuYeCong
Copy link
Author

LuYeCong commented Mar 5, 2025

宿主使用插件的classloader,直接反射出插件中的实现类
宿主会直接调用插件的实现类,这中间是不需要插件有activity的

问题是插件化之前我们这样调用是完全没有问题,现在也没法让第三方sdk大改
@zhuqichao

@zhuqichao
Copy link

如果我理解的没错,你的应用场景是需要调用SDK里面的一个方法,这个方法会启动SDK里面的一个activity,所以这个方法需要传入一个Activity类型的参数。
插件在编译的时候会把这个Activity类型参数转换为ShadowActivity,因此传入插件的Application或者宿主的activity都是类型不符合的,基于这个原因传入插件的PluginContainerActivity也是不符合类型的。只有插件自身的activity才符合类型。
通常的解决方案:
在插件中创建一个中转的透明的activity,在onCreate中调用SDK中的这个方法,传入这个activity,调用成功后立即结束这个activity。
另外,不建议宿主中使用插件的classlaoder直接反射调用插件的实现类,这样虽然可行,但是不符合shadow的设计原则,应该使用实现注入的方式进行调用。

@shifujun
Copy link
Collaborator

shifujun commented Mar 5, 2025

你只需要简单的在插件代码中调用那个第三方SDK就行了。如果那个SDK要求你传入的context只能是一个activity,你又非得兼容它,那你就简单的先启动一个不可见的插件activity好了。

你应该没有什么理由用在宿主里获取插件的classloader。这也不是shadow的设计用法。

@zhuqichao
Copy link

shadow非官方交流群,感兴趣可以进一下

Image

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

No branches or pull requests

3 participants