我有一个托管WebView组件的简单片段.在这个片段的初始化过程中,我向我的应用注册了一些JavaScript接口方法:
mJavaScriptHooks = new JavaScriptHooks();
...
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(mJavaScriptHooks, "Android");
Run Code Online (Sandbox Code Playgroud)
我的JavaScript钩子并不引人注目,所有都以下列方式声明:
public class JavaScriptHooks {
@JavascriptInterface
public void someMethod() {
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
为了确保这些方法不被混淆或优化而遗忘,我添加了以下我的ProGuard配置:
-keepattributes JavascriptInterface
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
Run Code Online (Sandbox Code Playgroud)
一切都按预期工作.网页通过提供的"Android"对象成功调用方法,调用方法并执行相应的任务.但是,它仅在我使用通过Android Studio的即时运行功能生成的APK运行应用程序时才有效.
如果APK是通过Android Studio安装的,或者我是否通过命令行使用安装它并不重要 adb install
如果我通过常规gradle编译我的APK(或者如果我禁用Instant-Run),那么JavaScript界面就会停止工作.
首先,我确保ProGuard被禁用.即使ProGuard以某种方式✨魔法✨启用,我的ProGuard配置也应该确保我的JS方法不受影响.
我还拆解了APK,以确保通过JS接口公开的方法不会以某种方式被破坏(或删除).他们不是.它们似乎在DEX文件中存在,如声明的那样.
当我运行启用了Instant-Run生成的APK时,我可以检查(通过Chrome)WebView中加载的页面并看到我的"Android"对象可用,并且我公开的所有方法都在那里(和可调用的):
> Android
Object
someMethod()
__proto__
Run Code Online (Sandbox Code Playgroud)
但是,当我运行禁用Instant-Run的APK(即vanilla gradle)时,"Android"对象可用,但我的方法都没有.它只是一个空物.
> Android
Object
__proto__
Run Code Online (Sandbox Code Playgroud)
我在WebView中加载的页面位于我控制的公共可见服务器上.在两个APK版本中加载相同的页面,并以相同的方式调用方法.只有使用Instant-Run功能构建的APK似乎才有效.
我一整天都在挖,但我找不到任何有用的东西.大多数建议都指向ProGuard配置问题或WebView中的旧错误(即Gingerbread时代).