sdk_script.py 7.2 KB

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