Xamarin iOS モバイル アプリのオフライン同期を有効にする
概要
このチュートリアルでは、Xamarin iOS 向けの Azure モバイル アプリのオフライン同期機能について説明します。 オフライン同期を使用すると、エンド ユーザーはネットワークにアクセスできなくても、データの表示、追加、変更など、モバイル アプリケーションとやり取りできます。 変更は、ローカル データベースに格納されます。 デバイスが再びオンラインになると、これらの変更がリモート サービスと同期されます。
このチュートリアルでは、「Xamarin.iOS アプリを作成する」で作成した Xamarin iOS アプリ プロジェクトを更新し、Azure Mobile Apps のオフライン機能をサポートできるようにします。 ダウンロードしたクイック スタートのサーバー プロジェクトを使用しない場合は、データ アクセス拡張機能パッケージをプロジェクトに追加する必要があります。 サーバーの拡張機能パッケージの詳細については、「 Work with the .NET backend server SDK for Azure Mobile Apps (Azure Mobile Apps 用の .NET バックエンド サーバー SDK を操作する)」を参照してください。
オフラインの同期機能の詳細については、トピック「 Azure Mobile Apps でのオフライン データ同期」をご覧ください。
オフライン機能をサポートするようにクライアント アプリを更新する
Azure モバイル アプリのオフライン機能を使用すると、オフラインになっている状況でも、ローカル データベースとやり取りすることができます。 アプリケーションでこれらの機能を使用するには、SyncContext をローカル ストアに初期化します。 [IMobileServiceSyncTable] インターフェイスを使用してテーブルを参照します。 SQLite は、デバイス上のローカル ストアとして使用されます。
- 「Xamarin iOS アプリの作成」チュートリアルで完了したプロジェクトで NuGet パッケージ マネージャーを開き、Microsoft.Azure.Mobile.Client.SQLiteStore パッケージを検索してインストールNuGetします。
- QSTodoService.cs ファイルを開き、
#define OFFLINE_SYNC_ENABLED
の定義をコメント解除します。 - クライアント アプリの再構築と実行 アプリは、オフライン同期を有効にする前と同じように動作します。ただし今度は、オフライン シナリオで使用できるデータがローカル データベースに格納されます。
アプリを更新してバックエンドから切断する
ここでは、オフライン状況をシミュレートするために、モバイル アプリ バックエンドへの接続を解除します。 データ項目を追加すると、例外ハンドラーによって、アプリがオフライン モードであることが通知されます。 この状態では、新しい項目はローカル ストアに追加され、プッシュが次に接続状態で実行したときに、モバイル アプリ バックエンドに同期されます。
共有プロジェクトの QSToDoService.cs を編集します。 applicationURL を、無効な URL を指すように変更します。
const string applicationURL = @"https://your-service.azurewebsites.fail";
また、デバイス上で Wi-Fi および移動体通信ネットワークを無効にするか、機内モードを使用して、オフライン動作をデモンストレーションすることもできます。
アプリケーションをビルドし、実行します。 アプリを起動した際の更新時には同期が失敗することに注意してください。
新しい項目を入力し、 [保存] をクリックするたびに [CancelledByNetworkError] ステータスでプッシュが失敗することを確認します。 ただし、新しい todo 項目は、モバイル アプリ バックエンドにプッシュされるまでは、ローカル ストア内に存在します。 運用アプリでは、これらの例外を抑制した場合、クライアント アプリはモバイル アプリ バックエンドにまだ接続されているかのように動作します。
アプリケーションを終了し、再起動して、作成した新しい項目がローカル ストアに保存されていることを確認します。
(省略可能) PC に Visual Studio がインストールされている場合は、サーバー エクスプローラーを開きます。 Azure-SQL>データベースに移動します。 データベースを右クリックし、 [SQL Server オブジェクト エクスプローラーで開く] を選択します。 これで SQL データベースのテーブルとその内容を参照できます。 バックエンド データベース内のデータが変更されていないことを確認します。
(省略可能) Fiddler や Postman などの REST ツールを使用して、モバイルのバックエンドをクエリします。その際、
https://<your-mobile-app-backend-name>.azurewebsites.net/tables/TodoItem
の形式で、GET クエリを使用します。
モバイル アプリ バックエンドに再接続するようにアプリケーションを更新する
ここでは、アプリをモバイル アプリ バックエンドに再接続します。 これは、アプリケーションがオフライン状態から、モバイル アプリ バックエンドとのオンライン状態に移行したことをシミュレートします。 ネットワーク接続を無効にしてネットワーク破損をシミュレートした場合、コードを変更する必要はありません。
ネットワークを再び有効にします。 初めてアプリケーションを実行すると、RefreshDataAsync
メソッドが呼び出されます。 これが次に SyncAsync
を呼び出し、ローカル ストアとバックエンドのデータベースを同期します。
共有プロジェクトの QSToDoService.cs を開き、applicationURL プロパティの変更を元に戻します。
アプリケーションを再構築して実行します。 アプリは、
OnRefreshItemsSelected
メソッドが実行されると、プッシュとプルの操作によって、ローカルでの変更を Azure Mobile Apps バックエンドに同期します。(省略可能) SQL Server Object Explorer または Fiddler などの REST ツールを使用して、更新データを表示します。 データが同期されるのは、Azure モバイル アプリのバックエンドのデータベースとローカル ストアの間であることに注意してください。
アプリケーションで、ローカル ストアで完了させる項目の横にあるチェック ボックスをクリックします。
CompleteItemAsync
はSyncAsync
を呼び出し、完了した各項目をモバイル アプリ バックエンドと同期します。SyncAsync
はプッシュとプルの両方を呼び出します。 クライアントが変更を行ったテーブルに対してプルを実行するたびに、クライアントの同期コンテキストへのプッシュが常に最初に自動的に実行されます。 暗黙的なプッシュは、ローカル ストアのすべてのテーブルとリレーションシップの一貫性を確実に保つためです。 この動作については、「 Azure Mobile Apps でのオフライン データ同期」を参照してください。
クライアント同期コードの確認
チュートリアル「 Xamarin.iOS アプリを作成する 」を完了した際にダウンロードした Xamarin クライアント プロジェクトには、ローカルの SQLite データベースを使用したオフライン同期をサポートするコードがすでに含まれてます。 チュートリアルのコードにすでに含まれているものの概要を示します。 機能の概念的な概要については、「 Azure Mobile Apps でのオフライン データ同期」をご覧ください。
テーブル操作を実行する前に、ローカル ストアを初期化する必要があります。
QSTodoListViewController.ViewDidLoad()
がQSTodoService.InitializeStoreAsync()
を実行すると、ローカル ストアのデータベースが初期化されます。 このメソッドにより、Azure Mobile Apps クライアント SDK で提供されるMobileServiceSQLiteStore
クラスを使用して、新しいローカルの SQLite データベースが作成されます。DefineTable
メソッドを実行すると、提供された型のフィールドに一致するテーブルがローカル ストアに作成されます。この例では、ToDoItem
になります。 この型に、リモート データベース内のすべての列を含める必要はありません。 列のサブセットのみ格納できます。// QSTodoService.cs public async Task InitializeStoreAsync() { var store = new MobileServiceSQLiteStore(localDbPath); store.DefineTable<ToDoItem>(); // Uses the default conflict handler, which fails on conflict await client.SyncContext.InitializeAsync(store); }
QSTodoService
のtodoTable
メンバーは、IMobileServiceTable
ではなく、IMobileServiceSyncTable
型です。 IMobileServiceSyncTable は、テーブルの作成、読み取り、更新、削除 (CRUD) などのすべての操作がローカル ストア データベースに対して行われるようにします。IMobileServiceSyncContext.PushAsync()
を呼び出すことによって、これらの変更がいつ Azure モバイル アプリ バックエンドにプッシュされるかを決定します。 同期コンテキストは、PushAsync
が呼び出されたときに、クライアント アプリが変更を行ったすべてのテーブルで、変更を追跡およびプッシュすることで、テーブルの関係を保持するのに役立ちます。todoitem リストの更新、または todoitem の追加や完了があれば、提供されているコードは
QSTodoService.SyncAsync()
を呼び出して同期します。 アプリは、ローカルの変更があるたびに同期されます。 コンテキストによって追跡された保留中のローカル更新のあるテーブルに対してプルが実行される場合、そのプル操作はコンテキストのプッシュを最初に自動的にトリガーします。提供されたコードでは、リモートの
TodoItem
テーブルのすべてのレコードはクエリされますが、クエリ ID やクエリをPushAsync
に渡すことでレコードをフィルター処理することも可能です。 詳細については、「 Azure Mobile Apps でのオフライン データ同期 」の「 Azure Mobile Apps でのオフライン データ同期」セクションを参照してください。// QSTodoService.cs public async Task SyncAsync() { try { await client.SyncContext.PushAsync(); await todoTable.PullAsync("allTodoItems", todoTable.CreateQuery()); // query ID is used for incremental sync } catch (MobileServiceInvalidOperationException e) { Console.Error.WriteLine(@"Sync Failed: {0}", e.Message); } }