iOS向けアプリでキーチェーンを使用するときに、それをUnityから設定するための方法。
iCloudの設定を行うときも、entitlementsの登録をする必要があるので、昨今はそちらのほうが多いかもしれません。
XCodeEditorを使用します。
また、PostProcessBuildで作業することになると思うので、
対象のプロジェクトフォルダはpathToBuiltProject(相対パス)とします。
entitlementsの生成
keychain情報が設定されている、entitlementsファイルを作成します。
中身はXMLファイルになっていて、こんな感じ。
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)hogehogegroup</string>
</array>
</dict>
</plist>
entitlementsは基本的に、key要素が「キー」、その次にくる要素が「値」という形になっているよう。
keychain-access-groupsキーの次にくるarrayが、キーチェーングループとして登録されます。
これをC#で生成するには次のようにしていきます。
まず、空のplistとdict要素を持つ、XmlDocumentオブジェクトを生成します。
XmlDocument document = new XmlDocument ();
XmlDocumentType doctype = document.CreateDocumentType ("plist", "-//Apple//DTD PLIST 1.0//EN", "http://www.apple.com/DTDs/PropertyList-1.0.dtd", null);
document.AppendChild (doctype);
XmlElement plist = document.CreateElement ("plist");
plist.SetAttribute ("version", "1.0");
XmlElement dict = document.CreateElement ("dict");
plist.AppendChild (dict);
document.AppendChild (plist);
というようにします。
ここで注意する点は、
document.CreateDocumentType ("plist", "-//Apple//DTD PLIST 1.0//EN", "http://www.apple.com/DTDs/PropertyList-1.0.dtd", null);
で、最後にある内部サブセットの指定する引数にnullを指定すること。
これをnullに指定しないと、document.Save()で出力されるXMLが
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" []>
となります。
最後に「[]」がついているのがお分かりいただけるだろうか。
これがあると、XCodeはentitlementsを認識しない。厄介。
すでにentitlemetnsファイルを用意する場合は、document.Load()で読み込むことになるけれど、
このときそれをそのままSave()で出力しても、同様に「[]」がついてしまう。
なので、すでにあるentitlementsを読み込む場合は、
XmlDocumentType oldType = document.DocumentType;
XmlDocumentType newType = document.CreateDocumentType (oldType.Name, oldType.PublicId, oldType.SystemId, null);
document.ReplaceChild (newType, oldType);
という形にして、DocumentTypeを作りなおしてやります。
この後は、普通に要素を追加していきます。
XmlElement e = (XmlElement) document.SelectSingleNode ("/plist/dict");
XmlElement key = document.CreateElement ("key");
key.InnerText = "keychain-access-groups";
e.AppendChild (key);
XmlElement value = document.CreateElement ("array");
XmlElement value2 = document.CreateElement ("string");
value2.InnerText = "$(AppIdentifierPrefix)hogehogegroup";
value.AppendChild (value2);
e.AppendChild (value);
そして、出力。
出力先は、XCodeプロジェクトのパスの下に、Libraries/hogehoge.entitlementsというファイルを作ることにします。
document.Save(pathToBuiltProject+"/Libraries/hogehoge.entitlements");
entitlementsの登録
作成したentitlementsをプロジェクトに登録します。
entitlementsはひとつしか登録できないため、上書きすることになります。
もし他のAssetsなどと競合する場合は、そのAssetsが登録しているentitlementsを修正するなどして、登録自体は行わないようにするなどしてやる必要が出てきます。
XCProjectオブジェクトの生成
XCodeのプロジェクトを操作するため、XCProjectオブジェクトを生成します。
string absPathToBuiltProject = System.IO.Path.GetFullPath (pathToBuiltProject);
XCProject project = new XCProject (absPathToBuiltProject);
というように、pathToBuiltProjectをSystem.IO.Path.GetFullPath()で絶対パスに直して使用します。
これは後にファイルを追加するとき、ここで指定したパスからSystem.Uriオブジェクトを生成しているところがあるのですが、そこで相対パスがエラーとなるためです。
entitlementsファイルをプロジェクトに登録
ファイルの登録は
project.AddFile (absPathToBuiltProject+"/Libraries/hogehoge.entitlements", null, "SOURCE_ROOT", true, false);
というように行います。
CODE_SIGN_ENTITLEMENTSの登録
各ビルド設定に、CODE_SIGN_ENTITLEMENTS要素を登録します。
foreach (KeyValuePair<string, XCBuildConfiguration> item in project.buildConfigurations) {
XCBuildConfiguration buildConfig = item.Value;
buildConfig.buildSettings.Add ("CODE_SIGN_ENTITLEMENTS", "/Libraries/hogehoge.entitlements");
}
プロジェクトの保存
最後にプロジェクトを保存します。
project.Save();
結構雑な感じはしています。もっとうまいやり方があったら教えて下さい。