文档章节

Jenkins中的Android打包任务设计

Lohanry
 Lohanry
发布于 2017/04/30 18:19
字数 1889
阅读 425
收藏 16

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来一起学习。

© 著作权归作者所有

共有 人打赏支持
Lohanry

Lohanry

粉丝 6
博文 10
码字总数 11765
作品 1
宁波
程序员
Jenkins中使用ant管理Android应用开发生命周期

软件环境 OS:CentOS 6.0 64-bit Android SDK:adt-bundle-linux-x86_64 Jenkins:1.529 Ant:1.8.2 配置管理 1.Jenkins中配置JDK,直接配置1.7+以上JDK。过程略。 2.把Android工程改造成具有A...

miscellanea
2013/11/19
0
0
Android直接用手机打包apk!

你没有看错,用手机浏览器访问Jenkins,就可以打包apk,并生成下载二维码,发送邮件通知测试人员下载,从此解放双手,告别打包测试。先上本人手机邮箱收到的打包成功通知效果图: 废话少说,...

Zachary46
08/01
0
0
自动化构建Android项目 ---- Jenkins自动化部署学习笔记(二)

  上篇文章跟大家分享了在Windows上安装Jenkins的方法,这篇文章来跟大家分享一下利用Jenkins自动化构建Android项目: 一、所需准备: Android项目上传至版本管理平台,这里我准备了Githu...

onestravel
05/22
0
0
配置项目构建完成后文件移动---- Jenkins自动化部署学习笔记(三)

  在前两篇文章中,跟大家分享了在 Windows 系统上安装 Jenkins 和使用 Jenkins 进行 Android 项目的编译打包;相信可能会有人疑问,打包完成之后,我需要将 apk 文件放入指定位置怎么办。...

onestravel
06/04
0
0
Tinker + Bugly + Jenkins 爬坑之路

前阵子 Android 端的线上崩溃比较多,热修复被提上日程。实现方案是 Tinker,Jenkins 打包,最后补丁包上传到 Bugly 进行分发。主要在 Jenkins 打包这一块爬了不少坑,现记录下来,供大家参考...

cspecialy
06/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 到底谁是小公猫……

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子:分享Trivium的单曲《Throes Of Perdition》 《Throes Of Perdition》- Trivium 手机党少年们想听歌,请使劲儿戳(这里) @小鱼丁:...

小小编辑
39分钟前
51
1
基础选择器

注意:本教程参考自网上流传的李兴华老师的jquery开发框架视频,但是苦于没有相应的配套笔记,由我本人做了相应的整理. 本次学习的内容 学习jquery提供的各种选择器的使用,掌握了jquery选择...

江戸川
44分钟前
1
0
Spring中static变量不能@value注入的原因

今天本想使用@Value的方式使类中的变量获得yml文件中的配置值,然而一直失败,获得的一直为null。 类似于这样写的。 public class RedisShardedPool { private static ShardedJedisPool pool...

钟然千落
今天
2
0
CentOS7防火墙firewalld操作

firewalld Linux上新用的防火墙软件,跟iptables差不多的工具。 firewall-cmd 是 firewalld 的字符界面管理工具,firewalld是CentOS7的一大特性,最大的好处有两个:支持动态更新,不用重启服...

dingdayu
今天
1
0
关于组件化的最初步

一个工程可能会有多个版本,有国际版、国内版、还有针对各种不同的渠道化的打包版本、这个属于我们日常经常见到的打包差异化版本需求。 而对于工程的开发,比如以前的公司,分成了有三大块业...

DannyCoder
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部