Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
Xamarin逆引きTips

Xamarin逆引きTips

MvvmCrossでWebBrowserプラグインを使用するには?

2015年6月4日

WebBrowserプラグインを追加・利用する例を通じて、MvvmCrossでのiOS/Androidアプリ開発におけるMvvmCrossプラグインの基本的な使い方を説明する。

  • このエントリーをはてなブックマークに追加

 MvvmCrossには非常に多くの機能が含まれているが、特に各プラットフォーム固有の処理を共通処理として扱えるものは「プラグイン」として分割して提供されている。

 今回はMvvmCrossのプラグイン機構の概略と、標準のプラグインをNuGetで導入して使用する方法を解説する。

  • *1 なお、本TipsはMac OS X(10.10.3), Xamarin Studio(5.9.1), MvvmCross(3.5.0)で動作を確認している(編集部注: Windows上のVisual Studioでも同様の手順で、本稿の内容が実現できることは確認している)。

プラグイン機構を使用したプラットフォーム固有処理の共通化と再利用

 プラットフォームごとの固有の処理は、iOS/Androidでそれぞれ記述して対応することもできる。しかしながらプラットフォーム固有の処理を一般化したインターフェースを用意しておき、ViewModelやServiceから一様に扱えば、ビジネスロジックは1度記述すればよくなり、生産性を向上できる。さらに、加速度センサー、位置情報の取得、Safariなどの標準ブラウザー起動といった処理は、どんなアプリでも使用する一般的なタスクのため、再利用性を上げることで多くのアプリで使用できる。

 MvvmCrossには、プラットフォームごとの固有処理をはじめとした、各種処理を再利用するための機構としてプラグインが用意されている。MvvmCrossのプラグイン機構は一定の決まりで実装されたアセンブリを、起動時にMvvmCrossが自動的に読み込み、起動コードを実行するようになっている。

 以下の図は実際のMvvmCrossプラグインの実装だが、Coreに当たるPCL(Portable Class Library)にPluginLoaderクラスが、各プラットフォーム固有実装部分にはPluginクラスがあることが分かる。Plugin.Load()メソッドが実際の処理の起点となり、多くのプラグインはこの部分でIoCコンテナー(DIコンテナー)にクラスを登録するが、コンバーターを使えるようにしたり、リソースをロードしたりするものもある。

図1 MvvmCrossプラグインの実装例

Coreに当たるPCLにPluginLoaderというクラスと、プラットフォーム固有実装部分にPluginというクラスがあることが分かる。Plugin.Load()メソッドがプラグインの処理の起点となる。

MvvmCross標準プラグイン

 MvvmCrossが提供するプラグインは本体同様、NuGetで提供されている。以下の表はMvvmCrossが標準で提供するプラグインの一覧だが、標準でも多くの機能が提供されていることが分かる。また、MvvmCross自体の一部機能も、プラグインのインストールを前提としているものもある。

プラグイン名機能概要iOSAndroidWindows PhoneWindows StoreアプリWindowsデスクトップ(WPF)
■標準機能の拡張
Messenger Messengerパターンに使用するMessenger機能を提供する
Color MvxColorを各プラットフォームのColorオブジェクトに変換するコンバーターを提供する
Visibility 表示状態へのコンバーターを提供する
JsonLocalisation JSONファイルを使用したテキストリソースローカライズ機能を提供する
ResourceLoader アプリのリソースとして埋め込まれているファイルへのアクセスを提供する
File ファイルの作成・保存機能を提供する
DownloadCache ダウンロードキャッシュ機能を提供する(MvxImageViewクラスの内部で使用される) - - -
■プラットフォーム機能やセンサーの呼び出し
Accelerometer 加速度センサーの値を取得する
Location 位置情報へのアクセスを提供する
Network ネットワークへの疎通判定(Reachability)機能を提供する
SoundEffects 音の再生機能を提供する - - - -
■外部アプリとの連携、標準ダイアログの呼び出し
PhoneCall 電話発信機能を提供する -
Email メール送信画面の起動を提供する
WebBrowser 標準ブラウザーの起動機能を提供する -
PictureChooser 写真の選択ダイアログを表示する -
Share ソーシャルへのシェア機能を提供する
Bookmarks ブラウザーブックマークへの登録機能を提供する - - - -
MvvmCrossが標準で提供する主要なプラグインと、その対応プラットフォーム

全てのプラットフォームで対応しているわけではないものや、プラットフォームによっては実装が不十分な場合もある。

 先述の通り、ほとんどのプラグインはIoCコンテナーにオブジェクトを追加するが、「Tips:MvvmCrossでカスタムコンバーターを作成するには?」でも紹介したColorプラグインとVisibilityプラグインは特殊で、コンバーターが追加される。

