Jenkins中的Android打包任务设计

原创
2017/04/30 18:19
阅读数 1.8K

Jenkins持续集成Unity游戏项目

Jenkins的安装部署和配置

Jenkins中的Android打包任务设计

Jenkins中的iOS打包任务设计

Jenkins中的测试任务设计 #Jenkins中的Android打包任务设计 #实现界面 实现界面 #Unity项目的结构

打包结构

Untiy代码管理中分支是上线的版本,所以主要以它为版本进行分析。 Unity导出时候分三个版本,官网,第三方,腾讯。以宏来控制版本,和脚本删除不需要的脚本 由于使用的是Jenkins全部是命令行出包,Unity打包脚本如下

static void ExportGYTProject_Online()
    {
        getCMDArgs();
        string[] NeedToDel = {
            "Assets/Resources/DaBao",
            "Assets/Resources/Audio",
            "Assets/Resources/BackgroundPrefabs",
            "Assets/Resources/BattleBackground",
            "Assets/Resources/Maps"};
        doDelWithRelativePath(NeedToDel);
        _LanguageBar.ToTraditionForAntBuild();
        PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, "XXXX");
        ExportAndroidProject(ExportPath);
    }
 static void getCMDArgs() {
        foreach (string arg in System.Environment.GetCommandLineArgs()){
            if (arg.StartsWith("-ExportPath")){
                ExportPath = arg.Split('=')[1].Trim('"');
            }else if (arg.StartsWith("-UseWeTest")) {
                UseWeTest = arg.Split('=')[1].Trim('"').Equals("true");
                Debug.Log(UseWeTest);
;            }
            Debug.Log(arg);
        }
        if (ExportPath.Equals("")){
            throw new NullReferenceException("缺少-ExportPath参数");
        }else{
            Debug.Log("导出路径:" + ExportPath);
        }
    }

代码中ExportGYTProject_Online为需要调用Unity的CMD命令,getCMDArgs为对进行传入Unity命令行的命令解析

System.Environment.GetCommandLineArgs() //获取命令行参数

导出Android的工程至指定目录 #Android工程区分 ##官网的Android模板 都是只需要修改Mainfast.xml中channelid的参数就可以,所以官网的Android模板只有一个,每次通过Ant来修改channelid然后直接执行Ant release即可,并移动到指定目录

