Xamarin.Forms PCLでのファイルIO ( PCL Storageを使用する )
1. PCL Storage
Xamarin.FormsのPCLでファイルのIOを書こうとしたとき、System.IOに File や Directory が無くて固まった経験はないでしょうか?もともと、ファイルの扱いはプラットフォーム固有なので、当然といえば当然なのですが・・・
しかし、Xamarin.iOSやXamarni.Androidでは、ちゃんと、System.IO.FileやSystem.IO.Directoryが使えるので、それをラッパーすればいいだけです。
フォルダのパスがプラットフォーム固有になるので、そこだけ気を付ければいいって事でしょうか。
と言いながら、いろいろ検索していると、コンポーネントストアに「PCL Storage」なるものを見つけました。
2. インストール
同プログラムは、CodePlexやGithubでコードも公開されています。
また、NuGetでのインストールも可能です。
コンソールでも可能ですが、今回は、「NnuGetパッケージの管理」から行いました。
※実は、ComponentsというフォルダがiOSとAndroidのプロジェクトにしかなく、PCLプロジェクトが無かったので、右クリックでの導入要領が分かりませんでした・・・
全プロジェクトにインストールされます。
3. 動作確認
次のようなサンプルを書いて、動作確認してみました。
EntryコントロールとButtonコントロールを配置し、ボタンを押すと、Entryコントロールの内容をファイルに書き込むものです。
//App.cs using PCLStorage; using Xamarin.Forms; namespace PCLStorageSample { public class App : Application { public App() { MainPage = new MyPage(); } } internal class MyPage : ContentPage { public MyPage() { var entry = new Entry(); var button = new Button() { Text = "OK", Command = new Command(async () => { // ルートフォルダの取得 var folder = FileSystem.Current.LocalStorage; // フォルダの作成 var subFolder = await folder.CreateFolderAsync("SubFolder", CreationCollisionOption.OpenIfExists); // フォルダの作成 var file = await subFolder.CreateFileAsync("Text.txt", CreationCollisionOption.ReplaceExisting); // Entryコントロール尾内容をの書き込む await file.WriteAllTextAsync(entry.Text); // ファイルの内容を読み込む var str = await file.ReadAllTextAsync(); str = ""; }) }; Content = new StackLayout{ Padding = new Thickness(0,Device.OnPlatform(20,0,0),0,0), Children = { entry,button } }; } } }
(1) iOS
上記のコードを実行すると、下記のような画面になります。Entryコントロールに「test-message」と入力して、OKボタンを押し、ファイルのIOを行ったところでブレークポイントで止めて、内容を確認してみました。
ファイルから読み込んだ内容が、書き込んだものと同じになっているのが、確認できます。
また、この時の、各オブジェクトの状況は次のようになっています。
PCLStorage.IFolder folder のパスは、「/User/username/Library/developer/CoreSimulator/Data/Application/A3297...C370/Document/..Library」となっており、そのサブフォルダ「SubFolder」とその中の
ファイル「Text.txt」が見て取れます。
※これは、シュミレータでの動作ですが、実機では「/var/mobile/Containers/Data/Application/53B38A17-AC94-49C9-A3E7-21A2B08F5706/Documents/../Library」のようになっています。
(2) Android
Androidでは、次のようになります。Entryコントロールに「test-android」と入力して、iOSと同じ要領で確認してみました。
今度は、PCLStorage.IFolder folder のパスが「/data/data/PCLStorageSample.Droid/files」となっているのが確認できます。
(3) WindowsPhone
最後に、WindowsPhoneです。こちらの、PCLStorage.IFolder folder は、「/data/data/PCLStorageSample.Droid/files」です。
4. ルートフォルダ
念のため、各プラットフォームごとのルートフォルダの取得について、Githubからコードを確認しておきます。https://github.com/dsplaisted/PCLStorage/blob/master/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs
public IFolder LocalStorage{ get{ // SpecialFolder.LocalApplicationData is not app-specific, so use the Windows Forms API to get the app data path //var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); #if ANDROID var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); #elif IOS var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var localAppData = Path.Combine(documents, "..", "Library"); #else var localAppData = System.Windows.Forms.Application.LocalUserAppDataPath; #endif return new FileSystemFolder(localAppData); } }
コードを確認すると、Android、iOS、WindowsPhoneについては、ルートフォルダの取得以外やパスの扱いいがは、ほとんど共通のようです。
しかし、何と言っても、パッケージインストールだけで簡単に使えてしまう魅力は捨てがたいです。