123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651 |
- import hashlib
- import os
- import os.path
- import platform
- import shutil
- import subprocess
- import sys
- def getFullToolPath(name):
- '''
- 获取工具的目录
- '''
- return get_full_path('tools', name)
- def getFullGameApk(name):
- '''
- 获取游戏的原始包
- '''
- return get_full_path('game', name, name + '.apk')
- def get_cache_game_apk(game, random, sdk):
- """
- 获取游戏的原始包
- """
- return get_full_path('game', game, sdk, random, game + '.apk')
- def get_full_sdk_path(sdk):
- """
- 获取sdk的目录
- """
- return get_full_path('sdk', sdk)
- def get_full_log_sdk_path(sdk, is_beta=False):
- """
- 获取logSdk的目录
- """
- if is_beta:
- return get_full_path('log_sdk_beta', sdk)
- else:
- return get_full_path('log_sdk', sdk)
- def get_full_log_sdk_v2_path(sdk, is_beta=False):
- """
- 获取logSdk的目录
- """
- if is_beta:
- return get_full_path('log_sdk_v2_beta', sdk)
- else:
- return get_full_path('log_sdk_v2', sdk)
- def getFullOaidSDKPath(version):
- """
- 获取oaid_sdk的目录
- """
- return get_full_path('oaid_sdk', version)
- def get_decompile_path(game, sdk, sub_channel, cache):
- """
- 获取解包的目录
- """
- return get_full_path('gen', game, sdk, sub_channel, cache)
- def getSubChannelPath(game, sdk, sub_channel):
- '''
- 获取子渠道的目录
- '''
- return get_full_path('game', game, sdk, sub_channel)
- def getSubChannelPath(game, sdk, tag, subChannel):
- """
- 获取子渠道的目录
- """
- return get_full_path('game', game, sdk, tag, subChannel)
- def getChannelPath(game, sdk):
- '''
- 获取渠道的目录
- '''
- return get_full_path('game', game, sdk)
- def getChannelPath(game, tag, sdk):
- """
- 获取渠道的目录
- """
- return get_full_path('game', game, sdk, tag)
- def get_full_game_path(game):
- """
- 获取游戏的目录
- """
- return get_full_path('game', game)
- def getFullInternalPath():
- """
- 获取内部目录
- """
- return os.path.join(get_current_path(), 'internal')
- def get_full_path(gen, *name):
- path = os.path.join(get_current_path(), gen)
- for n in name:
- path = os.path.join(path, str(n))
- return path
- def get_current_path():
- """
- 当前目录
- """
- return sys.path[0]
- def exec_format_cmd(cmd, cd=None):
- """
- 执行cmd命令
- 返回值:None —— 子进程尚未结束;
- ==0 —— 子进程正常退出;
- > 0—— 子进程异常退出,return code对应于出错码;
- < 0—— 子进程被信号杀掉了。
- """
- '''print(cmd)
- p = os.popen(cmd)
- print(p.read())'''
- ret = 0
- try:
- s = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=cd)
- std_output, err_output = s.communicate()
- if platform.system() == 'Windows':
- std_output = std_output.decode('gbk')
- err_output = err_output.decode('gbk')
- '''
- None —— 子进程尚未结束;
- ==0 —— 子进程正常退出;
- > 0—— 子进程异常退出,return code对应于出错码;
- < 0—— 子进程被信号杀掉了。
- '''
- ret = s.returncode
- if ret:
- print('*******ERROR*******')
- print(std_output)
- print(err_output)
- print('*******************')
- cmd = 'error::' + cmd + ' !!!exec Fail!!! '
- else:
- print(std_output)
- print(err_output)
- cmd = cmd + ' !!!exec success!!! '
- print(cmd)
- except Exception as e:
- print('Exception ' + e)
- return 1
- return ret
- def exec_jar_cmd(jar, params):
- """
- 执行jar
- """
- return exec_format_cmd('java -jar "%s" %s' % (jar, params))
- def copy_file_all_dir(from_dir, to_dir, delete=False, support=None):
- """
- 拷贝目录下所有文件文件
- """
- ret = copy_dir(from_dir, to_dir, delete, support)
- if ret:
- return ret
- if delete:
- delete_folder(from_dir)
- return 0
- def copy_dir(from_dir, to_dir, delete=False, support=None):
- """
- 拷贝目录下所有文件文件
- """
- # print('copy all file %s --> %s' % (fromDir, toDir))
- if not os.path.exists(from_dir):
- print('%s not exists!' % from_dir)
- return 1
- if not os.path.isdir(from_dir):
- print('%s not a dir!' % from_dir)
- return 1
- for fromFile in os.listdir(from_dir):
- from_file_path = os.path.join(from_dir, fromFile)
- to_file_path = os.path.join(to_dir, fromFile)
- if os.path.isdir(from_file_path):
- # 不支持的类型
- if support is not None and fromFile not in support:
- continue
- ret = copy_dir(from_file_path, to_file_path, delete, support)
- if ret:
- return ret
- else:
- ret = copy_file(from_file_path, to_file_path, delete)
- if ret:
- return ret
- return 0
- def copy_file(from_file, to_file, delete=False):
- """
- 拷贝文件
- """
- if not os.path.isfile(from_file):
- print('----> %s not a file!' % from_file)
- return 1
- # 分离文件名和路径
- file_path, file_name = os.path.split(to_file)
- if not os.path.exists(file_path):
- # 创建路径
- os.makedirs(file_path)
- if delete:
- # 移动文件
- shutil.move(from_file, to_file)
- else:
- # 复制文件
- shutil.copyfile(from_file, to_file)
- return 0
- def replace_content(file, old_txt, new_txt):
- """
- 全局替换
- """
- with open_file(file, 'r+') as f:
- t = f.read()
- t = t.replace(old_txt, new_txt)
- # 读写偏移位置移到最开始处
- f.seek(0, 0)
- # 清空内容
- f.truncate()
- f.write(t)
- def read_file(file):
- """
- 读取文件内容
- """
- content = ''
- with open_file(file, 'r') as f:
- content = f.read()
- return content
- def create_file(file, content):
- """
- 创建文件
- """
- file_path, file_name = os.path.split(file) # 分离文件名和路径
- if not os.path.exists(file_path):
- os.makedirs(file_path)
- with open_file(file, 'w') as f:
- f.write(content)
- f.close()
- def open_file(file, mode):
- return open(file, mode, encoding='UTF-8')
- def delete_folder(folder):
- """
- 删除目录以及目录下的文件
- """
- if not os.path.exists(folder):
- return
- shutil.rmtree(folder)
- def get_aapt_path():
- """
- 获取aapt
- """
- return getToolWithSystem('aapt')
- def get_aapt2_path():
- """
- 获取aapt2
- """
- return getToolWithSystem('aapt2')
- def get_android_compile_tool_path():
- """
- 获取android.jar
- """
- return getFullToolPath('android.jar')
- def get_dx_path():
- """
- 获取dx.jar
- """
- return getFullToolPath('dx.jar')
- def get_d8_path():
- """
- 获取d8.jar
- """
- return getFullToolPath('d8.jar')
- def get_zipalign_path():
- """
- 获取zipalign
- """
- return getToolWithSystem('zipalign')
- def get_multidex_path():
- """
- 获取multidex.jar
- """
- return getFullToolPath('android-support-multidex.jar')
- def get_apktool_path():
- """
- 获取apktool.jar
- """
- return getFullToolPath('apktool_2.6.0.jar')
- def get_baksmali_path():
- """
- 获取baksmali.jar
- """
- return getFullToolPath('baksmali-2.3.jar')
- def get_apksigner_path():
- '''
- 获取apksigner.jar
- '''
- return getFullToolPath('apksigner.jar')
- def getWallePath():
- '''
- 获取walle-cli-all.jar
- '''
- return getFullToolPath('walle-cli-all.jar')
- def getOutApkPath(game, sdk, subChannel, cache):
- '''
- 获取输出的apk的目录
- '''
- return get_full_path('target', game, sdk, cache, '%s_%s_%s.apk' % (game, sdk, subChannel))
- def getTargetApkPath(game, sdk, cache):
- '''
- 获取输出的apk的目录
- '''
- return get_full_path('target', game, sdk, cache)
- def getAlignApkPath(game, sdk, subChannel, cache):
- '''
- 获取输出的apk的目录
- '''
- return get_full_path('target', game, sdk, cache, '%s_%s_%s_align.apk' % (game, sdk, subChannel))
- def get_signed_apk_path(game, sdk, sub_channel, cache):
- """
- 获取输出的apk的目录
- """
- return get_full_path('target', game, sdk, cache, '%s_%s_%s_signed.apk' % (game, sdk, sub_channel))
- def getWalleApkPath(game, sdk, subChannel, cache):
- """
- 获取输出的apk的目录
- """
- return get_full_path('target', game, sdk, cache, '%s_%s_%s_walled.apk' % (game, sdk, subChannel))
- def getRenameApkPath(game, sdk, cache, name):
- '''
- 重命名输出的apk名称
- '''
- return get_full_path('target', game, sdk, cache, '%s.apk' % name)
- def getSignApkPath(game, sdk, subChannel, cache):
- '''
- 获取输出的apk的目录
- '''
- return get_full_path('target', game, sdk, cache, '%s_%s_%s_signed.apk' % (game, sdk, subChannel))
- def get_package_path(basePath, packageName):
- '''
- 包名对应的目录
- '''
- packageNameSplit = packageName.split('.')
- newPath = basePath
- for item in packageNameSplit:
- newPath = os.path.join(newPath, item)
- return newPath
- def getToolWithSystem(tool):
- '''
- 获取系统相关工具
- '''
- system = getSystemPath()
- suffix = getSystemSuffix()
- return os.path.join(getFullToolPath(system), tool + suffix)
- def getSystemPath():
- '''
- 获取系统目录
- '''
- if platform.system() == 'Windows':
- return 'win'
- elif platform.system() == 'Darwin':
- print('---------macos----------')
- return 'macos'
- else:
- return 'linux'
- def getSystemSuffix():
- """
- 系统工具后缀
- """
- if platform.system() == 'Windows':
- return '.exe'
- else:
- return ''
- def get_application_smali_index(file):
- """
- 获取application.smali的MultiDex信息
- """
- content = ('invoke-super', '->attachBaseContext(Landroid/content/Context;)V')
- index = -1
- with open_file(file, 'r') as f:
- line = f.readline()
- while line:
- if content[0] in line and content[1] in line:
- index = f.tell()
- break
- line = f.readline()
- return index
- def insert_application_smali(file, index):
- """
- 获取application.smali插入MultiDex的信息
- """
- if index == -1:
- # append
- content = '''# virtual methods
- .method protected attachBaseContext(Landroid/content/Context;)V
- .locals 0
- .param p1, "context" # Landroid/content/Context;
- invoke-super {p0, p1}, Landroid/app/Application;->attachBaseContext(Landroid/content/Context;)V
- invoke-static {p0}, Landroid/support/multidex/MultiDex;->install(Landroid/content/Context;)V
- return-void
- .end method'''
- with open_file(file, 'a') as f:
- f.write(content)
- else:
- # insert
- content = '\n\tinvoke-static {p0}, Landroid/support/multidex/MultiDex;->install(Landroid/content/Context;)V\n'
- with open_file(file, 'r+') as f:
- f.seek(index)
- last = f.read()
- f.seek(index)
- f.write(content)
- f.write(last)
- return 0
- def changeVersion(yml, versionCode=None, versionName=None, targetSdkVersion=None):
- if versionCode is None and versionName is None and targetSdkVersion is None:
- return 0
- tag = ['versionCode:', 'versionName:', 'targetSdkVersion:']
- with open_file(yml, 'r+') as f:
- content = ''
- line = f.readline()
- while line:
- if versionCode is not None and tag[0] in line:
- content += ' versionCode: \'%s\'\n' % versionCode
- elif versionName is not None and tag[1] in line:
- content += ' versionName: %s\n' % versionName
- elif targetSdkVersion is not None and tag[2] in line:
- content += ' targetSdkVersion: \'%s\'\n' % targetSdkVersion
- else:
- content += line
- line = f.readline()
- f.seek(0, 0)
- f.truncate()
- f.write(content)
- return 0
- def change_min_sdk_version(yml, min_sdk_version):
- with open_file(yml, 'r+') as f:
- content = ''
- line = f.readline()
- while line:
- if 'minSdkVersion' in line:
- start = line.index("'")
- version = int(line[start + 1:-2])
- if version < min_sdk_version:
- content += ' minSdkVersion: \'%s\'\n' % min_sdk_version
- else:
- return 0
- else:
- content += line
- line = f.readline()
- f.seek(0, 0)
- f.truncate()
- f.write(content)
- return 0
- def list_files(src, res_files):
- """
- 列出目录下所有的文件
- """
- if os.path.exists(src):
- if os.path.isfile(src):
- res_files.append(src)
- elif os.path.isdir(src):
- for f in os.listdir(src):
- list_files(os.path.join(src, f), res_files)
- return res_files
- def get_file_md5(f):
- """
- 获取文件的md5
- """
- m = hashlib.md5()
- while True:
- data = f.read(1024) # 将文件分块读取
- if not data:
- break
- m.update(data)
- return m.hexdigest()
- def equals_file(file1, file2):
- """
- 比较两个文件是否是同一个文件
- """
- with open(file1, 'rb') as f1, open(file2, 'rb') as f2:
- file1Md5 = get_file_md5(f1)
- file2Md5 = get_file_md5(f2)
- # print('file1Md5:',file1Md5)
- # print('file2Md5:',file2Md5)
- return file1Md5 == file2Md5
- def get_exec_permission(file):
- """
- linux下获取执行权限
- """
- if platform.system() == 'Windows':
- return 0
- return exec_format_cmd('chmod +x "%s"' % file)
- def copy_sdk_smali_code(game, sdk, sub_channel, config):
- """
- 拷贝代码
- """
- print('copy sdk smali code --> %s' % sdk)
- sdkPath = get_full_sdk_path(sdk)
- xmyFile = os.path.join(sdkPath, 'smali')
- decompliePath = get_decompile_path(game, sdk, sub_channel, config['cache'])
- smaliPath = os.path.join(decompliePath, 'smali')
- ret = copy_dir(xmyFile, smaliPath)
- return ret
- def copy_game_smali_code(game, sdk, sub_channel, config):
- """
- 拷贝代码
- """
- print('copy game smali code --> %s' % sdk)
- if not config['aapt2disable']:
- print('aapt2disable = false ~~~')
- return 0
- path = os.path.join(get_current_path(), "game_script", game, "gameSmali")
- print('copyDir = gameSmali~~~')
- decompliePath = get_decompile_path(game, sdk, sub_channel, config['cache'])
- smaliPath = os.path.join(decompliePath, 'smali')
- ret = copy_dir(path, smaliPath)
- return ret
|