Xamrin.FormsでDebugとReleaseで設定ファイルを切り替える方法 メモ
こちらの記事のとおりにやってみる. redth.codes
これは読み込む設定ファイルがDebugビルドとReleaseビルドで切り替わるようにするもので,asp.netのuser secretのように「接続情報などの機密情報をgit管理されるプロジェクトファイル群の外側におくことで機密情報が公開されないようにする」ものではないので注意.
設定ファイルを作成する
Releaseビルド用のsettings.json
ファイルとDebugビルド用のlocal.settings.json
ファイルを作成する.
ファイルの中はそれぞれ以下のように記述する.
settings.json
{ "apiUrlBase": "https://myserver.com/api/", "apiKey": "123456" }
local.settings.json
{ "apiUrlBase": "localhost", "apiKey": "abcdefg" }
設定ファイルをEmbedded Resource
に設定する
settings.jsonとlocal.settings.jsonファイルのプロパティを開きます.
Build Action
の項目をEmbedded resource
に変更します.
この時点で共有プロジェクトのcsprojファイルには以下のように2つのファイルがEmbedded resourceとして登録されていることがわかります.
<ItemGroup> <EmbeddedResource Include="Settings\local.settings.json" /> <EmbeddedResource Include="Settings\settings.json" /> </ItemGroup>
ビルド条件を追加する
Condition
にそれぞれのファイルをEmbedded resourceとしてアプリケーションに取り込む条件を設定します.
<ItemGroup> <EmbeddedResource Include="Settings\settings.json" Condition="'$(Configuration)' != 'Debug' or !Exists('Settings\local.settings.json')" /> <EmbeddedResource Include="Settings\local.settings.json" Link="settings.json" Condition="'$(Configuration)' == 'Debug' and Exists('Settings\local.settings.json')" /> </ItemGroup>
条件は以下のとおりです.
Debugビルドではない,または,
local.settings.json
ファイルがない場合はsettings.json
を使用する.Debugビルド,かつ,
local.settings.json
ファイルが存在する場合はlocal.settings.json
を使用する.
local.settings.jsonにはCondition
の他にLink="settings.json"
という指定があります.
この指定で,local.settings.jsonファイルがsettings.json
という名前でアプリに組み込まれます.これで,どちらのファイルが取り込まれたとしても,アプリケーション内で読み込む際にはsettings.json
と指定することができます.
設定ファイルを読み込む
設定ファイルはJSONで記述されているので,これをオブジェクトに変換するためにSystem.Text.Json
をNugetからインストールしておきます.
Embedded resourceなファイルを読み込む手順は以下のとおりです.
var assembly = Assembly.GetExecutingAssembly(); var resName = assembly.GetManifestResourceNames() ?.FirstOrDefault(r => r.EndsWith("settings.json", StringComparison.OrdinalIgnoreCase)); using var file = assembly.GetManifestResourceStream(resName); using var sr = new StreamReader(file); var jsonText = sr.ReadToEnd();
ここまでで文字列としてのJSONを読み込むことができました.
JSONのプロパティの値を取得する
プロパティの値を取得するためには文字列としてのJSONをオブジェクトに変換(デシリアライズ,逆シリアル化)する必要があります.
このとき,JSONのデータを表現するクラスを作成(定義が既知)してそれを利用してデシリアライズ→プロパティ取得する方法と,定義が未知のデータをデシリアライズ→プロパティ取得する方法があります.
今回はプロパティの数も少ないシンプルな内容なので,クラスを定義しない方法を取ります.
参考: C# で定義が未知の Json を扱う (.NET Core / System.Text.Json) - rksoftware
var jsonDocument = JsonDocument.Parse(jsonText); jsonDocument.RootElement.TryGetProperty("apiUrlBase", out var apiUrlBaseElement); var apiUrlBase = apiUrlBaseElement.GetString();
TryGetProperty
メソッド,またはGetProperty
メソッドでJSONのプロパティ名を文字列で指定することで,そのプロパティのオブジェクトを取得できます.
そこから文字列としてプロパティのデータを取得するためにGetString
メソッドを使います.
これをバインディングで画面に表示させます.
実行結果
Debugビルドの場合:
Releaseビルドの場合:
それぞれ,異なる設定ファイルの内容が表示されます.
エミュレータでReleaseしたときにエラーが出る場合
エミュレータでReleaseで実行した際に以下のようなエラーが出ることがあります.
ADB0020: Android ABI mismatch. You are deploying an app supporting 'armeabi-v7a;arm64-v8a' ABIs to an incompatible device of ABI 'x86'. You should either create an emulator matching one of your app's ABIs or add 'x86' to the list of ABIs your app builds for.
このような場合は,以下のようにします.
まず,Androidプロジェクトのプロパティを開きます.
プロパティが開いたら,左側のAndroid Options
タブを選択し,ページを一番下までスクロールさせるとAdvanced
というボタンがあるので,押します.
詳細設定のウィンドウが表示されるので,Supported architectures
の項目でx86
とx86_64
にもチェックを入れます.
これでエミュレータでも実行できます.
日本語対応について
JSONデータに日本語が含まれていた場合をみてみます.
local.settings.jsonファイルを以下のように変更します.
{ "apiUrlBase": "これはlocalhostです", "apiKey": "abcdefg" }
実行すると,文字化けしています.
これはVisual StudioでJSONファイルをテンプレートから作成すると,そのテンプレート自体がShif-JISで保存されていて,アプリケーション側ではそれをUTF-8で開くので結果文字化けします.
VS CodeなどのエディタでUTF-8で保存し直せばOKです.
文字コード問題の対処
- UTF-8で保存し直す.
- Visual Studio内で作成せず,外部でUTF-8で作成した後にVisual Studioのプロジェクトに取り込む.
- そもそもVisual StudioのファイルのテンプレートをUTF-8で保存する
3について,以下が詳しいです.
ところでこのテンプレートファイルの文字コードはなに由来で決まるんだろうか.
OSのロケールをもとにVisual Studioのインストール時に決まるのかな?
ソースコード
今回のソースコードはこちら.