webview上でjavascriptからjavaメソッドを実行する

書籍でみかけたりはしてた。
が、頭の中で整理できてない気がするので、すっきりしようと。

1. webkit上にHTMLを表示

WebView webView = new WebView(this);
webView.loadData("<h1>まずはHTMLを表示</h1>", "text/html", "utf-8");
setContentView(webView);

2. javascriptも表示

String html = "<script type='text/javascript'>alert('jsですよー');</script>\n" +
              "<h1>まずはHTMLを表示</h1>";
WebView webView = new WebView(this);

// JavaScriptを有効にする
webView.getSettings().setJavaScriptEnabled(true);

webView.loadData(html, "text/html", "utf-8");
setContentView(webView);

ここで、webkit(webview)にjavaオブジェクトを登録する方法を確認してみる.

マニュアル

public void  addJavascriptInterface  (Object obj, String interfaceName)
Use this function to bind an object to Javascript so that the methods can be accessed from Javascript. 

サンプルコード1

<html>
  <head><title>JS calls Android Method</title></head>
  <body>
    <h1>JS on Android</h1>
    <script type="text/javascript">
      document.write(roid.gps("<i>", "</i>"));
    </script>
  </body>
</html>
public class WebkitTest extends Activity {
  /** Called when the activity is first created. */
  @Override
   public void onCreate(Bundle icicle) {
      super.onCreate(icicle);
      WebView wv = new WebView(this);
      wv.getSettings().setJavaScriptEnabled(true);
      JsObj jo = new JsObj(this);
      wv.addJavascriptInterface(jo, "roid");
      setContentView(wv);
      wv.loadUrl("http://www.adamrocker.com/android/js2android.html");
  }
 
   class JsObj {
      private Context con;
 
      public JsObj(Context con) {
         this.con = con;
      }
 
      public String gps(String top, String end) {
         LocationManager locman = (LocationManager) con
              .getSystemService(Context.LOCATION_SERVICE);
         Location loc = locman.getCurrentLocation("gps");
         int lat = (int) (loc.getLatitude() * 1000000);
         int lon = (int) (loc.getLongitude() * 1000000);
         return top + "緯度:" + lat + ", 経度: " + lon + end;
      }
  }
}

サンプルコード2

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>JsTest</title>
  </head>
  <body>
    <div id="container">
        <div id="android_js"><h2>Broeser->Android</h2>
          <p id="android_js_get"></p>
          <form>
            <input type="button" value="送信" onClick="for_android()">
          </form>
          <script type="text/javascript">
            function for_android() {
              android.setString("for Browser");
            }
          </script>
        </div>
    </div>
  </body>
</html>
/* JavaScriptの許可と登録 */
webview.getSettings().setJavaScriptEnabled(true);
Hoge hoge = new Hoge();
webview.addJavascriptInterface(hoge, "android");

/* WebPage指定 */
webview.loadUrl("file:///android_asset/index.html");

public class Hoge {
  public void setString(final String arg) {
    /* メインスレッドの実行キューにセット */
    handler.post(new Runnable() {
      public void run() {
        textview.setText(arg);
      }
    });
  }
}

要するに、つながりかたは、

<script type="text/javascript">
javascript-object.android-method();
</script>
Hoge android-object = new Hoge();
webview.addJavascriptInterface(android-object, "javascript-object");

という雰囲気、うまくかけないけども。

3. javascriptからトーストを。

   <uses-permission android:name="android.permission.INTERNET" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
function for_android() {
  android.appearToast("パンが焼けましたよ");
}
</script>
</head>
<body>
  <input type="button" value="パンを焼く?" onClick="for_android()">
</body>
</html>
package com.example.js2toast;

import android.app.Activity;
import android.os.Bundle;
import android.content.Context;
import android.webkit.WebView;
import android.widget.Toast;

public class Js2Toast extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WebView webview = new WebView(this);
        webview.getSettings().setJavaScriptEnabled(true);
        Hoge hoge = new Hoge(this);
        webview.addJavascriptInterface(hoge, "android");
        setContentView(webview);
        webview.loadUrl("http://yourhost/js2toast.html");
    }

    public class Hoge {

        private Context con;

        public Hoge(Context con) {
          this.con = con;
        }

        public void appearToast(String message) {
            Toast.makeText(con, message,
                           Toast.LENGTH_LONG).show();
        }
    }

}

WEBサーバ上にあるHTMLファイル内のJavascript内の文字列の
「パンが焼けましたよ」
Androidアプリ上のトーストに表示される。