iPA 打包

如何区分企业版和正式版?

2017-03-02  本文已影响296人  勇往直前888

需求来源

基本知识

方案1:利用XCoede的Debug和Release模式区分

企业版就用Debug模式,正式版就用Release模式。工程配置好之后,只要稍微改一下命令就可以同时得到企业版和正式版的ipa包,前面的需求可以“基本满足”

这个要求是XCode7,具体的可以参考ios,jenkins,参数化构建,shell,xcodebuild,多bundle identifier,版本号同步

XCode7的配置

企业版和正式的的账号,密码,相应的p12导入,Provisioning Profile的文件的下载和导入等准备工作先做好

  1. 切换到标签Targets->Build Settings->Signing,以下几个标签分别设置好,分为DebugRelease两种模式。
    Code Signing Identity:证书
    Development Team:账号主体,企业版和正式版的邮箱账号主体都不一样
    Provisioning Profile:以前的真机调试文件
  2. 切换到标签Targets->Build Settings->Packaging,以下几个标签分别设置好,分为DebugRelease两种模式。
    Info.plist File:配置文件,DebugRelease可以配置得不一样,这个变动有点大,这里暂时不用
    Product Bundle IdentifierBundle Id,这个要和证书对应起来。这个需要改,企业版和正式版要不一样
    Product Name:编译build之后,.app文件的名字,可以不改,中间文件,关心的人不多
  3. 切换到标签Targets->General,检查一下标签Signing(Debug)Signing(Release),看看设置的对不对。如果设置不对,这里有红叉提醒的
  4. 注意标签Targets->General->Identity,这里的选项Bundle Identifier,只显示一个。这里千万不要改,不然Targets->Build Settings->Packaging下面设置会被改成一样。这个千万要注意。

命令行

// Debug模式是企业版,在文件夹enterprise中,输出增加_enterprise后缀
xcodebuild -workspace xxx.xcworkspace -scheme xxx -configuration Debug clean build archive -archivePath enterprise/xxx_enterprise

xcodebuild -exportArchive —exportFormat ipa -archivePath enterprise/xxx_enterprise.xcarchive -exportPath enterprise/xxx_enterprise -exportWithOriginalSigningIdentity

// Release模式是正式版,在文件夹appstore中
xcodebuild -workspace xxx.xcworkspace -scheme xxx -configuration Release clean build archive -archivePath appstore/xxx

xcodebuild -exportArchive —exportFormat ipa -archivePath appstore/xxx.xcarchive -exportPath appstore/xxx -exportWithOriginalSigningIdentity

此方案的不足之处

对于不足之处的改进

方案2:采用命令行指定签名参数

如果能够通过命令行的方式,灵活地指定签名证书,可以让企业版和正式版采用相同的模式(同为Debug或者Release),那么将是比方案1更为灵活地方案。
通过对xcodebuild命令的实际使用以及查找相关资料,应该分为单个Target的工程和由workspace管理的多个project,多个Target的工程两种情况考虑。下面这篇文章很好地说明了这一点
动手搭建 iOS CI 环境之「了解 xcodebuild 命令」

Case1:单个Target的工程

由于证书可以对应到Target,所以只有一个Target的工程可以通过命令行灵活地指定证书等信息。
Jenkins学习(三)脚本打包
iOS自动打包并发布脚本
xcodebuild命令简单使用

打包脚本

打开终端,cd到工程目录,和xxx.xcodeproj文件在同一目录

xcodebuild -project xxx.xcodeproj -scheme xxx -configuration Debug  DEVELOPMENT_TEAM=xxxxx PROVISIONING_PROFILE="xxxxxx-xxxx-xxxx-xxxx-xxxxxx"  PROVISIONING_PROFILE_SPECIFIER="xxxxxx" CODE_SIGN_IDENTITY="iPhone Developer: xxx (xxxxx)" PRODUCT_BUNDLE_IDENTIFIER=com.xxx.xxx.enterprise clean archive -archivePath enterprise/xxx_enterprise

这里-project xxx.xcodeproj可以省略
企业版和正式通过更换上面key=value的值进行区分

如何查找这些键值对?

Xcode6内置环境变量(Build Setting Macros)
打开终端,cd到工程目录,通过以下脚本可以查看当前的Build Setting

xcodebuild -showBuildSettings -scheme xxx -configuration Debug

如何查看证书

打开终端,输入以下命令

security find-identity -v -p codesigning

Case2:由workspace管理的工程

现在实际的工程一般都会用到大量的第三方库,第三方库一般会引入CocoaPods进行管理,默认会创建一个workspace。由于workspace可以包含多个Project,而每个Project又可以包含多个Target。每个Targetbundle idprovisioning profile等都可以分别指定,所以像单个Target那样用命令行来动态指定的方式就显得比较复杂。
对于workspace管理的工程,-workspace-scheme两个参数是必要的。而要像单个Target那样灵活地修改bundle idprovisioning profile等参数是很不方便的。先不考虑修改签名参数。

Step1: 打包

打开终端,cd到workspace所在目录,输入以下命令

xcodebuild -workspace xxx.xcworkspace -scheme xxx -configuration Debug clean archive -archivePath archiveOutput/xxx

archiveOutput可以换为其他喜欢的文件夹的名字,在当前目录下,这里是相对路径

Step2: 导出ipa包

