渠道名称写在文件channels.txt, 同一目录即可。

#coding:utf-8
OUTPUTS_PATH = "/Users/Shared/Jenkins/Home/workspace/"

GRADL_HOME = "/Users/lufei/Documents/gradle/gradle-2.10/bin/"

SOURCE_CODE = "sourcecode"

BUILD_TYPE = "release"

APP_NAME = "yourprojectname"

DECODE_PATH = "decode"

NAME_SPACE = "http://schemas.android.com/apk/res/android"
NAME_SPACE_ATTR = "{http://schemas.android.com/apk/res/android}"

OUTPUTS_PATH_TMP = "outputs"

from xml.etree.ElementTree import ElementTree, Element
from xml.etree import ElementTree as ET

def read_xml(path):
    ET.register_namespace('android', NAME_SPACE)
    tree = ET.ElementTree(file=path)
    return tree

def write_xml_to_file(tree, path):
    tree.write(path, encoding="utf-8", xml_declaration=True)

def is_match(node, kv):
    for key in kv:
        if node.get(key) != kv.get(key):
            return False
    return True

def find_nodes(tree):
    root = tree.getroot()
    applications = root.findall("application")
    nodes = []
    if len(applications) > 0:
        for meta in applications[0].findall("meta-data"):
            nodes.append(meta)
    return nodes

def get_node_by_key_value(nodelist, kv):
    result_nodes = []
    for node in nodelist:
        if (is_match(node, kv)):
            result_nodes.append(node)
    return result_nodes

def change_node_attr(nodelist, kv):
    for node in nodelist:
        for key in kv:
            node.set(key, kv.get(key))

def decode_and_build(market, version):

    tree = read_xml("./" + DECODE_PATH + "/AndroidManifest.xml")
    nodes = find_nodes(tree)

    channel_result_nodes = get_node_by_key_value(nodes,{ NAME_SPACE_ATTR + "name":"UMENG_CHANNEL"})
    change_node_attr(channel_result_nodes, {NAME_SPACE_ATTR+"value":market})

    log_result_nodes = get_node_by_key_value(nodes, {NAME_SPACE_ATTR + "name":"LOG"})
    change_node_attr(log_result_nodes, {NAME_SPACE_ATTR+"value":"false"})
    write_xml_to_file(tree, "./"+ DECODE_PATH + "/AndroidManifest.xml")

    new_apk_name = APP_NAME + market + ".apk"
    print ('apktool b ')
    os.popen("./apktool b -f ./"+ DECODE_PATH + " -o %s" %new_apk_name)

    new_apk_signed_name = APP_NAME + market + "_signed.apk"

    print ('jarsigner ')
    os.popen("jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore %s -storepass %s -signedjar %s %s %s"% ("android.keystore", "kiss584520", new_apk_signed_name, new_apk_name, "android.keystore")) 


    new_apk_aligned_name = OUTPUTS_PATH_TMP + "/" + APP_NAME + "-" + market + "-release-" + version + ".apk"
    print ('zipalign ')
    os.popen("./zipalign -v 4 %s %s" %(new_apk_signed_name, new_apk_aligned_name))
    print ("%s finished"%new_apk_aligned_name)

    os.remove(new_apk_name)
    os.remove(new_apk_signed_name)

def copyFiles(sourceDir,  targetDir): #把某一目录下的所有文件复制到指定目录中 
     for file in os.listdir(sourceDir): 
         sourceFile = os.path.join(sourceDir,  file) 
         targetFile = os.path.join(targetDir,  file) 
         if os.path.isfile(sourceFile): 
             if not os.path.exists(targetDir): 
                 os.makedirs(targetDir) 
             if not os.path.exists(targetFile) or(os.path.exists(targetFile) and (os.path.getsize(targetFile) != os.path.getsize(sourceFile))): 
                     open(targetFile, "wb").write(open(sourceFile, "rb").read()) 
         if os.path.isdir(sourceFile): 
             First_Directory = False 
             copyFiles(sourceFile, targetFile) 

