この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 プログラムからJavaScriptを操作する
ブラウザは、アプリの中で動作している場合に限り、コードからJavaScriptを実行したり、逆にJavaScriptからコードにアクセスすることが可能です。 今回は、Xamarin.FormsのWebViewでJavaScriptを実行することで、プログラムからGoogle検索をしてみました。
2 固有ブラウザ
Xamarin.Formsで使用するWebViewは、各プラットフォームごと動作しているブラウザが違うため、JavaScriptを実行する方法も異なります。 そこで、共通的に利用できるようにWebViewを拡張して、メソッドを1つ追加しました。 実際の実装は、レンダラーで行う事になります。
App.cs
public class ExWebView : WebView {
public delegate void CallJsHandler(string js);
public CallJsHandler CallJs;//JavaScriptの実行
}
3 レンダラー
続いて、各プラットフォームのレンダラーを実装します。
(1) iOS
iOSで動作しているUIKit.UIWebViewは、EvaluateJavascriptメソッドでJavaScript の実行が可能です。
ExWebViewRenderer.cs
using CallingJavascriptSample;
using CallingJavascriptSample.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms.CallingJavascriptSample;
[assembly: ExportRenderer(typeof(ExWebView), typeof(ExWebViewRenderer))]
namespace CallingJavascriptSample.iOS
{
public class ExWebViewRenderer : WebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e) {
base.OnElementChanged(e);
var exWebView = e.NewElement as ExWebView;
if (exWebView!=null) {
exWebView.CallJs = CallJs;
}
}
public void CallJs(string js) {
//this = UIKit.UIWebView
//this.EvaluateJavascript(js);
EvaluateJavascript(js);
}
}
}
(2) Android
Androidで動作しているAndroid.Webkit.WebViewは、LoadUrl("javascript:" + js)でJavaScript の実行が可能です。
ExWebViewRenderer.cs
using Android.Webkit;
using Xamarin.Forms.CallingJavascriptSample;
using Xamarin.Forms.CallingJavascriptSample.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using WebView = Xamarin.Forms.WebView;
[assembly: ExportRenderer(typeof(ExWebView), typeof(ExWebViewRenderer))]
namespace Xamarin.Forms.CallingJavascriptSample.Droid
{
class ExWebViewRenderer:WebViewRenderer{
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e){
base.OnElementChanged(e);
var exWebView = e.NewElement as ExWebView;
if (exWebView != null) {
exWebView.CallJs = CallJs;
}
Control.SetWebChromeClient(new WebChromeClient());
}
public void CallJs(string js){
//Android.Webkit.WebView
Control.LoadUrl("javascript:" + js);
}
}
}
4 JavaScriptの実行
それでは、この拡張ブラウザを使用して、JavaScriptを実行する画面を作成してみます。 Entryに入力された文字列をJavaScriptのコードとしてブラウザに送って実行するものです。
App.cs
namespace Xamarin.Forms.CallingJavascriptSample
{
public class App : Application
{
public App ()
{
MainPage = new MyPage();
}
}
class MyPage : ContentPage {
public MyPage() {
var webView = new ExWebView() {
Source = "http://www.google.com",
VerticalOptions = LayoutOptions.FillAndExpand,
};
var entry = new Entry() {
HorizontalOptions = LayoutOptions.FillAndExpand
};
var button = new Button {
WidthRequest = 60,
Text = "OK"
};
button.Clicked += async (s, a) => {
if (!string.IsNullOrEmpty(entry.Text)) {
webView.CallJs(entry.Text);
}
};
Content = new StackLayout {
Padding = new Thickness(0,Device.OnPlatform(20,0,0),0,0),
Children = {
new StackLayout {
BackgroundColor = Color.Navy,
Padding = 5,
Orientation = StackOrientation.Horizontal,
Children = { entry,button}
},webView
}
};
}
}
}
実行画面は、次の通りです。alert()が実行されていることを確認できます。
5 IDの取得と動作確認
JavaScriptの実行が確認できたので、続いて、目的のgoogle検索に移ります。
まずは、Chromeの「要素の検証」を使用して、検索文字の入力位置、及び検索開始ボタンのid(name)を確認します。
↓idは「lst-ib」であることが分かる
↓nameは「btnG」であることが分かる
続いて、ChromeのデベロッパーツールのConsoleを使用して、JavaScriptの動作を確認しています。
//検索文字列に「123」をセットする document.getElementById('lst-ib').value='123'; //「検索」ボタンをクリックする document.getElementsByName('btnG')[0].click();
↓スクリプトが実行されて、意図する動作をしていることが確認できる。
6 アプリからの操作(Google検索)
目的の動作をするJavaScriptができたので、検索文字列をEntryから取得して、OKボタンでブラウザに送り込むようにしてみます。 修正したのはボタンのイベントハンドラだけです。
App.cs
button.Clicked += async (s, a) => {
var js = string.Format("document.getElementById('lst-ib').value='{0}';",entry.Text);
webView.CallJs(js);
await Task.Delay(2000);//少しタイミングを計らないと、文字入力完了前にボタンを押してしまうためDelayを入れた
js = "document.ElementsByName('btnG')[0].click();";
webView.CallJs(js);
entry.Unfocus();//キーボード非表示
};
次の画面が動作している様子です。 ブラウザには触れずに検索を実行しています。
7 最後に
タイトルに自動化と書いてしまいましたが、今回のようにプログラムから制御できるとなれば、自動化も簡単でしょう。
最近は、各種のAPI等が公開されており、それらを駆使することで色々な機能を作り込むことが可能です。しかし、サービスによっては、どうしてもブラウザから実行するしかない作業も存在します。 そのような時、ブラウザを非表示にしてしまって、今回の手法でプログラムすれば、その制約をクリアできるかも知れません。
↓サンプルコードです。
https://github.com/furuya02/Xamarin.Forms.CallingJavascriptSample