import file_utils import xml_utils import package_utils import os.path import xml.etree.ElementTree as ET 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) createProperties(game, sdk, subChannel, config) orientation = getScreenOrientation(game, sdk, subChannel, config) if orientation is None: orientation = 'landscape' config['screenOrientation'] = orientation changePlaceholders(game, sdk, subChannel, config) if config['addLauncher']: ret = addLauncher(game, sdk, subChannel, config) if ret: return ret return copyWechatCode(game, sdk, subChannel, config) def checkConfig(config): ''' 检查配置 ''' if 'properties' not in config: print('properties not exists in config') return False if 'ysdk' not in config: print('ysdk 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 createProperties(game, sdk, subChannel, config): ''' 创建ysdkconf.ini ''' print('create ysdkconf.ini') ysdkConfig = config['ysdk'] decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache']) properties = os.path.join(decompliePath, 'assets', 'ysdkconf.ini') content = '' for key in ysdkConfig: content = '%s%s=%s\n' % (content, key, ysdkConfig[key]) file_utils.createFile(properties, content) return 0 def copyWechatCode(game, sdk, subChannel, config): ''' 拷贝微信sdk的代码 ''' print('copy WXEntryActivity.smali') sdkPath = file_utils.getFullSDKPath(sdk) WXEntryActivity = 'WXEntryActivity.smali' wxFile = os.path.join(sdkPath, 'smali', WXEntryActivity) decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache']) smaliPath = os.path.join(decompliePath, 'smali') targetPath = file_utils.getPackagePath(smaliPath, config['packageName']) targetFile = os.path.join(targetPath, 'wxapi', WXEntryActivity) ret = file_utils.copyFile(wxFile, targetFile) if ret: return ret file_utils.replaceContent(targetFile, '${packageName}', config['packageName'].replace('.', '/')) manifest = os.path.join(decompliePath, 'AndroidManifest.xml') changeLauncherLaunchMode(manifest) xml_utils.changeLauncherAttr(manifest, 'configChanges', 'orientation|screenSize|keyboardHidden') return 0 def addLauncher(game, sdk, subChannel, config): ''' 添加启动图 ''' channelPath = file_utils.getSubChannelPath(game, sdk, subChannel) splashPath = os.path.join(channelPath, 'splash') if len(os.listdir(splashPath)) == 0: print('dir splash is empty') return 0 print('add launcher...') decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache']) manifest = os.path.join(decompliePath, 'AndroidManifest.xml') activity = xml_utils.getLauncherActivityName(manifest) if activity == 'com.inner.sdk.ui.YsdkLauncherActivity': print('add launcher already exist...') return 1 # 添加关联资源 internalPath = file_utils.getFullInternalPath() ret = package_utils.copyAppResWithType(decompliePath, internalPath, 'launcher_res') if ret: return ret # 修改主文件信息 print('change launcher config...') activity = xml_utils.removeLauncherActivity(manifest) xml_utils.addLauncherActivity(manifest, config['screenOrientation'], 'com.inner.sdk.ui.YsdkLauncherActivity') # 修改跳转的 launcherActivity = os.path.join(decompliePath, 'smali', 'com', 'inner', 'sdk', 'ui', 'YsdkLauncherActivity.smali') file_utils.replaceContent(launcherActivity, '{class}', activity) print('change launcher %s to %s' % (activity, 'com.inner.sdk.ui.YsdkLauncherActivity')) if 'launcherTime' in config: timeHex = package_utils.formatHex(config['launcherTime']) file_utils.replaceContent(launcherActivity, '0x0BB8', timeHex) return 0 def changeLauncherLaunchMode(manifest): ''' 修改启动的activity的launchMode ''' for key in namespaces: ET.register_namespace(key, namespaces[key]) tree = ET.parse(manifest) root = tree.getroot() launcherActivity = xml_utils.getLauncherActivity(root) if launcherActivity is None: return 1 attrName = xml_utils.getNamespacesFormat('android:launchMode', namespaces) if attrName not in launcherActivity.attrib or 'standard' == launcherActivity.attrib[attrName]: launcherActivity.attrib[attrName] = 'singleTop' tree.write(manifest, encoding) return 0 def getScreenOrientation(game, sdk, subChannel, config): decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache']) manifest = os.path.join(decompliePath, 'AndroidManifest.xml') return getLauncherAttr(manifest, 'screenOrientation') def getLauncherAttr(manifest, attrType): ''' 获取启动的activity的属性 ''' for key in namespaces: ET.register_namespace(key, namespaces[key]) tree = ET.parse(manifest) root = tree.getroot() launcherActivity = xml_utils.getLauncherActivity(root) if launcherActivity is None: return None attrName = xml_utils.getNamespacesFormat('android:%s' % attrType, namespaces) if attrName in launcherActivity.attrib: return launcherActivity.attrib[attrName] return None def changePlaceholders(game, sdk, subChannel, config): decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache']) manifest = os.path.join(decompliePath, 'AndroidManifest.xml') file_utils.replaceContent(manifest, '${screenOrientation}', config['screenOrientation'])