我在我的原生应用程序中使用WebView
和许多JavaScript。如果JS方想要调用本机函数,那么使用JavaScriptInterface
就可以了。但是,如果native希望调用JS函数,那就不那么容易了。到目前为止,我尝试了两种解决方案:
loadUrl
网址调用javascript:something()
方法 - 不可接受,因为当用户在键盘WebView
上键入内容时,会在执行功能后隐藏它String
对象提供)和
在结果上调用eval()
- 有时在设置间隔1秒后,我在50-60秒后收到这些请求! 我想知道是否还有其他方法可以完成这种通信模式。假设在应用内创建本地Socket
/ HTTP
/ something-else服务器,并将其访问权限WebView
。我正在寻找任何提示(如果可能的话)。
答案 0 :(得分:3)
我有以下代码,它使用java反射从Java调用JavaScript。它避免了以下loadUrl错误: 1.当您将焦点放在输入中时,loadUrl可能会隐藏键盘。 2. loadUrl不能经常调用。
希望这会有所帮助:
public class AdvancedWebView extends WebView {
private static final int EXECUTE_JS = 194;
Method sendMessageMethod;
Object webViewCore;
boolean initFailed = false;;
InputMethodManager imm;
public AdvancedWebView(Context context, AttributeSet attrs) {
super(context, attrs);
imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
this.getSettings().setJavaScriptEnabled(true);
this.initReflection();
}
@SuppressWarnings("rawtypes")
private void initReflection() {
Object webViewObject = this;
Class webViewClass = WebView.class;
try {
Field f = webViewClass.getDeclaredField("mProvider");
f.setAccessible(true);
webViewObject = f.get(this);
webViewClass = webViewObject.getClass();
} catch (Throwable e) {
// mProvider is only required on newer Android releases.
}
try {
Field f = webViewClass.getDeclaredField("mWebViewCore");
f.setAccessible(true);
webViewCore = f.get(webViewObject);
if (webViewCore != null) {
sendMessageMethod = webViewCore.getClass().getDeclaredMethod("sendMessage", Message.class);
sendMessageMethod.setAccessible(true);
System.out.println("sendMessageMethod-----"+sendMessageMethod);
}
hasIntercepted = true;
} catch (Throwable e) {
hasIntercepted = false;
//Log.e(LOG_TAG, "PrivateApiBridgeMode failed to find the expected APIs.", e);
}finally{
if(sendMessageMethod == null)
{
hasIntercepted = false;
}
}
}
private void loadJs(String url) {
if (sendMessageMethod == null && !initFailed) {
initReflection();
}
// webViewCore is lazily initialized, and so may not be available right away.
if (sendMessageMethod != null) {
//String js = popAndEncodeAsJs();
Message execJsMessage = Message.obtain(null, EXECUTE_JS, url);
try {
sendMessageMethod.invoke(webViewCore, execJsMessage);
} catch (Throwable e) {
//Log.e(LOG_TAG, "Reflection message bridge failed.", e);
}
}
}
}
答案 1 :(得分:1)
我不知道如何让备用通信模型正常工作,但我想我已经找到了loadUrl-hides-the-keyboard问题的解决方法:https://stackoverflow.com/a/18776064/513038。这对你有帮助吗?