Lohanry

宠辱不惊,绝不妄自菲薄

少年,你对力量一无所知


一个浪荡的程序猿

Jenkins中的Android打包任务设计

Jenkins持续集成Unity游戏项目

Jenkins的安装部署和配置

Jenkins中的Android打包任务设计

Jenkins中的iOS打包任务设计

Jenkins中的测试任务设计

实现界面

实现界面

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,然后直接进行测试

发布

发布到百度云传给运营商,然后上线。

最后做个小广告~
喜欢的可以转载下我的小文章
Blog:http://www.hailantown.com

最近的文章

Jenkins中的iOS打包任务设计

Jenkins持续集成Unity游戏项目Jenkins的安装部署和配置Jenkins中的Android打包任务设计Jenkins中的iOS打包任务设计Jenkins中的测试任务设计iOS打包需要的流程整个打包流程与Android打包是类似的。难点主要集中在插入必要的FrameWork,修改Plist在Unity5.x上Unity官方已经帮我们提供了一套API用来对Xcode工程的处理。并且提供了[PostProcessBuild]这个标签来完成插入工作。在Unity4.x上使用这套API可...…

继续阅读
更早的文章

Jenkins的安装部署和配置

Jenkins持续集成Unity游戏项目Jenkins的安装部署和配置Jenkins中的Android打包任务设计Jenkins中的iOS打包任务设计Jenkins中的测试任务设计Jenkins的下载Jenkins可以点击链接跳转下载。推荐下载Jenkins的war包,然后再自己的服务器上安装Tomact然后直接上传war包然后来部署Jenkins。用这个办法是为了避免直接使用例如windows的exe安装包安装之后是无法修改Jenkins的主目录,它默认是存储在你的C盘下。像我现在的工作...…

继续阅读