sdk_script.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import file_utils
  2. import common_utils
  3. import xml_utils
  4. import os.path
  5. import xml.etree.ElementTree as ET
  6. import zipfile
  7. namespaces = {'android' : 'http://schemas.android.com/apk/res/android'}
  8. encoding = 'UTF-8'
  9. def execute(game, sdk, config):
  10. if not checkConfig(config):
  11. return 1
  12. subChannel = config['subChannel']
  13. createJmhyProperties(game, sdk, subChannel, config)
  14. createEjyxProperties(game, sdk, subChannel, config)
  15. #ret = deleteSplash(game, sdk, subChannel, config)
  16. ret = generateV7RFile(game, sdk, subChannel, config)
  17. if ret:
  18. return ret
  19. common_utils.changeApplication(game, sdk, subChannel, config, 'com.ejyx.common.EJYXApplication')
  20. return 0
  21. def checkConfig(config):
  22. '''
  23. 检查配置
  24. '''
  25. if 'properties' not in config:
  26. print('properties not exists in config')
  27. return False
  28. properties = config['properties']
  29. if 'agent' not in properties or 'version' not in properties:
  30. print('agent or version not exists in properties')
  31. return False
  32. '''if 'appid' not in config or 'appkey' not in config:
  33. print('appid or appkey not exists in config')
  34. return False'''
  35. return True
  36. def createJmhyProperties(game, sdk, subChannel, config):
  37. '''
  38. 创建jmhy.properties
  39. '''
  40. print('create jmhy.properties')
  41. propValue = config['properties']
  42. decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
  43. properties = os.path.join(decompliePath, 'assets', 'jmhy.properties')
  44. content = ''
  45. for key in propValue:
  46. content = '%s%s=%s\n' % (content, key, propValue[key])
  47. file_utils.createFile(properties, content)
  48. return 0
  49. def createEjyxProperties(game, sdk, subChannel, config):
  50. '''
  51. 创建jmhy.properties
  52. '''
  53. print('创建 ejyx.properties ......')
  54. decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
  55. properties = os.path.join(decompliePath, 'assets', 'ejyx.properties')
  56. content = 'version=1.1\n'
  57. content = '%s%s=%s\n' % (content, 'agent', config['channel_id'])
  58. file_utils.createFile(properties, content)
  59. return 0
  60. def deleteSplash(game, sdk, subChannel, config):
  61. '''
  62. 删除闪屏
  63. '''
  64. if game != 'wzjh':
  65. return 0
  66. channelPath = file_utils.getSubChannelPath(game, sdk, subChannel)
  67. print('delete Splash...')
  68. decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
  69. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  70. activity = xml_utils.getLauncherActivityName(manifest)
  71. activity = xml_utils.removeLauncherActivity(manifest)
  72. xml_utils.deleteActivityByName(manifest,'com.hugenstar.nanobox.NaNoUnityContext')
  73. addLauncherActivity(manifest, config['screenOrientation'], 'com.hugenstar.nanobox.NaNoUnityContext')
  74. return 0
  75. def addLauncherActivity(manifest, screenOrientation, activity):
  76. '''
  77. 添加启动的activity
  78. '''
  79. for key in namespaces:
  80. ET.register_namespace(key, namespaces[key])
  81. tree = ET.parse(manifest)
  82. root = tree.getroot()
  83. # activity
  84. '''<activity android:name=".LauncherActivity"
  85. android:theme="@style/LauncherStyle">
  86. <intent-filter>
  87. <action android:name="android.intent.action.MAIN" />
  88. <category android:name="android.intent.category.LAUNCHER" />
  89. </intent-filter>
  90. </activity>'''
  91. activity = ET.Element('activity', {'android:name' : activity,
  92. 'android:theme' : '@android:style/Theme.Holo.Light.NoActionBar.Fullscreen',
  93. 'android:launchMode' : 'singleTop',
  94. 'android:configChanges' : 'orientation|screenSize|keyboardHidden',
  95. 'android:screenOrientation' : screenOrientation})
  96. intent = ET.Element('intent-filter')
  97. action = ET.Element('action', {'android:name' : 'android.intent.action.MAIN'})
  98. category = ET.Element('category', {'android:name' : 'android.intent.category.LAUNCHER'})
  99. intent.append(action)
  100. intent.append(category)
  101. activity.append(intent)
  102. intent2 = ET.Element('intent-filter')
  103. category = ET.Element('category', {'android:name' : 'android.intent.category.LEANBACK_LAUNCHER'})
  104. intent2.append(category)
  105. activity.append(intent2)
  106. application = root.find('application')
  107. application.insert(0, activity)
  108. tree.write(manifest, encoding)
  109. def generateV7RFile(game, sdk, subChannel, config):
  110. '''
  111. 生成新的R文件
  112. '''
  113. decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
  114. androidPlatforms = file_utils.getAndroidCompileToolPath()
  115. manifest = os.path.join(decompliePath, 'assets','AndroidManifest.xml')
  116. decomplieResPath = file_utils.getFullPath(decompliePath, 'res')
  117. compliePath = file_utils.getFullPath(decompliePath, 'gen')
  118. if not os.path.exists(compliePath):
  119. os.makedirs(compliePath)
  120. # 生成R文件
  121. print('生成R文件 ...')
  122. if config['aapt2disable']:
  123. aapt = file_utils.getAAPTPath()
  124. ret = file_utils.getExecPermission(aapt)
  125. if ret:
  126. return ret
  127. createRCmd = '"%s" p -f -m -J "%s" -S "%s" -I "%s" -M "%s"' % (aapt, compliePath, decomplieResPath, androidPlatforms, manifest)
  128. ret = file_utils.execFormatCmd(createRCmd)
  129. if ret:
  130. return ret
  131. else:
  132. # compile
  133. aapt = file_utils.getAAPT2Path()
  134. ret = file_utils.getExecPermission(aapt)
  135. if ret:
  136. return ret
  137. print('compiled res ...')
  138. complieResPath = os.path.join(compliePath, 'compiled')
  139. complieResCmd = '"%s" compile --dir "%s" -o "%s"' % (aapt, decomplieResPath, complieResPath)
  140. file_utils.execFormatCmd(complieResCmd)
  141. # unzip
  142. print('unzip compiled res ...')
  143. unzipResPath = os.path.join(compliePath, 'aapt2_res')
  144. with zipfile.ZipFile(complieResPath) as zf:
  145. zf.extractall(unzipResPath)
  146. print('create unzip %s' % unzipResPath)
  147. # link
  148. print('link res ...')
  149. outApk = os.path.join(compliePath, 'res.apk')
  150. linkResCmd = '"%s" link -o "%s" -I "%s" --manifest "%s" --java "%s" --auto-add-overlay' % (aapt, outApk, androidPlatforms, manifest, compliePath)
  151. for filename in os.listdir(unzipResPath):
  152. linkResCmd += ' %s' % filename
  153. print('link cmd len is %s' % len(linkResCmd))
  154. ret = file_utils.execFormatCmd(linkResCmd, unzipResPath)
  155. if ret:
  156. return ret
  157. # 编译R文件
  158. print('complie R.java ...')
  159. packageName = xml_utils.getPackageName(manifest)
  160. packagePath = file_utils.getPackagePath(compliePath, packageName)
  161. RSourceFile = os.path.join(packagePath, 'R.java')
  162. complieRCmd = 'javac -source 1.8 -target 1.8 -encoding UTF-8 "%s"' % RSourceFile
  163. ret = file_utils.execFormatCmd(complieRCmd)
  164. if ret:
  165. return ret
  166. # 生成dex
  167. print('dex R.class ...')
  168. outDex = os.path.join(compliePath, 'classes.dex')
  169. if config['aapt2disable']:
  170. dx = file_utils.getDxPath()
  171. dexCmd = '--dex --no-warning --output="%s" "%s"' % (outDex, compliePath)
  172. else:
  173. dx = file_utils.getD8Path()
  174. clazz = os.path.join(packagePath, '*.class')
  175. dexCmd = '--lib "%s" --output "%s" %s' % (androidPlatforms, compliePath, clazz)
  176. ret = file_utils.execJarCmd(dx, dexCmd)
  177. if ret:
  178. return ret
  179. # 反向dex生成smali
  180. # 存放在out目录
  181. print('baksmali classes.dex ...')
  182. baksmaliPath = file_utils.getBaksmaliPath()
  183. outPath = file_utils.getFullPath(decompliePath, 'out')
  184. ret = file_utils.execJarCmd(baksmaliPath, 'd "%s" -o "%s"' % (outDex, outPath))
  185. if ret:
  186. return ret
  187. # 将生成的文件拷贝到目标目录
  188. print('copy R.smali ...')
  189. smaliPath = file_utils.getFullPath(decompliePath, 'smali')
  190. file_utils.copyFileAllDir(outPath, smaliPath)
  191. return 0