こんにちは、豚野郎です。 Xamarin 素敵ですね。XAMLでレイアウト組めるので、MVVMでのアプリ開発が捗ります。
さて、 アプリ開発をしていると、Twitterログインや広告を追加したくなります。
これらにはAPIキーをコードに埋め込む必要がありますが、当然リポジトリの管理化には置きたくありません。
Android では、 manifestPlaceHolders を使用してビルド時に挿入する事が可能ですが、どうググっても VisualStudio にはそのような素敵機能が見当たりません…。
とはいえ、APIキーを管理するクラスを .gitignore に埋め込むのは、クローン直後にビルドエラーになるためなんだかいやです。
できるならば manifestPlaceHolders のようにビルド時に挿入したいです。
標準機能で提供されていないので、ビルドイベントでファイル内の文字列を置換する事で実現してみようと思います。
対象ファイルに置換用文字列を埋め込む
public class Environment
{
/// <summary>
/// Twitter API の API KEY を取得します
/// </summary>
public string TwitterConsumerKey { get; } = "${TWITTER_CONSUMER_KEY}";
/// <summary>
/// Twitter API の API SECRET KEY を取得します
/// </summary>
public string TwitterConsumerSecretKey { get; } = "${TWITTER_CONSUMER_SECRET_KEY}";
}
${TWITTER_CONSUMER_KEY}
と ${TWITTER_CONSUMER_SECRET_KEY}
が置換用の文字列です。
ビルド時に上記の文字列を環境変数に定義された文字列に置換します。
Windows 環境用置換スクリプトを作成する
@echo off
set outpath=%1
set inpath=%outpath%.work
set before=%2
set after=%3
copy /Y %outpath% %inpath%
type nul > %outpath%
setlocal enabledelayedexpansion
for /f "tokens=1* delims=: eol=" %%a in ('findstr /n "^" %inpath%') do (
set line=%%b
if not "!line!" == "" (
set line=!line:%before%=%after%!
)
echo.!line!>> %outpath%
)
endlocal
del /Y %inpath%
exit /B 0
Windows には sed コマンドが存在しない為、 bat ファイルで代替します。
第一引数のファイル内に、第二引数で指定された文字列が存在する場合、第三引数で指定された文字列に置換します。
スクリプトは こちら を参考にさせて頂きました。
プロジェクトに PreBuildEvent と PostBuildEvent を埋め込む。
<Project>
... 中略 ...
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<PreBuildEvent>
copy /Y $(ProjectDir)Environment.cs $(ProjectDir)Environment.cs.bak
call $(ProjectDir)replace.bat $(ProjectDir)Environment.cs ${TWITTER_CONSUMER_KEY} $(TWITTER_CONSUMER_KEY)
call $(ProjectDir)replace.bat $(ProjectDir)Environment.cs ${TWITTER_CONSUMER_SECRET_KEY} $(TWITTER_CONSUMER_SECRET_KEY)
</PreBuildEvent>
<PostBuildEvent>move /Y $(ProjectDir)Environment.cs.bak $(ProjectDir)Environment.cs</PostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT' ">
<PreBuildEvent>
source ~/.bash_profile
cp $(ProjectDir)Environment.cs $(ProjectDir)Environment.cs.bak
sed -i '' 's/${TWITTER_CONSUMER_KEY}/'$TWITTER_CONSUMER_KEY'/g' $(ProjectDir)Environment.cs
sed -i '' 's/${TWITTER_CONSUMER_SECRET_KEY}/'$TWITTER_CONSUMER_SECRET_KEY'/g' $(ProjectDir)Environment.cs
</PreBuildEvent>
<PostBuildEvent>mv $(ProjectDir)Environment.cs.bak $(ProjectDir)Environment.cs</PostBuildEvent>
</PropertyGroup>
</Project>
PreBuildEvent にて、環境変数をコード中に存在する特定文字列を置換する事で、ビルド時の環境変数展開を実現しています。
また、誤って環境変数が展開されたソースコードを git にコミットしない為に、 PreBuildEvent にて作成したバックアップファイルを PostBuildEvent で元ファイルに上書きしています。