昨今の Android アプリ開発は主に Kotlin を用いて行われるようになりました。
Kotlin は 2011 年注1 に発表され、2017 年の Google I/O 注2 で Android 公式開発言語に追加されました。
本書では Android 向けの Tips 集として、Android アプリ開発に関するノウハウを紹介します。
本書に記載された内容は、情報の提供のみを目的としています。
したがって、本書を用いた開発・製作・運用は、必ず自身の責任と判断によって行ってください。
これらの情報による開発・製作・運用の結果について、著者はいかなる責任も負いません。
本書で紹介するソースコードは以下から入手できます。
https://github.com/usayuki/IntercommunicationWithJavascriptSample
https://github.com/usayuki/PhotoGallerySample
https://github.com/usayuki/crypto
注1 2011 年 7 月 20 日
注2 2017 年 5 月 17 日の Google I/O 2017
はじめに
第1章 JavaScript との相互通信
第2章 写真アプリを作成する
第3章 リソース管理術
第4章 暗号化、複合をコマンドラインで行う
おわりに
本章では、Web アプリ(JavaScript)とネイティブアプリ(Kotlin)とで相互通信を行う側アプリの作成方法を解説します。
作成するアプリは Web アプリで入力した数値をネイティブアプリで 2 倍し、その結果を Web アプリで表示するというシンプルなものです。
アプリ内で表示する Web アプリの UI を作成します。
head では次節以降で作成する index.js と interface.js と jQuery を読み込みます。
<head> <meta charset="utf-8"> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/ jquery/3.4.1/jquery.min.js"></script> <script src="interface.js"></script> <script src="index.js"></script> </head>
次に body で今回の Web アプリの UI を作成します。
UI はタイトルと数値の入力欄、ネイティブアプリで 2 倍にするための計算ボタンを配置します。
<body> <h1> 入力した値を 2 倍にする </h1> <input class="input_area" type="text"> <div class="text"> ここに結果が出る </div> <div class="btn"> 計算する </div> </body>
以下が index.html のソースコード全文です。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/ jquery/3.4.1/jquery.min.js"></script> <script src="interface.js"></script> <script src="index.js"></script> </head> <body> <h1> 入力した値を 2 倍にする </h1> <input class="input_area" type="text"> <div class="text"> ここに結果が出る </div> <div class="btn"> 計算する </div> </body> </html>
まず、さきほど作成した html の計算するボタンが押された際の処理を index.js ファイルに実装します。
「計算する」ボタンがクリックされたら、入力欄の値を取得します。
$('.btn').on('click', function() { var number = $('.input_area').val(); });
次に、ネイティブアプリと疎通を行う interface.js のインスタンスを作成し値を渡します。
var interface = new Interface(); interface.double(number);
以下が index.js のソースコード全文です。
$(function() { $('.btn').on('click', function() { var number = $('.input_area').val() var interface = new Interface(); interface.double(number); }); });
ネイティブアプリと疎通を行う interface.js を作成します。
まずは Interface オブジェクトを作成します。
var Interface = function() {};
次に、index.js から呼び出されるメソッドを Object.prototype を用いて実装します。
詳しい解説は 1-5「JavaScript から Kotlin のメソッドを実行する」の「JavaScript 側の実装をする」を参照してください。
Interface.prototype.double = function(number) { alert("double:" + number); };
次に、Kotlin 側から呼び出されるメソッドを定義します。
こちらは window オブジェクトを拡張して実装します。
ここで、Kotlin 側から送られてきた値を、html に表示します。
詳しい解説は 1-6「Kotlin から JavaScript のメソッドを実行する」の「JavaScript 側の実装をする」を参照してください。
window.double = function(number) { $('.text').text(number); };
以下が interface.js のソースコード全文です。
window.double = function(number) { $('.text').text(number); }; var Interface = function() {}; Interface.prototype.double = function(number) { alert("double:" + number); };
html と JavaScript ファイルを配置する assets ディレクトリを作成します。
右クリック > New > Folder > Assets Folder を選択します。
次に作成した Assets ディレクトリに html と JavaScript ファイルを配置します。
プロジェクト内に組み込んだ html と JavaScript ファイルを読み込みます。
webView.loadUrl("file:///android_asset/index.html")
JavaScript を実行するには、AndroidManifest に次の権限を設定します。
<uses-permission android:name="android.permission.INTERNET"/>
WebView の設定を行います。
今回は画面全体に WebView を配置します。
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity"> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent"/> </androidx.constraintlayout.widget.ConstraintLayout>
次に、WebView 内で JavaScript を有効にします。
val settings = webView.getSettings() settings.setJavaScriptEnabled(true)
JavaScript から Kotlin のメソッドを実行するには WebChromeClient の onJsAlert を使用します。
JavaScript から実行したメソッドは onJsAlert の message で受け取れます。
onJsAlert の戻り値で AlertView の表示を制御しており、今回は表示しないため true を設定します。
※ AlertView を表示しない場合、見た目上は表示されていませんが、透明な AlertView が表示された状態となっています。
そのため、そのままだと操作不能になってしまうので、result.cancel() で Alert のキャンセルを実行して AlertView を閉じる必要があります。
webView.setWebChromeClient(object: WebChromeClient() { override fun onJsAlert(view: WebView, url: String, message: String, result: JsResult): Boolean { result.cancel() return true } })
今回は「:」をセパレーターにして、メソッド名 : 値 1 としています。
そのため、受け取った message を「:」で分割し、JavaScript でどのメソッドを呼んだかを判断します。
val components = message.split(":") when(components[0]) { "double" - > { val numString = components[1] val number = numString.toInt() val result = number * 2 webView.evaluateJavascript("window.double($result)", null) } }
Kotlin のメソッドを呼び出したい箇所で、alert(method + messageBody) を実装します。
method の部分は Kotlin 側で定義した呼び出したいメソッド名を入れてください。
messageBody の部分は Kotlin 側に渡したい値を入れてください。
Kotlin は Swift と異なり、JavaScript の alert をハンドリングするため文字列しか使用できません。
そのため、呼び出したいメソッド名や渡したい値を 1 つの文字列にする必要があります。
今回は「:」をセパレーターにして、メソッド名 : 値 1 としています。
alert("double:" + number);
JavaScript のメソッドを呼び出したい箇所で、evaluateJavascript(String script, ValueCallback <String> resultCallback) を実装します。
このメソッドの第一引数は文字列のため、呼び出したい JavaScript のメソッドは "" で囲う必要があります。
webView.evaluateJavascript("window.double($result)", null)
window オブジェクトを拡張して Kotlin から呼び出せるようにします。
window.double = function(number) { $('.text').text(number); }