Xamarni.Forms AzureモバイルサービスによるToDoアプリ
はじめに
Microsoft Azure のドキュメントにある「モバイル サービスの使用」では、XamarinによるToDoアプリのチュートリアルが公開されています。
同ページのチュートリアルを進めると、Xamarin.iOS 及び Xamarin.Android の雛形プロジェクトをダウンロードしてそのまま実行できる手順となっています。
今回は、このToDoアプリをXamarin.Formsで作成してみました。
同チュートリアルではXamarinコンポーネントが使用されていますが、このコンポーネントは、iOS用とAndroid用しか無いため、本記事ではNuGet版のWindowsAzure.MobileServicesを使用しました。
コンポーネント版もNuGet版もインターフェースが全く同じようなので、雛形プロジェクトのコードは、そのまま利用可能です。
なお、本記事をまとめるにあたって色々検索してみたのですが、どこのコードもMobileServicesのインスタンスは、各ターゲットのプロジェクト側に置いてあり、コードの共通化は、Sharedクラスなどで行われていました。
何か制約があるのかなと思っていたのですが・・・結果的には、Xamarin.FormsのPCLでインスタンスを生成しても、まったく問題ないようです。
ただ、iOSとAndroidでは、CurrentPlatform.Init()という初期化コードが必要なのですが、この1行だけをそれぞれのプロジェクト側に記述する必要がありました。
モバイルサービスの作成とテーブル生成
Microsoft Azure のドキュメント「モバイル サービスの使用」では、下記の手順で紹介されています。
(1)新しいモバイル サービスを作成する
(2)新しい Xamarin.iOS アプリケーションを作成する
(3)新しい Xamarin.iOS アプリケーションを実行する
(1)で「モバイルサービス」を作成して、(2)でToDoアプリ用の「テーブル」を生成していますが、本記事では、ここまでをそのまま流用して、同テーブルをそのまま利用しています。
同チュートリアルで作成されるテーブルは下記のようになっています。
class ToDoItem { public string Id { get; set; } [JsonProperty(PropertyName = "text")] public string Text { get; set; } [JsonProperty(PropertyName = "complete")] public bool Complete { get; set; } }
また、URL及びキーは、雛形プロジェクトのコード(QSTodoService.cs)や、Azureポータル(ダッシュボード)で確認できます。
public class QSTodoService : DelegatingHandler static QSTodoService instance = new QSTodoService (); const string applicationURL = @"https://XXXXXX.azure-mobile.net/"; const string applicationKey = @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; MobileServiceClient client; IMobileServiceTable<ToDoItem> todoTable;
プロジェクトの作成(パッケージのインストールと初期化)

プロジェクトは、「Mobile Apps」の「Blank App(Xamarin.Forms Portable)」で作成します。
全プロジェクトにMobileServicesをインストールします。
PM> Install-Package WindowsAzure.MobileServices [全プラットフォーム]
MobileServicesは、いくつかの依存関係に基づいてインストールされます。
続いて、AndoroidとiOSのプロジェクトで、MobileServicesの初期化のため「CurrentPlatform.Init()」の1行を追加します。
Android【MainActivity.cs】
public class MainActivity : AndroidActivity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); Xamarin.Forms.Forms.Init(this, bundle); //初期化処理を追加 Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init(); .... } }
iOS【AppDelegate.cs】
public partial class AppDelegate : UIApplicationDelegate { public override bool FinishedLaunching(UIApplication app, NSDictionary options) { Forms.Init(); //初期化処理を追加 Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init(); .... } }
PCLの実装
PCLに記述した全てのコードは下記のとおりです。
非常にシンプルで、MobileServicesの威力を実感します。
public class App { public static Page GetMainPage() { //インジケータ(IsBusy)を表示するためにNavigationPageを使用する return new NavigationPage(new MainPage()); } class MainPage : ContentPage { //モバイルサービスへの接続のためのキー const string ApplicationUrl = "XXXXX"; const string ApplicationKey = "xxxxx"; readonly MobileServiceClient _client = new MobileServiceClient(ApplicationUrl, ApplicationKey); //リストボックスのデータソース readonly ObservableCollection<ToDoItem> _ar = new ObservableCollection<ToDoItem>(); public MainPage() { Title = "TodoAzure (Xamarin.Forms)"; //リストボックス var listView = new ListView { ItemsSource = _ar, ItemTemplate = new DataTemplate(typeof(TextCell)) }; //ToDoItemのTextプロパティを表示する listView.ItemTemplate.SetBinding(TextCell.TextProperty, "Text"); listView.ItemTapped += async (s, a) => { //タップ時のイベント処理 if (await DisplayAlert("確認", "削除して宜しいですか?", "OK", "Cancel")){ Del((ToDoItem) a.Item); }; }; //テキストボックス var entry = new Entry{ HorizontalOptions = LayoutOptions.FillAndExpand, }; //追加ボタン var buttonAdd = new Button { Text = "Add" }; buttonAdd.Clicked += (s, a) =>{ //クリック時のイベント処理 Add(entry.Text); entry.Text = ""; }; //更新ボタン var buttonRefresh = new Button { Text = "Refresh" }; buttonRefresh.Clicked += (s, a) => Refresh(); //クリック時のイベント処理 //画面構成 Content = new StackLayout { Children = { //上下にStackLayoutとListViewを配置する new StackLayout{ BackgroundColor = Color.FromRgb(169,206,152), Padding = 5, Spacing = 10, Orientation = StackOrientation.Horizontal, //左右にEdit・Button・Buttonを配置する Children = {entry,buttonAdd,buttonRefresh} },listView } }; Refresh();//表示更新 } //表示更新 async void Refresh(){ IsBusy = true;//インジケータのON //DB検索 (Complete==falseのデータだけ抽出する) var result = await _client.GetTable<ToDoItem>().Where(todoItem => todoItem.Complete == false).ToListAsync(); //リストボックスの更新 _ar.Clear(); foreach (var a in result) { _ar.Insert(0,a); } IsBusy = false;//インジケータのOFF } //追加 async void Add(string str){ if (str != ""){ IsBusy = true;//インジケータのON //DBへの追加 var item = new ToDoItem { Complete = false, Text = str }; await _client.GetTable<ToDoItem>().InsertAsync(item); //リストボックスへの追加 _ar.Insert(0, item); IsBusy = false;//インジケータのOFF } } //削除 private async void Del(ToDoItem item){ IsBusy = true;//インジケータのON //DB更新 item.Complete = true; await _client.GetTable<ToDoItem>().UpdateAsync(item); //リストボックスからの削除 _ar.Remove(item); IsBusy = false;//インジケータのOFF } } class ToDoItem { public string Id { get; set; } [JsonProperty(PropertyName = "text")] public string Text { get; set; } [JsonProperty(PropertyName = "complete")] public bool Complete { get; set; } } }
Android | |
![]() |
![]() |
iOS | |
![]() |
![]() |
WindowsPhone | |
![]() |
![]() |
[参考にさせて頂きました]
Azure Mobile Service は Nuget版とXamarin Components版があるので注意
http://www.moonmile.net/blog/archives/5773
モバイル サービスの使用
http://azure.microsoft.com/ja-jp/documentation/articles/partner-xamarin-mobile-services-ios-get-started/