前回の記事 で Windows Phone でのセッションデータの保存と復元を XML ファイルで行ったので、ついでに iOS と Android でもやってみます!
おもむろにリポジトリクラスを追加
#if __IOS__ namespace XamarinSessionRestore.iOS.Repositories #else namespace XamarinSessionRestore.Droid.Repositories #endif { /// <summary> /// XML リポジトリ /// </summary> public class XmlRepositories : ISessionRepository { /// <summary> /// 保存先フォルダ /// </summary> private static readonly string Folder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); /// <summary> /// データストア /// </summary> private Dictionary<Type, object> storage = new Dictionary<Type, object>(); /// <summary> /// コンストラクタ /// </summary> static XmlRepositories() { } /// <summary> /// データを設定します /// </summary> /// <typeparam name="T">データの型</typeparam> /// <param name="value">データ</param> public void SetValue<T>(T value) where T : class { this.storage[typeof(T)] = value; } /// <summary> /// データを取得します /// </summary> /// <typeparam name="T">データの型</typeparam> /// <returns>データ</returns> public T GetValue<T>() where T : class { if (!this.storage.ContainsKey(typeof(T))) { return null; } return this.storage[typeof(T)] as T; } /// <summary> /// 初期化します /// </summary> /// <returns>成功した場合<code>true</code>、それ以外は<code>false</code></returns> public bool Initilize() { try { this.storage.Clear(); return true; } catch (Exception) { return false; } } /// <summary> /// セッションデータを読み込みます /// </summary> /// <returns>成功した場合<code>true</code>、それ以外は<code>false</code></returns> public async Task<bool> LoadAsync() { var result = true; try { var types = new List<string>(); var indexFile = Path.Combine(Folder, "session-keys.xml"); using (var stream = new StreamReader(indexFile)) { var serializer = new XmlSerializer(types.GetType()); types = serializer.Deserialize(stream) as List<string>; } foreach (var typename in types) { this.storage[Type.GetType(typename)] = null; } } catch (Exception) { } foreach (var data in this.storage.ToList()) { try { var file = Path.Combine(Folder, string.Format("{0}.xml", data.Key.Name)); using (var stream = new StreamReader(file)) { var serializer = new XmlSerializer(data.Key); this.storage[data.Key] = serializer.Deserialize(stream); } } catch (FileNotFoundException) { this.storage[data.Key] = null; continue; } catch (InvalidOperationException) { this.storage[data.Key] = null; continue; } catch (Exception) { result = false; } } return result; } /// <summary> /// セッションデータを保存します /// </summary> /// <returns>成功した場合<code>true</code>、それ以外は<code>false</code></returns> public async Task<bool> SaveAsync() { var result = true; try { var types = (from t in this.storage select t.Key.AssemblyQualifiedName).ToList(); var indexFile = Path.Combine(Folder, "session-keys.xml"); using (var stream = new StreamWriter(indexFile)) { var serializer = new XmlSerializer(types.GetType()); serializer.Serialize(stream, types); } } catch (Exception) { } foreach (var data in this.storage) { try { var file = Path.Combine(Folder, string.Format("{0}.xml", data.Key.Name)); using (var stream = new StreamWriter(file)) { var serializer = new XmlSerializer(data.Key); serializer.Serialize(stream, data.Value); } } catch (FileNotFoundException) { continue; } catch (InvalidOperationException) { continue; } catch (Exception) { result = false; } } return result; } } }
名前空間のために #if を使ってますが別になくても問題ないです
こんな感じでクラスファイルをリンクとして追加すれば ioS と Android でワンソースが簡単に実現できます
あとはいつものように DI コンテナへの登録コードを追加
public class Application { // This is the main entry point of the application. static void Main(string[] args) { App.Container.RegisterType<ISessionRepository, XmlRepositories>(new ContainerControlledLifetimeManager()); // if you want to use a different Application Delegate class from "AppDelegate" // you can specify it here. UIApplication.Main(args, null, "AppDelegate"); } }
これが iOS で
[Activity(Label = "XamarinSessionRestore", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); App.Container.RegisterType<ISessionRepository, XmlRepositories>(new ContainerControlledLifetimeManager()); global::Xamarin.Forms.Forms.Init(this, bundle); LoadApplication(new App()); } }
こっちが Android です
さっそく実行!
操作の様子はこんな感じ
問題なく保存・復元できましたね