Android javascript混合开发

1.在WebView中使用JavaScript

Android提供了一个很强大的WebView控件用来处理Web网页,而在网页中JavaScript又是一个很举足轻重的脚本。因此,使用WebView时经常会涉及到Android代码和JavaScript代码的交互。

实现Java和js交互通常只需要以下几步:

①WebView开启JavaScript脚本执行。

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

WebSettings webSettings = myWebView.getSettings();

webSettings.setJavaScriptEnabled(true);

②WebView设置供JavaScript调用的交互接口。

③客户端和网页端编写调用对方的代码。

2.JavaScript调用Android中的方法

比如,可以用JavaScript代码调用Android代码中的方法,来展现一个对话框,而不是使用JS中的alert()方法。

在JS和Android代码间绑定一个新的接口,需要调用addJavascriptInterface()方法。该方法参数传入一个Java对象实例和一个字符串,该字符串是一个名字(interface name,注意此接口不是通常所说的那个用来实现的接口,而是传入的这个对象在JS中的别名),在JS代码中用此名字调用该Java对象的方法。

addJavascriptInterface()方法可以让JS代码控制宿主程序,这是一个非常有力的特性,但是同时也存在一些安全问题,因为进一步JS代码可以通过反射访问到注入对象的公有域。攻击者可能会在HTML和JavaScript中包含了有威胁性的代码。所以Android 4.1,API 17开始,只有被JavascriptInterface注解标识的公有方法可以被JS代码访问。

另外,因为JS代码和Java对象在这个WebView所私有的后台线程交互,所以还需要注意线程安全性问题。

注意,与JS代码绑定的的这个Java对象运行在另一个线程中,与创建它的线程不是一个线程。而且这个Java对象的域是不可访问的。

//自定义的Android代码和JavaScript代码之间的桥梁类

public class WebAppInterface {

    Context mContext;

    WebAppInterface(Context c) {

        mContext = c;

    }

    // 如果target>=API 17,则需要加上如下注解

   @JavascriptInterface

    public void showToast(String toast) {

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

    }

}

然后将这个类和WebView中的JS代码绑定:

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

webView.addJavascriptInterface(new WebAppInterface(this), "Android"); //给这个对象起的别名叫“Android”

这样就创立了一个接口名,叫“Android”,运行在WebView中的JS代码可以通过这个名字调用WebAppInterface类中的showToast()方法:

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">

    function showAndroidToast(toast) {

        Android.showToast(toast);

    }

</script>

3.Android调用JavaScript代码

这个还比较简单,需要调用的时候只需要一行代码:

myWebView.loadUrl("javascript:myFunction()");

其中myFunction()是JS函数。

注意:如果JavaScript函数是带参数的,那么调用时要特别注意。

比如下面这个JS函数,在原来内容上加入一行:

function writeLine(string) {

    console.log("Write a new Line");

    document.getElementById("content").inn erHTML += string + "<br />";//在content标签段落加入新行

}

其中content是自定义的标签,html中有一个段落是:<p id="content"></p>

那么在Android代码中调用这个writeLine()函数时,需要传入一个字符串参数,比如想要传入一个叫name的String:

myWebView.loadUrl("javascript:writeLine('"+name+"')");//JS代码要是带参数

注意:双引号中的函数名一定不要写错。

4.使用举例

①Android端代码:

public class MainActivity extends Activity {

  @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(this, 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>

③JS调用Java

调用格式为window.jsInterfaceName.methodName(parameterValues),此例中使用的是control作为注入接口名称。

function toastMessage(message) {

  window.control.toastMessage(message)

}

function sumToJava(number1, number2){

   window.control.onSumResult(number1 + number2)

}

④Java调用JS

webView调用js的基本格式为:webView.loadUrl(“javascript:methodName(parameterValues)”)

1)调用js无参无返回值函数:

String call = "javascript:sayHello()";

webView.loadUrl(call);

2)调用js有参无返回值函数:

String call = "javascript:alertMessage(\"" + "content" + "\")"; //注意对于字符串作为参数值需要进行转义双引号。

webView.loadUrl(call);

3)调用js有参数有返回值的函数

Android在4.4之前并没有提供直接调用js函数并获取值的方法,所以在此之前,常用的思路是 java调用js方法,js方法执行完毕,再次调用java代码将值返回。

第一步:Java调用js代码:

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

webView.loadUrl(call);

第二步:js函数处理,并将结果通过调用java方法返回

function sumToJava(number1, number2){

   window.control.onSumResult(number1 + number2)

}

第三步:Java在回调方法中获取js函数返回值

@JavascriptInterface

public void onSumResult(int result) {

  Log.i(LOGTAG, "onSumResult result=" + result);

}

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也执行在主线程。

猜你喜欢

转载自blog.csdn.net/zenmela2011/article/details/130970132