热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Unity打iOS包之xcodeapi的使用

xcodeapi我们在用Unity打包iOS的时候,经常需要自动化设置导出工程的各项配置,比如证书名、TeamId、mobileprovision文件

xcodeapi

我们在用Unity打包iOS的时候,经常需要自动化设置导出工程的各项配置,比如证书名、TeamId、mobileprovision文件等等。

在Unity 4.x时代,常用的工具是XUPorter(原作者已不再维护,如果坚持要用,可以从github上下载:https://github.com/onevcat/XUPorter)

在Unity 5.x之后,Unity官方提供了另外一套工具,叫做xcodeapi,因为是官方维护的,所以在使用上可以更放心,所以推荐使用。

xcodeapi的工程链接在Unity的开源bitbucket上:https://bitbucket.org/Unity-Technologies/xcodeapi

上面这个链接貌似失效了,我传了一份到GitHub上,可以从GitHub中下载xcodeapi:https://github.com/chenpindong/XcodeAPI

如果访问GitHub比较卡,也可以访问CODE.CHINA,我也传了一份:https://codechina.csdn.net/linxinfa/unity-xcodeapi

原理

其实,这个工具的工作原理并不复杂,利用的是Unity工作的一个固定流程:Unity在导出工程之后,会去继续搜索并执行被标记为[PostProcessBuildAttribute]的方法,而对于Unity导出的iOS工程,所有的配置信息都会被记录在一个固定名称的文件里面,其中一个是导出工程目录下的 Unity-iPhone.xcodeproj/project.pbxproj,是一个json格式的文本文件,所有的Build Setting项都在这个文件里面;另外一个叫Info.plist,是个xml格式的文件。所以,这个工具就是提供了json和xml文件操作的能力,和几个特定的接口,用于更改指定配置项的内容。

 

使用

明确这一点之后,使用起来应该就可以更有数了。使用方法很简单,只要把工程文件下载下来,把里面的xcode目录放到你工程的某个Editor目录下,然后在里面添加一个标记为PostProcessBuildAttribute的方法,在这个方法里面修改你的xcode工程配置就可以了,例如下面的类,也放在Editor目录下,类名随便取:

using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode.Custom;public class ProjectPostProcess
{[PostProcessBuildAttribute(1)]public static void OnPostProcessBuild(BuildTarget buildTarget, string pathToBuiltProject){// 只处理IOS工程, pathToBuildProject会传入导出的ios工程的根目录if (buildTarget != BuildTarget.iOS)return;// 创建工程设置对象var projectPath = pathToBuiltProject + "/Unity-iPhone.xcodeproj/project.pbxproj";PBXProject project = new PBXProject();project.ReadFromFile(projectPath);string targetGuid = project.TargetGuidByName("Unity-iPhone");// 修改BITCODE设置的例子project.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");// 你可能会设置的--------------------------------------------------//project.SetBuildProperty(targetGuid, "CODE_SIGN_IDENTITY", "p12证书的code_sign");// 把证书设置设置为手动,即不使用Automatically manage signing//project.SetTargetAttributes("ProvisioningStyle","Manual");//project.SetBuildProperty(targetGuid, "PROVISIONING_PROFILE", "mobileprovison文件的UUID");//project.SetBuildProperty(targetGuid, "PROVISIONING_PROFILE_SPECIFIER", "mobileprovison文件的Name");//project.SetTeamId(targetGuid,"证书的TeamId");//project.SetBuildProperty(targetGuid, "IPHONEOS_DEPLOYMENT_TARGET", "8.0");// 添加framework//project.AddFrameworkToProject(targetGuid, "StoreKit.framework", true);//----------------------------------------------------------------// 修改后的内容写回到配置文件File.WriteAllText(projectPath, project.WriteToString());// 修改Info.plist的示例var plistPath = Path.Combine(pathToBuiltProject, "Info.plist");var plist = new PlistDocument();plist.ReadFromFile(plistPath);// 增加字符串类型的设置plist.root.SetString("fieldname", "value");// 修改后的内容写回到文件Info.plistplist.WriteToFile(plistPath);}
}


关于这个方法的属性,网上的有些例子上写的是PostProcessBuild,其实只是PostProcessBuildAttribute的简写,意义是一样的,不需要纠结。

 

常用的的Property:


Property备注
CODE_SIGN_IDENTITYp12证书的code_sign

在钥匙串那里看

双击钥匙串里已安装的证书

最上面显示的标题就是code_sign

也叫“常用名称”

DEVELOPMENT_TEAM证书的TeamId

在钥匙串那里看,

查看方法同上,“组织单位”的值就是TeamId

使用project.SetTeamId接口进行设置

ENABEL_BITCODEYES / NO关于Bitcode:https://www.cnblogs.com/QianChia/p/6223047.html
IPHONEOS_DEPLOYMENT_TARGET8.0/8.1/8.2/..../12.1

Unity打出来的默认是6.0

目前最低必须设置为8.0以上

PRODUCT_BUNDLE_IDENTIFIER项目的bundleIdcom.xxx.xxxx
PRODUCT_NAME项目的名称 
PROVISIONING_PROFILE.mobileprovision的UUID

用vim打开.mobileprovision文件

然后查找UUID:

在vim中输入/UUID,然后按回车键

PROVISIONING_PROFILE_SPECIFIERmobileprovision的Name

用vim打开.mobileprovision文件

然后查找Name:

在vim中输入/UUID,然后按回车键


 


一步到位

如果想要一步到位,导出xcode后自动执行Archive和生产ipa,可以写好shell脚本自动运行

Archive脚本

xcodebuild -project "工程目录/Unity-iPhone.xcodeproj" -scheme Unity-iPhone archive -archivePath "Archive的目录"

生成ipa脚本

xcodebuild -project "工程目录/Unity-iPhone.xcodeproj" -exportArchive -exportFormat ipa -archivePath "Archive的目录" -exportPath "ipa的目录" -exportProvisioningProfile "mobileprovision文件的Name"

Xcode7之后取消了原来的-exportFormat,而是使用exportOptionsPlist 来取代

改用下面的命令

xcodebuild -exportArchive -exportOptionsPlist xxx/Info.plist -archivePath xxx.xcarchive -exportPath ~/Desktop/

xcodebuild -exportArchive -exportOptionsPlist ../ExportOptions.plist -archivePath ../testPacking.xcarchive -exportPath ./autoPackage -allowProvisioningUpdates

我们需要自己创建一个plist作为Export Options

写个工具类方便生成

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;class XcodeExportPlist
{///

/// 对应ios_build_config.json的exportArchiveMethod/// public static readonly string[] kMethods ={"app-store","enterprise","ad-hoc","development",};public static void GenFile(string filPath, string teamID, string method, string bundleID, string profileName){string text = GenText(teamID, method, bundleID, profileName);System.IO.File.WriteAllText(filPath, text);GameLogger.LogGreen("GenFile: " + filPath);}static string GenText(string teamID, string method, string bundleID, string profileName){var sb = new System.Text.StringBuilder();sb.Append("\n");sb.Append("\n");sb.Append("\n");sb.Append("\n");AppendTeamID(sb, teamID);AppendMethod(sb, method);AppendUploadSymbols(sb, false);AppendProfiles(sb, bundleID, profileName);sb.Append("\n");sb.Append("\n");return sb.ToString();}static void AppendTeamID(System.Text.StringBuilder sb, string teamID, string ind = "\t"){sb.Append(ind).Append("teamID\n");AppendPStr(sb, teamID, ind);}static void AppendMethod(System.Text.StringBuilder sb, string method, string ind = "\t"){sb.Append(ind).Append("method\n");AppendPStr(sb, method, ind);}static void AppendUploadSymbols(System.Text.StringBuilder sb, bool isUploadSymbols, string ind = "\t"){sb.Append(ind).Append("uploadSymbols\n");AppendPBool(sb, isUploadSymbols, ind);}static void AppendProfiles(System.Text.StringBuilder sb, string bundleID, string profilesName, string ind = "\t"){Dictionary dic = new Dictionary();if (!string.IsNullOrEmpty(bundleID)){dic.Add(bundleID, profilesName);}if (dic.Count > 0){sb.Append(ind).Append("provisioningProfiles\n");AppendPDict(sb, dic, ind);}}static void AppendPStr(System.Text.StringBuilder sb, string s, string ind){sb.Append(ind);sb.Append("");sb.Append(s);sb.Append("\n");}static void AppendPBool(System.Text.StringBuilder sb, bool b, string ind){sb.Append(ind).Append(b ? "" : "").Append("\n");}static void AppendPDict(System.Text.StringBuilder sb, Dictionary key_value, string ind){sb.Append(ind);sb.Append("");foreach (var item in key_value){sb.Append("\n").Append(ind);sb.Append("");sb.Append(item.Key);sb.Append("");sb.Append("\n").Append(ind);sb.Append("");sb.Append(item.Value);sb.Append("");}sb.Append("\n").Append(ind);sb.Append("\n");}
}// end class XcodeExportPlist

用上面的XcodeExportPlist工具类生成exportOption.plist

public static string GenArchiveOptPlist()
{var path = Application.dataPath.Replace("Assets", "Bin/exportOption.plist";var teamId = "BQCHO456";// "app-store","enterprise","ad-hoc","development"var archiveMethod = "enterprise";var bundleId = "com.linxinfa.test";var provisionName = "linxinfaEnt2019614";XcodeExportPlist.GenFile(path, teamId, archiveMethod, bundleId, provisionName);return path;
}

ExportOptionsPlist文件

结合《Unity中C#如何执行cmd命令(System.Diagnostics.Process的使用)》

https://blog.csdn.net/linxinfa/article/details/52982384

可以通过C#执行shell命令

//var version = "1.0.0";
//var binPath = Application.dataPath + "/../Bin";
//var xcodeProjPath = binPath + "/XcodeProj";
//var xcodeArchPath = binPath + "/Archives/Unity-iPhone-archive.xcarchive";
//var outputPath = string.Format("{0}/{1}/", binPath, version);
//var appName = string.Format("mygame_v{0}_{1}.ipa", version, DateTime.Now.ToString("yyyyMMdd"));private static void XCodeArchive(string xcodeProjPath, string xcodeArchPath)
{Debug.Log("XCodeArchive Begin");string args &#61; string.Format("-project \"{0}/Unity-iPhone.xcodeproj\" -scheme Unity-iPhone archive -archivePath \"{1}\" ", xcodeProjPath, xcodeArchPath);var r &#61; EdtUtil.RunCmd("xcodebuild", args);if (string.IsNullOrEmpty(r[0]) || r[0].LastIndexOf("ARCHIVE SUCCEEDED") <0){Debug.LogError("Build IPA : XCodeBuildArchive FAILED\n" &#43; r[0]);throw new Exception("Build IPA : XCodeBuildArchive FAILED");}Debug.LogGreen("Build IPA : XCodeBuildArchive OK");
}private static void XCodeExportIPA(string xcodeProjPath, string xcodeArchPath, string outputPath, string ipaName)
{// 生成plistvar expOptPath &#61; GenArchiveOptPlist();Debug.Log("XCodeExportIPA Begin\n xcodeProjPath: " &#43; xcodeProjPath &#43; "\nxcodeArchPath: " &#43; xcodeArchPath &#43; "\noutputPath: " &#43; outputPath);string args &#61; string.Format("-project \"{0}/Unity-iPhone.xcodeproj\" -exportArchive -archivePath \"{1}\" -exportPath \"{2}\" -exportOptionsPlist \"{3}\" ",xcodeProjPath, xcodeArchPath, outputPath, expOptPath);var r &#61; EdtUtil.RunCmd("xcodebuild", args);if (string.IsNullOrEmpty(r[0]) || r[0].LastIndexOf("EXPORT SUCCEEDED") <0){Debug.LogError("Build IPA : XCodeBuildIPA FAILED\n" &#43; r[0]);throw new Exception("Build IPA : XCodeBuildIPA FAILED");}Debug.LogGreen("Build IPA : XCodeBuild IPA OK");// 重命名File.Move(outputPath &#43; "Unity-iPhone.ipa", outputPath &#43; ipaName);
}

如果不放心&#xff0c;也可以到XCode进行手动ipa打包

Archive&#xff1a;

先检查Product->Scheme->Edit Scheme...中的设置是否正确&#xff0c;比如现在是要打的是面向外部玩家的版本&#xff0c;则要Run里面要选择Relaese&#xff0c;Archive里也要选择Release&#xff0c;记得勾选Archive的Options的Reveal Archive in Organizer&#xff0c;检查工程的General中的证书设置是否正确&#xff0c;检查工程的Images.xcassets中的AppIcon的图标设置是否正常

检查无误之后&#xff0c;就可以执行Archive了: Product->Archive

导出ipa&#xff1a;

Archive完之后&#xff0c;会自动弹出Organizer窗口&#xff0c;如果没有弹出来&#xff0c;则手动打开&#xff1a;Window->Organizer

然后点击Distribute App按钮&#xff0c;接下来一步一步Next&#xff0c;注意中间会让你选择一些选项&#xff0c;根据需求进行选择即可

补充&#xff1a;

如果要对不同的配置做修改&#xff0c;比如&#xff0c;单独修改Debug版本或者Release版本的配置项&#xff0c;那么就需要用BuildConfigByName先获取到指定的配置项&#xff0c;然后使用SetBuildPropertyForConfig设置对应的配置项&#xff0c;例如&#xff0c;单独修改debug版本的ENABLE_BITCODE设置&#xff1a;

string configGuid &#61; project.BuildConfigByName("targetGuid", "Debug");
project.SetBuildPropertyForConfig(configGuid, "ENABLE_BITCODE", "NO");

另外&#xff0c;对于XUPorter的导出插件和native代码的功能&#xff0c;Unity 5之后可以直接把需要的文件放在Assets/Plugins/iOS目录下面&#xff0c;文件就会被自动导出到目标工程中&#xff0c;请参考Unity文档&#xff1a;https://docs.unity3d.com/Manual/PluginsForIOS.html
 


参考&#xff1a;https://blog.csdn.net/yubo112002/article/details/83449694


推荐阅读
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • 微软评估和规划(MAP)的工具包介绍及应用实验手册
    本文介绍了微软评估和规划(MAP)的工具包,该工具包是一个无代理工具,旨在简化和精简通过网络范围内的自动发现和评估IT基础设施在多个方案规划进程。工具包支持库存和使用用于SQL Server和Windows Server迁移评估,以及评估服务器的信息最广泛使用微软的技术。此外,工具包还提供了服务器虚拟化方案,以帮助识别未被充分利用的资源和硬件需要成功巩固服务器使用微软的Hyper - V技术规格。 ... [详细]
  • iOS开发Debug和Release的理解
    2019独角兽企业重金招聘Python工程师标准参考:http:blog.csdn.netmad1989articledetails406580331&# ... [详细]
  • 如何使用Xcode7软件添加NTL库并运行C++程序。一、首先安装NTL库1、进入“ATourofNTL:ObtainingandInstallingNTLfor ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
  • VueCLI多页分目录打包的步骤记录
    本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 本文记录了作者对x265开源代码的实现与框架进行学习与探索的过程,包括x265的下载地址与参考资料,以及在Win7 32 bit PC、VS2010平台上的安装与配置步骤。 ... [详细]
  • 在应用开发中少不了界面元素的布局、适配、自适应。之前苹果已经为我们提供了 AutoLayout 和 SizeClasses,方便我们实现页面的自适应弹性布局。但对于一些复杂的交互界 ... [详细]
author-avatar
宠医_臻爱一生_156
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有