Tencent / Shadow

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

插件集成 nfc 功能问题 #1298

Closed qingsongwill closed 1 month ago

qingsongwill commented 3 months ago

插件中集成 nfc 功能,报错信息如下:

java.lang.NoSuchMethodError: No virtual method enableForegroundDispatch(Lcom/tencent/shadow/core/runtime/ShadowActivity;Landroid/app/PendingIntent;[Landroid/content/IntentFilter;[[Ljava/lang/String;)V in class Landroid/nfc/NfcAdapter; or its super classes (declaration of 'android.nfc.NfcAdapter' appears in /system/framework/framework.jar!classes2.dex)

NfcAdapter 中的 enableForegroundDispatch 第一个参数是 Activity 类型,在插件的 dex 文件中看到 Activity 类型已修改为 ShadowActivity,但是插件运行起来后查看 NfcAdapter 类的是由 BootClassLoader 加载,不是由插件的 ClassLoader 加载的修改后的 NfcAdapter类,这样就导致方法参数异常。不知道有没有遇到类似问题的,有没有什么解决方案啊?

shifujun commented 3 months ago

这些系统api需要activity的,基本上都可以转调时传对应的container activity。对系统来说插件activity只是container activity持有的普通逻辑类。你可以仿照已有的transform把对NfcAdapter的调用hook下来,修改参数再调用。

至于你提到的插件自带的NfcAdapter类实现,似乎是不必要的。

如果你的NfcAdapter支持实现好了欢迎贡献代码。

qingsongwill commented 3 months ago

@shifujun 感谢解答,目前采用的方案是 issues/596 中提到的宿主做一层封装,插件设置白名单依赖宿主可以解决 Activity 参数异常问题。现在遇到一个新问题插件中 onNewIntent 回调的 intent 中 Tag 为 null,插件单独运行可以读取标签数据,不知道是哪里的问题。

@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); // 处理 NFC 事件 handleNfcIntent(intent); }

private void handleNfcIntent(Intent intent) { String action = intent.getAction(); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { // 处理 NFC 标签数据 Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // 处理标签数据... } }

qingsongwill commented 3 months ago

@shifujun ShadowActivityDelegate 这里带有 nfc 扫描结果的 Intent 数据会被覆盖掉,应该是一个 bug 。

image

这样改不知道会不会有问题啊

   val pluginExtras: Bundle? = intent.getBundleExtra(CM_EXTRAS_BUNDLE_KEY)
   if (pluginExtras != null) {
        intent.putExtra(CM_EXTRAS_BUNDLE_KEY, pluginExtras)
    }
   mPluginActivity.onNewIntent(intent)