android 多渠道腳本

原創內容,轉載請註明出處html

背景

多渠道打包這個本沒啥難度,可是按照官方的作法通常都要從新編譯 apk, 當 apk 很大的時候,會很是耗時,美團已經提供了一種解決思路,請點擊這裏查看美圖的思路, 以前有個羣裏的同窗想讓我將他寫的 python 代碼改爲 shell,  很久沒寫 shell 也想增長點熟練度,因此便欣然贊成了。python

功能

將工做目錄下指定的 apk 文件夾中的 apk 進行復制,而後在新的 apk 的 meta-info 目錄下建立一個空的文件,這個文件以 channel.txt 中指定的渠道命名shell

代碼

shell腳本實現bash

 
 

# !/usr/bin/bashapp

  model=$1spa

channel_file=$2 # 空文件 便於寫入此空文件到apk包中做爲channel文件 src_empty_file='czt.txt' # 建立一個空文件(不存在則建立) if [ -e $src_empty_file ]; then rm -i $src_empty_file fi touch $src_empty_file if [ ! $? -eq 0 ]; then exit 1; fi # 獲取當前目錄中全部的apk源包 src_apks=()
if [ "$model" = "" ];then
  file_path="."
else   file_path
="./$model"
fi
for file in $(cd $file_path ; ls); do
file=${file_path}$file
if [ -f $file ];then basename $file | grep '\.apk$' && src_apks=("${src_apks[@]}" "$file") fi done # 獲取渠道列表 if [ "$channel_file" = "" ];then channel_file='channel.txt' fi f=$(cat $channel_file) function copy(){ if [ ! -e $1 ];then return 1 fi cp $1 $2 } for src_apk in ${src_apks[@]};do # file name (with extension) src_apk_file_name=$(basename $src_apk) # 分割文件名與後綴 src_apk_name=${src_apk_file_name%.apk} # 後綴名,包含. 例如: ".apk " src_apk_extension=${src_apk_file_name##*.} # 建立生成目錄,與文件名相關 output_dir='output-'${src_apk_name}/ if [ -e $output_dir ]; then rm -r $output_dir fi mkdir -p $output_dir # 遍歷渠道號並建立對應渠道號的apk文件 for line in $f;do target_channel=$line target_apk=${output_dir}${src_apk_name}-${target_channel}${src_apk_extension} echo "${output_dir}=======>${src_apk_name}=======>, ${target_channel} =======>, ${src_apk_extension} =======>" # 拷貝創建新apk cp $src_apk $target_apk # 初始化渠道信息 empty_channel_file="META-INF/cztchannel_${target_channel}" # 寫入渠道信息 if [ ! -e $(dirname $empty_channel_file) ]; then mkdir -p $(dirname $empty_channel_file) fi touch $empty_channel_file jar -uvf $target_apk -C . $empty_channel_file done done

 python 腳本實現code

# !/usr/bin/env python3

#  -*- encoding:utf-8 -*-

import os
import sys
import zipfile
'''
   多渠道打包
'''

dir_path = "./"

channel_path = "channel.txt"

apk_files = []
channels = []
ext = ["apk", ]

class Usage(object):
    info = [];
    def __init__(self, *args, **kw):
        pass

    @staticmethod
    def print():
        pass


class Shift(object):
    def __init__(self, *args, **kw):
        if 'argvs' in kw:
            self.argvs = kw['argvs']
        else:
            self.argvs = sys.argv[:]


    def __call__(self, *args, **kwargs):
        if self.argvs:
            return self.argvs.pop(0)
        else:
            return None

def getApkFiles():
    apk_files = []
    for file in os.listdir(dir_path):
        if os.path.splitext(file)[1][1:] in ext:
            apk_files.append(os.path.join(dir_path, file))
    return apk_files


def getChannels():
    channels = []
    with open(channel_path, 'r') as f:
        channels = f.readlines()

    return channels



def params():
    global dir_path

    global channel_path

    global apk_files
    global channels

    if len(sys.argv) != 1:
        shift = Shift(sys.argv[1:])
        p = shift()
        if p:
            dir_path = p

        p = shift()
        if p:
            channel_path = p

    apk_files = getApkFiles()

    channels = getChannels()

def copy(oldfile, newfile):
    if os.path.exists(newfile):
        os.remove(newfile)
    with open(oldfile, 'rb') as f:
        data = f.read()
        with open(newfile, 'wb') as f1:
            f1.write(data)


def main():
    import shutil
    temp_channel_path = './temp_channel.txt'
    with open(temp_channel_path, 'w') as f:
        pass

    for apk_file in apk_files:
        apk_file_name = os.path.splitext(os.path.basename(apk_file))[0]
        out_apk = 'output_%s' % apk_file_name
        out_abs_path = os.path.join(dir_path, out_apk)
        if os.path.exists(out_abs_path):
            shutil.rmtree(out_abs_path)
        os.mkdir(out_abs_path)
        for channel in channels:
            target_apk = os.path.join(out_abs_path, 'out_%s_%s.apk' % (channel.strip(), apk_file_name.strip()))
            copy(apk_file, target_apk)
            zipped = zipfile.ZipFile(target_apk, 'a', zipfile.ZIP_DEFLATED)
            zipped.write(temp_channel_path, '%s/czt_channel_%s' % ('META-INF', channel))
            zipped.close()
    os.remove(temp_channel_path)



if __name__ == '__main__':
    params()
    main()

 後記

目前的 v1 簽名機制下,對 meta-info 下的修改不會影響到 apk 簽名,可是在 Android 7.0 後提供了 v2 的簽名機制,這時候須要從新開發注入機制了,詳細請點我htm

相關文章
相關標籤/搜索