sdk_script.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import file_utils
  2. import xml_utils
  3. import package_utils
  4. import os.path
  5. import xml.etree.ElementTree as ET
  6. namespaces = {'android' : 'http://schemas.android.com/apk/res/android'}
  7. encoding = 'UTF-8'
  8. def execute(game, sdk, config):
  9. if not checkConfig(config):
  10. return 1
  11. subChannel = config['subChannel']
  12. createJmhyProperties(game, sdk, subChannel, config)
  13. createProperties(game, sdk, subChannel, config)
  14. orientation = getScreenOrientation(game, sdk, subChannel, config)
  15. if orientation is None:
  16. orientation = 'landscape'
  17. config['screenOrientation'] = orientation
  18. changePlaceholders(game, sdk, subChannel, config)
  19. if config['addLauncher']:
  20. ret = addLauncher(game, sdk, subChannel, config)
  21. if ret:
  22. return ret
  23. return copyWechatCode(game, sdk, subChannel, config)
  24. def checkConfig(config):
  25. '''
  26. 检查配置
  27. '''
  28. if 'properties' not in config:
  29. print('properties not exists in config')
  30. return False
  31. if 'ysdk' not in config:
  32. print('ysdk not exists in config')
  33. return False
  34. properties = config['properties']
  35. if 'agent' not in properties or 'version' not in properties:
  36. print('agent or version not exists in properties')
  37. return False
  38. '''if 'appid' not in config or 'appkey' not in config:
  39. print('appid or appkey not exists in config')
  40. return False'''
  41. return True
  42. def createJmhyProperties(game, sdk, subChannel, config):
  43. '''
  44. 创建jmhy.properties
  45. '''
  46. print('create jmhy.properties')
  47. propValue = config['properties']
  48. decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
  49. properties = os.path.join(decompliePath, 'assets', 'jmhy.properties')
  50. content = ''
  51. for key in propValue:
  52. content = '%s%s=%s\n' % (content, key, propValue[key])
  53. file_utils.createFile(properties, content)
  54. return 0
  55. def createProperties(game, sdk, subChannel, config):
  56. '''
  57. 创建ysdkconf.ini
  58. '''
  59. print('create ysdkconf.ini')
  60. ysdkConfig = config['ysdk']
  61. decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
  62. properties = os.path.join(decompliePath, 'assets', 'ysdkconf.ini')
  63. content = ''
  64. for key in ysdkConfig:
  65. content = '%s%s=%s\n' % (content, key, ysdkConfig[key])
  66. file_utils.createFile(properties, content)
  67. return 0
  68. def copyWechatCode(game, sdk, subChannel, config):
  69. '''
  70. 拷贝微信sdk的代码
  71. '''
  72. print('copy WXEntryActivity.smali')
  73. sdkPath = file_utils.getFullSDKPath(sdk)
  74. WXEntryActivity = 'WXEntryActivity.smali'
  75. wxFile = os.path.join(sdkPath, 'smali', WXEntryActivity)
  76. decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
  77. smaliPath = os.path.join(decompliePath, 'smali')
  78. targetPath = file_utils.getPackagePath(smaliPath, config['packageName'])
  79. targetFile = os.path.join(targetPath, 'wxapi', WXEntryActivity)
  80. ret = file_utils.copyFile(wxFile, targetFile)
  81. if ret:
  82. return ret
  83. file_utils.replaceContent(targetFile, '${packageName}', config['packageName'].replace('.', '/'))
  84. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  85. changeLauncherLaunchMode(manifest)
  86. xml_utils.changeLauncherAttr(manifest, 'configChanges', 'orientation|screenSize|keyboardHidden')
  87. return 0
  88. def addLauncher(game, sdk, subChannel, config):
  89. '''
  90. 添加启动图
  91. '''
  92. channelPath = file_utils.getSubChannelPath(game, sdk, subChannel)
  93. splashPath = os.path.join(channelPath, 'splash')
  94. if len(os.listdir(splashPath)) == 0:
  95. print('dir splash is empty')
  96. return 0
  97. print('add launcher...')
  98. decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
  99. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  100. activity = xml_utils.getLauncherActivityName(manifest)
  101. if activity == 'com.inner.sdk.ui.YsdkLauncherActivity':
  102. print('add launcher already exist...')
  103. return 1
  104. # 添加关联资源
  105. internalPath = file_utils.getFullInternalPath()
  106. ret = package_utils.copyAppResWithType(decompliePath, internalPath, 'launcher_res')
  107. if ret:
  108. return ret
  109. # 修改主文件信息
  110. print('change launcher config...')
  111. activity = xml_utils.removeLauncherActivity(manifest)
  112. xml_utils.addLauncherActivity(manifest, config['screenOrientation'], 'com.inner.sdk.ui.YsdkLauncherActivity')
  113. # 修改跳转的
  114. launcherActivity = os.path.join(decompliePath, 'smali', 'com', 'inner', 'sdk', 'ui', 'YsdkLauncherActivity.smali')
  115. file_utils.replaceContent(launcherActivity, '{class}', activity)
  116. print('change launcher %s to %s' % (activity, 'com.inner.sdk.ui.YsdkLauncherActivity'))
  117. if 'launcherTime' in config:
  118. timeHex = package_utils.formatHex(config['launcherTime'])
  119. file_utils.replaceContent(launcherActivity, '0x0BB8', timeHex)
  120. return 0
  121. def changeLauncherLaunchMode(manifest):
  122. '''
  123. 修改启动的activity的launchMode
  124. '''
  125. for key in namespaces:
  126. ET.register_namespace(key, namespaces[key])
  127. tree = ET.parse(manifest)
  128. root = tree.getroot()
  129. launcherActivity = xml_utils.getLauncherActivity(root)
  130. if launcherActivity is None:
  131. return 1
  132. attrName = xml_utils.getNamespacesFormat('android:launchMode', namespaces)
  133. if attrName not in launcherActivity.attrib or 'standard' == launcherActivity.attrib[attrName]:
  134. launcherActivity.attrib[attrName] = 'singleTop'
  135. tree.write(manifest, encoding)
  136. return 0
  137. def getScreenOrientation(game, sdk, subChannel, config):
  138. decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
  139. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  140. return getLauncherAttr(manifest, 'screenOrientation')
  141. def getLauncherAttr(manifest, attrType):
  142. '''
  143. 获取启动的activity的属性
  144. '''
  145. for key in namespaces:
  146. ET.register_namespace(key, namespaces[key])
  147. tree = ET.parse(manifest)
  148. root = tree.getroot()
  149. launcherActivity = xml_utils.getLauncherActivity(root)
  150. if launcherActivity is None:
  151. return None
  152. attrName = xml_utils.getNamespacesFormat('android:%s' % attrType, namespaces)
  153. if attrName in launcherActivity.attrib:
  154. return launcherActivity.attrib[attrName]
  155. return None
  156. def changePlaceholders(game, sdk, subChannel, config):
  157. decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
  158. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  159. file_utils.replaceContent(manifest, '${screenOrientation}', config['screenOrientation'])