Tips : WebViewからAndroid側の機能を利用する
Androidアプリをデザインしていると、表現に苦労することがあります。
CSSなら簡単にできるのに、、、とおもってWebViewを使ってみることにしました。
(場合によって、やはり表示までの時間とか、JSのアニメーションとかのパフォーマンス課題もあるようですが…)
WebViewを使うにあたって、例えばボタンおしたらActivity遷移したいとか、Android側の機能も使いたいと思って、まずはその方法を試しました。
(外部のWebサイトとかにアクセスするようにすると、セキュリティの危険などもあるので必要に応じて内部で利用するのがいいかなと思っています)
WebViewのaddJavascriptInterfaceを使う
WebViewにはaddJavascriptInterfaceというメソッドがあり、それを通してAndroid側の機能をAPIとしてJS側に見せることができます。 これを使えばWebViewの外、つまりAndroidアプリ側の制御をJS側からできるようになるので、HTML/CSSでアプリUIをデザインするのに役立ちます。
例えばJavascriptAdapterというクラスを用意して、こんな感じでそのインスタンスをセットできます。
ここではandroid
という名前をこのオブジェクトに与えているので、JS側からはandroid.xxx
という形で利用できます。
JavascriptAdapter jsobj = new JavascriptAdapter(position); webView.addJavascriptInterface(jsobj, "android");
WebViewのテキストをAndroidのTTSで読み上げる
このJavascriptInterfaceを使った例として、WebView内のコンテンツ読み上げをしてみたいと思います。
Java側のコードはこんな感じです。
public class MainActivity extends Activity implements TextToSpeech.OnInitListener { private TextToSpeech tts; private HashMap<String,String> param; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WebView webView = new WebView(this); webView.getSettings().setUseWideViewPort(true); webView.getSettings().setLoadWithOverviewMode(true); webView.getSettings().setJavaScriptEnabled(true); JavascriptAdapter jsobj = new JavascriptAdapter(); webView.addJavascriptInterface(jsobj, "android"); webView.loadUrl("file:///android_asset/www/index.html"); setContentView(webView); tts = new TextToSpeech(this,this); param = new HashMap<String, String>(); param.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "any"); } @Override protected void onDestroy() { super.onDestroy(); if (null != tts) { tts.shutdown(); } } @Override public void onInit(int status) { if (TextToSpeech.SUCCESS == status) { Locale locale = Locale.JAPANESE; if (tts.isLanguageAvailable(locale) >= TextToSpeech.LANG_AVAILABLE) { tts.setLanguage(locale); } else { Log.w("[TTS][Warning]","locale is not available"+locale); } } else { Log.e("[TTS][Error]","Init status:"+status ); } } class JavascriptAdapter { public JavascriptAdapter() { } public void speachText(String text) { if (0 < text.length()) { if (tts.isSpeaking()) { tts.stop(); } tts.speak(text, TextToSpeech.QUEUE_FLUSH,param); } } } }
まずWebViewを準備します。
setUseWideViewPort(true)
とsetLoadWithOverviewMode(true)
はHTMLコンテンツのViewPortや拡縮がおかしくならないようにするためのおまじないです。
ちなみに、日本語TTSエンジンはKDDIのN2を使っています。
今回はassets
以下に配置したローカルのHTMLコンテンツを使います。
HTML/JS側のコードはこちらです。
<!doctype html> <html lang="jp"> <head> <meta charset="UTF-8"/> <meta name="viewport" content="target-densitydpi=device-dpi, width=device-width" /> <title>Page</title> </head> <body> <input type="button" value="Speach!" onclick="speach()"> <script> function speach(){ android.speachText("こんにちは!"); } </script> </body> </html>
これで、JSからAndroid側のTTSを利用することができました。
応用すればHTML/CSSで記述したUIから、Android側の制御もできるかと思います。