当前位置: 首页 > 科技观察

iOS自动化渠道打包解决方案

时间:2023-03-11 22:16:10 科技观察

1.背景随着ios程序发布渠道的逐渐增多,对各个渠道进行打包成为了一项特别耗时耗力的技术活,而这些一般大部分都是由rd来完成的。这就占用了rd很多的开发时间,何不把这些东西写成一个自动化的脚本,然后交给qa或者pm来完成打包过程呢。经过一番研究,发现网上这样的脚本还是很少的,但是xcode提供了shell编译工具xcodebuild和ipa打包工具xcrun,这也是我们使用这两个工具编写自动化打包脚本的原因,以提高我们的工作效率和自动化。2.ios程序包格式,渠道包格式1)多渠道的原因及多渠道带来的打包问题:随着iphone、ipad、itouch等手持设备的火爆,其上的应用也蒸蒸日上,接下来就是以上设备越狱后,ipa程序包可以直接在越狱设备上运行,无需通过appstore下载。ipa包下载。随着渠道越来越多,在推广时对每个渠道进行包装成为一项耗时耗力的技术活,所以我们必须找到一种自动化的方式,让包装变得高效简单。2)Ios程序包分为appstore二进制文件和渠道包两种格式。Appstore二进制文件:可以通过xcode工具生成.app格式的二进制文件。频道包:格式为.ipa格式。之前没有自动打包工具,都是用xcode生成对应的频道包,一次只能生成一个频道包。每次打包前都要手动带上频道ID。问题在于它耗时、低效、容易出错且有风险。3、传统ios打包方式使用xcode打包1)Appstore二进制打包打开你的项目,进入“EditProjectSettings”,进入Configuration页面,选择Release点击下方Duplicate,复制一个新的配置项,命名为Distribution。然后进入Build页面,在上方的Configuration下拉框中选择Distribution,在下方CodeSigningIdentity中AnyiPhoneOSDevice后面对应的值选择你的Distributioncertificate。然后点击“Build”->“Build”编译程序。编译成功后,可以在对应的build目录下看到一个.app的二进制文件。2)通道ipa包也按照上述步骤配置好Distribution证书,然后点击“Build”->“BuildandArchive”编译程序。然后打开“Window”?“Organizer”,在左侧栏中选择“ARCHIVEDAPPLICATIONS”,然后在右侧的列表中选择刚刚编译好的包,点击右上角的“Share”按钮保存到磁盘。会生成一个.ipa文件,就是频道包。注意:以上操作设备必须选择“设备”。4.传统打包带来的问题费时费力,效率低下,只能由RD来完成,容易出错,发布风险比较高,QA回归确认困难,没有智能化。自动化打包的具体实现1、xcodebuild介绍:[html]viewplaincopyprint?xcodebuild[-project][-activetarget][-alltargets][-target]...[-parallelizeTargets][-activeconfiguration][-configuration][-sdk|][=]...[]...xcodebuild[-version[-sdk|]]xcodebuild[-showsdks]xcodebuild[-find][-sdk|]xcodebuild[-list]也可以输入终端:xcodebuild–help或–h查看具体选项显示xcodebuildversion:xcodebuild–version显示当前系统安装的sdk:xcodebuild–showsdks显示当前目录下的项目信息:xcodebuild–list需要注意的是,当执行以上命令,位置必须在ios中,否则会提示在工程文件的根目录下查找不相关的命令。2、xcrun简介:该工具主要用于将app文件打包成ipa格式的包。(主要针对越狱手机)。具体用法如下:/usr/bin/xcrun-sdkiphoneosPackageApplication–v[{TARGET}.app]-o[{TARGET}.ipa]--sign[{IphoneDistribution:xxx}]–embed[{xxx.mobileprovision}]其中:-v对应app文件的绝对相对路径–o对应ipa文件的路径和文件名–sign对应发布证书中对应的公司名或个人名–embed对应发布certificatefile注意如果对应如果在Distribution配置中已经配置了相关的证书信息,–sign和–embed可以忽略。3、具体解决方案a)从源程序中一次性打印所有渠道的ipa包和appstore二进制包,为了让自动化脚本执行一次,抓取所有渠道的包,所以必须要有一个配置文件来存储所有通道名称和通道号,工程文件中也应该有一个文件存储当前通道号。每次程序从这个存储频道号的文件开始,读取频道号即可。大致思路是使用脚本循环执行打包过程,在每次打包前,通过脚本修改项目中存放频道号的文件为当前周期最新的频道号,然后一一打包.注:具体示例见附录b)提供ipa格式的父包从父包生成所有其他渠道包和appstore包qa。如何确保所有的渠道包都是他们验证过的代码?的确,上面的代码每次都是重新打包程序,但是qa往往只测试和验证一个包。如果全部验证,无意中会增加qa的工作量!!而且风险不可控。因此,基于以上问题,我们想出了一个解决方案:qa只验证一个程序包(即母包)。如果包通过验证,我们会使用母包从其他渠道生成包,这样qa就不需要确认那么多渠道了,有效控制了风险。你可能会问:用一个包生成其他包是否可行??原因是这样的:因为每个频道只改变频道号,其他内容没有改变,而我们的频道号是保存在sourceid.dat文件中的,所以我们只需要改变父包中sourceid的内容即可.dat文件就够了,ipa包也是压缩成zip格式的,所以基本思路是先通过zip解压父包,然后改sourceid.dat***的内容再压缩成对应的频道包很好。Ipa包所在目录:注意:具体例子见附录一些问题在mac终端运行某些shell命令失败时,请确保你的shell脚本是在mac环境下写的,而不是从其他环境拷贝过来的比如xp的。因为mac和xp的编码不同,所以会有问题。总结:通过从父包导出其他渠道的包:获得以下好处i.减少rd的工作量和qa的工作量。二.让测试发布程序的风险得到控制。三.提高打包发布效率。(几分钟内就有几十个包裹)。四.改进的自动化。v.从父包生成其他包在linux下可以直接完成,不需要依赖mac和xcode环境。附录使用xcode环境一次生成所有包的shell脚本代码:#!/bin/shxcodebuildclean-configurationDistribution//cleanprojectdistDir="/Users/xxxx/dist"releaseDir="build/Distribution-iphoneos"version="1_0_0"rm-rdf"$distDir"mkdir"$distDir"forlinein$(catdata.dat)//读取所有通道号data.dat文件doipafilename=`echo$line|cut-f1-d':'`//channelnamesourceid=`echo$line|cut-f2-d':'`//频道号echo"ipafilename=$ipaname"echo"sourceid=$sourceid"targetName="youtargename"//项目名称(显示的项目名称在xcode左侧的列表中)echo"sourceid=$sourceid"echo"ipafilename=$ipafilename"echo"$sourceid">sourceid.datecho"sourceid.dat:??"catsourceid.datrm-rdf"$releaseDir"ipapath="${distDir}/${targetName}_${version}_from_${sourceid}.ipa"echo"***startbuildappfile***"xcodebuild-target"$targetName"-configurationDistribution-sdkiphoneosbuildappfile="${releaseDir}/${目标tName}.app"if[$sourceid=="appstore"]thencd$releaseDirzip-r"${targetName}_${ipafilename}_${version}.zip""${targetName}.app"mv"${targetName}_${ipafilename}.zip"$distDir2>/dev/nullcd../..elseecho"***开始播放ipa通道包****"/usr/bin/xcrun-sdkiphoneosPackageApplication-v"$appfile"-o"$ipapath"--sign"iPhoneDistribution:xxxxxx"fidone注:上面的data.dat文件是存放频道号列表的文件,格式为:3g:1001b(频道名:频道号)sourceid.dat是工程文件中存放频道号的文件(里面的内容只有一个频道号),当然上面的脚本只是说明了如何使用xcodebuild和xcrun打包自动打包一个逻辑,好的同学atshell脚本可以自由发挥...ipa格式的父包生成其他渠道包的shell脚本示例:[html]viewplaincopyprint?#!/bin/shsourceipaname="父包名.ipa"appname="app文件名.app"//pauload目录后加压Item.app文件名需要根据你的项目修改distDir="/Users/lxxx/Qa"//打包文件存放目录version="1.0.0"rm-rdf"$distDir"mkdir"$distDir"unzip$sourceipaname//解压父包文件forlinein$(catdata.dat)//读取通道号文件并循环doipafilename=`echo$line|cut-f1-d':'`sourceid=`echo$line|cut-f2-d':'`echo"ipafilename=$ipaname"echo"sourceid=$sourceid"targetName="ipa包名"echo"sourceid=$sourceid"echo"ipafilename=$ipafilename"cdPayloadcd$appnameecho"替换sourceid.dat之前:"catsourceid.datecho"$sourceid">sourceid.datecho"replacesourceid.dataafter:"catsourceid.datif[$sourceid=="appstroe"]thencd..zip-r"${targetName}_${version}_from_${sourceid}.zip"$appname//appstore二进制文件mv"${targetName}_${version}_from_${sourceid}.zip"$distDircd..elsecd../..zip-r"${targetName}_${version}_from_${sourceid}.ipa"payload//打包到其他通道mv"${targetName}_${version}_from_${sourceid}.ipa"$distDirfidonerm-rdfPayload注:上面的data.dat也是用来存放所有通道号的,sourceipaname是通过qa验证的父包,appname是ipa包加压后Payload目录下的app文件名而以上所有的文件必须和脚本文件放在同一个目录下,并在mac环境下执行