# -*- coding:utf-8 -*- import os, io, platform, subprocess, zipfile, sys from xml.etree import ElementTree as ET import file_utils, path_utils androidNS = 'http://schemas.android.com/apk/res/android' def update(): if len(sys.argv) < 2: print("参数数量不正确") exit(1) config = sys.argv[1] update_channel(config) pass def update_channel(channel): channel_path = path_utils.get_sdk_channel_path(channel) file_utils.delete_folder(channel_path) svn_up_cmd = "svn up %s" % channel_path print("svn_up_cmd:%s" % svn_up_cmd) ret, result = exec_common_cmd(svn_up_cmd) if ret: print("svn update fail.") return if not os.path.exists(channel_path): print("no such channel") return pretreatment_project = os.path.join(channel_path, "pretreatment_project") if not os.path.exists(pretreatment_project): os.mkdir(pretreatment_project) # 渠道使用jar包接入 jars_path = os.path.join(channel_path, 'jars') base_manifest_path = path_utils.get_sdk_channel_path('SDKManifest.xml') pre_manifest_path = os.path.join(pretreatment_project, 'SDKManifest.xml') if not os.path.exists(jars_path): file_utils.copy_file(base_manifest_path, pre_manifest_path) else: file_utils.copyAllFile(jars_path, pretreatment_project) # 渠道使用aar接入 aars_path = os.path.join(channel_path, 'aars') if not os.path.exists(aars_path): os.mkdir(aars_path) # 复制平台SDK 到aar 目录 if channel != 'share_sdk': platform_sdk_path = path_utils.get_full_path('platform_sdk', 'hnyy') file_utils.copyAllFile(platform_sdk_path, aars_path) # 解析 所有aar包 decompile_aar(aars_path, pretreatment_project) # 渠道使用gradle 依赖包接入 sdk_dependencies_gralde_path = os.path.join(channel_path, 'dependencies', 'build.gradle') if os.path.exists(sdk_dependencies_gralde_path): execute_gradlew(sdk_dependencies_gralde_path, pretreatment_project) pack_jar(pretreatment_project) remove_app_name(pretreatment_project) def decompile_aar(channel_aar_dir, pretreatment_project): for lib in os.listdir(channel_aar_dir): if lib.endswith(".aar"): aar_decom_dir = os.path.join(channel_aar_dir, lib.split('.aar')[0]) if os.path.exists(aar_decom_dir): file_utils.delete_folder(aar_decom_dir) os.mkdir(aar_decom_dir) aar_path = os.path.join(channel_aar_dir, lib) zip_file = zipfile.ZipFile(aar_path) for names in zip_file.namelist(): zip_file.extract(names, aar_decom_dir) zip_file.close() print("copy sdk resource:%s" % aar_decom_dir) copy_aar_jar_to_libs(aar_decom_dir, pretreatment_project, str(lib)) sdk_base_xml = os.path.join(pretreatment_project, "SDKManifest.xml") aar_decom_dir_manifest_xml = os.path.join(aar_decom_dir, 'AndroidManifest.xml') print("merge sdk manifest:%s" % aar_decom_dir_manifest_xml) merge_manifest_aar_to_sdk(aar_decom_dir_manifest_xml, sdk_base_xml) elif lib.endswith(".jar"): pre_libs_dir = os.path.join(pretreatment_project, "lib") if not os.path.exists(pre_libs_dir): os.makedirs(pre_libs_dir) jar_path = os.path.join(channel_aar_dir, lib) lib_path = os.path.join(pre_libs_dir, lib) print("copy sdk jar:%s" % jar_path) file_utils.copy_file(jar_path, lib_path) else: print('not support type') file_utils.delete_folder(lib) continue def merge_manifest_aar_to_sdk(manifest_from, manifest_to): """ Merge aars AndroidManifest.xml to the sdk SdkManifest.xml """ if not os.path.exists(manifest_to) or not os.path.exists(manifest_from): print("the manifest file is not exists.manifestTo:%s;manifestFrom:%s", manifest_to, manifest_from) return False ET.register_namespace('android', androidNS) targetTree = ET.parse(manifest_to) # 获取xml根节点 targetRoot = targetTree.getroot() ET.register_namespace('android', androidNS) aarTree = ET.parse(manifest_from) aarRoot = aarTree.getroot() f = open(manifest_to) targetContent = f.read() f.close() permissionConfigNode = targetRoot.find('permissionConfig') for child in list(aarRoot): # 子节点对应的values,uses-feature,uses-permission,permission key = '{' + androidNS + '}name' val = child.get(key) if val != None and len(val) > 0: attrIndex = targetContent.find(val) # values不存在添加 if -1 == attrIndex: permissionConfigNode.append(child) aarAppNode = aarRoot.find('application') sdkAppConfigNode = targetRoot.find('applicationConfig') if aarAppNode is not None: for aarChild in list(aarAppNode): key = '{' + androidNS + '}name' val = aarChild.get(key) if val is not None and len(val) > 0: attrIndex = targetContent.find(val) if -1 == attrIndex: sdkAppConfigNode.append(aarChild) targetTree.write(manifest_to, 'UTF-8') return True def copy_aar_jar_to_libs(aar_decom_dir, pretreatment_project, aar_name): pre_assets_dir = os.path.join(pretreatment_project, "assets") if not os.path.exists(pre_assets_dir): os.makedirs(pre_assets_dir) pre_libs_dir = os.path.join(pretreatment_project, "lib") if not os.path.exists(pre_libs_dir): os.makedirs(pre_libs_dir) pre_base_jni_dir = os.path.join(pretreatment_project, "jniLibs") if not os.path.exists(pre_base_jni_dir): os.makedirs(pre_base_jni_dir) pre_res_dir = os.path.join(pretreatment_project, "res") if not os.path.exists(pre_res_dir): os.makedirs(pre_res_dir) for f in os.listdir(aar_decom_dir): # 分割最后一个“.” name = aar_name.rsplit(".", 1)[0] pre_libs_name = os.path.join(pre_libs_dir, name + ".jar") if f.endswith(".jar"): file_utils.copy_file(os.path.join(aar_decom_dir, f), pre_libs_name) if "assets" == f: file_utils.copyAllFile(os.path.join(aar_decom_dir, f), pre_assets_dir) if "jni" == f: decom_jni_dir = os.path.join(aar_decom_dir, f) for jniF in os.listdir(decom_jni_dir): if "armeabi" == jniF or "armeabi-v7a" == jniF or "x86" == jniF or "arm64-v8a" == jniF \ or "x86_64" == jniF: pre_jni_dir = os.path.join(pre_base_jni_dir, jniF) if not os.path.exists(pre_jni_dir): os.makedirs(pre_jni_dir) file_utils.copyAllFile(os.path.join(decom_jni_dir, jniF), pre_jni_dir) if "libs" == f: decom_libs_dir = os.path.join(aar_decom_dir, f) # 部分aar包中的classes.jar里面并没有class,而是在aar包中libs里面的classes.jar for libF in os.listdir(decom_libs_dir): if libF == "classes.jar": # 如果SDK libs里面已经存在先删除,在复制一次 if os.path.exists(pre_libs_name): file_utils.del_file(pre_libs_name) file_utils.copyAllFile(os.path.join(decom_libs_dir, libF), pre_libs_name) else: file_utils.copyAllFile(os.path.join(decom_libs_dir, libF), os.path.join(pre_libs_dir, libF)) if "res" == f: copy_res_to_apk(os.path.join(aar_decom_dir, f), pre_res_dir) def copy_res_to_apk(copyFrom, copyTo): """ Copy two resource folders """ if not os.path.exists(copyFrom): print("the copyFrom %s is not exists.", copyFrom) return if not os.path.exists(copyTo): os.makedirs(copyTo) if os.path.isfile(copyFrom) and not merge_res_xml(copyFrom, copyTo): file_utils.copy_file(copyFrom, copyTo) print("copyResToApk:copyFrom-->%s;copyTo-->%s;", copyFrom, copyTo) return # 卢-->修改复制资源,并合并和删除重复资源 for f in os.listdir(copyFrom): sourcefile = os.path.join(copyFrom, f) targetfile = os.path.join(copyTo, f) if f == 'abc_action_menu_layout.xml' or f == 'abc_screen_toolbar.xml': file_utils.delete_folder(sourcefile) continue if os.path.isfile(sourcefile): if not os.path.exists(copyTo): os.makedirs(copyTo) delete_same_res(sourcefile, copyTo, 'attrs.xml') delete_same_res(sourcefile, copyTo, 'colors.xml') delete_same_res(sourcefile, copyTo, 'dimens.xml') delete_same_res(sourcefile, copyTo, 'drawables.xml') delete_same_res(sourcefile, copyTo, 'ids.xml') delete_same_res(sourcefile, copyTo, 'integers.xml') delete_same_res(sourcefile, copyTo, 'public.xml') delete_same_res(sourcefile, copyTo, 'strings.xml') delete_same_res(sourcefile, copyTo, 'styles.xml') if merge_res_xml(sourcefile, targetfile): continue destfilestream = open(targetfile, 'wb') sourcefilestream = open(sourcefile, 'rb') destfilestream.write(sourcefilestream.read()) destfilestream.close() sourcefilestream.close() if os.path.isdir(sourcefile): copy_res_to_apk(sourcefile, targetfile) def merge_res_xml(copyFrom, copyTo): """ Merge all android res xml """ if not os.path.exists(copyTo): return False fromName = os.path.basename(copyFrom) if not fromName.endswith('.xml'): return False f = io.open(copyTo, 'r', encoding='utf-8') targetContent = f.read() f.close() fromTree = ET.parse(copyFrom) fromRoot = fromTree.getroot() toTree = ET.parse(copyTo) toRoot = toTree.getroot() for fromNode in list(fromRoot): val = fromNode.get('name') if val is not None and len(val) > 0: # 如果出现name和parent字段一样也会删除,加上name= #