123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- import file_utils
- import common_utils
- import xml_utils
- import os.path
- import xml.etree.ElementTree as ET
- import zipfile
- namespaces = {'android' : 'http://schemas.android.com/apk/res/android'}
- encoding = 'UTF-8'
- def execute(game, sdk, config):
- if not checkConfig(config):
- return 1
- subChannel = config['subChannel']
- createJmhyProperties(game, sdk, subChannel, config)
- createEjyxProperties(game, sdk, subChannel, config)
- #ret = deleteSplash(game, sdk, subChannel, config)
- ret = generateV7RFile(game, sdk, subChannel, config)
- if ret:
- return ret
- common_utils.changeApplication(game, sdk, subChannel, config, 'com.ejyx.common.EJYXApplication')
- return 0
- def checkConfig(config):
- '''
- 检查配置
- '''
- if 'properties' not in config:
- print('properties not exists in config')
- return False
- properties = config['properties']
-
- if 'agent' not in properties or 'version' not in properties:
- print('agent or version not exists in properties')
- return False
- '''if 'appid' not in config or 'appkey' not in config:
- print('appid or appkey not exists in config')
- return False'''
- return True
- def createJmhyProperties(game, sdk, subChannel, config):
- '''
- 创建jmhy.properties
- '''
- print('create jmhy.properties')
- propValue = config['properties']
- decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
- properties = os.path.join(decompliePath, 'assets', 'jmhy.properties')
- content = ''
- for key in propValue:
- content = '%s%s=%s\n' % (content, key, propValue[key])
- file_utils.createFile(properties, content)
- return 0
- def createEjyxProperties(game, sdk, subChannel, config):
- '''
- 创建jmhy.properties
- '''
- print('创建 ejyx.properties ......')
- decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
- properties = os.path.join(decompliePath, 'assets', 'ejyx.properties')
- content = 'version=1.1\n'
- content = '%s%s=%s\n' % (content, 'agent', config['channel_id'])
- file_utils.createFile(properties, content)
- return 0
- def deleteSplash(game, sdk, subChannel, config):
- '''
- 删除闪屏
- '''
- if game != 'wzjh':
- return 0
- channelPath = file_utils.getSubChannelPath(game, sdk, subChannel)
- print('delete Splash...')
- decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
- manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
- activity = xml_utils.getLauncherActivityName(manifest)
- activity = xml_utils.removeLauncherActivity(manifest)
- xml_utils.deleteActivityByName(manifest,'com.hugenstar.nanobox.NaNoUnityContext')
- addLauncherActivity(manifest, config['screenOrientation'], 'com.hugenstar.nanobox.NaNoUnityContext')
- return 0
- def addLauncherActivity(manifest, screenOrientation, activity):
- '''
- 添加启动的activity
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- # activity
- '''<activity android:name=".LauncherActivity"
- android:theme="@style/LauncherStyle">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>'''
- activity = ET.Element('activity', {'android:name' : activity,
- 'android:theme' : '@android:style/Theme.Holo.Light.NoActionBar.Fullscreen',
- 'android:launchMode' : 'singleTop',
- 'android:configChanges' : 'orientation|screenSize|keyboardHidden',
- 'android:screenOrientation' : screenOrientation})
- intent = ET.Element('intent-filter')
- action = ET.Element('action', {'android:name' : 'android.intent.action.MAIN'})
- category = ET.Element('category', {'android:name' : 'android.intent.category.LAUNCHER'})
- intent.append(action)
- intent.append(category)
- activity.append(intent)
- intent2 = ET.Element('intent-filter')
- category = ET.Element('category', {'android:name' : 'android.intent.category.LEANBACK_LAUNCHER'})
- intent2.append(category)
- activity.append(intent2)
- application = root.find('application')
- application.insert(0, activity)
- tree.write(manifest, encoding)
- def generateV7RFile(game, sdk, subChannel, config):
- '''
- 生成新的R文件
- '''
- decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
- androidPlatforms = file_utils.getAndroidCompileToolPath()
- manifest = os.path.join(decompliePath, 'assets','AndroidManifest.xml')
- decomplieResPath = file_utils.getFullPath(decompliePath, 'res')
- compliePath = file_utils.getFullPath(decompliePath, 'gen')
- if not os.path.exists(compliePath):
- os.makedirs(compliePath)
- # 生成R文件
- print('生成R文件 ...')
- if config['aapt2disable']:
- aapt = file_utils.getAAPTPath()
- ret = file_utils.getExecPermission(aapt)
- if ret:
- return ret
- createRCmd = '"%s" p -f -m -J "%s" -S "%s" -I "%s" -M "%s"' % (aapt, compliePath, decomplieResPath, androidPlatforms, manifest)
- ret = file_utils.execFormatCmd(createRCmd)
- if ret:
- return ret
- else:
- # compile
- aapt = file_utils.getAAPT2Path()
- ret = file_utils.getExecPermission(aapt)
- if ret:
- return ret
- print('compiled res ...')
- complieResPath = os.path.join(compliePath, 'compiled')
- complieResCmd = '"%s" compile --dir "%s" -o "%s"' % (aapt, decomplieResPath, complieResPath)
- file_utils.execFormatCmd(complieResCmd)
- # unzip
- print('unzip compiled res ...')
- unzipResPath = os.path.join(compliePath, 'aapt2_res')
- with zipfile.ZipFile(complieResPath) as zf:
- zf.extractall(unzipResPath)
- print('create unzip %s' % unzipResPath)
- # link
- print('link res ...')
- outApk = os.path.join(compliePath, 'res.apk')
- linkResCmd = '"%s" link -o "%s" -I "%s" --manifest "%s" --java "%s" --auto-add-overlay' % (aapt, outApk, androidPlatforms, manifest, compliePath)
- for filename in os.listdir(unzipResPath):
- linkResCmd += ' %s' % filename
- print('link cmd len is %s' % len(linkResCmd))
- ret = file_utils.execFormatCmd(linkResCmd, unzipResPath)
- if ret:
- return ret
- # 编译R文件
- print('complie R.java ...')
- packageName = xml_utils.getPackageName(manifest)
- packagePath = file_utils.getPackagePath(compliePath, packageName)
- RSourceFile = os.path.join(packagePath, 'R.java')
- complieRCmd = 'javac -source 1.8 -target 1.8 -encoding UTF-8 "%s"' % RSourceFile
- ret = file_utils.execFormatCmd(complieRCmd)
- if ret:
- return ret
- # 生成dex
- print('dex R.class ...')
- outDex = os.path.join(compliePath, 'classes.dex')
- if config['aapt2disable']:
- dx = file_utils.getDxPath()
- dexCmd = '--dex --no-warning --output="%s" "%s"' % (outDex, compliePath)
- else:
- dx = file_utils.getD8Path()
- clazz = os.path.join(packagePath, '*.class')
- dexCmd = '--lib "%s" --output "%s" %s' % (androidPlatforms, compliePath, clazz)
- ret = file_utils.execJarCmd(dx, dexCmd)
- if ret:
- return ret
- # 反向dex生成smali
- # 存放在out目录
- print('baksmali classes.dex ...')
- baksmaliPath = file_utils.getBaksmaliPath()
- outPath = file_utils.getFullPath(decompliePath, 'out')
- ret = file_utils.execJarCmd(baksmaliPath, 'd "%s" -o "%s"' % (outDex, outPath))
- if ret:
- return ret
- # 将生成的文件拷贝到目标目录
- print('copy R.smali ...')
- smaliPath = file_utils.getFullPath(decompliePath, 'smali')
- file_utils.copyFileAllDir(outPath, smaliPath)
- return 0
|