def do_build(self): apk_rollback_obj = utils.FileRollback() apk_rollback_obj.record_file( utils.flat_path(os.path.join(self.proj_parth, 'main.js'))) # 编译creator工程 if self.rebuild_creator: self.build_creator_proj() # 删除和替换资源 self.op_creator_res() # 清理temp目录 self.temp_dir = os.path.join(self.root_dir, 'temp') if os.path.isdir(self.temp_dir): shutil.rmtree(self.temp_dir) os.makedirs(self.temp_dir) # 创建mainfest的结构体 self.gen_manifest_obj() # 更新资源目录 self.update_resources() # 生成zip包 self.write_zip_file() apk_rollback_obj.do_rollback() shutil.rmtree(self.temp_dir) Logging.debug_msg('热更包打包完成!\n') Logging.debug_msg('------------------------------------')
def do_build(self): #各个渠道的打包 for app_id in self.batch_info.keys(): app_id = utils.non_unicode_str(app_id) channels = self.batch_info[app_id] for channel_id in channels: Logging.debug_msg('----------------') apk_rollback_obj = utils.FileRollback() try: channel_str = self.get_string(channel_id) self.build_result['%s_%s' % (app_id, channel_str)] = '' self.build_one_apk(app_id, channel_str, apk_rollback_obj) except: Logging.warn_msg('打包失败') finally: Logging.debug_msg('finally :') if not self.no_rollback: apk_rollback_obj.do_rollback() Logging.debug_msg('----------------\n') Logging.debug_msg('\n打包结果汇总 :') for key in self.build_result.keys(): ids = key.split('_') value = self.build_result[key] if value and os.path.isfile(utils.get_sys_encode_str(value)): Logging.debug_msg( 'APP_ID : %s, CHANNEL_ID : %s。打包成功。apk 路径 : %s' % (ids[0], ids[1], value)) else: Logging.debug_msg('APP_ID : %s, CHANNEL_ID : %s。打包失败。' % (ids[0], ids[1])) #打开目录 os.system("start explorer %s" % self.output_path)
def do_build(self): try: for app_id in self.batch_info.keys(): app_id = utils.non_unicode_str(app_id) channels = self.batch_info[app_id] for channel_id in channels: Logging.debug_msg('----------------') apk_rollback_obj = utils.FileRollback() try: channel_str = self.get_string(channel_id) self.build_result['%s_%s' % (app_id, channel_str)] = '' self.build_one_apk(app_id, channel_str, apk_rollback_obj) except: Logging.warn_msg('打包失败') finally: if not self.no_rollback: apk_rollback_obj.do_rollback() Logging.debug_msg('----------------\n') Logging.debug_msg('\n打包结果汇总 :') for key in self.build_result.keys(): ids = key.split('_') value = self.build_result[key] if value and os.path.isfile(utils.get_sys_encode_str(value)): Logging.debug_msg( 'APP_ID : %s, CHANNEL_ID : %s。打包成功。apk 路径 : %s' % (ids[0], ids[1], value)) else: Logging.debug_msg('APP_ID : %s, CHANNEL_ID : %s。打包失败。' % (ids[0], ids[1])) except Exception: raise finally: if os.path.isdir(self.temp_dir): shutil.rmtree(self.temp_dir)
def getProjectConfigPath(): return "%s/../%s.xcodeproj/project.pbxproj" % (m_projectDir, m_newProjName) if __name__ == "__main__": # record the start time begin_time = time.time() tmp_files = [] # 读取配置表 loadConfig() sys.path.append( os.path.normpath(os.path.join(os.path.dirname(__file__), '../utils'))) import utils file_recorder = utils.FileRollback() file_recorder.record_file(m_infoPlistPath) try: # 创建一个新名字的 xcode 工程 createNewProj(file_recorder, tmp_files) # 创建IPA文件夹 createIpaDir() # 安装证书 installCertificate() # 修改版本号 modifyVersion()
def build_one_apk(self, app_id, channel_id, rollback_obj): apk_cfg_file = os.path.join(self.root_dir, app_id, channel_id, 'package.json') if not os.path.isfile(apk_cfg_file): Logging.warn_msg('未找到 %s 文件,打包失败' % apk_cfg_file) return Logging.debug_msg('开始使用配置文件 %s 打包' % apk_cfg_file) apk_cfg_info = self._parse_json(apk_cfg_file) if apk_cfg_info is None: Logging.warn_msg('解析文件 %s 出错,打包失败' % apk_cfg_file) return cfg_dir = os.path.dirname(apk_cfg_file) check_gt_ret = self._check_gt_info(apk_cfg_info, cfg_dir) if check_gt_ret: Logging.warn_msg(check_gt_ret + ', 打包失败') return check_ret = self._check_cfg_info(apk_cfg_info, cfg_dir) if check_ret: Logging.warn_msg(check_ret + ',打包失败') return # 备份文件和文件夹 rollback_obj.record_file(utils.flat_path(self.library_manifest)) rollback_obj.record_file(utils.flat_path(self.manifest)) rollback_obj.record_folder(os.path.join(self.proj_android_path, 'res')) game_name = utils.non_unicode_str(apk_cfg_info[PackAPK.CFG_GAME_NAME]) pkg_name = utils.non_unicode_str(apk_cfg_info[PackAPK.CFG_PKG_NAME]) gaode_key = utils.non_unicode_str(apk_cfg_info[PackAPK.CFG_GAODE_KEY]) ver_name = utils.non_unicode_str( apk_cfg_info[PackAPK.CFG_VERSION_NAME]) ver_code = utils.non_unicode_str( apk_cfg_info[PackAPK.CFG_VERSION_CODE]) app_scheme = utils.non_unicode_str( apk_cfg_info[PackAPK.CFG_APP_SCHEME]) need_remove_agora = True # Android 去掉视频 SDK apk_cfg_info.get(PackAPK.CFG_NO_AGORA, False) # 修改 java 文件中 R 的包名 self._modify_java_files(pkg_name, rollback_obj) # 对需要修改包名的文件进行包名替换 self._change_pkg_name(pkg_name, rollback_obj) # 修改 bugly appid if apk_cfg_info.has_key(PackAPK.CFG_BUGLY_ID): bugly_appid = utils.non_unicode_str( apk_cfg_info[PackAPK.CFG_BUGLY_ID]) else: bugly_appid = "" if len(bugly_appid) > 0: self._modify_bugly(self.library_manifest, bugly_appid, channel_id) # 修改高德 key if len(gaode_key) > 0: self._modify_gaode_key(self.library_manifest, gaode_key) # 修改 Agora id if apk_cfg_info.has_key(PackAPK.CFG_AGORA_ID): self._modify_agora_id(self.library_manifest, apk_cfg_info[PackAPK.CFG_AGORA_ID]) # 修改 AndroidManifest.xml self._modify_manifest(pkg_name, ver_name, ver_code) # 替换 java res for p in apk_cfg_info[PackAPK.CFG_JAVA_RES].split(','): java_res_path = utils.flat_path(os.path.join(cfg_dir, p.strip())) copy_cfg = {'from': '.', 'to': 'res', 'exclude': ['**/.DS_Store']} excopy.copy_files_with_config(copy_cfg, java_res_path, self.proj_android_path) # 替换 个推通知图标push.png # isTurnOffPush = apk_cfg_info.get(PackAPK.CFG_TURNOFF_PUSH, None) # if isTurnOffPush != "1": push_res_path = utils.flat_path(os.path.join(cfg_dir, "../pushRes")) proj_getui_path = utils.flat_path( os.path.join(self.proj_android_path, '../library.pushgetui.android')) if not os.path.isdir(proj_getui_path): raise_known_error("未找到 getui 工程文件夹 %s" % proj_getui_path) copy_cfg = {'from': '.', 'to': 'res', 'exclude': ['**/.DS_Store']} rollback_obj.record_folder(os.path.join(proj_getui_path, "res")) if os.path.isdir(push_res_path): excopy.copy_files_with_config(copy_cfg, push_res_path, proj_getui_path) else: # raise_known_error('文件夹 %s 不存在,放置个推通知图标pushRes/drawable-xxhdpi/push.png|push_small.png' % push_res_path, KnownError.ERROR_PATH_NOT_FOUND) res_path = utils.flat_path( os.path.join(self.proj_android_path, "res")) pushSmallSrc_path = utils.flat_path( os.path.join(res_path, "mipmap-hdpi/ic_launcher.png")) pushSrc_path = utils.flat_path( os.path.join(res_path, "mipmap-xxxhdpi/ic_launcher.png")) pushDes_path = utils.flat_path( os.path.join(proj_getui_path, "res/drawable-xxhdpi/push.png")) pushSmallDes_path = utils.flat_path( os.path.join(proj_getui_path, "res/drawable-xxhdpi/push_small.png")) # excopy.copy_files_with_config(copy_cfg, push_res_path, proj_getui_path) shutil.copyfile(pushSrc_path, pushDes_path) shutil.copyfile(pushSmallSrc_path, pushSmallDes_path) Logging.debug_msg('个推通知图标替换完成') # 修改 strings.xml self._modify_strings_xml(game_name, app_scheme) # 获取并清理临时的 assets 文件夹 temp_assets_path = os.path.join(self.temp_dir, '%s_%s_assets' % (app_id, channel_id)) if os.path.isdir(temp_assets_path): shutil.rmtree(temp_assets_path) Logging.debug_msg('开始处理资源文件') # 拷贝大厅的资源文件 for p in PackAPK.DEFAULT_HALL_DIRS: copy_cfg = { 'from': p, 'to': p, 'exclude': ['**/.DS_Store', 'LuaDebugjit.lua'] } excopy.copy_files_with_config(copy_cfg, self.res_root_path, temp_assets_path) # 拷贝游戏通用组件的各个部分 game_common_parts = apk_cfg_info.get(PackAPK.CFG_GAME_COMMON_PARTS, None) self._copy_game_common_parts(game_common_parts, temp_assets_path) # 拷贝指定的游戏文件 games_dirs = [] games = apk_cfg_info.get(PackAPK.CFG_GAMES, None) if isinstance(games, list) and len(games) > 0: games_dirs.extend(games) if len(games_dirs) > 0: if not os.path.isdir(self.games_root_path): raise_known_error('文件夹 %s 不存在' % self.games_root_path, KnownError.ERROR_PATH_NOT_FOUND) for game in games_dirs: copy_cfg = { 'from': '%s' % game, 'to': 'games/%s' % game, 'exclude': ['**/.DS_Store', '*.git'] } excopy.copy_files_with_config(copy_cfg, self.games_root_path, temp_assets_path) # 替换游戏配置文件 for p in apk_cfg_info[PackAPK.CFG_FILES].split(','): cfg_path = utils.flat_path(os.path.join(cfg_dir, p.strip())) copy_cfg = {'from': '.', 'to': 'src', 'exclude': ['**/.DS_Store']} excopy.copy_files_with_config(copy_cfg, cfg_path, temp_assets_path) # cfg_package.lua文件末尾写入打包文件夹名称时间戳 tmpFile = open(os.path.join(temp_assets_path, "src/cfg_package.lua"), 'a') tmpFile.write('\nPACKAGE_TIMESTAMP=' + '\"' + self.packageTimestamp + '\"') tmpFile.close() # 替换 res 文件夹 if apk_cfg_info.has_key(PackAPK.CFG_RES_FILES): for p in apk_cfg_info[PackAPK.CFG_RES_FILES].split(','): res_path = utils.flat_path(os.path.join(cfg_dir, p.strip())) copy_cfg = { 'from': '.', 'to': 'res', 'exclude': ['**/.DS_Store'] } excopy.copy_files_with_config(copy_cfg, res_path, temp_assets_path) # 删除不需要的品牌资源文件夹 for brand in utils.get_support_brands(): brand_path = utils.flat_path( os.path.join(temp_assets_path, 'res', brand)) if brand != self.brand and os.path.isdir(brand_path): shutil.rmtree(brand_path) # 删除不属于该地区的地图资源文件 if apk_cfg_info.has_key(PackAPK.CFG_REGION) and apk_cfg_info[ PackAPK.CFG_REGION] != 'all': region_list = [] new_list = apk_cfg_info[PackAPK.CFG_REGION].split(',') for r in new_list: if r.strip() != '': region_list.append(r) # 超过1个地区时需要带上全国地图 if len(region_list) > 1: region_list.append('0') keep_name_list = [] for region in region_list: keep_name = 'map_%s' % region keep_name_list.append(keep_name) map_path = utils.flat_path( os.path.join(temp_assets_path, 'res/hall/map')) if os.path.isdir(map_path): for f in os.listdir(map_path): full_path = os.path.join(map_path, f) if f not in keep_name_list and os.path.isdir(full_path): shutil.rmtree(full_path) # 如果不显示全国地图,则删除云动画的图片 if len(region_list) <= 1: cloud1_path = os.path.join(map_path, "yun1.png") cloud2_path = os.path.join(map_path, "yun2.png") os.remove(cloud1_path) os.remove(cloud2_path) # 清理 assets 文件夹,只保留需要的文件 assets_path = os.path.join(self.proj_android_path, 'assets') file_recorder = utils.FileRollback() for f in PackAPK.NEED_BACKUP_ASSETS: file_recorder.record_file( utils.flat_path(os.path.join(assets_path, f))) if os.path.isdir(assets_path): shutil.rmtree(assets_path) if not self.no_rollback: file_recorder.do_rollback() # 进行加密或者直接拷贝资源文件 if os.path.isdir(temp_assets_path): # 生成 native 环境信息文件 params = None if need_remove_agora: # 需要移除 agora params = {"no_agora": "true"} utils.write_native_info( os.path.join(temp_assets_path, 'src/NativeInfo.lua'), params) if not self.no_encrypt: self._do_encrypt(temp_assets_path, assets_path) else: copy_cfg = { 'from': '.', 'to': '.', 'exclude': ['**/.DS_Store'] } excopy.copy_files_with_config(copy_cfg, temp_assets_path, assets_path) f = open(os.path.join(assets_path, 'src/myflag'), 'w') f.write('') f.close() Logging.debug_msg('资源文件处理结束') # 处理 SDK 相关的配置 Logging.debug_msg('处理 SDK 相关的配置开始') sdks_cfg = apk_cfg_info.get(PackAPK.CFG_SDKS, {}) remove_weixin = apk_cfg_info.get(PackAPK.CFG_REMOVE_WEIXIN, False) remove_youqu = apk_cfg_info.get(PackAPK.CFG_REMOVE_YOUQU, False) sdk_mgr = SDKManager.SDKManager(rollback_obj, pkg_name, sdks_cfg, remove_weixin, remove_youqu, self.build_gradle, self.proj_android_path, self.proj_androidStudio_path) sdk_mgr.prepare_sdk() Logging.debug_msg('处理 SDK 相关的配置结束') # 检查是否需要删除 agora 的库文件 if need_remove_agora: self._do_remove_agora(rollback_obj) # 最终 apk 文件名格式为:GAMENAME_PKGNAME_APPID_CHANNELID_VERNAME_VERCODE.apk Logging.debug_msg('生成apk文件名') name_infos = [pkg_name, app_id, channel_id, ver_name, ver_code] remark = utils.non_unicode_str(apk_cfg_info.get( PackAPK.CFG_REMARK, "")) if len(remark) is not 0: name_infos.append(remark) if self.no_encrypt: name_infos.append('NO_ENCRYPT') # 是否删除 agora # if need_remove_agora: # name_infos.append("NO_AGORA") # 文件名增加时间戳 Logging.debug_msg('文件名增加时间戳') cur_time_str = datetime.datetime.fromtimestamp( time.time()).strftime('%Y%m%d_%H%M%S') name_infos.append(cur_time_str) apk_name = '_'.join(name_infos) + '.apk' out_file_path = os.path.join(self.output_path, apk_name) if not os.path.isdir(self.output_path): os.makedirs(self.output_path) if self.build_gradle: # 进行 gradle 打包 Logging.debug_msg('进行 gradle 打包') try: self.build_apk_gradle(rollback_obj, cfg_dir, apk_cfg_info, apk_name) self.build_result['%s_%s' % (app_id, channel_id)] = out_file_path except: print 'traceback.format_exc():\n%s' % traceback.format_exc() return else: # 进行 ant 打包 Logging.debug_msg('进行 ant 打包') keystore_path = utils.flat_path( os.path.join( cfg_dir, apk_cfg_info[PackAPK.CFG_SIGN][PackAPK.CFG_SIGN_FILE])) keystore_pass = apk_cfg_info[PackAPK.CFG_SIGN][ PackAPK.CFG_SIGN_PASSWORD] alias = apk_cfg_info[PackAPK.CFG_SIGN][PackAPK.CFG_SIGN_ALIAS] alias_pass = apk_cfg_info[PackAPK.CFG_SIGN][ PackAPK.CFG_SIGN_ALIAS_PASSWORD] ant_cmd = PackAPK.ANT_CMD_FMT % (self.ant_bin, self.build_xml, self.sdk_root, keystore_path, alias, keystore_pass, alias_pass) try: utils.run_shell(ant_cmd) except: Logging.warn_msg('打包失败') return # 将 apk 包拷贝到指定位置 build_path = utils.flat_path( os.path.join(self.proj_android_path, 'bin/%s-release.apk' % self.proj_name)) shutil.copy(utils.get_sys_encode_str(build_path), utils.get_sys_encode_str(out_file_path)) Logging.debug_msg('生成的 apk 文件路径:%s' % out_file_path) self.build_result['%s_%s' % (app_id, channel_id)] = out_file_path try: shutil.rmtree(temp_assets_path) except: pass