Xamarin逆引きTips
Xamarin.FormsでAzureモバイルサービスによるToDoアプリを作成するには?
ひな型プロジェクトが用意されているXamarin.iOSやXamarin.Androidではなく、Xamarin.FormsからAzureモバイルサービスを活用する基本的な方法を、簡単なToDoアプリを題材に解説する。
1. Microsoft Azureモバイルサービス(Mobile Services)
Microsoft Azureモバイルサービス(※プレビュー版の新ポータルでは「Azure Mobile Apps」という名前に変更されているが、執筆時点でまだ現ポータルと同等の機能が使えないため、本稿では現ポータルを使用する)では、モバイルアプリ開発に使える各種SDKとプラットフォーム別のひな型プロジェクト(後述の図1)が用意されており、モバイルアプリの開発を容易に行うことができる。また、同サービスでは、初めて利用する場合でも簡単に開発が進められるように、導入用のチュートリアルが準備されており、そこにはXamarin用のものも含まれている。
そして、このチュートリアル(現ポータルの場合/新ポータルの場合)では、プロジェクトのひな型をダウンロードして進める手順が紹介されている(図1は現ポータルでモバイルサービスを作成した直後に表示されるチュートリアル)。
しかし、ここでダウンロードできるプロジェクトは、Xamarin.iOS用とXamarin.Android用の2種類であり、残念ながら、Xamarin.Forms用は提供されていない。
そこで今回は、このチュートリアルを真似た簡単なToDoアプリを題材に、Xamarin.Formsによるアプリ作成をステップバイステップで解説する。
- *1 なお本Tipsは、Windows上でVisual Studio 2013を使用してXamarin.Forms開発をすることを前提としている(※編集部注: Mac上のXamarin Studioでも同様の手順で、本稿の内容が実現できることは確認している)。使用しているXamarin.Formsのバージョンは、プロジェクト作成時に利用されている「1.3.1.6296」である。
2. モバイルサービスの設定
Azureモバイルサービスを、現Azureポータルを使って作成する手順を説明する。
(1)モバイルサービスの作成
現Azureポータルにアクセスし、以下の手順でモバイルサービスを作成する。
(2)テーブルの作成
モバイルサービスの一覧から、新規に作成したサービスを選択すると、そのサービスに関する各種の設定や状態を確認できる。次に、図3の手順でテーブルを作成する。
(3)テーブルへの列の追加
続いて、今、作成したテーブルに列を追加する。テーブル一覧から「ToDoItem」をクリックし、それにより表示されるページで[列]タブメニューを開くと、図4のようにいくつかの列が自動的に作成されていることが確認できる。
下段の[列の追加]ボタンを押すと、列を追加するためのポップアップが表示されるので(図5)、表1の2つを追加する。
データ型 | 列名 |
---|---|
String | text |
Boolean | complete |
追加が完了すると、列の一覧は、次のようになっている。
(4)URLとアクセスキー
ここまでで、モバイルサービスの準備は完了だが、作成するアプリからアクセスするために必要な情報として、URLおよびアクセスキーをコピーしておく。URLは、ダッシュボードの右枠に表示されている(図7)。また、下部の[キーの管理]ボタンをクリックすると「アクセスキー」を表示させることができる。
3. Xamarin.Formsプロジェクトの作成
メニューバーの[ファイル]-[新規作成]-[プロジェクト]から表示したダイアログで、[テンプレート]-[Visual C#]-[Mobile Apps]-[Blank App (Xamarin.Forms Portable)]を選択し、名前を「AzureToDoSample」として[OK]ボタンを押す。
4. WindowsAzure.MobileServicesのインストール
Azureモバイルサービスにアクセスするためには、NuGet版で提供されている、WindowsAzure.MobileServicesをインストールする必要がある。
NuGetからパッケージをインストールするには、メニューバーの[ツール]-[NuGetパッケージマネージャ]-[パッケージ マネージャー コンソール]を選択し、表示されたコンソールで次のように入力する
PM>Install-Package WindowsAzure.MobileServices -ProjectName AzureToDoSample
PM>Install-Package WindowsAzure.MobileServices -ProjectName AzureToDoSample.iOS
PM>Install-Package WindowsAzure.MobileServices -ProjectName AzureToDoSample.Droid
|
本来は、これでパッケージのインストールは完了なのだが、最新のWindowsAzure.MobileServicesでは、iOSで参照重複のエラーが出てコンパイルできない(図9)。
このエラーを回避するためには、ソリューションエクスプローラーでプロジェクトの参照設定から、System.IO、System.Runtaime、およびSystem.Threading.Tasksの3つを削除する必要がある。
5. メイン画面の作成
ToDoアプリの画面を作成するには、App.csファイルを以下のように修正する。
using Xamarin.Forms;
namespace WebViewSample {
public class App : Application {
public App() {
if (Device.OS == TargetPlatform.Android) {
MainPage = new NavigationPage(new MyPage()); // <-1
} else {
MainPage = new MyPage();
}
}
……省略……
}
class MyPage : ContentPage {
public MyPage() {
var entry = new Entry { // <-2
HorizontalOptions = LayoutOptions.FillAndExpand,
Placeholder = "ここへ入力してください",
};
var buttonAdd = new Button { // <-3
Text = "追加",
WidthRequest = 60,
};
var listView = new ListView(); // <-4
Content = new StackLayout { // <-5
Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0),
Children = {
new StackLayout { // <-6
Padding = new Thickness(5),
Orientation = StackOrientation.Horizontal,
Children = {entry, buttonAdd }
},
listView
}
};
}
}
}
|
Entry
コントロール(1)とButton
コントロール(2)を作成し、StackLayout
によって横に並べた(6)。
また、ListView
コントロール(4)は、その下になるように配置されてる(5)。
なお、Azureとの通信中を表わすためにインジケーターを表示する予定だが、Androidでは、NavigationPage
でないと、このインジケーターが表示できない。このため、トップページとなるMyPage
は、Androidの場合だけ、NavigationPage
のルートページとして生成している(1)。
このコードを実行すると、次のような画面になる。
【コラム】Androdiでのインジケーター
Xamarin.Formsでは、Forms.Page
のIsBusy
プロパティでインジケーターをON/OFFできる。しかし、Androidでは、このインジケーターが、ActionBarの位置に表示されるため、NavigationPage
を使用しないと、インジケーターが確認できなくなる。
6. MobileServicesの初期化
MobileServices
を使用するためには、各プラットフォームごとに初期化のコードが必要になる。初期化コードを追加するためには、AzureToDoSample.iOSプロジェクトのAppDelegate.csファイルを次のように修正する。
……省略……
namespace AzureToDoSample.iOS {
……省略……
public override bool FinishedLaunching(UIApplication app, NSDictionary options) {
global::Xamarin.Forms.Forms.Init();
Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init(); // <-1
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
}
}
|
FinishedLaunching
メソッドにおいて、Xamarin.Formsの初期化コードの直後に、CurrentPlatform.Init()
を追加する(1)。
同様に、AzureToDoSample.DroidプロジェクトのMainActivity.csファイルも次のように修正する。
……省略……
namespace ToDoSample.Droid {
……省略……
protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init(); // <-1
LoadApplication(new App());
}
}
}
|
OnCreate
メソッドにおける、Xamarin.Formsの初期化コードの直後に、CurrentPlatform.Init()
を追加する(1)。
7. データクラスの定義とリストビューへのバインド
Azureモバイルサービス上で作成したテーブルにアクセスするため、AzureToDoSampleプロジェクトにToDoItem.csファイルを追加して、次のように修正する。
using Newtonsoft.Json;
namespace AzureToDoSample {
class ToDoItem {
public string Id { get; set; }
[JsonProperty(PropertyName = "text")] // <-1
public string Text { get; set; } // <-2
[JsonProperty(PropertyName = "complete")]
public bool Complete { get; set; }
}
}
|
データクラスは、ToDoItem
として定義した。ToDoItem
クラスでは、キーとなるId
プロパティと、追加した列にアクセスするText
プロパティおよびComplete
プロパティを定義している。
JsonProperty
属性を使用すると、テーブル上の列名を指定できるため(1)、プロパティ名を自由に指定できる。ここでは、C#の命名規約に従うため、キャメルケースにしている(2)。
次に、作成したToDoItem
クラスをリストビューのアイテムとしてひも付けるには、App.csファイルを次のように修正する。
using System.Collections.ObjectModel;
using Xamarin.Forms;
namespace AzureToDoSample {
……省略……
class MyPage : ContentPage {
readonly ObservableCollection<ToDoItem> _ar = new ObservableCollection<ToDoItem>(); // <-1
public MyPage() {
……省略……
var listView = new ListView() {
ItemsSource = _ar, // <-2
ItemTemplate = new DataTemplate(typeof (TextCell)), // <-3
};
listView.ItemTemplate.SetBinding(TextCell.TextProperty, "Text");// <-4
……省略……
}
}
}
|
ToDoItem
クラスは、ObservableCollection
クラスを使用してコレクションとしてインスタンス化した(1)。
インスタンス化したデータは、リストビューのItemSource
プロパティにセットする(2)。
表示用のテンプレートには、汎用のTextCell
を使用することとし(3)、TextCell.TextProperty
にToDoItem
クラスのText
プロパティをバインドした。
8. MobileServiceClientの生成
MobileServiceClient
クラスをインスタンス化するには、App.csファイルを次のように修正する。
using System.Collections.ObjectModel;
using Microsoft.WindowsAzure.MobileServices;
using Xamarin.Forms;
namespace AzureToDoSample {
……省略……
class MyPage : ContentPage {
const string ApplicationUrl = "https://xamarinformstodosample.azure-mobile.net/"; // <-1
const string ApplicationKey = "xxxxxxxxxxxxxxxxxxxxxxxxxx"; // <-2
readonly MobileServiceClient _client = new MobileServiceClient(ApplicationUrl, ApplicationKey); // <-3
……省略……
}
}
|
URL(1)およびアクセスキー(2)は、モバイルサービスを作成した際に、管理ポータルで確認したものだ。
この2つのキーを使用して、MobileServiceClient
クラスをインスタンス化する(3)。
9. データの追加
いよいよ、Azureモバイルサービスへのアクセスである。[追加]ボタンを押したときに、データを追加するには、App.csを次のように修正する。
using System;
using System.Collections.ObjectModel;
using Microsoft.WindowsAzure.MobileServices;
using Xamarin.Forms;
namespace AzureToDoSample {
……省略……
class MyPage : ContentPage {
……省略……
public MyPage() {
……省略……
var buttonAdd = new Button() {
Text = "追加",
WidthRequest = 60,
};
buttonAdd.Clicked += (s, a) => Add(entry); // <-1
……省略……
}
async void Add(Entry entry) {
if (!String.IsNullOrEmpty(entry.Text)) {
IsBusy = true; // <-2
var item = new ToDoItem { Complete = false, Text = entry.Text }; // <-3
await _client.GetTable<ToDoItem>().InsertAsync(item); // <-4
_ar.Insert(0, item); // <-5
entry.Text = "";
IsBusy = false; // <-6
}
}
}
}
|
[追加]ボタンのクリックイベントでAdd
メソッドが実行されるように指定した(1)。
Add
メソッドでは、Entry
コントロールに入力された文字列を使用して、ToDoItem
オブジェクトを生成し(3)、MobileServices
のInsertAsync
メソッドを使用して、Azure上のデータベースに追加する(4)。
なお、クライアント側は、ListView
コントロールのデータソースであるコレクションに同オブジェクトを追加し、データバインディングで表示を更新する(5)。
処理の前後では、インジケーターを表示している(2 6)。
このコードを実行すると、次のような画面になる。
10. データの削除
リストビューをタップしたときに、データを削除するには、App.csファイルを次のように修正する。
……省略……
namespace AzureToDoSample {
……省略……
class MyPage : ContentPage {
……省略……
public MyPage() {
……省略……
var listView = new ListView() {
ItemsSource = _ar,
ItemTemplate = new DataTemplate(typeof (TextCell)),
};
listView.ItemTemplate.SetBinding(TextCell.TextProperty, "Text");
listView.ItemTapped += async (s, a) => {
if (await DisplayAlert("確認", "削除して宜しいですか?", "OK", "Cancel")) { // <-1
Del((ToDoItem)a.Item); // <-2
};
};
……省略……
}
async void Del(ToDoItem item) {
IsBusy = true; // <-3
item.Complete = true; // <-4
await _client.GetTable<ToDoItem>().UpdateAsync(item); // <-5
_ar.Remove(item); // <-6
IsBusy = false; // <-7
}
……省略……
}
}
|
リストビューのタップイベントで、実行の確認をした後(1)、Del
メソッドが実行されるように指定した(2)。
Del
メソッドでは、リストビューから得たToDoItem
オブジェクトのComplete
プロパティをtrueに変更し(4)、MobileServices
のUpdateAsync
メソッドを使用して、Azure上のデータベースを更新する(5)。
なお、追加と同じようにクライアント側は、データバインディングで更新されている(6)。
インジケーターの処理も同じである(3 7)。
このコードを実行すると、次のような画面になる。
11. データの更新
リストビューの内容をサーバー上のデータに合わせて更新するためには、App.csファイルを以下のように修正する。
……省略……
namespace AzureToDoSample {
……省略……
class MyPage : ContentPage {
……省略……
public MyPage() {
……省略……
Refresh(); // <-1
}
async void Refresh() {
IsBusy = true;
_ar.Clear(); // <-2
var result = await _client.GetTable<ToDoItem>().Where(item => item.Complete == false).ToListAsync(); // <-3
result.Reverse();
foreach (var a in result) { // <-4
_ar.Add(a);
}
IsBusy = false;
}
}
}
|
メインページのコンストラクターで、Refresh
メソッドを呼び出している(1)。
Refresh
メソッドでは、いったんデータソースをクリアする(2)。
MobileServices
のGetTable
メソッドを使用して、Azure上のデータベースからをcomplete
列がfalseのものだけを検索し(3)、あらためてデータソースを初期化している(4)。
これにより、アプリ起動時に、前回の状態が復元できるようになる。
12. まとめ
今回は、Azureモバイルサービスを使用した、簡単なToDoアプリの作成を紹介した。Azureモバイルサービスでは、今回使用したデータ保存の機能だけでなく、認証や通知なども簡単に利用できるようになっている。今後、これらの機能についても機会があれば紹介したいと考えている。
【コラム】自動で追加されるカラム
Azureモバイルサービスでは、テーブル内のカラムは、自動的に追加される。本記事では、最初に必要なカラムを手動で追加したが、データにアクセスするクラスで、適切なプロパティを定義すれば、最初にアクセスした時点で自動的にカラムが追加される。
次のようにデータクラスにDmy
プロパティを追加してアクセスするだけで、列が追加されているのを確認できる。
using Newtonsoft.Json;
namespace AzureToDoSample {
class ToDoItem {
……省略……
[JsonProperty(PropertyName = "dmy")] // <-追加
public bool Dmy { get; set; } // <-追加
}
}
|
一度追加されたカラムは、データベースの仕様上、自動的に削除されることは無い。従って、うっかりクラスのプロパティ名を間違えてアクセスしたりすると、不要なカラムがごみとなって残ってしまう事になる。ポータルサイトからもデータベースのレコードなどを確認することが可能なので、リリース前には、再確認することが重要である。
※以下では、本稿の前後を合わせて5回分(第54回~第58回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
54. コードを書く前に正規表現をテストするには?(.NET/Xamarin対応)
.NET/Monoの基本クラスライブラリを使って正規表現を書く場合、そのテストはどうする? Xamarin Studioの正規表現ツールキットを使って手軽に行う方法を紹介。
55. MvvmCrossでカスタムコントロールをTwo-Wayバインディングに対応させるには?
MvvmCrossでのiOS/Androidアプリ開発において、カスタムビュークラスをTwo-Wayバインディングに対応させる方法を解説する。
56. 【現在、表示中】≫ Xamarin.FormsでAzureモバイルサービスによるToDoアプリを作成するには?
ひな型プロジェクトが用意されているXamarin.iOSやXamarin.Androidではなく、Xamarin.FormsからAzureモバイルサービスを活用する基本的な方法を、簡単なToDoアプリを題材に解説する。
57. MvvmCrossで画像をバインディングするには?
MvvmCrossでのiOS/Androidアプリ開発において、画像のURLをViewへバインディングできるMvxImageViewの使い方を説明する。
58. MvvmCrossで文字列をローカライズ(多言語化)するには?
MvvmCrossでのiOS/Androidアプリ開発において、ViewModelの文字列リソースを多言語化してローカライズする方法を解説する。