目录
1. 代码仓库
2. 代码展示
3. Feature 2017.3.29 设置Xcode Capabilities
4. Add Localizations 2017-04-07
5. 构建API
6. XUPorter 不建议使用
7. 新问题-2017.10.27
添加微信SDK导出,修改xcode工程 添加plist scheme。
下载地址: https://bitbucket.org/Unity-Technologies/xcodeapi
支持:Unity : 5.4.1p1+ / Xcode: 8.1+
PostProcessBuild (在Unity编译的最后加入了一个脚本调用的命令,会自动搜索Editor文件夹下的PostprocessBuildPlayer,并进行调用)。
public override void OnPostprocessBuild (BuildTarget BuildTarget, string path){
if (BuildTarget == BuildTarget.iOS) {
string projPath = PBXProject.GetPBXProjectPath (path);
PBXProject proj = new PBXProject ();
proj.ReadFromString (File.ReadAllText (projPath));
generateProjFile (proj, path);//处理Xcode工程
string plistPath = path + "/Info.plist";
PlistDocument plist = new PlistDocument ();
plist.ReadFromString (File.ReadAllText (plistPath));
generatePlistFile (plist.root, path);//处理plist文件
File.WriteAllText (projPath, proj.WriteToString ());
File.WriteAllText (plistPath, plist.WriteToString ());
this.ParseIcon ();
/*
this.ParseSplashXLib (new Color (34 / 255f, 44 / 255f, 55 / 255f));//修改背景色
this.Buildipa();//代码请见Part2博客
generateFBSettingsConfig();// FaceBook SDK
generateHelpShiftConfig();//Helpshift SDK
*/
}
}
private void generateProjFile(PBXProject proj,string path){
string target = proj.TargetGuidByName (PBXProject.GetUnityTargetName ());
var codesign = Debug.isDebugBuild ? "iPhone Developer: xxxxxxxxxxx" : "iPhone Distribution: xxxxxxxx";
var provision = Debug.isDebugBuild ? "xxxxx" : "xxxxx";
proj.SetBuildProperty (target, "CODE_SIGN_IDENTITY", codesign);
proj.SetBuildProperty (target, "PROVISIONING_PROFILE_SPECIFIER", provision);
proj.SetBuildProperty (target, "CODE_SIGN_ENTITLEMENTS", "KeychainAccessGroups.plist");
proj.SetBuildProperty (target, "DEVELOPMENT_TEAM", "xxxxxxxxxx");
proj.SetBuildProperty (target, "ENABLE_BITCODE", "NO");
proj.SetSystemCapabilities (target, "com.apple.Push", "1");
proj.SetSystemCapabilities (target, "com.apple.GameCenter", "1");
proj.SetSystemCapabilities (target, "com.apple.InAppPurchase", "1");
proj.RemoveFilesByProjectPathRecursive ("Libraries/Plugins/Android"); // 移除某个目录,根据开发者需求
proj.AddBuildProperty (target, "HEADER_SEARCH_PATHS", Application.dataPath + "/_PlatformAssets/Platforms/xxxxxxxx");//修改Xcode索引目录
//keychain
proj.AddFile (Application.dataPath + "你的目录/KeychainAccessGroups.plist", "KeychainAccessGroups.plist");
proj.SetBuildProperty (target, "CODE_SIGN_ENTITLEMENTS", Application.dataPath + "你的目录/KeychainAccessGroups.plist");
// weixin framework
// proj.AddFrameworkToProject (target, "SystemConfiguration.framework", false);
// SvUDIDTools是UDID文件,可以忽略。
// AddFile添加文件到Xcode目录,返回文件GUID
// AddFileToBuild功能是将GUID文件添加到Xcode BuildPhases阶段
var fileGUID = "";
fileGUID = proj.AddFile (Application.dataPath + "你的目录/SvUDIDTools.h", "Libraries/Plugins/IOS/SvUDIDTool/SvUDIDTools.h");
proj.AddFileToBuild (target, fileGUID);
fileGUID = proj.AddFile (Application.dataPath + "你的目录/SvUDIDTools.m", "Libraries/Plugins/IOS/SvUDIDTool/SvUDIDTools.m");
proj.AddFileToBuild (target, fileGUID);//添加到Xcode BuildPhases阶段
// localizable 自动添加Xcode语言文件
var infoDirs = Directory.GetDirectories (Application.dataPath + "你的目录/lang/infoplist/");
for (var i = 0; i < infoDirs.Length; ++i) {
var files = Directory.GetFiles (infoDirs [i], "*.strings");
proj.AddLocalization (files [0], "InfoPlist.strings", "InfoPlist.strings");
}
var localdirs = Directory.GetDirectories (Application.dataPath + "你的目录/lang/localizable/");
for (var i = 0; i < localdirs.Length; ++i) {
var files = Directory.GetFiles (localdirs [i], "*.strings");
proj.AddLocalization (files [0], "Localizable.strings", "Localizable.strings");
}
fileGUID = proj.AddFile (Application.dataPath + "/Plugins/IOS/notificationsound.caf", "notificationsound.caf"); // 添加推送音效
proj.AddFileToBuild (target, fileGUID);
}
private void generatePlistFile(PlistElementDict rootDict,string path){
rootDict.SetString ("CFBundleIdentifier", "com.gekko.rok");
rootDict.SetString ("CFBundleDisplayName", "Rage of Kings");
rootDict.SetString ("CFBundleVersion", GetVer ());
rootDict.SetString ("NSPhotoLibraryUsageDescription", "Use Photo");
rootDict.SetString ("NSCameraUsageDescription", "Use Camera");
rootDict.SetString ("CFBundleShortVersionString", GKVersion.GAME_VERSION);
rootDict.SetString ("ITSAppUsesNonExemptEncryption", "false");
rootDict.SetString ("LSHasLocalizedDisplayName","true");
// weixin scheme
PlistElementArray urlArray = null;
if (!rootDict.values.ContainsKey ("CFBundleURLTypes")) {
urlArray = rootDict.CreateArray ("CFBundleURLTypes");
} else {
urlArray = rootDict.values ["CFBundleURLTypes"].AsArray ();
}
var urlTypeDict = urlArray.AddDict();
urlTypeDict.SetString("CFBundleURLName", "weixin");
var urlScheme = urlTypeDict.CreateArray("CFBundleURLSchemes");
urlScheme.AddString("weixin_id");
if (!rootDict.values.ContainsKey ("LSApplicationQueriesSchemes")) {
urlArray = rootDict.CreateArray ("LSApplicationQueriesSchemes");
} else {
urlArray = rootDict["LSApplicationQueriesSchemes"].AsArray();
}
urlArray.AddString ("weixin");
// Gamecenter
if (rootDict.values.ContainsKey ("UIRequiredDeviceCapabilities")) {
rootDict.values.Remove ("UIRequiredDeviceCapabilities");
}
var arr = rootDict.CreateArray ("UIRequiredDeviceCapabilities");
arr.AddString ("armv7");
arr.AddString ("gamekit");
}
protected void ParseIcon(){
string sourcePath = "/_ExportTextures/appIcon/{0}.png";
var icoList = new List () {
"Icon",
"Icon-72",
"Icon-76",
"Icon-120",
"Icon@2x",
"Icon-144",
"Icon-152",
"Icon-167",
"Icon-180",
"Icon-Store"//1024*1024 , xcode9+
};
foreach (var ico in icoList) {
File.Copy (Application.dataPath + string.Format (sourcePath, ico), XCodeProjectMod.XcodePath() + string.Format ("/Unity-iPhone/Images.xcassets/AppIcon.appiconset/{0}.png", ico), true);
}
}
//using System.Xml;
protected void ParseSplashXLib(Color color){
Action ModifyXML = (xmlPath) => {
XmlDocument xmlDoc = new XmlDocument ();
xmlDoc.Load (xmlPath);
XmlNodeList nodelist = xmlDoc.SelectSingleNode ("document").ChildNodes;
foreach (XmlElement item in nodelist) {
if (item.Name == "objects") {
foreach (XmlElement item1 in item.ChildNodes) {
if (item1.Name == "view") {
foreach (XmlElement item2 in item1.ChildNodes) {
if (item2.Name == "color") {
item2.SetAttribute ("red", color.r.ToString ());
item2.SetAttribute ("green", color.g.ToString ());
item2.SetAttribute ("blue", color.b.ToString ());
item2.SetAttribute ("alpha", color.a.ToString ());
}
}
}
}
}
}
xmlDoc.Save (xmlPath);
};
ModifyXML (XCodeProjectMod.XcodePath () + "/LaunchScreen-iPhone.xib");
ModifyXML (XCodeProjectMod.XcodePath () + "/LaunchScreen-iPad.xib");
}
SetSystemCapabilities函数实现 //proj.SetSystemCapabilities (target, "com.apple.Push","1")
//PBXProjects.cs文件
public void SetSystemCapabilities(string target,string key,string value){
project.project.SetSystemCapabilities (target, key, value);
}
//找到Objects.cs => internal class PBXProjectObjectData : PBXObjectData类内添加此函数
public void SetSystemCapabilities(string target,string key,string value){
if (m_Properties.Contains ("attributes")) {
var attributes = m_Properties ["attributes"].AsDict ();
var targetAttributes = attributes ["TargetAttributes"].AsDict ();
if (targetAttributes.Contains (target)) {
var targetDict = targetAttributes [target].AsDict ();
if (!targetDict.Contains ("SystemCapabilities")) {
var dict = targetDict.CreateDict ("SystemCapabilities");
var record = dict.CreateDict (key);
record.SetString ("enabled", value);
} else {
var dict = targetDict ["SystemCapabilities"].AsDict ();
if (!dict.Contains (key)) {
var record = dict.CreateDict (key);
record.SetString ("enabled", value);
} else {
var record = dict [key].AsDict ();
record.SetString ("enabled", value);
}
}
} else {
//error
}
}
}
添加本地化文件此功能没有进入到stable分支, 而是在pull requests内 。
https://bitbucket.org/Unity-Technologies/xcodeapi/pull-requests/13/creation-of-variantgroup-and/diff
代码需要自己移植到项目内,语言文件需要自己首先在Xcode工程里创建好,然后拷贝到Unity Assets内。
我的Unity文件目录:
示例代码:
var infoDirs = Directory.GetDirectories (Application.dataPath + "/IOS/lang/infoplist/");
for (var i = 0; i < infoDirs.Length; ++i) {
var files = Directory.GetFiles (infoDirs [i], "*.strings");
proj.AddLocalization (files [0], "InfoPlist.strings", "InfoPlists.strings");
}
var localdirs = Directory.GetDirectories (Application.dataPath + "/IOS/lang/localizable/");
for (var i = 0; i < localdirs.Length; ++i) {
var files = Directory.GetFiles (localdirs [i], "*.strings");
proj.AddLocalization (files [0], "Localizable.strings", "Localizable.strings");
}
最终会在Xcode工程内出现下图内容:
case Configuration.Debug:
BuildPipeline.BuildPlayer (GetBuildScenes(),XcodePath(),BuildTarget.iOS,BuildOptions.AllowDebugging | BuildOptions.SymlinkLibraries | BuildOptions.Development);
break;
case Configuration.Release:
BuildPipeline.BuildPlayer (GetBuildScenes(),XcodePath(),BuildTarget.iOS,BuildOptions.None);
break;
*上面贴的代码是调用unity build命令,开始build。
*可以添加Menu Item 功能菜单,点击Item按钮调用代码,自动打包构建Xcode工程,上传bugly,发邮件通知(都已实现)
之前用的是这款开源工具,现该项目作者已不维护,Unity5.x 之后版本更换方式。
新版本的Unity 2017 有一些问题。暂时降级Unity 5.6.4p3
Xcode升级到Xcode9 ,打包会遇到一些问题。Xcode9打包解决方案