def execFormatCmd(cmd): cmd = cmd.replace('\\', '/') cmd = re.sub('/+', '/', cmd) if platform.system() == 'Windows': st = subprocess.STARTUPINFO st.dwFlags = subprocess.STARTF_USESHOWWINDOW st.wShowWindow = subprocess.SW_HIDE else: cmd = cmd.encode('utf-8').decode('iso-8859-1') # findret = cmd.find('jarsigner') # if findret > -1: # import shlex # cmds = shlex.split(cmd) # log_utils.getLogger().debug('the execformatCmd cmds:'+str(cmds)) # s = subprocess.Popen(cmds) # else: # s = subprocess.Popen(cmd, shell=True) import shlex cmds = shlex.split(cmd) s = subprocess.Popen(cmds) ret = s.wait() if ret: # 为什么还要这里?? s = subprocess.Popen(str(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) stdoutput, erroutput = s.communicate() reportError(str(cmd), stdoutput, erroutput) cmd = 'ERROR:' + str(cmd) + ' ===>>> exec Fail <<<=== ' else: cmd += ' ===>>> exec success <<<=== ' log_utils.getLogger().debug(cmd) return ret
def decompileApk(apkFile, targetDir, tmpPath, apkTool=env.TOOL_DEF_APKTOOL_JARFILE): ''' @brief 反编译apk文件 @param[in] apkFile apk文件路径 @param[in] targetDir 反编译文件存放目录 @param[in] tmpPath 反编译文件apktool工具 @param[in] apkTool 反编译工具jar包 @return 1:失败; 0:成功 ''' apkFile = my_utils.getFullPath(apkFile) targetDir = my_utils.getFullPath(targetDir) apkTool = my_utils.getToolPath(apkTool) if not os.path.exists(apkFile) or not os.path.exists(apkTool): my_utils.printf("decompileApk: %s or %s file not exist." % (apkFile, apkTool)) return 1 if os.path.exists(targetDir): my_utils.delete_file_folder(targetDir) os.makedirs(targetDir) # tmpPath 没有用 # cmd = '"{0}" -jar "{1}" -q d --frame-path "{2}" -b -f -o "{3}" "{4}"'.format( cmd = '"{0}" -jar "{1}" d --frame-path "{2}" -f -o "{3}" "{4}"'.format( my_utils.getJavaPath('java'), apkTool, tmpPath, targetDir, apkFile) log_utils.getLogger().debug(cmd) ret = my_utils.execFormatCmd(cmd) if ret: #my_utils.printf("decompileApk: execFormatCmd failure ret = %d." % ret) return ret else: return 0
def __init__(self): self.sdksRootDir = os.path.join(env.SUPPORT_DIR, self._projectShorName) self.outputDir = ConfigParse.shareInstance().getOutputDir() if self.outputDir is None: raise PackException(pack_exception.PHP_PARAMS_ERROR, 'outputDir is None') self.outputName = ConfigParse.shareInstance().getOutputName() self.apkFile = ConfigParse.shareInstance().getApkPath() timestamp_str = ConfigParse.shareInstance().getTimestamp() self.taskWorkDir = os.path.join(self.outputDir, timestamp_str, "temp") if not os.path.exists(self.taskWorkDir): os.makedirs(self.taskWorkDir) self.__saveLog = ConfigParse.shareInstance().getSaveLog() log_utils.getLogger().info('taskWorkDir == ' + self.taskWorkDir.decode('utf-8')) self.decompileDir = self.taskWorkDir + '/decompile' self.tmpApkToolPath = os.path.join(self.taskWorkDir, 'apktooltmp') if not os.path.exists(self.tmpApkToolPath): os.makedirs(self.tmpApkToolPath) self.__debug = ConfigParse.shareInstance().getSaveFile()
def decompile(self): log_utils.getLogger().info('start decompiling...') taskLogDir = os.path.join(self.taskWorkDir, 'log') if not os.path.exists(taskLogDir): os.makedirs(taskLogDir) logFileName = os.path.join(taskLogDir, 'repack.log') log_utils.changeLoggerFileHandler(logFileName) if not os.path.exists(self.apkFile): raise PackException( pack_exception.SOURCE_APK_NOT_EXIST, 'source apk file %s does not exist' % self.apkFile) tmpApkSource = self.taskWorkDir + '/temp.apk' my_utils.copyFile(self.apkFile, tmpApkSource) log_utils.getLogger().info('decompiling apk ... ') #apk反编译 ret = cmd_tools.decompileApk(tmpApkSource, self.decompileDir, self.tmpApkToolPath) if ret: raise PackException(pack_exception.DECOMPLE_APK_FAILED, 'decompile apk %s failed' % tmpApkSource)
def addRootFileToApkRoot(apk, srcDir, ignoreList=[ 'AndroidManifest.xml', 'apktool.yml', 'plugin.xml', 'script.py', 'script.pyo', 'script.pyc' ]): if not file_utils.isExistFile(apk): return False if not file_utils.isExistDir(srcDir): return False with zipfile.ZipFile(apk, 'a', zipfile.ZIP_DEFLATED) as f: name_list = f.namelist() for file in os.listdir(srcDir): targetFile = os.path.join(srcDir, file) if os.path.isfile(targetFile): if file in ignoreList: # 如果在忽略列表中 log_utils.getLogger().debug( 'addRootFileToApkRoot: %s is in the ignore list' % file) continue if file in name_list: log_utils.getLogger().warning( 'addRootFileToApkRoot :%s is in the name_list, zipFile %s has a same name file!' % (file, apk)) raise PackException( pack_exception.ZIP_DEFLATED_ADD_FILE_EXCEPTION, 'addRootFileToApkRoot :%s is in the name_list, zipFile %s has a same name file!' % (file, apk)) else: f.write(targetFile, file) else: continue return True
def search(self): log_utils.getLogger().debug("EXTRA_DIR:" + env.EXTRA_DIR) address = "file:///" + os.path.join(env.EXTRA_DIR, "readme", env.README_TOOLS) log_utils.getLogger().debug("address:" + address) if address: if address.find('://') == -1: address = 'http://' + address url = QUrl(address) self.webView.load(url)
def modifyComponentAuthorities(node): '''将Authorities中的旧包名替换为新包名''' if keyAuthorities not in node.attrib: return authorities = node.attrib[keyAuthorities] log_utils.getLogger().debug( "origin authorities = {}".format(authorities)) authorities = authorities.replace(oldPackageName, newPackageName) log_utils.getLogger().debug("new authorities = %s" % authorities) node.attrib[keyAuthorities] = authorities
def repackTestBundleForMatch(self, sdksRootDir, decompileDir, targetPackageName): cfgResRootDir = sdksRootDir #apk资源修改 decompileManifest = os.path.join(decompileDir, 'AndroidManifest.xml') log_utils.getLogger().info('modifying AndroidManifest.xml ... ') manifest_utils.modifyManifestForTestBundle(decompileManifest, decompileManifest, targetPackageName)
def configChannelIdCheck(self): self.parent.logControl = self.ConfigLogBrowser self.ConfigLogBrowser.clear() titleMsg = '查看apk渠道信息' path = self.ConfigPathEdit.text() log_utils.getLogger().debug(path) if self.checkFormat(titleMsg,path): result = channel_util.checkApkComment(path) if result: self.parent.showMsgBox(titleMsg,result)
def __init__(self,parent,tabWidget,Windows,settings): self.parent = parent configPathLabelT = QLabel("Path: ") rememberPath = None try: rememberPath = bool(int(settings.value("rememberpath", 1 if Windows else 0))) except ValueError: rememberPath = True if rememberPath == "true" else False log_utils.getLogger().debug("ConfigureInfo path rememberPath:" + str(rememberPath)) if rememberPath: log_utils.getLogger().debug("ConfigureInfo path:" + str(settings.value("path"))) apkPath = settings.value("path") or os.getcwd() else: apkPath = (sys.argv[1] if len(sys.argv) > 1 and QFile.exists(sys.argv[1]) else os.getcwd()) self.ConfigPathEdit = custom_edit.AutoEdit(parent) self.ConfigPathEdit.setFocusPolicy(Qt.NoFocus) self.ConfigPathEdit.setStyleSheet("color:gray") self.ConfigPathEdit.setPlaceholderText('支持直接拖拽文件到文本框') ConfigPathButton = QPushButton("&Path") self.ConfigLogBrowser = QTextBrowser() self.ConfigLogBrowser.setLineWrapMode(QTextEdit.NoWrap) ConfigTopLayout = QHBoxLayout() ConfigTopLayout.addWidget(configPathLabelT) ConfigTopLayout.addWidget(self.ConfigPathEdit, 1) ConfigTopLayout.addWidget(ConfigPathButton) ConfigCheckChannelIdButton = QPushButton("&查看") ConfigCheckLayout = QHBoxLayout() ConfigCheckLayout.addStretch() # ConfigCheckLayout.addWidget(ConfigCheckInfoButton) ConfigCheckLayout.addWidget(ConfigCheckChannelIdButton) ConfigCheckLayout.addStretch() layout = QVBoxLayout() layout.addLayout(ConfigTopLayout) layout.addLayout(ConfigCheckLayout) layout.addWidget(self.ConfigLogBrowser) ConfigInfoWidget = QFrame() ConfigInfoWidget.setLayout(layout) tabWidget.addTab(ConfigInfoWidget,'查看渠道') parent.connect(ConfigPathButton, SIGNAL("clicked()"), self.configSetPath) parent.connect(ConfigCheckChannelIdButton, SIGNAL("clicked()"), self.configChannelIdCheck) parent.connect(log_utils.aSigalOutLog,SIGNAL("displayLog(QString)"), parent.displayLog)
def modifyManifest(srcManifest, manifestCfg, outManifest): log_utils.getLogger().debug('Merge Manifest') if not os.path.exists(srcManifest): log_utils.getLogger().warning( 'modifyManifest: srcManifest %s not exist!' % srcManifest) return False if not os.path.exists(manifestCfg): log_utils.getLogger().warning( 'modifyManifest: manifestCfg %s not exist!' % manifestCfg) return False ElementTree.register_namespace(androidN, androidNS) srcTree = ElementTree.parse(srcManifest) srcRoot = srcTree.getroot() srcAppNode = srcRoot.find('application') configTree = ElementTree.parse(manifestCfg) configRoot = configTree.getroot() configAppNode = configRoot.find('application') providerNode = configAppNode.find('provider') providerNode.set('android:authorities', getPackageName(srcManifest) + '.providers.element') srcAppNode.append(providerNode) prettyXml(srcRoot) srcTree.write(outManifest, 'UTF-8') log_utils.getLogger().debug('Merge Manifest Done')
def addUserUploadRootFilesToApkRoot(apk, sdkList): for sdk in sdkList: if 'Files' in sdk and 'root' in sdk['Files']: rootFileList = sdk['Files']['root'] if len(rootFileList) > 0: with zipfile.ZipFile(apk, 'a', zipfile.ZIP_DEFLATED) as f: name_list = f.namelist() for fileDict in rootFileList: for srcFileName, savedFilePath in fileDict.items(): if srcFileName in name_list: log_utils.getLogger().warning('addUserUploadRootFilesToApkRoot: zipFile %s has a same name %s file!' % (apk, srcFileName)) raise PackException(pack_exception.ZIP_DEFLATED_ADD_FILE_EXCEPTION, 'addUserUploadRootFilesToApkRoot: zipFile %s has a same name %s file!' % (apk, srcFileName)) else: f.write(savedFilePath, srcFileName)
def copyFiles(sourceDir, targetDir): if not os.path.exists(sourceDir): log_utils.getLogger().debug('source %s does not exist' % sourceDir) return False if os.path.isfile(sourceDir): return copyFile(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): copyFile(sourceFile, targetFile) else: copyFiles(sourceFile, targetFile) return True
def displayLog(self, log, level=logging.DEBUG): if not self.logControl: return if (log is not None and log.find("DEBUG") == -1): self.logControl.append("<font color=green>{}</font>".format( log.replace("\n", ""))) elif (level == log_utils.getLogger().DEBUG): self.logControl.append("<font color=blue>{}</font>".format( log.replace("\n", ""))) elif (level == log_utils.getLogger().INFO): self.logControl.append("<font color=green>{}</font>".format( log.replace("\n", ""))) else: self.logControl.append("<font color=red>{}</font>".format( log.replace("\n", "")))
def doPackWithOneChannelSymbol(self, channelId, tempRecompileApk, tempSignedApkName, outputDir, outputName, symbol, taskWorkDir): ''' @param channelId 渠道id,用于获取keystore @param tempRecompileApk 重打包后的未签名apk path @param tempSignedApkName 签名对齐后的包名称 @param outputDir 输出路径(非完整path) @param outputName 输出名称(非完整path) @param symbol 自定义渠道标记 @param taskWorkDir 工作目录 ''' log_utils.getLogger().info('doPackWithOneChannelSymbol ... ') #添加渠道标识 log_utils.getLogger().info('adding channel symbol to /assets/ ... ') channelSymbolFileName = ConfigParse.shareInstance( ).getChannelSymbolFileName() zip_utils.addChannelSymbolFile(tempRecompileApk, symbol, channelSymbolFileName, taskWorkDir) #apk签名 log_utils.getLogger().info('signing apk') keystoreInfo = ConfigParse.shareInstance().getKeystoreInfoByChannelId( channelId) ret = cmd_tools.signApk(tempRecompileApk, keystoreInfo['file'], keystoreInfo['storePassword'], keystoreInfo['keyAlias'], keystoreInfo['aliasPassword']) if ret: raise PackException(pack_exception.SIGN_APK_FAILED, 'sign apk failed') #apk优化 apkName = '%s/%s' % (outputDir, outputName) outputDir = os.path.dirname(apkName) if not os.path.exists(outputDir): os.makedirs(outputDir) log_utils.getLogger().debug(outputDir) log_utils.getLogger().info('zipaligning and renaming apk apkName == ' + apkName) ret = cmd_tools.alignAPK(tempRecompileApk, tempSignedApkName) if ret: raise PackException(pack_exception.ALIGN_APK_FAILED, 'align apk failed') os.rename(tempSignedApkName, apkName)
def run(self): sys.stdout = self.ctrl_process sys.stderr = self.ctrl_process for h in log_utils.getLogger().handlers: log_utils.getLogger().removeHandler(h) ctrl_handler = log_utils.WxTextCtrlHandler(self.ctrl_process) log_utils.getLogger().addHandler(ctrl_handler) timestamp_str = str(time.time()) if self.save_log: myFH = log_utils.MyFileHandler(filename=os.path.join( self.output_path, timestamp_str, 'repack.log')) # myFH.setLevel(log_utils.FILE_HANDLER_LEVEL) myFH.setFormatter(log_utils.formatter) log_utils.getLogger().addHandler(myFH) argjson = entry.windowsDebugJson(self.apk_path, self.output_path, self.save_log, self.save_file, timestamp=timestamp_str, lua_version=self.lua_version) entry.php_entry(argjson) self.ctrl_process.AppendText("Completed!\n\n\n") sys.stdout = self.old_stdout sys.stderr = self.old_stderr if self.cb: self.cb()
def execFormatCmd(cmd): cmd = cmd.replace('\\', '/') cmd = re.sub('/+', '/', cmd) if platform.system() == 'Windows': st = subprocess.STARTUPINFO st.dwFlags = subprocess.STARTF_USESHOWWINDOW st.wShowWindow = subprocess.SW_HIDE else: cmd = cmd.encode('utf-8').decode('iso-8859-1') # findret = cmd.find('jarsigner') # if findret > -1: # import shlex # cmds = shlex.split(cmd) # log_utils.getLogger().debug('the execformatCmd cmds:'+str(cmds)) # s = subprocess.Popen(cmds) # else: # s = subprocess.Popen(cmd, shell=True) #=========================================================================== # import shlex # cmds = shlex.split(cmd) # #log_utils.getLogger().debug("eeeeeeeeeeeeeeeeeee" + cmd) # s = subprocess.Popen(cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE) #=========================================================================== import locale cmd = cmd.encode(locale.getdefaultlocale()[1]) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) ConfigParse.shareInstance().setCurrentSubProcess(p) while p.poll() == None: line = p.stdout.readline() if not line: break # print line log_utils.getLogger().info(line) p.wait() return p.returncode
def s3_index_run(options): log = log_utils.getLogger(options.log_level, options.log_config) s3lib.setLogger(log) log.trace('s3_index_run args %s: ' % options) # Import user specified html template or the default if options.html_template: try: template_file = importlib.import_module(options.html_template) create_html_index = getattr(template_file, 'create_html_index') except Exception as err: log.fatal('Import of HTML template failed: ' + err.message) exit(1) else: from default_html_index import create_html_index target_dir = parse_dir_name(options.target_dir) if options.root_dir: root_dir = parse_dir_name(options.root_dir) s3_objs = s3lib.recursive_index_search(options.bucket, target_dir, root_dir, options.obj_name, options.ignore_pattern) else: s3_objs = s3lib.single_index_search(options.bucket, target_dir, options.obj_name, options.ignore_pattern) log.trace('directory search s3 objects: %s' % s3_objs) uploaded_indexs = [] for dir_name, dir_objs in s3_objs: s3_obj_path = str(dir_name) + consts.index_file log.debug('Creating index file for ' + s3_obj_path) log.trace('create_html_index dir objects: %s' % dir_objs) html = create_html_index(str(dir_name), str(dir_name.parent), dir_objs) log.trace('%s %s %s' % ('--------------', s3_obj_path, '-------------- ')) log.trace(html) if not options.no_upload: log.debug('Preparing to upload index file.') uploaded_indexs.append([ s3lib.upload_file_to_s3(options.bucket, html.encode(), s3_obj_path), s3_obj_path ]) else: # File creation will go here pass # Fix this when there are no sucessful uploads if len(uploaded_indexs): log.info('The following index pages have been uploaded:') unloaded_indexs = [] for status, index_file in uploaded_indexs: if status: log.info('- ' + index_file) else: log.info('No index pages have been uploaded.')
def makeConStart(self): self.parent.logControl = None titleMsg = 'fail' originApk = self.makeConPathEdit.text() channelList = self.makeConChannelEdit.text() extraInfo = self.makeConExtraLabelEdit.text() outPath = self.makeConOutputPathEdit.text() log_utils.getLogger().debug(originApk) log_utils.getLogger().debug(extraInfo) log_utils.getLogger().debug(outPath) if self.checkFormat(titleMsg,originApk,outPath,channelList): result = channel_util.changeNativeChannel(originApk,channelList,extraInfo,outPath) if result == '': self.parent.showMsgBox("Success","请到 " + outPath + " 目录下查看!") else: originName = os.path.split(originApk)[1] tempFile = os.path.join(outPath,originName) if os.path.exists(tempFile): os.remove(tempFile) self.parent.showMsgBox(titleMsg,result)
def addOneFileToApkRoot(apk, srcFile): if not file_utils.isExistFile(apk): log_utils.getLogger().debug('%s not exist' % apk) return False if not file_utils.isExistFile(srcFile): log_utils.getLogger().debug('%s not exist' % srcFile) return False with zipfile.ZipFile(apk, 'a', zipfile.ZIP_DEFLATED) as f: name = os.path.basename(srcFile) if name in f.namelist(): log_utils.getLogger().debug('%s was existed in root' % name) return False else: f.write(srcFile, name) log_utils.getLogger().debug('addOneFileToApkRoot done') return True
def doPackWithoutChannelSymbol(self, tempRecompileApk, tempSignedApkName, outputDir, outputName): ''' @param channelId 渠道id,用于获取keystore @param tempRecompileApk 重打包后的未签名apk path @param tempSignedApkName 签名对齐后的包名称 @param outputDir 输出路径(非完整path) @param outputName 输出名称(非完整path) ''' log_utils.getLogger().info('doPackWithoutChannelSymbol ... ') #apk签名 log_utils.getLogger().info('signing apk') keystoreInfo = ConfigParse.shareInstance().getKeystoreInfo() # 签名,没细看 ret = cmd_tools.signApk(tempRecompileApk, keystoreInfo['file'], keystoreInfo['storePassword'], keystoreInfo['keyAlias'], keystoreInfo['aliasPassword']) if ret: raise PackException(pack_exception.SIGN_APK_FAILED, 'sign apk failed') #apk优化 apkName = '%s/%s' % (outputDir, outputName) outputDir = os.path.dirname(apkName) if not os.path.exists(outputDir): os.makedirs(outputDir) log_utils.getLogger().debug(outputDir) log_utils.getLogger().info('zipaligning and renaming apk apkName == ' + apkName) # 调用工具里的 zipalign.exe 对temRecompileApk 进行优化,生成tempSignedApkName ret = cmd_tools.alignAPK(tempRecompileApk, tempSignedApkName) if ret: raise PackException(pack_exception.ALIGN_APK_FAILED, 'align apk failed') import shutil shutil.move(tempSignedApkName, apkName)
def addFilesToApkRoot(apk, srcDir): if not file_utils.isExistFile(apk): log_utils.getLogger().debug('%s not exist' % apk) return False if not file_utils.isExistDir(srcDir): log_utils.getLogger().debug('%s not exist' % srcDir) return False with zipfile.ZipFile(apk, 'a', zipfile.ZIP_DEFLATED) as f: name_list = f.namelist() for parent, dirnames, filenames in os.walk(srcDir): for file in filenames: sourceFile = os.path.join(parent, file) targetFile = sourceFile[len(srcDir):] if targetFile in name_list: log_utils.getLogger().debug('%s was existed in root' % targetFile) return False else: f.write(sourceFile, targetFile) log_utils.getLogger().debug('add file %s to apk root' % targetFile); return True
def checkApkComment(signedApk): log_utils.getLogger().info('do checkApkComment') info, tag = readComment(signedApk) if info: if tag == 'comment': log_utils.getLogger().info('apkComment result: ' + info) commentDict = eval(info) if 'channelId' in commentDict.keys(): print('channelId:' + commentDict['channelId']) else: return '该apk不包含渠道id信息,读取失败' else: log_utils.getLogger().info('channelId result: ' + info) print('channelId:' + info) else: return '该apk不包含渠道id信息,读取失败'
def modifyManifestForTestBundle(srcManifest, outManifest, targetPackageName): log_utils.getLogger().debug('Merge Manifest') if not os.path.exists(srcManifest): log_utils.getLogger().warning( 'modifyManifest: srcManifest %s not exist!' % srcManifest) return False return False ElementTree.register_namespace(androidN, androidNS) srcTree = ElementTree.parse(srcManifest) srcRoot = srcTree.getroot() srcInstrumentationNode = srcRoot.find('instrumentation') srcInstrumentationNode.clear() srcInstrumentationNode.set('android:name', "android.test.InstrumentationTestRunner") srcInstrumentationNode.set('android:targetPackage', targetPackageName) prettyXml(srcRoot) srcTree.write(outManifest, 'UTF-8') log_utils.getLogger().debug('Merge Manifest Done')
def copyFile(sourceFile, targetFile): sourceFile = os.path.abspath(sourceFile) targetFile = os.path.abspath(targetFile) if not os.path.exists(sourceFile): log_utils.getLogger().debug('copyFile: sourceFile %s does not exist' % sourceFile) return False else: if os.path.exists(targetFile): log_utils.getLogger().warning('copyFile: target file %s exists, overwrite' % targetFile) targetDir = os.path.dirname(targetFile) if not os.path.exists(targetDir): os.makedirs(targetDir) print(targetFile) targetFileHandle = open(targetFile, 'wb') sourceFileHandle = open(sourceFile, 'rb') targetFileHandle.write(sourceFileHandle.read()) targetFileHandle.close() sourceFileHandle.close() log_utils.getLogger().debug('copyFile: copy from %s to %s' % (sourceFile, targetFile)) return True
# dict -> str return json.dumps(arg) if __name__ == '__main__': targetDir = None luaversion = '4.0' if len(sys.argv) == 1: apkPath = r'C:\Users\LukeJiang\Desktop\kk\engine_android(1)(1).apk' else: apkPath = sys.argv[1] if len(sys.argv) == 3: targetDir = sys.argv[2] if len(sys.argv) == 4: targetDir = sys.argv[2] luaversion = sys.argv[3] argjson = windowsDebugJson(apkPath, targetDir, luaversion) #=========================================================================== # if platform.system() == 'Linux': # apkPath = sys.argv[1] # argjson = windowsDebugJson(apkPath) # elif platform.system() == 'Windows': # argjson = windowsDebugJson(r'C:\Users\LukeJiang\Desktop\scancase\repack\engine_android(4).apk') #=========================================================================== import log_utils log_utils.getLogger().info('sys.argv == %s', sys.argv) log_utils.getLogger().info('argjson == %s', argjson) php_entry(argjson)
def pack(self): try: log_utils.getLogger().info('generating new r file ... ') #重新生成R文件 ret = cmd_tools.produceNewRFile(self._packageName, self.decompileDir) if ret: raise PackException(pack_exception.PRODUCE_NEW_R_FILE_FAILED, 'produce new r file failed') #重新编译成apk tempRecompileApkDir = self.taskWorkDir + '/tempRecompileApk' tempRecompileApk = '%s/nosig.apk' % (tempRecompileApkDir) tempSignedApkName = '%s/_sig.apk' % (tempRecompileApkDir) log_utils.getLogger().info( 'recompiling apk ... tempRecompileApk = ' + tempRecompileApk) ret = cmd_tools.recompileApk(self.decompileDir, tempRecompileApk, self.tmpApkToolPath) if ret: raise PackException(pack_exception.RECOMPILE_APK_FAILED, 'recompile apk failed') # self.outputName是 autotest_xxx.apk self.doPackWithoutChannelSymbol(tempRecompileApk, tempSignedApkName, self.outputDir, self.outputName) #测试桩重打包 import env testbundle_apkFile = os.path.join(env.SUPPORT_DIR, self._projectShorName, 'testbundle', 'TestBundle.apk') #testbundle_apkFile = os.path.join(env.GOD_TOOL_DIR, 'TestBundle_base.apk') if not os.path.exists(testbundle_apkFile): raise PackException( pack_exception.SOURCE_APK_NOT_EXIST, 'testbundle_base apk file %s does not exist' % testbundle_apkFile) # 拷贝TestBundle.apk 到 工作目录下/testbundle_temp.apk tmpTestBundleApk = self.taskWorkDir + '/testbundle_temp.apk' my_utils.copyFile(testbundle_apkFile, tmpTestBundleApk) testbundle_decompileDir = self.taskWorkDir + '/testbundle_decompile' testbundle_tmpApkToolPath = os.path.join(self.taskWorkDir, 'testbundle_apktooltmp') log_utils.getLogger().info('decompiling testbundle apk ... ') #测试桩反编译 到 工作目录下/testbundle_decompile ret = cmd_tools.decompileApk(tmpTestBundleApk, testbundle_decompileDir, testbundle_tmpApkToolPath) if ret: raise PackException( pack_exception.DECOMPLE_APK_FAILED, 'decompile testbundle apk %s failed' % tmpTestBundleApk) testbundle_packageName = "com.boyaa.application.testbundle" # 修改manifest.xml self.repackTestBundleForMatch(self.sdksRootDir, testbundle_decompileDir, self._packageName) log_utils.getLogger().info( 'generating new r file for testbundle... ') #重新生成测试桩的R文件 ret = cmd_tools.produceNewRFile(testbundle_packageName, testbundle_decompileDir) if ret: raise PackException( pack_exception.PRODUCE_NEW_R_FILE_FAILED, 'produce new r file for testbundle failed') #重新编译测试桩apk testbundle_tempRecompileApkDir = self.taskWorkDir + '/testbundle_tempRecompileApk' testbundle_tempRecompileApk = '%s/testbundle_nosig.apk' % ( testbundle_tempRecompileApkDir) testbundle_tempSignedApkName = '%s/testbundle_sig.apk' % ( testbundle_tempRecompileApkDir) log_utils.getLogger().info( 'recompiling apk ... tempRecompileApk = ' + testbundle_tempRecompileApk) ret = cmd_tools.recompileApk(testbundle_decompileDir, testbundle_tempRecompileApk, testbundle_tmpApkToolPath) if ret: raise PackException(pack_exception.RECOMPILE_APK_FAILED, 'recompile test bundle apk failed') self.doPackWithoutChannelSymbol( testbundle_tempRecompileApk, testbundle_tempSignedApkName, os.path.join(self.outputDir, 'testbundle'), "testbundle.apk") #log_utils.getLogger().info('doPack: =============================================success=============================================' + StreamHandler.terminator) except PackException as pe: log_utils.getLogger().error(pe) #log_utils.getLogger().info('doPack: =============================================Failed=============================================' + StreamHandler.terminator) return
def doBatchPackWithChannelSymols(self, channelId, unsignedApk, tempSignedApkName, outputDir, outputName, symbolList, taskWorkDir): ''' @param channelId 渠道id,用于获取keystore @param unsignedApk 重打包后的未签名apk path @param tempSignedApkName 签名对齐后的包名称 @param outputDir 输出路径(非完整path) @param outputName 输出名称(非完整path) @param symbolList 自定义渠道标记列表 @param taskWorkDir 工作目录 ''' log_utils.getLogger().info('doBatchPackWithChannelSymols ... ') batchPackDir = os.path.join(taskWorkDir, 'batch') if not os.path.exists(batchPackDir): os.makedirs(batchPackDir) copiedUnsignedApk = os.path.join(os.path.dirname(unsignedApk), 'batchTmpApk.apk') log_utils.getLogger().info('start batch packing ... ') for symbol in symbolList: if not file_utils.copyFile(unsignedApk, copiedUnsignedApk): raise PackException( pack_exception.COPY_FILE_EXCEPTION, 'cannot copy apk during doBatchPackWithChannelSymols') #添加渠道标识 log_utils.getLogger().info( 'adding channel symbol to /assets/ ... ') channelSymbolFileName = ConfigParse.shareInstance( ).getChannelSymbolFileName() zip_utils.addChannelSymbolFile(copiedUnsignedApk, symbol, channelSymbolFileName, taskWorkDir) #apk签名 log_utils.getLogger().info('signing apk') keystoreInfo = ConfigParse.shareInstance( ).getKeystoreInfoByChannelId(channelId) ret = cmd_tools.signApk(copiedUnsignedApk, keystoreInfo['file'], keystoreInfo['storePassword'], keystoreInfo['keyAlias'], keystoreInfo['aliasPassword']) if ret: raise PackException(pack_exception.SIGN_APK_FAILED, 'sign apk failed') #apk优化 apkName = '%s/%s' % (batchPackDir, outputName) basename = os.path.splitext(os.path.basename(apkName))[0] apkOutputDir = os.path.dirname(apkName) if not os.path.exists(apkOutputDir): os.makedirs(apkOutputDir) apkName = os.path.join(apkOutputDir, basename + '(' + symbol + ').apk') log_utils.getLogger().debug(apkOutputDir) log_utils.getLogger().info( 'zipaligning and renaming apk apkName == ' + apkName) ret = cmd_tools.alignAPK(copiedUnsignedApk, tempSignedApkName) if ret: raise PackException(pack_exception.ALIGN_APK_FAILED, 'align apk failed') os.rename(tempSignedApkName, apkName) log_utils.getLogger().info('batch packing success... ') log_utils.getLogger().info('zip apk files ... ') zip_utils.zipApks(batchPackDir, '%s/%s' % (outputDir, outputName))
def getChannelConfig(package_info): try: package_dic = eval(package_info) except: print '{"status":0}' orginal_package_dic = {} orginal_package_dic['plugins'] = {} orginal_package_dic['ad_sdk'] = {} orginal_package_dic['game_info'] = {} msglist = [] #登录插件 if package_dic.has_key('channel_flag') and len( package_dic['channel_flag']) > 0: if loginPluginsDic.has_key(package_dic['channel_flag']) and len( loginPluginsDic[package_dic['channel_flag']]) > 0: orginal_package_dic['plugins']['login_plugin'] = loginPluginsDic[ package_dic['channel_flag']] else: msglist.append("ERROR:channel flag is illegal") print '{"status":0}' else: msglist.append("ERROR:no channel flag") print '{"status":0}' # 媒体插件标识 if package_dic.has_key('media_flag') and len( package_dic['media_flag']) > 0: orginal_package_dic['ad_sdk']['channel_flag'] = package_dic[ 'channel_flag'] #广告插件 ad_plugin = '' #gdt if package_dic.has_key('gdt_id') and len( package_dic['gdt_id']) > 0 and package_dic.has_key( 'gdt_secret_key') and len(package_dic['gdt_secret_key']) > 0: if ad_plugin == '': orginal_package_dic['plugins'][ 'ad_plugin'] = 'com.jiyou.gdtpluginlib.openapi.GdtPluginStatistic' else: orginal_package_dic['plugins'][ 'ad_plugin'] = '|com.jiyou.gdtpluginlib.openapi.GdtPluginStatistic' #tt if package_dic.has_key('tt_id') and len(package_dic['tt_id']) > 0: if ad_plugin == '': orginal_package_dic['plugins'][ 'ad_plugin'] = 'com.jiyou.toutiaopluginlib.openapi.ToutiaoStatistic' else: orginal_package_dic['plugins'][ 'ad_plugin'] = '|com.jiyou.toutiaopluginlib.openapi.ToutiaoStatistic' #ks if package_dic.has_key('ks_id') and len( package_dic['ks_id']) > 0 and package_dic.has_key( 'ks_name') and len(package_dic['ks_name']) > 0: if ad_plugin == '': orginal_package_dic['plugins'][ 'ad_plugin'] = 'com.jiyou.kuaishoupluginlib.openapi.KuaishouStatistic' else: orginal_package_dic['plugins'][ 'ad_plugin'] = '|com.jiyou.kuaishoupluginlib.openapi.KuaishouStatistic' #广告参数 if package_dic.has_key('gdt_id') and len(package_dic['gdt_id']) > 0: orginal_package_dic['ad_sdk']['gdt_id'] = package_dic['gdt_id'] if package_dic.has_key('gdt_secret_key') and len( package_dic['gdt_secret_key']) > 0: orginal_package_dic['ad_sdk']['gdt_secret_key'] = package_dic[ 'gdt_secret_key'] if package_dic.has_key('gdt_reporting_probability') and len( package_dic['gdt_reporting_probability']) > 0: orginal_package_dic['ad_sdk'][ 'gdt_reporting_probability'] = package_dic[ 'gdt_reporting_probability'] if package_dic.has_key('tt_id') and len(package_dic['tt_id']) > 0: orginal_package_dic['ad_sdk']['tt_id'] = package_dic['tt_id'] if package_dic.has_key('ks_id') and len(package_dic['ks_id']) > 0: orginal_package_dic['ad_sdk']['ks_id'] = package_dic['ks_id'] if package_dic.has_key('ks_name') and len(package_dic['ks_name']) > 0: orginal_package_dic['ad_sdk']['ks_name'] = package_dic['ks_name'] #游戏包参数 #partner_id if package_dic.has_key('partner_id') and len( package_dic['partner_id']) > 0: orginal_package_dic['game_info']['partner_id'] = package_dic[ 'partner_id'] else: msglist.append("ERROR:no partner_id") print '{"status":0}' #game_id if package_dic.has_key('game_id') and len(package_dic['game_id']) > 0: orginal_package_dic['game_info']['game_id'] = package_dic['game_id'] else: msglist.append("ERROR:no game_id") print '{"status":0}' #game_key if package_dic.has_key('game_key') and len(package_dic['game_key']) > 0: orginal_package_dic['game_info']['game_key'] = package_dic['game_key'] else: msglist.append("ERROR:no game_id") print '{"status":0}' #pay_key if package_dic.has_key('pay_key') and len(package_dic['pay_key']) > 0: orginal_package_dic['game_info']['pay_key'] = package_dic['pay_key'] else: msglist.append("ERROR:no game_id") print '{"status":0}' #channel_flag orginal_package_dic['game_info']['channel_flag'] = package_dic[ 'channel_flag'] #game_name if package_dic.has_key('game_name') and len(package_dic['game_name']) > 0: orginal_package_dic['game_info']['game_name'] = package_dic[ 'game_name'].encode('utf-8') else: msglist.append("WARN:no game_name") #game_bundle_id if package_dic.has_key('game_bundle_id') and len( package_dic['game_bundle_id']) > 0: orginal_package_dic['game_info']['game_bundle_id'] = package_dic[ 'game_bundle_id'] else: msglist.append("WARN:no game_bundle_id") #server_url if package_dic.has_key('server_url') and len( package_dic['server_url']) > 0: orginal_package_dic['game_info']['server_url'] = package_dic[ 'server_url'] else: msglist.append("ERROR:no server_url") print '{"status":0}' #icon_name if package_dic.has_key('icon_name') and len(package_dic['icon_name']) > 0: orginal_package_dic['game_info']['icon_name'] = package_dic[ 'icon_name'] else: msglist.append("WARN:no icon_name") #icon_file if package_dic.has_key('icon_file') and len(package_dic['icon_file']) > 0: orginal_package_dic['game_info']['icon_file'] = package_dic[ 'icon_file'] else: msglist.append("WARN:no icon_file") #source_apk if package_dic.has_key('source_apk') and len( package_dic['source_apk']) > 0: orginal_package_dic['game_info']['source_apk'] = package_dic[ 'source_apk'] else: msglist.append("ERROR:no source_apk") print '{"status":0}' #resource_path if package_dic.has_key('resource_path') and len( package_dic['resource_path']) > 0: orginal_package_dic['game_info']['resource_path'] = package_dic[ 'resource_path'] else: msglist.append("WARN:no resource_path") #game_resources if package_dic.has_key('game_resources') and len( package_dic['game_resources']) > 0: orginal_package_dic['game_info']['game_resources'] = package_dic[ 'game_resources'] else: msglist.append("WARN:no game_resources") #orientation #if package_dic.has_key('orientation') and len(package_dic['orientation']) > 0: # orginal_package_dic['game_info']['orientation'] = package_dic['orientation'] #else: # msglist.append("ERROR:no orientation") # print '{"status":0}' #yyb_qq_app_id if package_dic.has_key('yyb_qq_app_id') and len( package_dic['yyb_qq_app_id']) > 0: orginal_package_dic['game_info']['yyb_qq_app_id'] = package_dic[ 'yyb_qq_app_id'] else: msglist.append("WARN:no yyb_qq_app_id") #yyb_wx_app_id if package_dic.has_key('yyb_wx_app_id') and len( package_dic['yyb_wx_app_id']) > 0: orginal_package_dic['game_info']['yyb_wx_app_id'] = package_dic[ 'yyb_wx_app_id'] else: msglist.append("WARN:no yyb_wx_app_id") #target_sdk_version if package_dic.has_key('target_sdk_version') and len( package_dic['target_sdk_version']) > 0: orginal_package_dic['game_info']['target_sdk_version'] = package_dic[ 'target_sdk_version'] else: msglist.append("WARN:no target_sdk_version") #target_apk if package_dic.has_key('target_apk') and len( package_dic['target_apk']) > 0: orginal_package_dic['game_info']['target_apk'] = package_dic[ 'target_apk'] else: msglist.append("ERROR:no target_apk") print '{"status":0}' #bugly_id if package_dic.has_key('bugly_id') and len(package_dic['bugly_id']) > 0: orginal_package_dic['game_info']['bugly_id'] = package_dic['bugly_id'] else: msglist.append("WARN:no bugly_id") #version_code if package_dic.has_key('version_code') and len( package_dic['version_code']) > 0: orginal_package_dic['game_info']['version_code'] = package_dic[ 'version_code'] else: msglist.append("WARN:no version_code") #channel_version if package_dic.has_key('channel_version') and len( package_dic['channel_version']) > 0: orginal_package_dic['game_info']['channel_version'] = package_dic[ 'channel_version'] else: msglist.append("ERROR:no channel_version") print '{"status":0}' #media_version 媒体SDK版本 if package_dic.has_key('media_version') and len( package_dic['media_version']) > 0: orginal_package_dic['game_info']['media_version'] = package_dic[ 'media_version'] #is_dudai if package_dic.has_key('is_dudai') and len(package_dic['is_dudai']) > 0: orginal_package_dic['game_info']['is_dudai'] = package_dic['is_dudai'] else: msglist.append("WARN:no is_dudai") #buildtools if package_dic.has_key('buildtools') and len( package_dic['buildtools']) > 0: orginal_package_dic['game_info']['buildtools'] = package_dic[ 'buildtools'] else: orginal_package_dic['game_info']['buildtools'] = '' #其他渠道字段(huawei/oppo/vivo...) for channelKey in channelConfigKeys: if package_dic.has_key(channelKey) and len( package_dic[channelKey]) > 0: orginal_package_dic['game_info'][channelKey] = package_dic[ channelKey] targetLogFilename = orginal_package_dic['game_info'][ 'game_bundle_id'] + '_' + time.strftime('%y-%m-%d_%H_%M_%S', time.localtime()) + '.log' logfilepath = os.path.join( orginal_package_dic['game_info']['target_apk'], orginal_package_dic['game_info']['game_id'], orginal_package_dic['game_info']['channel_flag'], orginal_package_dic['game_info']['game_bundle_id'], targetLogFilename) if not os.path.exists(os.path.dirname(logfilepath)): os.makedirs(os.path.dirname(logfilepath)) logger = log_utils.getLogger(logfilepath) logger.info(package_info) for msg in msglist: if "ERROR" in msg: logger.error(msg) elif "WARN" in msg: logger.warn(msg) else: logger.info(msg) return orginal_package_dic, logger, logfilepath
def renameManifestPackage(manifest, newPackageName): manifest = os.path.abspath(manifest) if not os.path.exists(manifest): log_utils.getLogger().warning('renameManifestPackage: %s not exist!' % manifest) return False if text_utils.isStr(newPackageName) and text_utils.isEmpty(newPackageName): log_utils.getLogger().warning( 'renameManifestPackage: newPackageName isEmpty') return False ElementTree.register_namespace(androidN, androidNS) targetTree = ElementTree.parse(manifest) root = targetTree.getroot() oldPackageName = root.attrib.get('package') log_utils.getLogger().debug('original packageName == %s' % oldPackageName) if oldPackageName == newPackageName: log_utils.getLogger().debug( 'original packageName is same as newPackageName') return True keyName = '{' + androidNS + '}name' keyProcess = '{' + androidNS + '}process' keyAuthorities = '{' + androidNS + '}authorities' applicationNode = root.find('application') def modifyComponentName(node): '''将组件名称中的旧包名替换为新包名''' if keyName not in node.attrib: return name = node.attrib[keyName] if name.startswith('.'): name = newPackageName + name elif '.' not in name: name = newPackageName + '.' + name elif name.startswith(oldPackageName): name = name.replace(oldPackageName, newPackageName) node.attrib[keyName] = name def modifyComponentProcess(node): '''将进程名中的旧包名替换为新包名''' if keyProcess not in node.attrib: return processName = node.attrib[keyProcess] if processName.startswith('.'): return elif processName.startswith(':'): return elif oldPackageName in processName: processName = processName.replace(oldPackageName, newPackageName) node.attrib[keyProcess] = processName def modifyComponentAuthorities(node): '''将Authorities中的旧包名替换为新包名''' if keyAuthorities not in node.attrib: return authorities = node.attrib[keyAuthorities] log_utils.getLogger().debug( "origin authorities = {}".format(authorities)) authorities = authorities.replace(oldPackageName, newPackageName) log_utils.getLogger().debug("new authorities = %s" % authorities) node.attrib[keyAuthorities] = authorities if applicationNode != None: # 重名名Application节点本身android:name modifyComponentName(applicationNode) # 重命名四大组件 activityList = applicationNode.findall('activity') if activityList != None and len(activityList) > 0: for node in activityList: modifyComponentName(node) modifyComponentProcess(node) modifyComponentAuthorities(node) serviceList = applicationNode.findall('service') if serviceList != None and len(serviceList) > 0: for node in serviceList: modifyComponentName(node) modifyComponentProcess(node) modifyComponentAuthorities(node) receiverList = applicationNode.findall('receiver') if receiverList != None and len(receiverList) > 0: for node in receiverList: modifyComponentName(node) modifyComponentProcess(node) modifyComponentAuthorities(node) providerList = applicationNode.findall('provider') if providerList != None and len(providerList) > 0: for node in providerList: modifyComponentName(node) modifyComponentProcess(node) modifyComponentAuthorities(node) root.attrib['package'] = newPackageName prettyXml(root) targetTree.write(manifest, 'UTF-8') log_utils.getLogger().debug('renameManifestPackage done') return True