xcodebuild -exportArchive -exportFormat ipa -archivePath archiveOutput/xxx.xcarchive -exportPath archiveOutput/xxx_original -exportWithOriginalSigningIdentity
xcodebuild -exportArchive —exportFormat ipa -archivePath archiveOutput/xxx.xcarchive -exportPath archiveOutput/xxx_appstore -exportProvisioningProfile "xxxxxx"
xcodebuild -exportArchive -archivePath <xcarchivepath> -exportPath <destinationpath> -exportOptionsPlist <plistpath>

exportOptionsPlist 解释

Available keys for -exportOptionsPlist:

    compileBitcode : Bool

        For non-App Store exports, should Xcode re-compile the app from bitcode? Defaults to YES.

    embedOnDemandResourcesAssetPacksInBundle : Bool

        For non-App Store exports, if the app uses On Demand Resources and this is YES, asset packs are embedded in the app bundle so that the app can be tested without a server to host asset packs. Defaults to YES unless onDemandResourcesAssetPacksBaseURL is specified.

    iCloudContainerEnvironment

        For non-App Store exports, if the app is using CloudKit, this configures the "com.apple.developer.icloud-container-environment" entitlement. Available options: Development and Production. Defaults to Development.

    manifest : Dictionary

        For non-App Store exports, users can download your app over the web by opening your distribution manifest file in a web browser. To generate a distribution manifest, the value of this key should be a dictionary with three sub-keys: appURL, displayImageURL, fullSizeImageURL. The additional sub-key assetPackManifestURL is required when using on demand resources.

    method : String

        Describes how Xcode should export the archive. Available options: app-store, ad-hoc, package, enterprise, development, and developer-id. The list of options varies based on the type of archive. Defaults to development.

    onDemandResourcesAssetPacksBaseURL : String

        For non-App Store exports, if the app uses On Demand Resources and embedOnDemandResourcesAssetPacksInBundle isn't YES, this should be a base URL specifying where asset packs are going to be hosted. This configures the app to download asset packs from the specified URL.

    teamID : String

        The Developer Portal team to use for this export. Defaults to the team used to build the archive.

    thinning : String

        For non-App Store exports, should Xcode thin the package for one or more device variants? Available options: <none> (Xcode produces a non-thinned universal app), <thin-for-all-variants> (Xcode produces a universal app and all available thinned variants), or a model identifier for a specific device (e.g. "iPhone7,1"). Defaults to <none>.

    uploadBitcode : Bool

        For App Store exports, should the package include bitcode? Defaults to YES.

    uploadSymbols : Bool

        For App Store exports, should the package include symbols? Defaults to YES.

methodteamID这两个参数指定一下,就起到了老格式修改签名文件的功能

在导出时修改签名是可行的,比如编译打包时用正式版证书打包,在导出时用企业版打包。不过这里有个比较尴尬的问题,就是Bundle ID不能更改,有可能会导致签名不一致而不能安装。签名是不同,但是Info.plist文件内容还是一样的。这样必然导致有一个ipa包不能用。

方法2小结

对于单Target的工程来说,可以用命令行灵活配置企业版和正式版。但是对于大多数的workspace管理的工程来说,这种方法很难达到目的。虽然可以在导出ipa的时候更改签名,但是bundle id不会变,这个导致区分困难。至于在打包前修改参数,有点复杂,目前还没有找到好的方法。
在xcodebuild中修改的build settings是在内存中动态修改的,并不会更改实际的文件。下次读出来之后,就像从来没修改过一样

修改Info.plit文件

PlistBuddy
这是系统提供的操作plist文件的工具,不在默认的PATH里,需要通过绝对路径/usr/libexec/PlistBuddy引用。
可以CD到工程目录,使用相对路径。注意./开头

/usr/libexec/PlistBuddy -c 'set:CFBundleDisplayName "用户看到的程序名称"' ./相对目录/info.plist

也可以在任意地方,采用绝对目录

/usr/libexec/PlistBuddy -c 'set:CFBundleDisplayName "用户看到的程序名称"' 绝对目录/info.plist

如果设置成功,不会有任何输出,不过确实起作用了。如果出错,会有错误信息,常见的比如文件不存在:

File Doesn't Exist, Will Create: /ifaex_ios/info.plist
Set: Entry, ":CFBundleDisplayName", Does Not Exist

其他话题

其他工具,不用Jekins

网上有介绍其他打包工具,比如fastlane
iOS打包发布工具fastlane初级攻略
这个据说很好用,可以研究一下,作为方案三。这个另外写一篇来记录学习情况。

通过Info.plist本地化文件InfoPlist.strings修改Info.plist内容

CFBundleDisplayName="xxx企业版";
CFBundleIdentifier="com.xxx.yyy.enterprise";

正式版:

CFBundleDisplayName="xxx";
CFBundleIdentifier="com.xxx.yyy";

文件Info.plist是二进制的,看不懂也不方便修改,怎么办?

XCode的标签Targets->Build Settings->Packaging,下面有个选项Info.plist Output Encoding,选项有binary、XML、same-as-input;默认是binary。估计只要改为same-as-input就能够看懂了

其他编译命令

网上出现过xcrunxctool,不过现在好像不需要用到
xcodebuild和xcrun自动化编译ipa包 笔记

上一篇下一篇

猜你喜欢

热点阅读