プラグインの追加方法

 サンプルプロジェクトを通じてプラグインの使い方を確認していこう。今回はMvvmCross標準のWebBrowserプラグインを使用して標準ブラウザーを起動させるプログラムを作る。

プロジェクトの作成

 「Tips:MvvmCrossのプロジェクトをセットアップするには?」の手順に従い、MvvmCrossプロジェクトを作成する。ソリューション名は「OpenBrowserSample」と設定する(以下のコラムでは、「MvvmCrossSample」というソリューション名で作成しており、名前に違いがあるので注意してほしい)。

【コラム】Xamarin Studio 5.9でのプロジェクト新規作成ダイアログの変更

 Xamarin Studio 5.9ではプロジェクト新規作成時のダイアログが変更されており、ウィザード形式になり分かりやすくなった。また、ストアに公開するに当たって適切に設定すべきBundle Identifier(iOS)およびパッケージID(Android)の入力が、そのウィザードで求められるようになっている。これにより、「Tips:MvvmCrossのプロジェクトをセットアップするには?」の当初の説明からプロジェクトの作成について変更が生じている(編集部注: 該当記事も新ダイアログによる操作方法の説明を更新した)。以下の内容はリンク先の記事に対する差分となる。

 まず、ソリューションおよび、共通部分となるCoreプロジェクトを作成する。

 具体的には、Xamarin Studioで(メニューバーにある)[ファイル]メニューの[新規]から[ソリューション]を選択して、ソリューション新規作成用のダイアログ(図A)を開く。プロジェクトの種類から[その他]の[.NET]にある[Portable Library]を選択し、[Next]ボタンを押す。

図A プロジェクトの種類の選択

 ダイアログ画面が[Configure your project](図B)になるので、[プロジェクト名]を「MvvmCrossSample.Core」とし、[Solution Name]は「MvvmCrossSample」とする。[位置]のテキストフィールドの下にある[Create a project within solution directory.]にチェックが入っているかを確認し、最後に[作成]ボタンを押せば、実際にソリューションとCoreプロジェクトが作成される。

図B プロジェクト名の設定

名前のフィールドと連動してソリューション名のフィールドも変化するため、名前を設定してからソリューション名を変更するとよい。

 次に、作成されたソリューションにiOSアプリのプロジェクトを追加する。

 これには、[ソリューション]ビューのソリューション項目を右クリックし、(表示されるコンテキストメニューの)[追加]から[新しいプロジェクトを追加]を選択する。それにより表示されるダイアログ(図C)で、プロジェクトの種類から[iOS]の[App]にある[空のプロジェクト]を選択し、[Next]ボタンを押す。

図C プロジェクトの選択

iOSの[空のプロジェクト]を選択する。

 ダイアログ画面が[Configure your iOS app](図D)になるので、[App Name]を「MvvmCrossSample」とし、[Identififer]はiOSのApplication Identifierとなるので、所有しているドメインの逆順表記+アプリケーション名とする命名規則に沿って指定する(例えば、「jp.co.fenrir.mvvmcrosssample」などとする)。[Devices]は今回の開発ではiPadは対象外とするため、iPadのチェックを外す。[ターゲット]のiOSは、サポートしたい下限のiOSを選択する。入力が完了すれば[Next]ボタンを押す。これにより図Bと同じような「プロジェクト名の設定」をするための[Configure your new project]画面になるので、そこで[プロジェクト名]を「MvvmCrossSample.Touch」として、最後に[作成]ボタンを押せば、実際にiOSプロジェクトが作成される。

図D iOSプロジェクトの設定

アプリの識別名やターゲットOSなどを指定する。

 さらに、AndroidアプリのプロジェクトをiOSと同様の手順で追加する。プロジェクトの種類は[Android]-[App]から[Android App]だ。[Configure your Android app]の画面(図E)では、[App Name]を「MvvmCrossSample」とし、[Identififer]はAndroidのパッケージ名となるので、所有しているドメインの逆順表記+アプリケーション名とする命名規則に沿って指定する(iOS同様、「jp.co.fenrir.mvvmcrosssample」などとするとよいだろう)。[Target Platforms]には、どのAndroidバージョンで使用できるアプリを作るかを指定する(各選択肢の意味は次の表を参照されたい)。MvvmCrossは、3.5からAndroid 2.3に対するサポートが終了しているため、実際は[Modern Development]を選択する場面が多くなるだろう。

Target Platforms の選択対応バージョン
Modern Development Android 4.4 (API Level 19) をターゲットとし、Android 4.1 (API Level 16) 以上で動作する
Maximum Compatibility Android 4.4 (API Level 19) をターゲットとし、Android 2.3 (API Level 10) 以上で動作する
Latest and Greatest 最新SDKをターゲットとし、Android 5.0 (API Level 21) 以上で動作する
ターゲットプラットフォームの選択肢
図E Androidプロジェクトの設定

