package_channel.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import file_utils
  2. import config_utils
  3. import sys
  4. import os.path
  5. import json
  6. def packageChannel():
  7. if len(sys.argv) < 2:
  8. print('argument is missing')
  9. return 1
  10. channelConfig = sys.argv[1]
  11. jsonText = file_utils.readFile(channelConfig)
  12. config = json.loads(jsonText)
  13. print('*************config*****************')
  14. print(jsonText)
  15. print('************************************')
  16. # 检查配置
  17. if not checkConfig(config):
  18. return 1
  19. # 检查文件
  20. gameApk = config['package']
  21. if not os.path.exists(gameApk):
  22. print('%s not exists' % gameApk)
  23. if supportSignV2(gameApk):
  24. packageChannelV2(gameApk, config)
  25. else:
  26. packageChannelV1(gameApk, config)
  27. def supportSignV2(gameApk):
  28. '''
  29. 验证是否APK Signature Scheme v2
  30. '''
  31. apksigner = file_utils.getApksignerPath()
  32. ret = getJavaResult(apksigner, 'verify --verbose "%s"' % gameApk)
  33. if '(APK Signature Scheme v2): true' in ret:
  34. return True
  35. return False
  36. def packageChannelV2(gameApk, config):
  37. walle = file_utils.getWallePath()
  38. if not os.path.exists(config['outPath']):
  39. os.makedirs(config['outPath'])
  40. successCount = 0
  41. failureCount = 0
  42. channels = config['channel']
  43. for channel in channels:
  44. signedApk = os.path.join(config['outPath'], channel['outName'] + '.apk')
  45. print('add channel package %s...' % signedApk)
  46. appid = ''
  47. appkey = ''
  48. version = config_utils.getDate()
  49. if 'appid' in channel:
  50. appid = channel['appid']
  51. if 'appkey' in channel:
  52. appkey = channel['appkey']
  53. if 'version' in channel:
  54. version = channel['version']
  55. ret = file_utils.execJarCmd(walle, 'put -e version=%s,agent=%s,appid=%s,appkey=%s "%s" "%s"' % (version, channel['agent'], appid, appkey, gameApk, signedApk))
  56. if ret:
  57. failureCount += 1
  58. else:
  59. successCount += 1
  60. print('success %d, failure %d' % (successCount, failureCount))
  61. def packageChannelV1(gameApk, config):
  62. # 解包
  63. decompliePath = os.path.join(file_utils.getCurrentPath(), 'gen', 'channel')
  64. if os.path.exists(decompliePath):
  65. print('delete decomplie folder...')
  66. file_utils.deleteFolder(decompliePath)
  67. print('decomplie apk...')
  68. apktoolPath = file_utils.getApkToolPath()
  69. ret = file_utils.execJarCmd(apktoolPath, 'd -f "%s" -o "%s"' % (gameApk, decompliePath))
  70. if ret:
  71. return ret
  72. if not os.path.exists(config['outPath']):
  73. os.makedirs(config['outPath'])
  74. alignapkTool = file_utils.getAlignPath()
  75. apksigner = file_utils.getApksignerPath()
  76. path = os.path.join(file_utils.getCurrentPath(), 'keystore', 'key.json')
  77. jsonText = file_utils.readFile(path)
  78. signConfig = json.loads(jsonText)
  79. keystore = signConfig['default']
  80. storeFile = os.path.join(file_utils.getCurrentPath(), 'keystore', keystore['storeFile'])
  81. successCount = 0
  82. failureCount = 0
  83. channels = config['channel']
  84. for channel in channels:
  85. changeChannel(decompliePath, channel)
  86. temp = channel['agent']
  87. backApk = os.path.join(decompliePath, temp + '.apk')
  88. alignApk = os.path.join(decompliePath, temp + '_align.apk')
  89. signedApk = os.path.join(config['outPath'], channel['outName'] + '.apk')
  90. print('add channel package %s...' % signedApk)
  91. print('recomplie apk...')
  92. ret = file_utils.execJarCmd(apktoolPath, 'b -f "%s" -o "%s"' % (decompliePath, backApk))
  93. if ret:
  94. failureCount += 1
  95. continue
  96. print('align apk...')
  97. ret = file_utils.execFormatCmd('"%s" -f -p 4 "%s" "%s"' % (alignapkTool, backApk, alignApk))
  98. if ret:
  99. failureCount += 1
  100. continue
  101. print('sign apk...')
  102. ret = file_utils.execJarCmd(apksigner, 'sign --v2-signing-enabled=false --ks "%s" --ks-key-alias %s --ks-pass pass:%s --key-pass pass:%s --out "%s" "%s"' % (storeFile, keystore['keyAlias'], keystore['storePassword'], keystore['keyPassword'], signedApk, alignApk))
  103. if ret:
  104. failureCount += 1
  105. else:
  106. successCount += 1
  107. if os.path.exists(alignApk):
  108. os.remove(alignApk)
  109. if os.path.exists(backApk):
  110. os.remove(backApk)
  111. print('success %d, failure %d' % (successCount, failureCount))
  112. def changeChannel(decompliePath, channel):
  113. '''
  114. 修改渠道
  115. '''
  116. properties = os.path.join(decompliePath, 'assets', 'jmhy.properties')
  117. appid = ''
  118. appkey = ''
  119. version = config_utils.getDate()
  120. if 'appid' in channel:
  121. appid = channel['appid']
  122. if 'appkey' in channel:
  123. appkey = channel['appkey']
  124. if 'version' in channel:
  125. version = channel['version']
  126. content = 'version=%s\nagent=%s\nappid=%s\nappkey=%s' % (version, channel['agent'], appid, appkey)
  127. file_utils.createFile(properties, content)
  128. def checkConfig(config):
  129. if 'package' not in config:
  130. print('package not exists in config')
  131. return False
  132. if 'outPath' not in config:
  133. print('outPath not exists in config')
  134. return False
  135. if 'channel' not in config:
  136. print('channel not exists in config')
  137. return False
  138. return True
  139. def getJavaResult(jar, cmd):
  140. return getCmdResult('java -jar "%s" %s' % (jar, cmd))
  141. def getCmdResult(cmd):
  142. p = os.popen(cmd)
  143. content = p.read()
  144. return content
  145. packageChannel()