<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules" >
	<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
	<property name="_APKPATH" value=""/>
	<property name="_game_channelid" value=""/>
	<target name="BuildAPK">
		<antcall target="BuildAPK_All"/>
		<antcall target="BuildAPK_Alone"/>
	</target>
	<target name="BuildAPK_Alone" if="${isBuildAlone}">  
		<foreach list="${channelList}" target="UpdateChannelid" param="channel_id" delimiter=",">
			
		</foreach>
  	</target>
  	<target name="UpdateChannelid">
  		<propertyregex property="_temp_game_channelid"  
                  input="${channel_id}"  
                  regexp="&quot;?(.*)###"  
                  select="\1"  
                  casesensitive="false" />
        <echo message="${_temp_game_channelid}"/>
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:name=&quot;game_channelid&quot; android:value=&quot;(.*?)&quot;"/>
			<substitution expression="android:name=&quot;game_channelid&quot; android:value=&quot;${_temp_game_channelid}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
		<echo message="${channel_id}"/>
		<propertyregex property="_temp_platform_channel_id"  
                  input="${channel_id}"  
                  regexp="###(.*[^&quot;])"  
                  select="\1"  
                  casesensitive="false" />
        <echo message="${_temp_platform_channel_id}"/>
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:name=&quot;platform_channel_id&quot; android:value=&quot;(.*?)&quot;"/>
			<substitution expression="android:name=&quot;platform_channel_id&quot; android:value=&quot;${_temp_platform_channel_id}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
		<antcall target="release"/>
  		<copy  
            file="${out.absolute.dir}/${ant.project.name}-release-unsigned.apk"  
            tofile="${APKPATH}/${ant.project.name}-v${VERSIONNAME}-${_temp_game_channelid}-${_temp_platform_channel_id}-unsigned.apk" />
  	</target>
  	<target name="BuildAPK_All" unless="${isBuildAlone}">  
  		<var name="_game_channelid" value="${game_channelid}"/>
    	<antcall target="BuildGW"/>
    	<var name="_game_channelid" value="${CPSgame_channelid}"/>
    	<antcall target="BuildCPS"/>
  	</target>

  	<target name="BuildCPS">
  		<echo message="${VERSIONNAME}/${VERSIONCODE}"/>
		<echo message="打包官网CPS版本!" /> 
		<antcall target="UpdateVersionName"/>
		<antcall target="UpdateVersionCode"/>
		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:name=&quot;game_channelid&quot; android:value=&quot;(.*?)&quot;"/>
			<substitution expression="android:name=&quot;game_channelid&quot; android:value=&quot;${CPSgame_channelid}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
		<var name="_APKPATH" value="${APKPATH}"/>
		<foreach list="${CPSplatform_channel_idList}" target="Updateplatform_channel_idForMu" param="channel_id" delimiter=",">
			
		</foreach>
  	</target>

  	<target name="BuildGW">
  		<echo message="${VERSIONNAME}/${VERSIONCODE}"/>
		<echo message="打包官网多渠道版本!" /> 
		<antcall target="UpdateVersionName"/>
		<antcall target="UpdateVersionCode"/>
		<antcall target="Updategame_channelid"/>
		<var name="_APKPATH" value="${APKPATH}"/>
		<foreach list="${platform_channel_idList}" target="Updateplatform_channel_idForMu" param="channel_id" delimiter=",">
			
		</foreach>
  	</target>

  	<target name="UpdateVersionName">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:versionName=&quot;(.*?)&quot;"/>
			<substitution expression="android:versionName=&quot;${VERSIONNAME}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>

  	<target name="UpdateVersionCode">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:versionCode=&quot;(.*?)&quot;"/>
			<substitution expression="android:versionCode=&quot;${VERSIONCODE}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>

  	<target name="Updategame_channelid">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:name=&quot;game_channelid&quot; android:value=&quot;(.*?)&quot;"/>
			<substitution expression="android:name=&quot;game_channelid&quot; android:value=&quot;${game_channelid}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>


  	<target name="Updateplatform_channel_idForMu"> <!-- 多渠道循环 -->
  		<echo message="${_APKPATH}"/>
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:name=&quot;platform_channel_id&quot; android:value=&quot;(.*?)&quot;"/>
			<substitution expression="android:name=&quot;platform_channel_id&quot; android:value=&quot;${channel_id}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  		<antcall target="release"/>
  		<copy  
            file="${out.absolute.dir}/${ant.project.name}-release-unsigned.apk"  
            tofile="${APKPATH}/${ant.project.name}-v${VERSIONNAME}-${_game_channelid}-${channel_id}-unsigned.apk" />
  	</target>
</project>

##第三方的Android模板 由于每个渠道都是需要接入指定的SDK。一开始考虑接入所有SDK,然后通过修改XML中的配置参数然后来调用不同SDK,然后发现部分SDK有冲突而且包会变得巨大无比,然后修改为每个渠道一个Android模板,然后在导出指定版本的Unity后,移动Assets下的目录到Android工程包,然后执行Ant release。

<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules" >
	<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
	<target name="BuildAPK">
		<antcall target="preBuildProject"/>
		<echo message="${VERSIONNAME}/${VERSIONCODE}"/>
		<antcall target="UpdateVersionName"/>
		<antcall target="UpdateVersionCode"/>
		<antcall target="Updateplatform_channel_id"/>
		<antcall target="Updategame_channelid"/>
		<antcall target="release"/>
		<copy  
            file="${out.absolute.dir}/${ant.project.name}-release-unsigned.apk"  
            tofile="${APKPATH}/${ant.project.name}-v${VERSIONNAME}-${game_channelid}-${platform_channel_id}-unsigned.apk" />
  	</target>
  	
  	<target name="preBuildProject">
  		<foreach target="preBuildSubProject" param="_path">
  			<path>
  				<dirset dir=".." includes="/*"/>
  			</path>
  		</foreach>
  	</target>
  	<target name="UpdateVersionName">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:versionName=&quot;(.*?)&quot;"/>
			<substitution expression="android:versionName=&quot;${VERSIONNAME}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>
  	<target name="UpdateVersionCode">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:versionCode=&quot;(.*?)&quot;"/>
			<substitution expression="android:versionCode=&quot;${VERSIONCODE}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>
  	<target name="Updateplatform_channel_id">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:name=&quot;platform_channel_id&quot; android:value=&quot;(.*?)&quot;"/>
			<substitution expression="android:name=&quot;platform_channel_id&quot; android:value=&quot;${platform_channel_id}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>
  	<target name="Updategame_channelid">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:name=&quot;game_channelid&quot; android:value=&quot;(.*?)&quot;"/>
			<substitution expression="android:name=&quot;game_channelid&quot; android:value=&quot;${game_channelid}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>