こちらもiOS同様、アプリの識別名やターゲットOSなどを指定する。

 その次の画面[Configure your new project]では、[プロジェクト名]として「MvvmCrossSample.Droid」として作成する。

プラグインの導入

 プロジェクトが作成されたら、プラグインを追加する。今回はMvvmCross標準の「MvvmCross - WebBrowser Plugin」を追加する。

 [ソリューション]ビューの「Core」プロジェクト項目を右クリックし、[追加]から[Add NuGet Packages]を選択して、ダイアログ(図2)を開く。右上の検索フィールドから「MvvmCross」という名前でパッケージを検索すると、MvvmCrossに関連するパッケージが列挙される。このリストの中から[MvvmCross - WebBrowser Plugin]を選択してインストールする。現在は独自フォークされたMvvmCrossとそのパッケージも上がっているので、公式のプラグインを追加する場合は、パッケージIDがMvvmCross.HotTuna.Pluginで始まることを確認しておくとよい。

図2 プラグインパッケージの追加

MvvmCross - WebBrowser Pluginを追加する。公式のプラグインを追加する場合はパッケージIDがMvvmCross.HotTuna.Pluginであることを確認すること。

 この操作を用意した全てのプロジェクト(つまりiOSやAndroidのプロジェクト)にも行う。各プラットフォームのプロジェクトへの追加を行うと、「Bootstrap」というフォルダーができ、「WebBrowserPluginBootstrap.cs」というファイルができている(図3)。このクラスはMvxPluginBootstrapActionクラスを継承したもので、MvvmCrossは起動時にこのクラスを検索してプラグインをロードするため、削除しないようにする。

図3 プラグインパッケージの追加後のソリューション

Bootstrapフォルダーが作られ、その中にPluginBootstrapクラスが作成される。プラグインの読み込みに使用されるので削除しないこと。

Coreプロジェクトの実装

 FirstViewModelクラスを以下のように実装する。

C#
using Cirrious.MvvmCross.ViewModels;
using Cirrious.MvvmCross.Plugins.WebBrowser;

namespace OpenBrowserSample.Core.ViewModels
{
  public class FirstViewModel : MvxViewModel
  {
    readonly IMvxWebBrowserTask _webBrowserTask;

    // 1
    public FirstViewModel(IMvxWebBrowserTask webBrowserTask)
    {
      _webBrowserTask = webBrowserTask;
    }

    // 2
    string _url = "https://www.buildinsider.net/";
    public string Url
    { 
      get { return _url; }
      set
      {
        _url = value;
        RaisePropertyChanged(() => Url);
      }
    }

    MvxCommand _openBrowserCommand;
    public MvxCommand OpenBrowserCommand
    {
      get
      {
        // 3
        return _openBrowserCommand ??
        (_openBrowserCommand = new MvxCommand(() => _webBrowserTask.ShowWebPage(Url)));
      }
    }
  }
}
WebBrowserプラグインを使用するためのCoreプロジェクトの実装(FirstViewModel.cs)

 まず、引数にWebBrowser Pluginが提供するIMvxWebBrowserTaskを指定したコンストラクターを定義している。このようにすることで、ViewModelが作成されるときにIoCコンテナーに入っているプラットフォームごとのIMvxWebBrowserTaskインターフェースの実装が渡されるので、この先の処理のためにフィールド変数に格納しておく(1)。

 次に、開くURLを入力するためのテキストフィールドとなるUrlプロパティを定義した(2)。

 また、ボタンをタップしたときの処理として、OpenBrowserCommandを定義した(3)。ここではIMvxWebBrowserTaskが提供するShowWebPageメソッドを実行して、UrlプロパティにセットされているURLを標準ブラウザーで開くように実装している。

Touchプロジェクトの実装

 iOS側の実装は、「Tips:MvvmCrossで画面遷移するには?」で紹介した.xibファイルを使う方法で行う。このページを参考にFirstViewを作成し、URL入力用にText Field(UITextField=iOS標準の単一行テキスト入力コンポーネント)と、ブラウザー起動用にButton(UIButton=iOS標準のボタン)を画面上に配置し、それぞれUrlTextFieldOpenBrowserButtonとしてアウトレットを作成する(図4)。

図4 iOSのユーザーインターフェース定義

Text FieldとButtonを配置する。

 次にバインディングを定義する。ViewsフォルダーのFirstView.csファイルを次のように修正する。

