history.back()が出来る状況が毎度毎度分からなくなってしまうので、ここにまとめておきます。
また、AppからWebViewの機能を呼ぶ、WebViewからAppの機能を呼ぶということもどうゆう状況だとできるのかもまとめておきます。
むしろこっちのほうが忘れやすい。
history.back()
ローカルHTMLファイルの場合
iPhone | 動かない |
Android | 動く |
リモートHTMLファイルの場合
iPhone | 動く |
Android | 動く |
なので、history.back()を前提にしているjQueryMobileを使うサイトは、ローカルではなくリモートを参照したほうがいいでしょう。
Titanium.App.fireEvent
ここはTitaniumのfireEventが動く範囲をまとめてみました。
ローカルHTMLファイルの場合
iPhone | 動く |
Android | 動く |
リモートHTMLファイルの場合
iPhone | 動かない |
Android | 動かない |
iPhoneとWebView
ここからはネイティブの話しになります。
iPhoneでアプリ側からWebViewに対してJavaScriptを実行する方法
「App → WebView」
WebViewをもつViewControllerのヘッダファイルにて、UIWebViewDelegateプロトコルを指定しておく。
@interface ViewController : UIViewController <UIWebViewDelegate>
すると以下のメソッドたちが使えるので、準備しておく。
- (void)webViewDidStartLoad:(UIWebView *)webView { } - (void)webViewDidFinishLoad:(UIWebView *)webView { } - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { return YES; // Return YES to make sure regular navigation works as expected.} }
あとはstringByEvaluatingJavaScriptFromStringを呼び出すだけ。
- (void)webViewDidFinishLoad:(UIWebView *)webView { NSString *title = [self.webView stringByEvaluatingJavaScriptFromString:@"$.method()"]; NSLog(@"title - %@", title); }
このメソッドの便利なところは、returnがあるところ、後述するがAndroidのほうだとreturnが返ってこないので、少し強引に取得する必要があったりする。
WebViewからiPhoneアプリ側に処理を通知する方法
「WebView → App」
こっちはURLのリクエスト時に、自分宛、つまり自分のアプリ内で処理して欲しいURLを渡して、それを監視している。
結果、ルールにのっとったURLの場合は、適切な処理を呼べば良い。
面白いところは、自分宛のリクエストはreturn NOを返してなかったことにしている。
これをしないと、真っ白な画面に遷移してしまう。
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString *requestString = [[request URL] absoluteString]; NSArray *components = [requestString componentsSeparatedByString:@":"]; if ([components count] > 1 && [(NSString *) [components objectAtIndex:0] isEqualToString:@"myapp"]) { if ([(NSString *) [components objectAtIndex:1] isEqualToString:@"myfunction"]) { // ここで何か処理 NSLog(@"%@", [components objectAtIndex:2]); // param1 NSLog(@"%@", [components objectAtIndex:3]); // param2 } return NO; } return YES; // Return YES to make sure regular navigation works as expected.} }
WebViewからの呼び出し方。
location.href = "myapp:" + "myfunction:" + param1 + ":" + param2;
比較的にシンプルにできるが、ディレクトリトラバーサルなど、セキュリティに気をつける必要がある。
AndroidとWebView
Androidでアプリ側からWebViewに対してJavaScriptを実行する方法
iPhone型と違って、view.loadUrlにjavascriptスキームを渡してもreturnが得られません。
なので、ハックに近いですが、あえてalertを実行させ、そのアラートが出る前のイベントonJsAlertでメッセージから情報を取得します。
そのあとに、result.confirm()をすることで、アラートがなかったことにできるようです。
なかなか面白いですね。
WebView webview = (WebView) findViewById(R.id.webView1); webview.getSettings().setJavaScriptEnabled(true); webview.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { view.loadUrl("javascript:alert($.method())"); } }); webview.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { try { System.out.println("onJsAlert - " + message); return true; } finally { // アラートが出ないようにしている result.confirm(); } } }); webview.loadUrl("http://lab.hisasann.com/appEval/");
WebViewからAndroidアプリ側に処理を通知する方法 – その1
WebViewからAndroidアプリ側に情報を渡すのは以下の感じで、iPhone側とすごく似ていますね。
ただ、Androidのほうは直接JavaScriptコードからAndroid側のアプリをキックできるようです。
それは後述します。
webview.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { String[] components = url.split(":"); // 特定のURLの場合、ダイアログを表示する等 if (components[0].length() > 1 && "myapp".equals(components[0])) { if ("myfunction".equals(components[1])) { System.out.println(components[2]); System.out.println(components[3]); return true; } } return false; } });
WebViewからの呼び出し方。
location.href = "myapp:" + "myfunction:" + param1 + ":" + param2;
WebViewからAndroidアプリ側に処理を通知する方法 – その2
先ほどのwebview変数にJavascriptInterfaceをセットします。
webview.addJavascriptInterface(new JavascriptAdapter(), "android");
そのアダプターの中で、JavaScriptから呼び出されるメソッドを定義しておきます。
package com.example.sample_webvieweval; import android.os.Handler; public class JavascriptAdapter { private Handler handler = new Handler(); // JavaScriptから呼び出されるメソッド public void getFromJS(final String s) { handler.post(new Runnable() { public void run() { System.out.println(s); } }); } }
WebViewからの呼び出し方。
// Javaのメソッドを呼び出す window.android.getFromJS("called getFromJS");
するとこのようにwindowオブジェクトの中にJavascriptInterfaceの名前空間が追加されているので、そこから呼びたいメソッドをコールできます。
すごく簡単!
すごく簡単なんだけど、やっぱりこれもセキュリティをかなり意識しないといけないですね。
参考リンク
- TitaniumMobileのハマりポイントとお作法メモ at HouseTect, JavaScriptな情報をあなたに
- AndroidのWebViewでJavaScriptを実行する
- AndroidのWebViewを使う
- JavaとJavascriptの連携 | Android Wiki for Developers
- WebViewでshouldOverrideUrlLoading()が反応しない問題|てくめも@ecoop.net
インプレスジャパン
売り上げランキング: 13499