def chdir(dir):
    os.chdir(dir)
    print ('当前目录:' + os.getcwd())

def getVersionName(path):
    import re
    versionName = ""
    f = open(path)
    for line in f:
        searchObj = re.search( r'android:versionName="(.*)"', line, re.M|re.I)
        if searchObj:
            versionName = searchObj.group(1) 
            break
    return versionName

def timeCost(startTime):
    cost_time  = (time.time() - startTime)
    minutes = cost_time/60
    seconds = cost_time - 60 * minutes
    print ('当前用时 : %d mins %d secs' %(minutes, seconds))


if __name__ == "__main__":

    import shutil
    import sys
    import os
    content = "n"

    print sys.path[0]
    chdir(sys.path[0])

    import time    
    start_time = time.time()
    print ('start time %f' %start_time)

    # 开始读取参数
    if len(sys.argv) < 4:
        print "构建脚本 参数不够3个,第一个是脚本路径,第二个是项目名称,第三个是git地址,第四个是构建分支"
        exit()

    if len(sys.argv) >= 5:
        BUILD_TYPE = sys.argv[4]
        pass

    OUTPUTS_PATH = OUTPUTS_PATH + sys.argv[1] + "/outputs"

    if os.path.exists(OUTPUTS_PATH):
        shutil.rmtree(OUTPUTS_PATH)

    # 代码
    branch = sys.argv[3] 
    module = sys.argv[2] 
    print ('代码地址:' + module + ",分支:" + branch)

# clone代码

    if os.path.exists(SOURCE_CODE):
        shutil.rmtree(SOURCE_CODE)
    os.mkdir(SOURCE_CODE)
    chdir(SOURCE_CODE)
    print ('start to clone codes')

    os.system("/usr/bin/git clone -b " + branch + " " + module)

# 读取版本号
    versionName = getVersionName(APP_NAME + "/AndroidManifest.xml")
    print ("版本号为:" + versionName)

# 复制gradle配置文件
    chdir(os.path.dirname(os.getcwd()))
    print ('copy files from gradle_config to ' + SOURCE_CODE)
    copyFiles('../gradle_config', SOURCE_CODE)


# 开始编译
    chdir(SOURCE_CODE)
    if os.path.exists("outputs"):
        shutil.rmtree("outputs")
    os.mkdir("outputs") 
    print ('start to build apk')
    os.system(GRADL_HOME + "gradle clean assemble" + BUILD_TYPE)
    os.system(GRADL_HOME + "gradle copyTask")

# 开始decode 打不同的渠道包
    chdir(os.path.dirname(os.getcwd()))
    market = "channels.txt"

    if (False == os.path.exists(OUTPUTS_PATH_TMP)):
        os.mkdir(OUTPUTS_PATH_TMP) 

    OUTPUTS_PATH_TMP = OUTPUTS_PATH_TMP + "/" + versionName

    copyFiles(SOURCE_CODE + "/outputs", OUTPUTS_PATH_TMP)

    print ('decode apk start')
    print os.popen("./apktool d -f " + OUTPUTS_PATH_TMP + "/apk/" + APP_NAME + ".apk -o " + DECODE_PATH)
    print ('decode apk end')

    print ("read channel from " + market)
    f = open(market)
    for line in f:
        if line.strip().startswith('#'):
            continue
        channel = line
        channel = channel.strip()
        if len(channel) == 0:
            pass
        print ('channel:' + channel + ", version: " + versionName)
        decode_and_build(channel, versionName)
        timeCost(start_time)

    copyFiles(OUTPUTS_PATH_TMP, OUTPUTS_PATH)

    shutil.rmtree(DECODE_PATH)

    shutil.rmtree(SOURCE_CODE)

    end_time = time.time()
    print ('end time %f' %end_time)

    timeCost(start_time)

    print ('打包完成,发布之前请先完成自测')

标签: none

添加新评论