sdk_script.py 7.2 KB

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