简介:
Unity配置XCode自动化打包,有些Capability无法自动开启,需要自己手动开启,这其实很繁琐,需要复制粘贴文本等。
刚开始怀疑是不是Unity版本的问题,因为用的是Unity官方自带的API来添加Capability。之前的Unity版本是2017.4.7f1,最近项目升级了Unity版本,现在是2017.4.22f1版本,但测试了,还是开启不了有些Capability。
project.AddCapability(target, PBXCapabilityType.InAppPurchase);
project.AddCapability(target, PBXCapabilityType.BackgroundModes);
注释掉的代码测试过,开启不了PushNotifications,下面的2个能给开启。但也有问题,看下图:
也用过ProjectCapabilityManager来尝试开启Capability,发现没有用,倒是能修复BackgroudModes的问题。网上找了一堆文章,发现都没有好的解决方案。最后不甘心的去官网下载了源码来看,官网地址:https://bitbucket.org/Unity-Technologies/xcodeapi/src。最后终于解决一键生成XCode工程的问题,虽然还剩下一个问题,这估计不好解决。
看了ProjectCapabilityManager源码后,大致清楚开启Capability需要修改3个地方,一个是project.pbxproj,一个是info.plist,一个则是entitlements。
举个例子BackgroudModes的问题,其实只要修改info.plist,就可以开启。代码如下:
/// <summary>
/// 处理Plist工程
/// </summary>
/// <param name="project"></param>
/// <param name="plistPath"></param>
private static void GeneratePlistFile(PlistElementDict rootDict, string plistPath)
{
PlistElementArray urlArray = null;
//Add BackgroundModes
if (!rootDict.values.ContainsKey("UIBackgroundModes"))
{
urlArray = rootDict.CreateArray("UIBackgroundModes");
}
else
{
urlArray = rootDict.values["UIBackgroundModes"].AsArray();
urlArray.values.Clear();
urlArray.AddString("remote-notification");
}
加不加这句代码都没问题,已测试:
project.AddCapability(target, PBXCapabilityType.BackgroundModes);
entitlements的用法则是动态生成一个entitlements文件,举个例子,添加KeychainSharing:
string key_KeychainSharing = "keychain-access-groups";
var arr = (tempEntitlements.root[key_KeychainSharing] = new PlistElementArray()) as PlistElementArray;
arr.values.Add(new PlistElementString("$(AppIdentifierPrefix)com.tencent.lycqsh"));
arr.values.Add(new PlistElementString("$(AppIdentifierPrefix)com.tencent.wsj.keystoregroup"));
}
最重要的是entitlements的路径不要写错,是相对路径,我之前写成绝对路径,找这个问题,找了半天,这个路径也是有问题的,要去掉最前面的/,路径应该Unity-iPhone/test.entitlements或者test.entitlements。
最终项目使用的代码:
private static void AddCapability(PBXProject project, string pathToBuiltProject)
{
string target = project.TargetGuidByName(PBXProject.GetUnityTargetName());
// Add BackgroundModes And Need to modify info.plist
project.AddCapability(target, PBXCapabilityType.BackgroundModes);
project.AddCapability(target, PBXCapabilityType.InAppPurchase);
// Need Create entitlements
string relativeEntitlementFilePath = "Unity-iPhone/xxxx.entitlements";
string absoluteEntitlementFilePath = pathToBuiltProject + "/" + relativeEntitlementFilePath;
PlistDocument tempEntitlements = new PlistDocument();
string key_KeychainSharing = "keychain-access-groups";
var arr = (tempEntitlements.root[key_KeychainSharing] = new PlistElementArray()) as PlistElementArray;
arr.values.Add(new PlistElementString("$(AppIdentifierPrefix)com.tencent.xxxx"));
arr.values.Add(new PlistElementString("$(AppIdentifierPrefix)com.tencent.wsj.keystoregroup"));
string key_PushNotifications = "aps-environment";
tempEntitlements.root[key_PushNotifications] = new PlistElementString("development");
project.AddCapability(target, PBXCapabilityType.PushNotifications, relativeEntitlementFilePath);
project.AddCapability(target, PBXCapabilityType.KeychainSharing, relativeEntitlementFilePath);
string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
File.WriteAllText(projPath, project.WriteToString());
tempEntitlements.WriteToFile(absoluteEntitlementFilePath);
ModifyEntitlementFile(absoluteEntitlementFilePath);
}
private static void ModifyEntitlementFile(string absoluteEntitlementFilePath)
{
if (!File.Exists(absoluteEntitlementFilePath)) return;
try
{
StreamReader reader = new StreamReader(absoluteEntitlementFilePath);
var content = reader.ReadToEnd().Trim();
reader.Close();
var needFindString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
var changeString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n" + "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">";
Debug.Log("Before: " + content);
content = content.Replace(needFindString, changeString);
Debug.Log("After: " + content);
StreamWriter writer = new StreamWriter(new FileStream(absoluteEntitlementFilePath, FileMode.Create));
writer.WriteLine(content);
writer.Flush();
writer.Close();
}
catch (Exception e)
{
Debug.Log("ModifyEntitlementFile - Failed: " + e.Message);
}
}