連載
» 2016年10月19日 05時00分 UPDATE

.NET TIPS:Xamarin.Forms:ユーザーデータを保存するには?

Xamarin.Formsアプリでは、ユーザーデータを保存する場所はプラットフォームごとに異なる。PCL Storageライブラリを使うとこれを透過的に扱えるようになる。

[山本康彦,BluewaterSoft/Microsoft MVP for Windows Development]
「.NET TIPS」のインデックス

連載目次

対象:Visual Studio 2015以降


 Xamarin.FormsのPCLプロジェクトでユーザーごとのデータ(ユーザーデータ)を保存する場合の問題点と、それをPCL Storageというオープンソースのライブラリを使って解決する方法を説明する。

プラットフォームごとに異なるユーザーデータの保存場所

 ユーザーデータをテキストファイルとして読み書きすること自体は、簡単だ。問題は、どこに保存するかである。アプリから自由にアクセスできる場所であって、ユーザーデータを保存するのにふさわしい場所が、プラットフォームごとに異なっているのだ(以下3つのコード*1)。

// Androidの場合
var localAppData
  = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

Androidのユーザーデータ保存フォルダー(C#)

// iOSの場合
var documents
  = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var localAppData = Path.Combine(documents, "..", "Library");

iOSのユーザーデータ保存フォルダー(C#)

// Windows系(UWP/Windows/WinPhone)の場合
var localAppData
  = System.Windows.Forms.Application.LocalUserAppDataPath;

Windows系のユーザーデータ保存フォルダー(C#)

 しかも、上のコードはどれもプラットフォーム依存なのである。つまり、上のコードをPCLプロジェクト内には書けないのだ。

 従って、何も使わずにコーディングするとしたら、「プラットフォームに依存する処理を書くには?」で解説したDependencyServiceを使って、依存性を注入する面倒なコードを書くことになるだろう。

*1 これら3つのコードは、PCL Storageのソースコードから引用させていただいた。


NuGetパッケージ「PCL Storage」を導入する

 オープンソースのPCL Storageというライブラリがある*2。これを使えば、DependencyServiceを作らずに済む。

 PCL Storageを導入するには、NuGetパッケージマネージャーのGUIで操作する。このGUIを出すには、メニューバーから[ツール]−[NuGetパッケージ マネージャー]−[ソリューションのNuGetパッケージの管理]を選ぶ。

 次いで、[参照]タブを選び、検索ボックスに「PCLStorage」と入力して検索する。検索結果の一覧からPCLStorageを選択し、右にあるプロジェクトの一覧では全てのプロジェクトを選択し、[インストール]ボタンをクリックする(次の画像)*3

PCL Storageをソリューションに導入する(Visual Studio 2015) PCL Storageをソリューションに導入する(Visual Studio 2015)
(1) [参照]タブを選ぶ
(2) 検索ボックスに「PCLStorage」と入力して検索する
(3) 検索結果の一覧からPCLStorageを選択
(4) 全てのプロジェクトを選択
(5) [インストール]ボタンをクリックする

*2 PCL StorageのライセンスはMS-PLである。利用に先立って確認しておいてほしい。

*3 PCL Storageは、他のパッケージに依存していない。それなのに、依存関係のチェックでエラーになってインストールできないことがあるかもしれない(筆者の環境で発生した)。その場合は、[オプション](上の画像で[インストール]ボタンの左下に見えている)を展開し、[依存関係の動作]ドロップダウンを[依存関係を無視する]に切り替えて、インストールを試してみてほしい。


PCL Storageを使ってユーザーデータを読み書きする

 PCL Storageを使うと、ユーザーデータ保存フォルダーはFileSystemクラス(PCLStorage名前空間)のLocalStorageプロパティで取得できる。もちろん、PCLの中からだ。

 また、Windows系プロジェクト(プロジェクト名の末尾がUWP/Windows/WinPhone)では、RoamingStorageプロパティでローミングフォルダーも得られる。

 例として、ユーザーデータ保存フォルダーの下の「SampleData」というサブフォルダーで「Sample.txt」という名前のファイルを読み書きするコードは、次のようになる。

const string SubFolderName = "SampleData";
const string TextFileName = "Sample.txt";

// ユーザーデータを読み取るメソッド
async Task<string> LoadTextAsync()
{
  // ユーザーデータ保存フォルダー
  PCLStorage.IFolder localFolder = PCLStorage.FileSystem.Current.LocalStorage;

  // サブフォルダーを作成、または、取得する
  PCLStorage.IFolder subFolder
    = await localFolder.CreateFolderAsync(SubFolderName,
                          PCLStorage.CreationCollisionOption.OpenIfExists);

  // ファイルを取得する
  PCLStorage.IFile file = await subFolder.GetFileAsync(TextFileName);

  // テキストファイルを読み込む
  // ファイル冒頭に「using PCLStorage;」が必要
  return await file.ReadAllTextAsync();
}

ユーザーデータを読み取るコードの例(C#)
ユーザーデータ保存フォルダーの下の「SampleData」フォルダーにある「Sample.txt」ファイルを読み取って、そのファイルに保存されている文字列を返すメソッド。非同期メソッドなので、呼び出す側はawaitキーワードで終了を待機する必要がある。
また、ファイルがないときは、ファイルを取得するところでFileNotFoundException例外(PCLStorage.Exceptions名前空間)が発生する。呼び出す側で正しく例外をトラップしてほしい。

// 定数定義を再掲
//const string SubFolderName = "SampleData";
//const string TextFileName = "Sample.txt";

// ユーザーデータを書き出すメソッド
async Task<string> SaveTextAsync(string text)
{
  // ユーザーデータ保存フォルダー
  PCLStorage.IFolder localFolder = PCLStorage.FileSystem.Current.LocalStorage;

  // サブフォルダーを作成、または、取得する
  PCLStorage.IFolder subFolder
    = await localFolder.CreateFolderAsync(SubFolderName,
                          PCLStorage.CreationCollisionOption.OpenIfExists);

  // ファイルを作成、または、取得する
  PCLStorage.IFile file
    = await subFolder.CreateFileAsync(TextFileName,
                        PCLStorage.CreationCollisionOption.ReplaceExisting);

  // テキストをファイルに書き込む
  // 冒頭に「using PCLStorage;」が必要
  await file.WriteAllTextAsync(text);

  return file.Path;
}

ユーザーデータを書き出すコードの例(C#)
引数の文字列を、ユーザーデータ保存フォルダーの下の「SampleData」フォルダーにある「Sample.txt」ファイルに書き出すメソッド。非同期メソッドなので、呼び出す側はawaitキーワードで終了を待機する必要がある。
このメソッドは、保存したファイルのフルパスを返すようにしてある。

実行結果

 上で示したメソッドを使って、画面上のEditorコントロールにキー入力された文字列を保存し、起動時には読み込んで表示するアプリを作ってみた。

 このサンプルコードは「Microsoft Developer Network > サンプル > .NET TIPS #1163」からダウンロードできる。なお、このサンプルコードには、アプリが中断状態にされるときに、自動的に保存する機能も付け加えてある。

 一度実行して文字列を保存させてから終了し、再び起動したときの画面を次の画像に示す。

実行結果(Visual Studio Emulator for Android)
実行結果(iOS Simulator for Windows)
実行結果(Mobile Emulator) 実行結果
一度実行して文字列を保存させてから終了し、再び起動したときの画面である。前回で保存したテキストファイルを、アプリ起動時に読み込んで表示している。
上はVisual Studio Emulator for Androidでの実行結果。中はiOS Simulator for Windowsでの実行結果。下はMobile Emulator(Windows 10)での実行結果。なお、iOS Simulator for Windowsは本稿執筆段階でプレビュー段階となっている。使用方法については「XamarinアプリのMacでのビルドとiOS Simulator for Windows」を参照されたい。

まとめ

 PCL内でユーザーデータ保存フォルダーを読み書きするには、PCL Storageライブラリを利用すると簡単だ。PCL Storageライブラリを利用しないのであれば、DependencyServiceクラスを利用したちょっと面倒なコードを書くことになる。

利用可能バージョン:Visual Studio 2015以降
カテゴリ:Xamarin 処理対象:Xamarin.Forms
カテゴリ:オープンソース・ライブラリ 処理対象:Xamarin.Forms
関連TIPS:Xamarin.Forms:プロジェクトにXamlページを追加するには?
関連TIPS:Xamarin.Forms:プラットフォームに応じて画面の一部を変えるには?
関連TIPS:Xamarin.Forms:プラットフォームに依存する処理を書くには?


「.NET TIPS」のインデックス

.NET TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。