android 和JS互调

Android提供了三个很强盛的WebView控件用来管理Web网页,而在网页中,JavaScript又是三个十分重视的剧本。本文将介绍如何促成Java代码和Javascript代码的彼此调用。

JS与Native交互

福寿齐天JS和Native有二种艺术:

shouldOverrideUrlLoading(WebView view, String url) js与java相互调用

先来讲一下首先种方法shouldOverrideUrlLoading(WebView view, String url)

通过给WebView加三个事变监听目的(WebViewClient卡塔尔国一视同仁写shouldOverrideUrlLoading(WebView
view, String
url)方法。当按下有个别连接时WebViewClient会调用那一个点子,并传递参数view和url

开始第三种.JS和Java互调

怎么样贯彻java和js互调

WebView开启JavaScript脚本实施WebView设置供JavaScript调用的交互作用接口客商端和网页端编写调用对方的代码

JS调用JAVA
JS : window.jsInterfaceName.methodName(parameterValues)
native: webView.addJavascriptInterface(new JsInteration(),
“androidNative”);

下边给出三个实例,方便清楚

webView.addJavascriptInterface(new JsInteration(), “androidNative”);
@JavascriptInterface
public void helloJS(){…}

window.androidNative.helloJS();

Java调用JS

webView调用js的基本格式为webView.loadUrl(“javascript:methodName(parameterValues卡塔尔国”卡塔尔(قطر‎

调用js无参无重返值函数: String call
=“javascript:sayHello(卡塔尔国”;webView.loadUrl(call卡塔尔(قطر‎;
调用js有参无再次来到值函数:String call = “javascript:alertMessage(”” +
“content” + “”State of Qatar”; webView.loadUrl(call); 调用js有参数有再次回到值的函数
Android在4.4事前并从未提供直接调用js函数并获得值的秘籍,所以早前,常用的思路是
java调用js方法,js方法施行完结,再一次调用java代码将值重临。
Android 4.4从此现在接受evaluateJavascript就可以。

private void testEvaluateJavascript(WebView webView) {
  webView.evaluateJavascript("getGreetings()", new ValueCallback() {
  @Override
  public void onReceiveValue(String value) {
      Log.i(LOGTAG, "onReceiveValue value=" + value);
  }});
}

注:

参数类型假使是简单的int或String,可以一直传,对于复杂的数据类型,提议以字符串格局的json再次回到。
evaluateJavascript方法必得在UI线程(主线程)调用,因而onReceiveValue也施行在主线程。

当native与js交互作用时存cookie看见不胜枚贡士超出过那样一个主题材料,cookie存不步入,网络有成都百货上千演讲方案,但是众多没说起爱戴上,这里一贯贴一下代码:

public static void synCookies(Context context, String url, String version) {
        CookieSyncManager.createInstance(context);
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
        cookieManager.removeAllCookie();
        cookieManager.setCookie(url, "sessionKey=" + UserInfoShareprefrence.getInstance(context).getLocalSessionKey());
        cookieManager.setCookie(url, "productVersion=android-epocket-v" + version);
        CookieSyncManager.getInstance().sync();

    }

存不步入的一点都不小片段原因是你的url不对,他官方给出的分解是那般的

 /**
     * Sets a cookie for the given URL. Any existing cookie with the same host,
     * path and name will be replaced with the new cookie. The cookie being set
     * will be ignored if it is expired.
     *
     * @param url the URL for which the cookie is to be set
     * @param value the cookie as a string, using the format of the 'Set-Cookie'
     *              HTTP response header
     */
    public void setCookie(String url, String value) {
        throw new MustOverrideException();
    }

骨子里没证了然url到底是怎样,这里的url正是显示的url的域名,这里顺便贴出取域名的点子,给出的是经过正则提取域名

    /**
     * 获得域名
     *
     * @param url
     * @return
     */
    public static String getDomain(String url) {
        Pattern p = Pattern.compile("[^//]*?\.(com|cn|net|org|biz|info|cc|tv)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = p.matcher(url);
        matcher.find();
        return matcher.group();
    }

再有少数正是,固然你想传递多个值给cookie的话,能够频仍运用set库克ie,不要狂妄的友好拼值,因为你拼的字符串中也许存在分号,内部多分号做了特出管理,截取分号在此以前的,之后的第一手甩掉!

实现JS和Native有三种方式:
shouldOverrideUrlLoading(WebView view, String url) js与java相互调用
先来讲一下首先种方法shouldOverrideUrlLoadin…

什么得以完毕

福寿双全Java和js人机联作十一分方便人民群众。平常只必要以下几步。

  • WebView开启JavaScript脚本执行
  • WebView设置供JavaScript调用的相互作用接口。
  • 顾客端和网页端编写调用对方的代码。

一、Android调用JS方法

本例代码

为了方便解说,先贴出全体代码

Java代码

package com.example.javajsinteractiondemo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class MainActivity extends Activity {
  private static final String LOGTAG = "MainActivity";
  @SuppressLint("JavascriptInterface")
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      final WebView myWebView = (WebView) findViewById(R.id.myWebView);
      WebSettings settings = myWebView.getSettings();
      settings.setJavaScriptEnabled(true);
      myWebView.addJavascriptInterface(new JsInteration(), "control");
      myWebView.setWebChromeClient(new WebChromeClient() {});
      myWebView.setWebViewClient(new WebViewClient() {

          @Override
          public void onPageFinished(WebView view, String url) {
              super.onPageFinished(view, url);
              testMethod(myWebView);
          }

      });
      myWebView.loadUrl("file:///android_asset/js_java_interaction.html");
  }

  private void testMethod(WebView webView) {
      String call = "javascript:sayHello()";

      call = "javascript:alertMessage("" + "content" + "")";

      call = "javascript:toastMessage("" + "content" + "")";

      call = "javascript:sumToJava(1,2)";
      webView.loadUrl(call);

  }

  public class JsInteration {

      @JavascriptInterface
      public void toastMessage(String message) {
          Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
      }

      @JavascriptInterface
      public void onSumResult(int result) {
          Log.i(LOGTAG, "onSumResult result=" + result);
      }
  }

}

前面八个网页代码

<html>
<script type="text/javascript">
    function sayHello() {
        alert("Hello")
    }

    function alertMessage(message) {
        alert(message)
    }

    function toastMessage(message) {
        window.control.toastMessage(message)
    }

    function sumToJava(number1, number2){
       window.control.onSumResult(number1 + number2)
    }
</script>
Java-Javascript Interaction In Android
</html>

1.Java调用js代码(Android4.4以前)

调用示例

mWebView.loadUrl(“javascript:sum(3,8)”);

js调用Java

调用格式为window.jsInterfaceName.methodName(parameterValues卡塔尔此例中大家接收的是control作为注入接口名称。

function toastMessage(message) {
  window.control.toastMessage(message)
}

function sumToJava(number1, number2){
   window.control.onSumResult(number1 + number2)
}

细心,这里通过addJavascriptInterface将MyActiviy所对应的目的记入到WebView中了。

Java调用JS

webView调用js的主导格式为webView.loadUrl(“javascript:methodName(parameterValues卡塔尔(قطر‎”卡塔尔国

js函数管理,并将结果通过调用java方法再次来到

调用js无参无重回值函数

String call = "javascript:sayHello()";
webView.loadUrl(call);

function sum(i,m){

调用js有参无重回值函数

留意对于字符串作为参数值须求举行转义双引号。

String call = "javascript:alertMessage("" + "content" + "")";
webView.loadUrl(call);

var result = i+m;

调用js有参数有重回值的函数

Android在4.4事前并未提供第一手调用js函数并获得值的点子,所以以前,常用的笔触是
java调用js方法,js方法施行达成,再度调用java代码将值再次来到。

1.Java调用js代码

String call = "javascript:sumToJava(1,2)";
webView.loadUrl(call);

2.js函数拍卖,并将结果通过调用java方法重回

function sumToJava(number1, number2){
       window.control.onSumResult(number1 + number2)
}

3.Java在回调方法中得到js函数重回值

@JavascriptInterface
public void onSumResult(int result) {
  Log.i(LOGTAG, "onSumResult result=" + result);
}

document.getElementById(“h”).innerHTML= result;

4.4处理

Android 4.4事后采用evaluateJavascript就可以。这里显得二个总结的并行示例
具备再次回到值的js方法

function getGreetings() {
      return 1;
}

java代码时用evaluateJavascript方法调用

private void testEvaluateJavascript(WebView webView) {
  webView.evaluateJavascript("getGreetings()", new ValueCallback<String>() {

  @Override
  public void onReceiveValue(String value) {
      Log.i(LOGTAG, "onReceiveValue value=" + value);
  }});
}

出口结果

I/MainActivity( 1432): onReceiveValue value=1

注意

  • 上边限制了结果重返结果为String,对于简易的类型会尝试转换来字符串重回,对于复杂的数据类型,建议以字符串情势的json重回。
  • evaluateJavascript方法必须在UI线程(主线程)调用,由此onReceiveValue也举办在主线程。

}

疑点解答

2.JAVA中怎么着收获JS中的再次来到值(Android4.4之后State of Qatar

Alert不能够弹出

您应该是还没安装WebChromeClient,依据以下代码设置

myWebView.setWebChromeClient(new WebChromeClient() {});

Android 4.4之后选取evaluateJavascript就可以。这里显得二个简便的并行示例

Uncaught ReferenceError: functionName is not defined

难题应运而生原因,网页的js代码未有加载成功,就调用了js方法。驱除措施是在网页加载成功之后调用js方法

myWebView.setWebViewClient(new WebViewClient() {

  @Override
  public void onPageFinished(WebView view, String url) {
      super.onPageFinished(view, url);
      //在这里执行你想调用的js函数
  }

});

先写三个存有重临值的js方法

Uncaught TypeError: Object [object Object] has no method

function getGreetings(str) {

康宁限定难点

万一头在4.2本子以上的机械出标题,那么正是系统处于安全范围的主题素材了。Android文书档案那样说的

Caution: If you’ve set your targetSdkVersion to 17 or higher, you must
add the @JavascriptInterface annotation to any method that you want
available your web page code (the method must also be public). If you
do not provide the annotation, then the method will not accessible by
your web page when running on Android 4.2 or higher.

汉语概况为

警示:要是你的主次目的平台是17要么是更加高,你应当要在爆出给网页可调用的秘籍(那个方式必需是当着的)加上@JavascriptInterface注释。假若你不那样做的话,在4.2以事后的平台上,网页不可能访问到您的不二等秘书诀。

return str;

二种缓慢解决办法
  • 将targetSdkVersion设置成17或更高,引入@JavascriptInterface注释
  • 自个儿创制三个讲解接口名叫@JavascriptInterface,然后将其引进。注意这几个接口无法歪曲。

注,创建@JavascriptInterface代码

public @interface JavascriptInterface {

}

}

代码混淆难题

如若在并未有歪曲的本子运转正常化,在混淆后的本子的代码运营错误,并提醒Uncaught
TypeError: Object [object Object] has no
method,那正是您未曾做混淆例外管理。 在混淆文件插手相近那样的代码

-keep class com.example.javajsinteractiondemo$JsInteration {
    *;
}

java代码时用evaluateJavascript方法调用:(在乎:1.evaluateJavascript试行JS方法时,网页必须加载达成 
2.网页中的JS方法是全局方法

All WebView methods must be called on the same thread

过滤日志曾开掘过那几个主题材料。

E/StrictMode( 1546): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {528712d4} called on Looper (JavaBridge, tid 121) {52b6678c}, FYI main Looper is Looper (main, tid 1) {528712d4})
E/StrictMode( 1546):   at android.webkit.WebView.checkThread(WebView.java:2063)
E/StrictMode( 1546):   at android.webkit.WebView.loadUrl(WebView.java:794)
E/StrictMode( 1546):   at com.xxx.xxxx.xxxx.xxxx.xxxxxxx$JavaScriptInterface.onCanGoBackResult(xxxx.java:96)
E/StrictMode( 1546):   at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
E/StrictMode( 1546):   at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
E/StrictMode( 1546):   at android.os.Handler.dispatchMessage(Handler.java:102)
E/StrictMode( 1546):   at android.os.Looper.loop(Looper.java:136)
E/StrictMode( 1546):   at android.os.HandlerThread.run(HandlerThread.java:61)

在js调用后的Java回调线程并不是主线程。如打字与印刷日志可验证

ThreadInfo=Thread[WebViewCoreThread,5,main]

化解上述的十三分,将webview操作放在主线程中就能够。

webView.post(new Runnable() {
    @Override
    public void run() {
        webView.loadUrl(YOUR_URL).
    }
});

private void testEvaluateJavascript(WebView webView) {

webView.evaluateJavascript(“javascript:getGreetings(‘”+”hello
world!”+”‘)”,newValueCallback() {

@Override

publicvoidonReceiveValue(String value) {

Log.i(LOGTAG,”onReceiveValue value=”+ value);

}

});

}

从上面的用法中很领悟看见,通过evaluateJavascript调用JS中的方法,能够向个中增添结果回调,来选拔JS的return值。

注意:

地点节制了结果回到结果为String,对于简易的类型会尝试调换来字符串再次来到,对于复杂的数据类型,建议以字符串格局的json重回。

evaluateJavascript方法必得在UI线程(主线程)调用,由此onReceiveValue也推行在主线程。

—————————————————————-分割线————

二、JS调用Android

在WebView中使用JavaScript

一经在您的WebView中您就要加载的网页使用JavaScript,你必得为您的WebView启用JavaScript。一旦Javascript启用,你能够在您的施用代码和你的JavaScript代码之间创立接口。

Enabling JavaScript

启用Javascript

Javascript在WebView中暗中同意是禁止使用的,你不得不为您的WebView启用Javascript。你能够透过getSetting(State of Qatar方法取得WebSettings,然后使用setJavaScriptEnabled())启用Javascript。

例如:

WebView myWebView=(WebView)findViewById(R.id.webview);

WebSettings webSettings=myWebView.getSettings();

webSettings.setJavaScriptEnabled(true);

WebSettings提供了拜谒琳琅满指标别的有效的安装。举例,固然您正在开采一款在你的Android应用中钦赐WebView设计的web应用,然后您能够接收setUserAgentString(State of Qatar定义一个自定义用户代理字符,然后在你的网页中询问自定义顾客代理字符来核算客商端诉求网页确实来自Android应用。

Binding JavaScript code to Android code

绑定JavaScript代码到Android代码

当正在开辟一款在Android应用中钦点WebView设计的web应用时,你能够在你的Javascript和客户端Android代码之间创设接口。比如,在您的Android代码中您的Javascript代码能够调用几个方法来展现贰个会话框Dialog,并非选用Javascript的alert(卡塔尔国成效。

在您的JavaScript和Android代码之间,要绑定贰个新的接口,须调用addJavascriptInterface()卡塔尔国方法,给这一个法子传进贰个绑定到你的JavaScript的类实例和一个(你的JavaScript能够调用来拜会这几个类)的接口名。

譬喻,你能够在您的Android应用中富含下边包车型大巴类:

public class WebAppInterface{

ContextmContext;

/** Instantiate the interface and set the context */

WebAppInterface(Contextc){

mContext=c;

}

/** Show a toast from the web page */

@JavascriptInterface

publicvoidshowToast(Stringtoast){

Toast.makeText(mContext,toast,Toast.LENGTH_SHORT).show();

}

}

悉心:借使您曾经设置你的 targetSdkVersion
为17还是越来越高版本,你必须给你的的JavaScript能够拿走到的艺术(方法必需是Public)增添@JavascriptInterface注释。借让你不提供注释,当您的网页运转在Android
4.2照旧越来越高版本的系统时,这几个主意是获得不到的。

在此个事例中,WebAppInterface类允许网页使用showToast(State of Qatar方法成立一个Toast音信。

通过addJavascriptInterface()卡塔尔(قطر‎方法,你能够绑定这些类到您的WebView运维的JavaScript中,并命名Android接口。比方:

WebView webView=(WebView)findViewById(R.id.webview);

webView.addJavascriptInterface(newWebAppInterface(this),”Android”);

那给运转在WebView中的JavaScript创立了叫“Android”的接口。在那,你的网页应用能够访问WebAppInerface类。举个例子,这有局地HTML和JavaScript(当顾客点击按键时接受新接口创制toast消息的Javascript):

function showAndroidToast(toast){

Android.showToast(toast);

}

从JavaScript带头化Android接口是没有必要的。WebView自动使接口能够被您的网页获取。所以,点击开关时,showAndroidToast(卡塔尔(قطر‎作用使用Android接口调用WebAppInterface.showToast(State of Qatar方法。

注:绑定到您的JavaScript对象运营在另二个线程,并非在它被创建的线程。

注意:使用addJavascriptInterface()卡塔尔方法JavaScript调整你的Android应用。这是那一个实用的特征照旧是叁个危险的安全主题材料。当HTML在WebView中是不可靠的(比如,部分或任何的HTML是由笼统身份的人和经过提供的),攻击者能够在您的HTML中实践你的顾客端代码,并且攻击者选拔的代码恐怕是别的代码。那样,除非在您的WebView中的全体的HTML和JavaScript代码都以你写的,不然,你绝不选取addJavascriptInterface()卡塔尔(قطر‎方法。在您的WebView中,你也理应不要允许顾客去导航到此外的不是您本身的网页(相反,允许客户的私下认可浏览器去开荒不相干的链接——暗中同意情况下,客户的浏览器展开所有的链接,所以在下边小节的叙说中一旦您管理网页导航应小心)。

发表评论

电子邮件地址不会被公开。 必填项已用*标注