C#
using Cirrious.MvvmCross.Touch.Views;
using Cirrious.MvvmCross.Binding.BindingContext;
using OpenBrowserSample.Core.ViewModels;

namespace OpenBrowserSample.Touch.Views
{
  public partial class FirstView : MvxViewController // 1
  {
    public FirstView() : base("FirstView", null)
    {
    }

    public override void ViewDidLoad()
    {
      base.ViewDidLoad();

      // 2
      var set = this.CreateBindingSet<FirstView, FirstViewModel>();
      set.Bind(UrlTextField).To(vm => vm.Url);
      set.Bind(OpenBrowserButton).To(vm => vm.OpenBrowserCommand);
      set.Apply();
    }
  }
}
Touchプロジェクト側でのバインディング定義(FirstView.cs)

 継承元のクラスをMvxViewControllerへ変更し(1)、バインディングを定義している(2)。

Droidプロジェクトの実装

 Droidプロジェクトについてもレイアウトを作成し、バインディングを定義する。

 これには、[ソリューションビュー]からDroidプロジェクトのResources-layoutフォルダーにあるFirstView.axmlファイルを次のように編集する。

XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:local="http://schemas.android.com/apk/res-auto"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <!-- 1 -->
  <EditText
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    local:MvxBind="Text Url" />
  <!-- 2 -->
  <Button
    android:text="Open Browser"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    local:MvxBind="Click OpenBrowserCommand" />
</LinearLayout>
Droidプロジェクト側でのバインディング定義(FirstView.axml)

 URL入力用のEditTextを用意して、TextプロパティをViewModelのUrlプロパティへバインディングし(1)、ブラウザー起動用のButton(2)を作り、ClickイベントにViewModelのOpenBrowserCommandをバインディングしている2

アプリケーションの実行

 この状態でアプリを実行すると、URL入力用のテキストフィールドと、ブラウザー起動用のボタンが表示される。デフォルトでURLが入力されているので、そのままボタンをタップするとiOSではSafariが、Androidではユーザーがデフォルト設定しているブラウザーが起動してBuild Insiderのトップページが表示される。

図5 完成したアプリ

ボタンをタップするとiOSではSafariが、Androidではユーザーがデフォルト設定しているブラウザーが起動する。

 ViewModelでの記述のみで、目的としている標準ブラウザーの起動をさせることができた。

 このように、プラグインを活用することで、クロスプラットフォーム開発の効率を向上させることができる。プラットフォーム固有の実装をする前に、「プラグインが利用できないか」もしくは「新規にプラグインを作成できないか」を検討してみてほしい。

【コラム】コミュニティで提供されているプラグイン

 NuGetにはMvvmCrossの機能として提供されているものの他、コミュニティによって作成されたプラグインも存在している。例えば、以下のようなものである。

 こういったプラグインも今回の方法で読み込めるが、プラグインの使用方法などは追加するときには分からないことが多い。多くの場合はnuget.orgで当該のプラグインを検索し、詳細ページからProject Siteを開くことでそのプラグインの配布元サイトを参照できるので、ドキュメントはここから得られる。

 なお、NuGetにはMvvmCrossバージョン1.x系をターゲットとしたプラグインも残っているので、間違って追加しないように注意が必要となる。

※以下では、本稿の前後を合わせて5回分(第51回~第55回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

Xamarin逆引きTips
51. MvvmCrossでカスタムコンバーターを作成するには?

MvvmCrossでのiOS/Androidアプリ開発において、バインディングする値を変換できるカスタムコンバーターの使い方を説明する。

Xamarin逆引きTips
52. Xamarin.FormsでTwitterクライアントを作成するには?

TwitterのAPIを扱えるライブラリであるCoreTweetを使用して、Twitterデータを検索するアプリを作成。CoreTweetの導入と、検索したテキストの表示までを紹介する。

Xamarin逆引きTips
53. 【現在、表示中】≫ MvvmCrossでWebBrowserプラグインを使用するには?

WebBrowserプラグインを追加・利用する例を通じて、MvvmCrossでのiOS/Androidアプリ開発におけるMvvmCrossプラグインの基本的な使い方を説明する。

Xamarin逆引きTips
54. コードを書く前に正規表現をテストするには?(.NET/Xamarin対応)

.NET/Monoの基本クラスライブラリを使って正規表現を書く場合、そのテストはどうする? Xamarin Studioの正規表現ツールキットを使って手軽に行う方法を紹介。

Xamarin逆引きTips
55. MvvmCrossでカスタムコントロールをTwo-Wayバインディングに対応させるには?

MvvmCrossでのiOS/Androidアプリ開発において、カスタムビュークラスをTwo-Wayバインディングに対応させる方法を解説する。

サイトからのお知らせ

Twitterでつぶやこう!