242 lines
12 KiB
Python
242 lines
12 KiB
Python
# coding:utf-8
|
|
import json
|
|
|
|
import os
|
|
|
|
import shutil
|
|
|
|
from core.config import settings
|
|
|
|
|
|
class MakeTool:
|
|
MakeDir = os.path.join(settings.ROOT_DIR, 'ApkTool')
|
|
|
|
def __init__(self, channel_path):
|
|
self.channel_path = channel_path
|
|
self.apkName = ''
|
|
self.apkNameSuffix = '0'
|
|
self.easyName = ''
|
|
self.easyNameSuffix = '0'
|
|
self.packageId = ''
|
|
self.packageIdSuffix = '0'
|
|
self.keystore = ''
|
|
self.storepass = ''
|
|
self.alianame = ''
|
|
self.keypass = ''
|
|
self.owner = ''
|
|
self.packNum = 0
|
|
self.start = 0
|
|
self.appid = ''
|
|
self.gism_id = ''
|
|
self.gism_name = ''
|
|
self.gism_channel = ''
|
|
self.lg_ad_id = ''
|
|
self.lg_ad_name = ''
|
|
self.gactionId = ''
|
|
self.gappSecretKey = ''
|
|
self.baiduId = ''
|
|
self.baiduSecretKey = ''
|
|
self.lg_reyun_game_appkey = ''
|
|
self.lg_reyun_game_channelId = ''
|
|
self.lg_reyun_io_appkey = ''
|
|
self.lg_reyun_io_channelId = ''
|
|
self.eventType = ''
|
|
self.master_package = ''
|
|
|
|
def _init_props(self):
|
|
# 提取参数
|
|
props = dict()
|
|
with open(self.channel_path, 'r') as f:
|
|
props = json.load(f)
|
|
# 母包路径
|
|
self.apkName = props.get('apkname', {}).get('value') or self.apkName
|
|
self.apkNameSuffix = props.get('apkname', {}).get('suffix') or self.apkNameSuffix
|
|
|
|
self.easyName = props.get('leguChannel', {}).get('value') or self.easyName
|
|
self.easyNameSuffix = props.get('leguChannel', {}).get('suffix') or self.easyNameSuffix
|
|
|
|
self.packageId = props.get('packageId', {}).get('value') or self.packageId
|
|
self.packageIdSuffix = props.get('packageId', {}).get('suffix') or self.packageIdSuffix
|
|
|
|
self.keystore = props.get('keystore', {}).get('filename') or self.keystore
|
|
self.storepass = props.get('keystore', {}).get('storepass') or self.storepass
|
|
self.alianame = props.get('keystore', {}).get('alianame') or self.alianame
|
|
self.keypass = props.get('keystore', {}).get('keypass') or self.keypass
|
|
|
|
self.owner = props.get('owner', {}).get('value') or self.owner
|
|
|
|
self.packNum = props.get('num', {}).get('value') or self.packNum
|
|
self.start = props.get('num', {}).get('start') or self.start
|
|
self.start = int(self.start)
|
|
self.packNum = int(self.packNum) + self.start
|
|
|
|
self.appid = props.get('appid', {}).get('value') or self.appid
|
|
self.gism_id = props.get('gism_id', {}).get('value') or self.gism_id
|
|
self.gism_name = props.get('gism_name', {}).get('value') or self.gism_name
|
|
self.gism_channel = props.get('gism_channel', {}).get('value') or self.gism_channel
|
|
self.lg_ad_id = props.get('lg_ad_id', {}).get('value') or self.lg_ad_id
|
|
self.lg_ad_name = props.get('lg_ad_name', {}).get('value') or self.lg_ad_name
|
|
self.gactionId = props.get('gactionId', {}).get('value') or self.gactionId
|
|
self.gappSecretKey = props.get('gappSecretKey', {}).get('value') or self.gappSecretKey
|
|
self.baiduId = props.get('baiduId', {}).get('value') or self.baiduId
|
|
self.baiduSecretKey = props.get('baiduSecretKey', {}).get('value') or self.baiduSecretKey
|
|
self.lg_reyun_game_appkey = props.get('lg_reyun_game_appkey', {}).get('value') or self.lg_reyun_game_appkey
|
|
self.lg_reyun_game_channelId = props.get('lg_reyun_game_channelId', {}).get(
|
|
'value') or self.lg_reyun_game_channelId
|
|
self.lg_reyun_io_appkey = props.get('lg_reyun_io_appkey', {}).get('value') or self.lg_reyun_io_appkey
|
|
self.lg_reyun_io_channelId = props.get('lg_reyun_io_channelId', {}).get('value') or self.lg_reyun_io_channelId
|
|
self.eventType = props.get('eventType', {}).get('value') or self.eventType
|
|
|
|
self.master_package = props.get('master_package', {}).get('value') or self.master_package
|
|
|
|
def _init_path(self):
|
|
bin_dir = os.path.join(self.MakeDir, 'bin')
|
|
if os.path.exists(bin_dir):
|
|
shutil.rmtree(bin_dir)
|
|
os.makedirs(bin_dir)
|
|
|
|
def check_props(self):
|
|
if self.packNum < 1:
|
|
return False, '打包数不能小于1'
|
|
|
|
if not os.path.exists(self.master_package):
|
|
return False, '缺少母包路径'
|
|
|
|
if not os.path.exists(self.keystore):
|
|
return False, '缺少keystore路径'
|
|
|
|
if self.easyName:
|
|
self.apkName = self.easyName
|
|
|
|
return True, 'ok'
|
|
|
|
def modify_channel(self, value):
|
|
tempXML = ''
|
|
with open(os.path.join(self.MakeDir, 'AndroidManifest.xml')) as f:
|
|
for line in f:
|
|
if line.find('leguChannel') > 0 and self.easyName != '':
|
|
if self.easyNameSuffix == "1":
|
|
|
|
line = '<meta-data android:name="leguChannel" android:value="%s_%d"/>' % (
|
|
self.easyName, value)
|
|
else:
|
|
line = '<meta-data android:name="leguChannel" android:value="%s"/>' % (self.easyName)
|
|
elif line.find('owner') > 0 and self.owner != '':
|
|
print('owner====%s' % line)
|
|
line = '<meta-data android:name="owner" android:value="%s"/>' % (self.owner)
|
|
elif line.find('package') > 0 and self.packageId != '':
|
|
print('package====%s' % line)
|
|
line = '<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:compileSdkVersion="30" android:compileSdkVersionCodename="11" android:installLocation="auto" package="%s" platformBuildVersionCode="30" platformBuildVersionName="11">' % (
|
|
self.packageId)
|
|
elif line.find('appid') > 0 and self.appid != '':
|
|
print('appid====%s' % line)
|
|
line = '<meta-data android:name="appid" android:value="%s"/>' % (self.appid)
|
|
elif line.find('gism_id') > 0 and self.gism_id != '':
|
|
print('gism_id====%s' % line)
|
|
line = '<meta-data android:name="gism_id" android:value="%s"/>' % (self.gism_id)
|
|
elif line.find('gism_name') > 0 and self.gism_name != '':
|
|
print('gism_name====%s' % line)
|
|
line = '<meta-data android:name="gism_name" android:value="%s"/>' % (self.gism_name)
|
|
elif line.find('gism_channel') > 0 and self.gism_channel != '':
|
|
print('gism_channel====%s' % line)
|
|
line = '<meta-data android:name="gism_channel" android:value="%s"/>' % (self.gism_channel)
|
|
elif line.find('lg_ad_id') > 0 and self.lg_ad_id != '':
|
|
print('lg_ad_id====%s' % line)
|
|
line = '<meta-data android:name="lg_ad_id" android:value="%s"/>' % (self.lg_ad_id)
|
|
elif line.find('lg_ad_name') > 0 and self.lg_ad_name != '':
|
|
print('lg_ad_name====%s' % line)
|
|
line = '<meta-data android:name="lg_ad_name" android:value="%s"/>' % (self.lg_ad_name)
|
|
elif line.find('gactionId') > 0 and self.gactionId != '':
|
|
print('gactionId====%s' % line)
|
|
line = '<meta-data android:name="gactionId" android:value="%s"/>' % (self.gactionId)
|
|
elif line.find('gappSecretKey') > 0 and self.gappSecretKey != '':
|
|
print('gappSecretKey====%s' % line)
|
|
line = '<meta-data android:name="gappSecretKey" android:value="%s"/>' % (self.gappSecretKey)
|
|
elif line.find('baiduId') > 0 and self.baiduId != '':
|
|
print('baiduId====%s' % line)
|
|
line = '<meta-data android:name="baiduId" android:value="%s"/>' % (self.baiduId)
|
|
elif line.find('baiduSecretKey') > 0 and self.baiduSecretKey != '':
|
|
print('baiduSecretKey====%s' % line)
|
|
line = '<meta-data android:name="baiduSecretKey" android:value="%s"/>' % (self.baiduSecretKey)
|
|
elif line.find('lg_reyun_game_appkey') > 0 and self.lg_reyun_game_appkey != '':
|
|
print('lg_reyun_game_appkey====%s' % line)
|
|
line = '<meta-data android:name="lg_reyun_game_appkey" android:value="%s"/>' % (
|
|
self.lg_reyun_game_appkey)
|
|
elif line.find('lg_reyun_game_channelId') > 0 and self.lg_reyun_game_channelId != '':
|
|
print('lg_reyun_game_channelId====%s' % line)
|
|
line = '<meta-data android:name="lg_reyun_game_channelId" android:value="%s"/>' % (
|
|
self.lg_reyun_game_channelId)
|
|
elif line.find('lg_reyun_io_appkey') > 0 and self.lg_reyun_io_appkey != '':
|
|
print('lg_reyun_io_appkey====%s' % line)
|
|
line = '<meta-data android:name="lg_reyun_io_appkey" android:value="%s"/>' % (
|
|
self.lg_reyun_io_appkey)
|
|
elif line.find('lg_reyun_io_channelId') > 0 and self.lg_reyun_io_channelId != 0:
|
|
print('lg_reyun_io_channelId====%s' % line)
|
|
line = '<meta-data android:name="lg_reyun_io_channelId" android:value="%s"/>' % (
|
|
self.lg_reyun_io_channelId)
|
|
elif line.find('eventType') > 0 and self.eventType != '':
|
|
print('eventType====%s' % line)
|
|
line = '<meta-data android:name="eventType" android:value="%s"/>' % (self.eventType)
|
|
tempXML += line
|
|
|
|
with open(os.path.join(self.MakeDir, 'temp/AndroidManifest.xml'), 'w') as f:
|
|
f.write(tempXML)
|
|
|
|
|
|
unsignApk = os.path.join(self.MakeDir, f'bin/{self.apkName}_{value}_unsigned.apk')
|
|
|
|
cmdPack = f'cd {self.MakeDir} && java -jar apktool.jar b temp -o {unsignApk}'
|
|
os.system(cmdPack)
|
|
|
|
signedjar = os.path.join(self.MakeDir, f'bin/{self.apkName}_{value}.apk')
|
|
unsignedjar = os.path.join(self.MakeDir, f'bin/{self.apkName}_{value}_unsigned.apk')
|
|
|
|
cmd_sign = f'cd {self.MakeDir} && jarsigner -verbose -digestalg SHA1 -sigalg MD5withRSA -keystore {self.keystore} -storepass {self.storepass} -keypass {self.keypass} -signedjar {signedjar} {unsignedjar} {self.alianame}'
|
|
os.system(cmd_sign)
|
|
os.remove(unsignedjar)
|
|
|
|
def _unpack(self, pack_name):
|
|
"""
|
|
解包
|
|
:param pack_name:
|
|
:return:
|
|
"""
|
|
cmd = f'cd {self.MakeDir} && java -jar apktool.jar d -f -s {self.master_package} -o temp'
|
|
os.system(cmd)
|
|
androidmanifest_path = os.path.join(self.MakeDir, 'AndroidManifest.xml')
|
|
if os.path.exists(androidmanifest_path):
|
|
os.remove(androidmanifest_path)
|
|
new_androidmanifest_path = os.path.join(self.MakeDir, 'temp/AndroidManifest.xml')
|
|
shutil.copyfile(new_androidmanifest_path, androidmanifest_path)
|
|
|
|
def _clear(self):
|
|
path = os.path.join(self.MakeDir, 'temp')
|
|
if os.path.exists(path):
|
|
shutil.rmtree(path)
|
|
path = os.path.join(self.MakeDir, 'AndroidManifest.xml')
|
|
if os.path.exists(path):
|
|
os.remove(path)
|
|
|
|
def _make(self):
|
|
"""
|
|
重新编译包
|
|
:return:
|
|
"""
|
|
for i in range(self.start, self.packNum):
|
|
self.modify_channel(i)
|
|
|
|
def run(self):
|
|
try:
|
|
self._init_props()
|
|
self._init_path()
|
|
is_ok, msg = self.check_props()
|
|
if not is_ok:
|
|
return False, msg
|
|
self._unpack(self.master_package)
|
|
self._make()
|
|
self._clear()
|
|
except Exception as e:
|
|
return False, str(e)
|
|
else:
|
|
return True, 'ok'
|