在之前的文章里面,我总结过WebView如何与网页交互,也就是Java如何和JS交互 —— Android WebView 总结 —— Java和JavaScript交互。 基于这篇文章,我们基本上能完成绝大部分交互的逻辑。但是,因为业务需要,最近加载的JS都是超长的数据,但测试发现在Android 16及以下的手机上,能正常使用,但是在17 及以上的手机上,发现JS没有执行。
这是因为,WebView在Android 17及以后对之前的WebView存在的安全问题做了调整。那怎么办呢?答:使用 evaluateJavaScript 方法。
这个方法不仅能执行JS,还可以获取到返回数据,下面是针对这个方法的原文说明:
Asynchronously evaluates JavaScript in the context of the currently displayed page. If non-null, |resultCallback| will be invoked with any result returned from that execution. This method must be called on the UI thread and the callback will be made on the UI thread. Parameters script the JavaScript to execute. resultCallback A callback to be invoked when the script execution completes with the result of the execution (if any). May be null if no notificaion of the result is required.
那么Android 17之前的该怎么办?目前的解决方案是通过java反射机制!
在android.webkit包中有个BrowserFrame私有类,该类中有个Native方法:
public native String stringByEvaluatingJavaScriptFromString(String script)
使用步骤
1.扩展WebView添加方法,并使用反射实现。
2.将布局文件中的WebView修改为自定义的WebView
3.使用新的WebView调用方法,执行js方法获取返回值
实现后的自定义WebView调用方法代码如下:
public String stringByEvaluatingJavaScriptFromString(String script) { try { //由webview取到webviewcore Field field_webviewcore = WebView.class.getDeclaredField("mWebViewCore"); field_webviewcore.setAccessible(true); Object obj_webviewcore = field_webviewcore.get(this); //由webviewcore取到BrowserFrame Field field_BrowserFrame = obj_webviewcore.getClass().getDeclaredField("mBrowserFrame"); field_BrowserFrame.setAccessible(true); Object obj_frame = field_BrowserFrame.get(obj_webviewcore); //获取BrowserFrame对象的stringByEvaluatingJavaScriptFromString方法 Method method_stringByEvaluatingJavaScriptFromString = obj_frame.getClass().getMethod("stringByEvaluatingJavaScriptFromString", String.class); //执行stringByEvaluatingJavaScriptFromString方法 Object obj_value = method_stringByEvaluatingJavaScriptFromString.invoke(obj_frame, script); //返回执行结果 return String.valueOf(obj_value); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }
当然,还有更简单的方法,那就是使用腾讯X5内核的WebView提供的evaluateJavaScript,在他们的WebView里面,针对这个问题已经做好的处理。下面是他们的SDK里面的相关代码,在这里做一下展示:
public void evaluateJavascript(String var1, ValueCallback<String> var2) { if (this.e) { try { View var3 = this.f.getView(); Method var4 = com.tencent.smtt.utils.q.a(var3, "evaluateJavascript", new Class[]{String.class, android.webkit.ValueCallback.class}); var4.setAccessible(true); var4.invoke(this.f.getView(), var1, var2); } catch (Exception var7) { var7.printStackTrace(); this.loadUrl(var1); } } else if (VERSION.SDK_INT >= 19) { try { Class var8 = Class.forName("android.webkit.WebView"); Class[] var9 = new Class[]{String.class, android.webkit.ValueCallback.class}; Method var5 = var8.getDeclaredMethod("evaluateJavascript", var9); var5.setAccessible(true); var5.invoke(this.g, var1, var2); } catch (Exception var6) { var6.printStackTrace(); } } }
原文地址:https://www.cnblogs.com/renhui/p/9330844.html
时间: 2024-10-10 04:55:28