shuhelohelo’s blog

Xamarin.Forms多めです.

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ファイルのプロパティを開きます.

f:id:shuhelohelo:20200528115540p:plain

Build Actionの項目をEmbedded resourceに変更します.

f:id:shuhelohelo:20200528115637p:plain

この時点で共有プロジェクトの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からインストールしておきます.

f:id:shuhelohelo:20200528133216p:plain

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ビルドの場合:

f:id:shuhelohelo:20200528142900p:plain

Releaseビルドの場合:

f:id:shuhelohelo:20200528143132p:plain

それぞれ,異なる設定ファイルの内容が表示されます.

エミュレータで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プロジェクトのプロパティを開きます. f:id:shuhelohelo:20200528143800p:plain

プロパティが開いたら,左側のAndroid Optionsタブを選択し,ページを一番下までスクロールさせるとAdvancedというボタンがあるので,押します.

f:id:shuhelohelo:20200528144110p:plain

詳細設定のウィンドウが表示されるので,Supported architecturesの項目でx86x86_64にもチェックを入れます.

f:id:shuhelohelo:20200528144327p:plain

これでエミュレータでも実行できます.

日本語対応について

JSONデータに日本語が含まれていた場合をみてみます.

local.settings.jsonファイルを以下のように変更します.

{
  "apiUrlBase": "これはlocalhostです",
  "apiKey": "abcdefg"
}

実行すると,文字化けしています. f:id:shuhelohelo:20200528145052p:plain

f:id:shuhelohelo:20200528145120p:plain

これはVisual StudioJSONファイルをテンプレートから作成すると,そのテンプレート自体がShif-JISで保存されていて,アプリケーション側ではそれをUTF-8で開くので結果文字化けします.

VS CodeなどのエディタでUTF-8で保存し直せばOKです.

f:id:shuhelohelo:20200528150724p:plain

f:id:shuhelohelo:20200528150747p:plain

文字コード問題の対処

  1. UTF-8で保存し直す.
  2. Visual Studio内で作成せず,外部でUTF-8で作成した後にVisual Studioのプロジェクトに取り込む.
  3. そもそもVisual StudioのファイルのテンプレートをUTF-8で保存する

3について,以下が詳しいです.

  • テンプレートファイルをUTF-8で保存し直す. qiita.com

  • UTF-8テンプレートファイルを作成して追加する qiita.com

ところでこのテンプレートファイルの文字コードはなに由来で決まるんだろうか.

OSのロケールをもとにVisual Studioのインストール時に決まるのかな?

ソースコード

今回のソースコードはこちら.

github.com