ネイティブアプリなんだけどネイティブのコードは極力書かず、WebViewを使ってhtml+JavaScriptを使ってアプリを組みたい。今回はAndroid, Javaで作ってみる。

コード

  • ‘16/12/01: 環境をAndroidStudio、使用言語をKotlinに変更しました

WebViewを全画面の大きさで配置する

レイアウトのxmlで指定する

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.tyfkda.gawanativeandroid.MainActivity" >

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>
  • layout_widthlayout_heightともにmatch_parentを指定することで全画面にする

htmlの表示

配置したWebViewを使ってJavaからブラウザを操作する。

// MainActivity.kt
class MainActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val webView = findViewById(R.id.webView) as WebView
    webView.loadUrl("http://www.example.com/")
  }
}
  • findViewByIdでWebViewを取得して、WebView#loadUrl でページの読み込みを指定できる
  • インターネットからウェブページを読み込むためにはAndroidManifest.xmlで<uses-permission android:name="android.permission.INTERNET"/> を指定して、アプリでのインターネット利用を有効にする必要がある

アセット内のhtmlの表示

外部のurlではなく、アセットに含めたhtmlファイルを読み込むにはURLにfile:///android_asset/〜と指定する

// Kotlin
    webView.loadUrl("file:///android_asset/index.html")
  • Android Stuidoでassetsフォルダを追加するには、appを選択して、メニューのFile > New > Folder > Assets Folder

アセット内のhtmlから画像、JavaScript、CSSを読み込む

html内で相対パスで書けばアセット内のファイルが自動的に読み込まれる

<link rel="stylesheet" type="text/css" href="main.css" />
<img src="hydlide.png" />
<script type="text/javascript" src="main.js"></script>

JavaScriptとネイティブの連携

JavaScriptからネイティブ(Java)を呼び出す

JavaScriptからネイティブに対してなにか起動するにはWebViewにインタフェース用のクラスを定義し

class MyJavaScriptInterface(private val context: Context) {
  @JavascriptInterface
  fun showToast(string: String) {
    Toast.makeText(context, string, Toast.LENGTH_SHORT).show()
  }
}

オブジェクトを登録してやると

// Kotlin
    webView.addJavascriptInterface(MyJavaScriptInterface(this), "Native")

JavaScriptから呼び出すことができる:

// JavaScript
Native.showToast('PushMe clicked!')

ネイティブからJavaScriptを呼び出す

WebView#loadUrlを使用する:

// Kotlin
    webView.evaluateJavascript("(JavaScriptのコード)", null)
  • WebView#evaluateJavascriptを使う
    • 第二引数は結果受け取りコールバック
  • API level 19(KITKAT)より前の場合には上のメソッドがないので、JavaScriptのコードを表す文字列の前に"javascript:"を追加した内容をurlとしてloadUrlを呼び出すことでJavaScriptコードが実行される

URLリクエストを横取りする

Javaで登録したインタフェースのメソッドをJavaScriptから呼び出せるので、使うかどうかわからないけど、URLリクエストも横取りできる。

// Kotlin
    webView.setWebViewClient(object : WebViewClient() {
      override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
        ...
      }
    })
  • WebViewに対して setWebViewClientWebViewClient を登録できて、そのshouldOverrideUrlLoadingでURLに対する処理を扱える
    • 横取りしてなにか処理した時にはtrueを返す、そうでなくて通常の読み込みを継続する場合には false を返す

実行例

ss.png

注意