もしかしたら私が知らなかっただけで常識だったのかもしれません。
だったらみんなもっと早く教えてくれればよかったのに!的なww
Xamarin.iOS/Androidアプリで画像やjson設定ファイル、内部html等のリソースを、iOSのBundleResourceやAndroidのAndroidAssetの形で持ってませんか。
私はそうしていたので、リソースアクセスのロジックを書く時もいつも場合分けしてました。
(もちろん普通は隠蔽化しますが)こんな感じで
#if __IOS__
var bundlePath = NSBundle.MainBundle.BundlePath;
var filePath = Path.Combine(bundlePath, "Assets/hoge.png");
InputStream attachmentStream = File.OpenRead(filePath);
#else
InputStream attachmentStream = Application.Context.Assets.Open ("hoge.png");
#endif
これ、ビルドアクションとしてBundleResourceやAndroidAssetではなく、EmbeddedResourceというのを使ってやると、共通化できるようです。
EmbeddedResourceを使うと、そのリソースが含まれたアセンブリのアセンブリ名(デフォルト名前空間かもしれない。前記事で問題になった、Xamarin.iOSでのアセンブリ名でドットが外れる問題が、こちらでは存在しないので)をベースにして、プロジェクト内でのフォルダ構成を加えたものをアクセス子としてアクセスできるようです。
例えば、デフォルト名前空間がHoge.Fuga.Fooのアセンブリ内で、プロジェクト内での配置がBar/Baz.pngだった場合、アクセス子は「Hoge.Fuga.Foo.Bar.Baz.png」になります。
このアクセス子を利用して、
using System.Reflection;
...
//thisはとりあえずクラスだと何でもいい模様?
//その後の文法からして、アクセスするリソースのアセンブリに属するクラスでないといけないかもしれません。
//その辺は要追調査…
Type type = this.GetType();
Stream manifestResourceStream = type.Assembly.GetManifestResourceStream ("Hoge.Fuga.Foo.Bar.Baz.png");
InputStream resourceInputStream = InputStream.Wrap (manifestResourceStream);
のような形でアクセスしてやると、リソースからのStreamが取れます!
AOTかJITかの違いで、実機とシミュレータの動作が異なる事で不安のあるXamarinですが、Android/iOS実機でも(Debugモードでの流し込みのみですが)確認したので、多分共通に使えるはずです。
公式の情報としては、この辺にサンプルがあるようです(今まで知らなかったので未見…)。
環境変数での処理分けなんか必要なかったんや…。
これで相当レベル、下位レイヤの処理もPCL化できる?
書き込み可能フォルダ(iOSだとDocument/Cacheフォルダ、Androidだとdataフォルダとか)も隠蔽化/共通化できる仕様ってあるんだろか?
Xamarin.Mobileあたりがなんかしてるんだっけ?