</project>

##腾讯的Android模板 由于比较奇特,所以单独抽取了出来进行打包。

<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules" >
	<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
	<target name="BuildAPK">
		<echo message="${VERSIONNAME}/${VERSIONCODE}"/>
		<antcall target="UpdateVersionName"/>
		<antcall target="UpdateVersionCode"/>
		<antcall target="Updateplatform_channel_id"/>
		<antcall target="Updategame_channelid"/>
		<antcall target="release"/>
		<copy  
            file="${out.absolute.dir}/${ant.project.name}-release-unsigned.apk"  
            tofile="${APKPATH}/${ant.project.name}-v${VERSIONNAME}-${game_channelid}-${platform_channel_id}-unsigned.apk" />
  	</target>
  	<target name="UpdateVersionName">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:versionName=&quot;(.*?)&quot;"/>
			<substitution expression="android:versionName=&quot;${VERSIONNAME}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>

  	<target name="UpdateVersionCode">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:versionCode=&quot;(.*?)&quot;"/>
			<substitution expression="android:versionCode=&quot;${VERSIONCODE}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>

  	<target name="Updateplatform_channel_id">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:name=&quot;platform_channel_id&quot; android:value=&quot;(.*?)&quot;"/>
			<substitution expression="android:name=&quot;platform_channel_id&quot; android:value=&quot;${platform_channel_id}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>

  	<target name="Updategame_channelid">
  		<replaceregexp byline="false" encoding="UTF-8" flags="g">
			<regexp pattern="android:name=&quot;game_channelid&quot; android:value=&quot;(.*?)&quot;"/>
			<substitution expression="android:name=&quot;game_channelid&quot; android:value=&quot;${game_channelid}&quot;" />
			<fileset dir=""
				includes="AndroidManifest.xml" />
		</replaceregexp>
  	</target>

</project>

#打包流程 打包流程 ##CheckOut 使用的是Jenkins的SVN自己输出但是这里有个特殊点我们的项目由于前期的历史问题主干与分支是同级目录,所以在使用获取SVN目录时候使用的是我自己的脚本如下: SVN目录 ##reBuildAndroidLib 由于是Unity导出时候分主工程和一个Lib在导入后需要重新应用Lib一开始使用的手工加上引用,但是后来发现Android命令可以直接引用,但是没来的及修改代码参考如下:

import sys;
import os;

filePath = sys.argv[1] 
ShareSDKPath = sys.argv[2] 
file = open(filePath)
count = 1;
isNeedAdd = 1;
while 1:
    line = file.readline()
    if not line:
        break
    if "ShareSDK" in line:
        isNeedAdd = 0;
    if "android.library.reference" in line:
        count = count +1;
file.close();
if isNeedAdd == 1:
    file = open(filePath,'a');
    ShareSDKPath = ShareSDKPath.replace('\\','/').replace('//','/');
    file.write("\nandroid.library.reference.%d=%s" % (count,ShareSDKPath));
    file.close();
    //这个脚本只能作为参考因为有挺多问题了,但是由于懒得修改就一直在用,可以用Android命令来替代

##reBuildAndroid 这里的--tatget 3 是根据自己的本地Android来设置的,可以参考命令说明修改

cd %1
@call ant clean
@call android update project -p ./ --subprojects --target 3

##BuildApk 代码上面已经给出 ##SignApk 采用python脚本,由于这个脚本不是我们提供的,所以不贴出脚本了,也比较简单的。根据不同渠道签名。 ##加固混淆包 采用python脚本,由于加固的提供方是公司购买的也不提供代码了,由于他们不支持curl所以都是网页提交的,这里的python脚本主要是直接进行模拟网页操作提交。 ##分析APK文件 使用的JAVA来实现。Java代码比较多,我就说下思路,或者有空我开个新的帖子说下Ant的扩展实现。 思路根据APK使用CMD命令来调用Android命令行工具获取返回值,然后进行输出。 ##QA测试 QA测试使用WeTest,在Jenkins的打包选项内可以进行设置是否集成Wetest,然后直接进行测试 ##发布 发布到百度云传给运营商,然后上线。

#总结 其实这些都已经非常的概括的来说明整个思路了,事实上每一步流程都可以开一个日志来说明是如何分析,有空我将会单独开日志来解释。感谢大家阅读,如果有兴趣可以添加我的QQ792667487来一起学习。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
16 收藏
0
分享
返回顶部
顶部