package_utils.py 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902
  1. # 安卓游戏打包脚本
  2. # 1.用apktool解包
  3. # 2.复制res资源、assets资源、jniLib资源
  4. # 3.修改包名、app名、渠道文件
  5. # 4.添加app icon、合并AndroidManifest文件
  6. # 5.添加app启动图,修改AndroidManifest文件
  7. # 6.生成新的R文件
  8. # 7.将新的R文件编译,生成dex,再用baksmali生成smali,替换旧的R文件
  9. # 8.将jar资源打包成dex,再用baksmali生成smali,拷贝到smali目录下
  10. # 9.统计方法量,并分割dex(将smali文件拷贝到目录smali_classes2)
  11. # 10.用apktool回包
  12. # 11.重新签名
  13. import datetime
  14. import importlib
  15. import json
  16. import os
  17. import os.path
  18. import re
  19. import sys
  20. import uuid
  21. import zipfile
  22. import common_utils
  23. import config_utils
  24. import file_utils
  25. import game_utils
  26. import smali_utils
  27. import xml_utils
  28. ignoreLauncher = ['jm_ysdk', 'jm_yijie', 'jm_quick',
  29. 'jm_beiyu', 'jm_xq_jrtt', 'jm_zy_ysdk']
  30. adaptApp = ['yjzx']
  31. startTime = ''
  32. def pack(game, sdk, config):
  33. config['cache'] = uuid.uuid1()
  34. sub_channel = config['subChannel']
  35. print('game = %s, sdk = %s, subChannel = %s, ...' % (game, sdk, sub_channel))
  36. # 解包
  37. print('解包')
  38. ret = decomplie(game, sdk, sub_channel, config)
  39. if ret:
  40. return ret
  41. if is_refactor_sdk(config):
  42. return pack_v2(game, sdk, sub_channel, config)
  43. else:
  44. return pack_v1(game, sdk, sub_channel, config)
  45. def pack_v1(game, sdk, sub_channel, config):
  46. # 删除旧代码
  47. print('删除旧代码')
  48. ret = handle_jm_old_code(game, sdk, sub_channel, config)
  49. if ret:
  50. return ret
  51. # 删除一些不支持的属性
  52. print('删除一些不支持的属性')
  53. ret = remove_no_support_attr(game, sdk, sub_channel, config)
  54. if ret:
  55. return ret
  56. # 删除一些不支持的配置
  57. print('删除一些不支持的配置')
  58. ret = fix_un_support_config(game, sdk, sub_channel, config)
  59. if ret:
  60. return ret
  61. # 合并Drawable-v4目录
  62. ret = merge_drawable_res(game, sdk, sub_channel, config)
  63. if ret:
  64. return ret
  65. # 移除相同的资源
  66. ret = remove_same_values_res(game, sdk, sub_channel, config)
  67. if ret:
  68. return ret
  69. # 复制res资源
  70. ret = copy_res(game, sdk, sub_channel, config)
  71. if ret:
  72. return ret
  73. # 合并主文件
  74. ret = merge_manifest_res(game, sdk, sub_channel, config)
  75. if ret:
  76. return ret
  77. # 替换占位符
  78. ret = change_placeholders(game, sdk, sub_channel, config)
  79. if ret:
  80. return ret
  81. # 添加meta-data
  82. ret = add_meta_data(game, sdk, sub_channel, config)
  83. if ret:
  84. return ret
  85. # 增加配置文件
  86. ret = add_v1_config(game, sdk, sub_channel, config)
  87. if ret:
  88. return ret
  89. # 复制app res资源
  90. ret = copy_app_res(game, sdk, sub_channel, config)
  91. if ret:
  92. return ret
  93. # 更改包名
  94. if 'packageName' in config and config['packageName'] != '':
  95. ret = change_package_name(game, sdk, sub_channel, config)
  96. if ret:
  97. return ret
  98. # 更改app名
  99. if 'name' in config and config['name'] != '':
  100. ret = change_app_name(game, sdk, sub_channel, config)
  101. if ret:
  102. return ret
  103. # 更改app icon
  104. if config['changeIcon']:
  105. ret = change_app_icon(game, sdk, sub_channel, config)
  106. if ret:
  107. return ret
  108. # 添加启动图操作
  109. if config['addLauncher']:
  110. ret = add_launcher(game, sdk, sub_channel, config)
  111. if ret:
  112. return ret
  113. # 添加多图标
  114. # ret = addMoreIcon(game, sdk, subChannel, config)
  115. # 复制icon图标到res
  116. copy_icon(game, sdk, sub_channel, config)
  117. # 打包lib依赖
  118. ret = pack_jar(game, sdk, sub_channel, config)
  119. if ret:
  120. return ret
  121. # 修改继承Application
  122. print('修改继承Application')
  123. common_utils.change_application(game, sdk, sub_channel, config, 'com.jmhy.sdk.common.JMApplication')
  124. # sdk脚本处理
  125. ret = do_sdk_post_script(game, sdk, config)
  126. if ret:
  127. return ret
  128. # 乐变sdk的特殊处理
  129. ret = game_utils.sdkLebianChange(game, sdk, config)
  130. if ret:
  131. return ret
  132. # 游戏脚本处理
  133. ret = do_game_post_script(game, sdk, config)
  134. if ret:
  135. return ret
  136. # 游戏独立处理
  137. ret = do_game_script(game, sdk, config)
  138. if ret:
  139. return ret
  140. # log sdk
  141. if 'logSdk' in config:
  142. for log in config['logSdk']:
  143. ret = add_log_sdk(game, sdk, sub_channel, config, log)
  144. if ret:
  145. return ret
  146. # oaid sdk
  147. ret = addOaidSdk(game, sdk, sub_channel, config, "1.0.10")
  148. if ret:
  149. return ret
  150. # 生成R文件
  151. '''ret = generateNewRFile(game, sdk, subChannel, config)
  152. if ret:
  153. return ret'''
  154. # 添加MultiDex支持
  155. if config['splitDex']:
  156. ret = split_dex(game, sdk, sub_channel, config)
  157. if ret:
  158. return ret
  159. # 更改版本号
  160. ret = changeVersion(game, sdk, sub_channel, config)
  161. if ret:
  162. return ret
  163. # 更改HardwareAccelerated属性
  164. replace_hardware_accelerated(game, sdk, sub_channel, config)
  165. if ret:
  166. return ret
  167. # 回编译
  168. ret = recomplie(game, sdk, sub_channel, config)
  169. if ret:
  170. return ret
  171. # 对齐apk
  172. ret = alignApk(game, sdk, sub_channel, config)
  173. if ret:
  174. return ret
  175. # 签名
  176. ret = apk_signer_apk(game, sdk, sub_channel, config)
  177. if ret:
  178. return ret
  179. # 添加渠道信息
  180. ret = add_channel(game, sdk, sub_channel, config)
  181. if ret:
  182. return ret
  183. copy_v1_apk_2_out_dir(game, sdk, sub_channel, config)
  184. if ret:
  185. return ret
  186. # 清理产生的中间文件
  187. if config['clearCache']:
  188. clearTemp(game, sdk, sub_channel, config)
  189. endTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  190. d1 = datetime.datetime.strptime(endTime, '%Y-%m-%d %H:%M:%S')
  191. d2 = datetime.datetime.strptime(startTime, '%Y-%m-%d %H:%M:%S')
  192. d = d1 - d2
  193. print('开始时间:' + startTime)
  194. print('结束时间:' + endTime)
  195. print('用时:{}'.format(config_utils.getTime(d.seconds)))
  196. return 0
  197. def pack_v2(game, sdk, sub_channel, config):
  198. # 删除旧代码
  199. ret = handle_qingshi_old_code(game, sdk, sub_channel, config)
  200. if ret:
  201. return ret
  202. # 删除一些不支持的属性
  203. ret = remove_no_support_attr(game, sdk, sub_channel, config)
  204. if ret:
  205. return ret
  206. # 删除一些不支持的配置
  207. ret = fix_un_support_config(game, sdk, sub_channel, config)
  208. if ret:
  209. return ret
  210. # 合并Drawable-v4目录
  211. ret = merge_drawable_res(game, sdk, sub_channel, config)
  212. if ret:
  213. return ret
  214. # 移除旧sdk资源
  215. remove_v2_old_res(game, sdk, sub_channel, config)
  216. # 移除旧abi文件
  217. remove_v2_old_abi(game, sdk, sub_channel, config)
  218. # 移除相同的资源
  219. ret = remove_same_values_res(game, sdk, sub_channel, config)
  220. if ret:
  221. return ret
  222. # 复制res资源
  223. ret = copy_res(game, sdk, sub_channel, config)
  224. if ret:
  225. return ret
  226. # 合并主文件
  227. ret = merge_manifest_res(game, sdk, sub_channel, config)
  228. if ret:
  229. return ret
  230. # 替换占位符
  231. ret = change_placeholders(game, sdk, sub_channel, config)
  232. if ret:
  233. return ret
  234. # 添加meta-data
  235. ret = add_meta_data(game, sdk, sub_channel, config)
  236. if ret:
  237. return ret
  238. # 增加配置文件
  239. ret = add_v2_config(game, sdk, sub_channel, config)
  240. if ret:
  241. return ret
  242. # 复制app res资源
  243. ret = copy_app_res(game, sdk, sub_channel, config)
  244. if ret:
  245. return ret
  246. # 更改包名
  247. if 'packageName' in config and config['packageName'] != '':
  248. ret = change_package_name(game, sdk, sub_channel, config)
  249. if ret:
  250. return ret
  251. # 更改app名
  252. if 'name' in config and config['name'] != '':
  253. ret = change_app_name(game, sdk, sub_channel, config)
  254. if ret:
  255. return ret
  256. # 更改app icon
  257. if config['changeIcon']:
  258. ret = change_app_icon(game, sdk, sub_channel, config)
  259. if ret:
  260. return ret
  261. # 添加启动图操作
  262. if config['addLauncher']:
  263. ret = add_launcher(game, sdk, sub_channel, config)
  264. if ret:
  265. return ret
  266. copy_icon(game, sdk, sub_channel, config)
  267. # 打包lib依赖
  268. ret = pack_jar(game, sdk, sub_channel, config)
  269. if ret:
  270. return ret
  271. # sdk脚本处理
  272. ret = do_sdk_post_script(game, sdk, config)
  273. if ret:
  274. return ret
  275. # 游戏脚本处理
  276. ret = do_game_post_script(game, sdk, config)
  277. if ret:
  278. return ret
  279. # 游戏独立处理
  280. ret = do_game_script(game, sdk, config)
  281. if ret:
  282. return ret
  283. # log sdk
  284. if 'logSdk' in config:
  285. for log in config['logSdk']:
  286. ret = add_log_sdk(game, sdk, sub_channel, config, log)
  287. if ret:
  288. return ret
  289. # 生成R文件
  290. '''ret = generateNewRFile(game, sdk, subChannel, config)
  291. if ret:
  292. return ret'''
  293. # 添加MultiDex支持
  294. if config['splitDex']:
  295. print('重构sdk split smali')
  296. decompile_path = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  297. manifest = os.path.join(decompile_path, 'AndroidManifest.xml')
  298. application = xml_utils.get_application_attr(manifest, 'name')
  299. ret = split_smali(game, sdk, sub_channel, config, application)
  300. if ret:
  301. return ret
  302. # 更改版本号
  303. ret = changeVersion(game, sdk, sub_channel, config)
  304. if ret:
  305. return ret
  306. # 更改HardwareAccelerated属性
  307. replace_hardware_accelerated(game, sdk, sub_channel, config)
  308. if ret:
  309. return ret
  310. # 回编译
  311. ret = recomplie(game, sdk, sub_channel, config)
  312. if ret:
  313. return ret
  314. # 对齐apk
  315. ret = alignApk(game, sdk, sub_channel, config)
  316. if ret:
  317. return ret
  318. # 签名
  319. ret = apk_signer_apk(game, sdk, sub_channel, config)
  320. if ret:
  321. return ret
  322. copy_v2_apk_2_out_dir(game, sdk, sub_channel, config)
  323. if ret:
  324. return ret
  325. # 清理产生的中间文件
  326. if config['clearCache']:
  327. clearTemp(game, sdk, sub_channel, config)
  328. endTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  329. d1 = datetime.datetime.strptime(endTime, '%Y-%m-%d %H:%M:%S')
  330. d2 = datetime.datetime.strptime(startTime, '%Y-%m-%d %H:%M:%S')
  331. d = d1 - d2
  332. print('开始时间:' + startTime)
  333. print('结束时间:' + endTime)
  334. print('用时:{}'.format(config_utils.getTime(d.seconds)))
  335. return 0
  336. def decomplie(game, sdk, sub_channel, config):
  337. """
  338. 解包
  339. """
  340. apktoolPath = file_utils.get_apktool_path()
  341. cacheGameApk = file_utils.get_cache_game_apk(game, config['random'], sdk)
  342. decompliePath = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  343. if os.path.exists(decompliePath):
  344. print('delete decomplie folder...')
  345. file_utils.delete_folder(decompliePath)
  346. print('decomplie apk...')
  347. return file_utils.exec_jar_cmd(apktoolPath, 'd -f "%s" -o "%s"' % (cacheGameApk, decompliePath))
  348. def remove_old_code(game, sdk, sub_channel, config):
  349. """
  350. 删除旧代码
  351. """
  352. print(config)
  353. if config['refactorSdk']:
  354. return handle_qingshi_old_code(game, sdk, sub_channel, config)
  355. else:
  356. return handle_jm_old_code(game, sdk, sub_channel, config)
  357. def handle_jm_old_code(game, sdk, sub_channel, config):
  358. decompliePath = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  359. codePath = os.path.join(decompliePath, 'smali', 'com', 'jmhy', 'sdk')
  360. # file_utils.deleteFolder(codePath)
  361. allFiles = []
  362. allFiles = file_utils.list_files(codePath, allFiles)
  363. for f in allFiles:
  364. fpath, fname = os.path.split(f) # 分离文件名和路径
  365. if fname == 'R.smali' or fname.startswith('R$'):
  366. continue
  367. os.remove(f)
  368. return 0
  369. def handle_qingshi_old_code(game, sdk, sub_channel, config):
  370. print('handle_qingshi_old_code')
  371. decompile_path = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  372. qingshi_path = os.path.join(decompile_path, 'smali', 'cn', 'qingshi')
  373. support_path = os.path.join(decompile_path, 'smali', 'cn', 'yyxx')
  374. xi_path = os.path.join(decompile_path, 'smali', 'XI')
  375. ali_path = os.path.join(decompile_path, 'smali', 'com', 'alibaba')
  376. asus_path = os.path.join(decompile_path, 'smali', 'com', 'asus')
  377. bun_path = os.path.join(decompile_path, 'smali', 'com', 'bun')
  378. cmic_path = os.path.join(decompile_path, 'smali', 'com', 'cmic')
  379. dolin_path = os.path.join(decompile_path, 'smali', 'com', 'dolin')
  380. huawei_path = os.path.join(decompile_path, 'smali', 'com', 'huawei')
  381. mobile_path = os.path.join(decompile_path, 'smali', 'com', 'mobile')
  382. netease_path = os.path.join(decompile_path, 'smali', 'com', 'netease')
  383. nirvana_path = os.path.join(decompile_path, 'smali', 'com', 'nirvana')
  384. samsung_path = os.path.join(decompile_path, 'smali', 'com', 'samsung')
  385. mmkv_path = os.path.join(decompile_path, 'smali', 'com', 'tencent', 'mmkv')
  386. zui_path = os.path.join(decompile_path, 'smali', 'com', 'zui')
  387. annotation_path = os.path.join(decompile_path, 'smali', 'android', 'support', 'annotation')
  388. v4_path = os.path.join(decompile_path, 'smali', 'android', 'support', 'v4')
  389. file_utils.delete_folder(qingshi_path)
  390. file_utils.delete_folder(support_path)
  391. file_utils.delete_folder(xi_path)
  392. file_utils.delete_folder(ali_path)
  393. file_utils.delete_folder(asus_path)
  394. file_utils.delete_folder(bun_path)
  395. file_utils.delete_folder(cmic_path)
  396. file_utils.delete_folder(dolin_path)
  397. file_utils.delete_folder(huawei_path)
  398. file_utils.delete_folder(mobile_path)
  399. file_utils.delete_folder(netease_path)
  400. file_utils.delete_folder(nirvana_path)
  401. file_utils.delete_folder(samsung_path)
  402. file_utils.delete_folder(mmkv_path)
  403. file_utils.delete_folder(zui_path)
  404. file_utils.delete_folder(qingshi_path)
  405. file_utils.delete_folder(annotation_path)
  406. file_utils.delete_folder(v4_path)
  407. return 0
  408. def copy_res(game, sdk, sub_channel, config):
  409. """
  410. 复制res资源
  411. """
  412. # 拷贝sdk资源
  413. print('copy res...')
  414. decompliePath = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  415. sdkPath = file_utils.get_full_sdk_path(sdk)
  416. resPath = os.path.join(sdkPath, 'res')
  417. decomplieResPath = file_utils.get_full_path(decompliePath, 'res')
  418. for d in os.listdir(resPath):
  419. copy_res_with_type(resPath, decomplieResPath, d)
  420. # 拷贝assets
  421. print('copy assets...')
  422. assetsPath = file_utils.get_full_path(sdkPath, 'assets')
  423. decomplieAssetsPath = file_utils.get_full_path(decompliePath, 'assets')
  424. if os.path.exists(assetsPath):
  425. ret = file_utils.copy_file_all_dir(assetsPath, decomplieAssetsPath)
  426. if ret:
  427. return ret
  428. # 拷贝jniLib
  429. print('copy jniLibs...')
  430. jniPath = file_utils.get_full_path(sdkPath, 'jniLibs')
  431. decomplieJniPath = file_utils.get_full_path(decompliePath, 'lib')
  432. abiFilters = []
  433. if os.path.exists(decomplieJniPath):
  434. for abi in os.listdir(decomplieJniPath):
  435. # if abi == 'armeabi-v7a' or abi == 'armeabi' or abi == 'arm64-v8a':
  436. print('append : ' + abi)
  437. abiFilters.append(abi)
  438. else:
  439. abiFilters = ['armeabi-v7a']
  440. if os.path.exists(jniPath):
  441. ret = file_utils.copy_file_all_dir(
  442. jniPath, decomplieJniPath, False, abiFilters)
  443. if ret:
  444. return ret
  445. return 0
  446. def merge_drawable_res(game, sdk, sub_channel, config):
  447. """
  448. 合并Drawable-v4目录
  449. """
  450. print('merge drawable path...')
  451. decompliePath = file_utils.get_decompile_path(
  452. game, sdk, sub_channel, config['cache'])
  453. resPath = os.path.join(decompliePath, 'res')
  454. for path in os.listdir(resPath):
  455. # print('res path %s' % path)
  456. if (path.startswith('drawable') or path.startswith('mipmap')) and path.endswith('-v4'):
  457. # print('merge path %s' % path)
  458. v4DrawablePath = os.path.join(resPath, path)
  459. drawablePath = os.path.join(resPath, path[:-3])
  460. if os.path.exists(drawablePath):
  461. ret = file_utils.copy_file_all_dir(
  462. v4DrawablePath, drawablePath, True)
  463. if ret:
  464. return ret
  465. else:
  466. os.rename(v4DrawablePath, drawablePath)
  467. return 0
  468. def remove_v2_old_res(game, sdk, sub_channel, config):
  469. print('remove v2 sdk old res...')
  470. decompile_path = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  471. res_path = os.path.join(decompile_path, 'res')
  472. sub_folders = os.listdir(res_path)
  473. for folder in sub_folders:
  474. sub_folder_path = os.path.join(res_path, folder)
  475. qs_xml_docs = os.listdir(sub_folder_path)
  476. for xml in qs_xml_docs:
  477. if xml.startswith('qs_') or xml.startswith('authsdk_'):
  478. xml_path = os.path.join(sub_folder_path, xml)
  479. print(xml_path)
  480. os.remove(xml_path)
  481. if xml == 'widget_pns_action_bar.xml' or xml == 'widget_pns_optional_viewgroup.xml' or xml == 'widget_pns_protocol.xml':
  482. xml_path = os.path.join(sub_folder_path, xml)
  483. print(xml_path)
  484. os.remove(xml_path)
  485. def remove_same_values_res(game, sdk, sub_channel, config):
  486. """
  487. 移除相同的资源
  488. """
  489. # 读取sdk的资源
  490. print('remove same res...')
  491. sdk_path = file_utils.get_full_sdk_path(sdk)
  492. sdk_res_path = os.path.join(sdk_path, 'res')
  493. print('sdk res path: %s' % sdk_res_path)
  494. res_list = []
  495. for path in os.listdir(sdk_res_path):
  496. print('path: %s' % path)
  497. if not path.startswith('values'):
  498. continue
  499. abs_path = os.path.join(sdk_res_path, path)
  500. print('abs path: %s' % abs_path)
  501. for res_file in os.listdir(abs_path):
  502. if res_file.endswith('.DS_Store'):
  503. continue
  504. res_list = xml_utils.read_all_res(os.path.join(abs_path, res_file), res_list)
  505. if len(res_list) == 0:
  506. print('no same res found')
  507. return 0
  508. # 移除相同的资源
  509. decompile_path = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  510. resPath = os.path.join(decompile_path, 'res')
  511. for path in os.listdir(resPath):
  512. if not path.startswith('values'):
  513. continue
  514. abs_path = os.path.join(resPath, path)
  515. for res_file in os.listdir(abs_path):
  516. xml_utils.remove_same_values_res(os.path.join(abs_path, res_file), res_list)
  517. return 0
  518. def merge_manifest_res(game, sdk, sub_channel, config):
  519. """
  520. 合并主文件
  521. """
  522. print('merge AndroidManifest...')
  523. decompliePath = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  524. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  525. sdkPath = file_utils.get_full_sdk_path(sdk)
  526. libManifest = file_utils.get_full_path(sdkPath, 'manifest.xml')
  527. return xml_utils.merge_manifest_res(manifest, libManifest)
  528. def copy_app_res(game, sdk, sub_channel, config):
  529. """
  530. 拷贝app的资源,比如app icon、启动图等
  531. """
  532. random = config['random']
  533. channelPath = file_utils.getSubChannelPath(game, sdk, random, sub_channel)
  534. decompliePath = file_utils.get_decompile_path(
  535. game, sdk, sub_channel, config['cache'])
  536. # assets
  537. print('copy assets...')
  538. # 适配一剑斩仙
  539. if game in adaptApp:
  540. print('适配一剑斩仙...')
  541. decomplieAssetsPath = file_utils.get_full_path(decompliePath, 'assets')
  542. skinZipPath = os.path.join(decomplieAssetsPath, 'skin.zip')
  543. skinPath = os.path.join(decomplieAssetsPath, 'skin')
  544. if os.path.exists(skinZipPath):
  545. with zipfile.ZipFile(skinZipPath) as zf:
  546. zf.extractall(decomplieAssetsPath)
  547. print('create unzip skin')
  548. assetsPath = file_utils.get_full_path(channelPath, 'assets')
  549. decomplieAssetsPath = file_utils.get_full_path(
  550. decompliePath, 'assets')
  551. if os.path.exists(assetsPath):
  552. ret = file_utils.copy_file_all_dir(
  553. assetsPath, decomplieAssetsPath)
  554. with zipfile.ZipFile(skinZipPath, 'w') as z:
  555. for root, dirs, files in os.walk(skinPath):
  556. for single_file in files:
  557. filepath = os.path.join(root, single_file)
  558. print('create zip ---> ' + filepath)
  559. temPath = 'skin/' + single_file
  560. z.write(filepath, temPath)
  561. z.close()
  562. else:
  563. print('normal copy assets...')
  564. assetsPath = file_utils.get_full_path(channelPath, 'assets')
  565. decomplieAssetsPath = file_utils.get_full_path(
  566. decompliePath, 'assets')
  567. if os.path.exists(assetsPath):
  568. ret = file_utils.copy_file_all_dir(
  569. assetsPath, decomplieAssetsPath)
  570. if ret:
  571. return ret
  572. else:
  573. print('normal copy assets...')
  574. assetsPath = file_utils.get_full_path(channelPath, 'assets')
  575. decomplieAssetsPath = file_utils.get_full_path(decompliePath, 'assets')
  576. if os.path.exists(assetsPath):
  577. ret = file_utils.copy_file_all_dir(assetsPath, decomplieAssetsPath)
  578. if ret:
  579. return ret
  580. # icon
  581. print('copy icon...')
  582. ret = copy_app_res_with_type(decompliePath, channelPath, 'icon')
  583. if ret:
  584. return ret
  585. # 启动图
  586. print('copy splash...')
  587. ret = copy_app_res_with_type(decompliePath, channelPath, 'splash')
  588. if ret:
  589. return ret
  590. # 其他图片
  591. print('copy image...')
  592. ret = copy_app_res_with_type(decompliePath, channelPath, 'image')
  593. if ret:
  594. return ret
  595. return 0
  596. def copy_app_res_with_type(decompile_path, channel_path, type_name):
  597. decomplieResPath = os.path.join(decompile_path, 'res')
  598. iconPath = os.path.join(channel_path, type_name)
  599. if not os.path.exists(iconPath):
  600. print('dir "%s" not exists' % iconPath)
  601. return 0
  602. for d in os.listdir(iconPath):
  603. ret = copy_res_with_type(iconPath, decomplieResPath, d)
  604. if ret:
  605. return ret
  606. return 0
  607. def copy_res_with_type(res_path, decompile_res_path, type_name):
  608. # aapt的打包目录会带-v4后缀
  609. resDir = os.path.join(res_path, type_name)
  610. target = os.path.join(decompile_res_path, type_name)
  611. targetV4 = os.path.join(decompile_res_path, type_name + '-v4')
  612. if not os.path.exists(target) and not os.path.exists(targetV4):
  613. os.makedirs(target)
  614. return file_utils.copy_file_all_dir(resDir, target, False)
  615. elif not os.path.exists(target):
  616. return file_utils.copy_file_all_dir(resDir, targetV4, False)
  617. else:
  618. return file_utils.copy_file_all_dir(resDir, target, False)
  619. def remove_no_support_attr(game, sdk, sub_channel, config):
  620. """
  621. 删除一些不支持的属性
  622. """
  623. decompile_path = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  624. manifest = os.path.join(decompile_path, 'AndroidManifest.xml')
  625. xml_utils.remove_root_attr(manifest, 'compileSdkVersion')
  626. xml_utils.remove_root_attr(manifest, 'compileSdkVersionCodename')
  627. return 0
  628. def fix_un_support_config(game, sdk, sub_channel, config):
  629. """
  630. 删除一些不支持的配置
  631. """
  632. # 检查minSdkVersion
  633. decompile_path = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  634. yml = os.path.join(decompile_path, 'apktool.yml')
  635. min_sdk_version = 21
  636. file_utils.change_min_sdk_version(yml, min_sdk_version)
  637. res_path = os.path.join(decompile_path, 'res')
  638. tag = '-v'
  639. for res in os.listdir(res_path):
  640. # print('res = ' + res)
  641. if res.startswith('values') and tag in res:
  642. start = res.index(tag)
  643. version = res[start + len(tag):]
  644. if not version.isdigit():
  645. continue
  646. version = int(version)
  647. print('version = %d' % version)
  648. if version < min_sdk_version:
  649. un_support_path = os.path.join(res_path, res)
  650. print('un_support_path = ' + un_support_path)
  651. file_utils.delete_folder(un_support_path)
  652. print('deleteFolder = ' + un_support_path)
  653. return 0
  654. def change_package_name(game, sdk, sub_channel, config):
  655. """
  656. 更改包名
  657. """
  658. # 全局替换AndroidManifest里面的包名
  659. newPackageName = config['packageName']
  660. decompliePath = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  661. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  662. packageName = xml_utils.get_package_name(manifest)
  663. config['oldPackageName'] = packageName
  664. xml_utils.change_package_name(manifest, newPackageName)
  665. print('change package name %s --> %s' % (packageName, newPackageName))
  666. return 0
  667. def change_app_name(game, sdk, sub_channel, config):
  668. """
  669. 更改app名
  670. """
  671. # 生成string.xml文件
  672. name = config['name']
  673. resName = 'common_sdk_name'
  674. if 'outName' in config:
  675. resName = resName + '_' + config['outName']
  676. decompliePath = file_utils.get_decompile_path(
  677. game, sdk, sub_channel, config['cache'])
  678. stringFile = os.path.join(decompliePath, 'res',
  679. 'values', 'sdk_strings_temp.xml')
  680. content = '<?xml version="1.0" encoding="utf-8"?><resources><string name="%s">%s</string></resources>' % (
  681. resName, name)
  682. file_utils.create_file(stringFile, content)
  683. # 修改主文件的app名的值
  684. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  685. xml_utils.change_app_name(manifest, '@string/%s' % resName)
  686. print('change app name %s' % name)
  687. return 0
  688. def change_app_icon(game, sdk, subChannel, config):
  689. '''
  690. 更改app icon
  691. '''
  692. print('change app icon...')
  693. resName = 'common_sdk_icon'
  694. decompliePath = file_utils.get_decompile_path(
  695. game, sdk, subChannel, config['cache'])
  696. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  697. xml_utils.change_app_icon(manifest, '@mipmap/%s' % resName)
  698. return 0
  699. def add_meta_data(game, sdk, subChannel, config):
  700. '''
  701. 添加meta-data
  702. '''
  703. if 'metaData' not in config:
  704. return 0
  705. print('add meta-data...')
  706. decompliePath = file_utils.get_decompile_path(
  707. game, sdk, subChannel, config['cache'])
  708. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  709. xml_utils.addMetaData(manifest, config['metaData'])
  710. return 0
  711. def add_v1_config(game, sdk, sub_channel, config):
  712. """
  713. 添加config.json
  714. """
  715. if 'configData' not in config:
  716. return 0
  717. print('add config.json...')
  718. decompile_path = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  719. configJson = os.path.join(decompile_path, 'assets', 'jmhy_config.json')
  720. jsonText = json.dumps(config['configData'], ensure_ascii=False)
  721. file_utils.create_file(configJson, jsonText)
  722. return 0
  723. def add_v2_config(game, sdk, sub_channel, config):
  724. """
  725. 添加config.json
  726. """
  727. if 'configData' not in config:
  728. return 0
  729. print('add config.json...')
  730. decompile_path = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  731. config_json = os.path.join(decompile_path, 'assets', 'qs_game', 'qs_analytics.json')
  732. if os.path.exists(config_json):
  733. os.remove(config_json)
  734. json_text = json.dumps(config['configData']['channel_sdk_list'], ensure_ascii=False)
  735. file_utils.create_file(config_json, json_text)
  736. return 0
  737. def change_placeholders(game, sdk, sub_channel, config):
  738. """
  739. 处理掉占位符
  740. """
  741. if 'placeholders' not in config:
  742. return 0
  743. decompliePath = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  744. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  745. placeholders = config['placeholders']
  746. for placeholder in placeholders:
  747. oldText = '${%s}' % placeholder
  748. newText = placeholders[placeholder]
  749. print('change placeholder %s -> %s' % (oldText, newText))
  750. file_utils.replace_content(manifest, oldText, newText)
  751. return 0
  752. def add_launcher(game, sdk, subChannel, config):
  753. '''
  754. 添加启动图
  755. '''
  756. # ysdk的特殊处理
  757. if sdk in ignoreLauncher:
  758. return 0
  759. random = config['random']
  760. channelPath = file_utils.getSubChannelPath(game, sdk, random, subChannel)
  761. splashPath = os.path.join(channelPath, 'splash')
  762. if len(os.listdir(splashPath)) == 0:
  763. print('dir splash is empty')
  764. return 0
  765. print('add launcher...')
  766. decompliePath = file_utils.get_decompile_path(
  767. game, sdk, subChannel, config['cache'])
  768. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  769. activity = xml_utils.get_launcher_activity_name(manifest)
  770. if activity == 'com.jmhy.sdk.template.LauncherActivity':
  771. print('add launcher already exist...')
  772. return 1
  773. # 添加关联资源
  774. internalPath = file_utils.getFullInternalPath()
  775. ret = copy_app_res_with_type(decompliePath, internalPath, 'launcher_res')
  776. if ret:
  777. return ret
  778. # 拷贝代码
  779. print('copy launcher code...')
  780. codePath = os.path.join(internalPath, 'launcher_code', 'smali')
  781. smaliPath = file_utils.get_full_path(decompliePath, 'smali')
  782. ret = file_utils.copy_file_all_dir(codePath, smaliPath)
  783. if ret:
  784. return ret
  785. # 修改主文件信息
  786. print('change launcher config...')
  787. orientation = xml_utils.get_screen_orientation(manifest)
  788. activity = xml_utils.remove_launcher_activity(manifest)
  789. xml_utils.add_launcher_activity(
  790. manifest, orientation, 'com.jmhy.sdk.template.LauncherActivity')
  791. # 修改跳转的
  792. launcherActivity = os.path.join(
  793. decompliePath, 'smali', 'com', 'jmhy', 'sdk', 'template', 'LauncherActivity.smali')
  794. file_utils.replace_content(launcherActivity, '{class}', activity)
  795. print('change launcher %s to %s' %
  796. (activity, 'com.jmhy.sdk.template.LauncherActivity'))
  797. # config['oldLauncher'] = activity
  798. if 'launcherTime' in config:
  799. timeHex = formatHex(config['launcherTime'])
  800. file_utils.replace_content(launcherActivity, '0x0BB8', timeHex)
  801. return 0
  802. def addMoreIcon(game, sdk, subChannel, config):
  803. '''
  804. 添加多个图标
  805. '''
  806. print('add more icon support...')
  807. decompliePath = file_utils.get_decompile_path(
  808. game, sdk, subChannel, config['cache'])
  809. icon = '@mipmap/common_sdk_icon'
  810. if not config['changeIcon']:
  811. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  812. icon = xml_utils.get_application_attr(manifest, 'icon')
  813. switchIcon = icon
  814. if config['switchIcon']:
  815. switchIcon = '@mipmap/common_sdk_icon2'
  816. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  817. return xml_utils.add_more_icon(manifest, icon, switchIcon)
  818. def copy_icon(game, sdk, subChannel, config):
  819. '''
  820. 复制icon到res ,一键登录使用
  821. '''
  822. if config['changeIcon']:
  823. decompliePath = file_utils.get_decompile_path(game, sdk, subChannel, config['cache'])
  824. decomplieResPath = file_utils.get_full_path(decompliePath, 'res')
  825. iconPath = os.path.join(decomplieResPath, 'mipmap-xhdpi', 'common_sdk_icon.png')
  826. desPath = os.path.join(
  827. decomplieResPath, 'drawable-hdpi', 'jm_cmcc_icon.png')
  828. file_utils.copy_file(iconPath, desPath)
  829. else:
  830. decompliePath = file_utils.get_decompile_path(game, sdk, subChannel, config['cache'])
  831. decomplieResPath = file_utils.get_full_path(decompliePath, 'res')
  832. desPath = os.path.join(decomplieResPath, 'drawable-hdpi', 'jm_cmcc_icon.png')
  833. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  834. icon = xml_utils.get_application_attr(manifest, 'icon')
  835. tag = icon[1:].split("/")
  836. if len(tag) < 1:
  837. return
  838. hdpi = ['-xhdpi', '-xxhdpi', '-xxxhdpi']
  839. for h in hdpi:
  840. p1 = '%s%s' % (tag[0], h)
  841. png = tag[1] + ".png"
  842. iconPath = os.path.join(decomplieResPath, p1, png)
  843. if os.path.exists(iconPath):
  844. print('iconPath = ' + iconPath)
  845. file_utils.copy_file(iconPath, desPath)
  846. break
  847. def formatHex(millisecond):
  848. '''
  849. 将毫秒转为16进制,4位格式
  850. '''
  851. timeHex = str(hex(millisecond)).upper()
  852. timeHex = timeHex[2:]
  853. formatHex = ''
  854. if len(timeHex) == 3:
  855. formatHex = '0x0' + timeHexaddLauncher
  856. elif len(timeHex) == 4:
  857. formatHex = '0x' + timeHex
  858. else:
  859. formatHex = '0x0BB8'
  860. return formatHex
  861. def do_sdk_post_script(game, sdk, config):
  862. """
  863. 执行sdk相关特殊处理脚本
  864. """
  865. sdkPath = file_utils.get_full_sdk_path(sdk)
  866. scriptPath = os.path.join(sdkPath, 'script')
  867. targetScript = os.path.join(scriptPath, 'sdk_script.py')
  868. if not os.path.exists(targetScript):
  869. print('sdk_script no exists')
  870. return 0
  871. print('do sdk post script...')
  872. sys.path.append(scriptPath)
  873. module = importlib.import_module('sdk_script')
  874. ret = module.execute(game, sdk, config)
  875. sys.path.remove(scriptPath)
  876. return ret
  877. def do_game_post_script(game, sdk, config):
  878. """
  879. 执行游戏相关特殊处理脚本
  880. """
  881. channelPath = file_utils.get_full_game_path(game)
  882. scriptPath = os.path.join(channelPath, 'script')
  883. targetScript = os.path.join(scriptPath, 'game_script.py')
  884. if not os.path.exists(targetScript):
  885. print('game_script no exists')
  886. return 0
  887. print('doGamePostScript...')
  888. sys.path.append(scriptPath)
  889. module = importlib.import_module('game_script')
  890. ret = module.execute(game, sdk, config)
  891. sys.path.remove(scriptPath)
  892. return ret
  893. def do_game_script(game, sdk, config):
  894. """
  895. 执行游戏相关特殊处理脚本
  896. """
  897. channelPath = file_utils.get_full_path('game_script', game)
  898. targetScript = os.path.join(channelPath, 'game_script.py')
  899. print(targetScript + "--------")
  900. if not os.path.exists(targetScript):
  901. print('game_script no exists')
  902. return 0
  903. print('doGameScript...')
  904. sys.path.append(channelPath)
  905. module = importlib.import_module('game_script')
  906. ret = module.execute(game, sdk, config)
  907. sys.path.remove(channelPath)
  908. return ret
  909. def add_log_sdk(game, sdk, sub_channel, config, logSdk):
  910. # 拷贝jniLibs
  911. decompliePath = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  912. print('add log sdk, sdk:' + sdk)
  913. if sdk == 'jm_beta_sdk' or sdk == 'beta_sdk':
  914. sdk_path = file_utils.get_full_log_sdk_path(logSdk, True)
  915. elif sdk == 'qingshi':
  916. sdk_path = file_utils.get_full_log_sdk_v2_path(logSdk)
  917. else:
  918. sdk_path = file_utils.get_full_log_sdk_path(logSdk)
  919. print('copy log jniLibs...')
  920. jni_path = file_utils.get_full_path(sdk_path, 'jniLibs')
  921. decomplie_jni_path = file_utils.get_full_path(decompliePath, 'lib')
  922. abiFilters = []
  923. if os.path.exists(decomplie_jni_path):
  924. for abi in os.listdir(decomplie_jni_path):
  925. if abi == 'armeabi-v7a' or abi == 'x86' or abi == 'x86_64' or abi == 'arm64-v8a':
  926. abiFilters.append(abi)
  927. else:
  928. abiFilters = ['armeabi-v7a']
  929. if os.path.exists(jni_path):
  930. ret = file_utils.copy_file_all_dir(jni_path, decomplie_jni_path, False, abiFilters)
  931. if ret:
  932. return ret
  933. print('merge log AndroidManifest...')
  934. libManifest = file_utils.get_full_path(sdk_path, 'manifest.xml')
  935. if os.path.exists(libManifest):
  936. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  937. ret = xml_utils.merge_manifest_res(manifest, libManifest)
  938. if ret:
  939. return ret
  940. change_placeholders(game, sdk, sub_channel, config)
  941. return pack_log_jar(game, sdk, sub_channel, config, logSdk)
  942. def addOaidSdk(game, sdk, subChannel, config, oaidVersion):
  943. sdkPath = file_utils.getFullOaidSDKPath(oaidVersion)
  944. decompliePath = file_utils.get_decompile_path(
  945. game, sdk, subChannel, config['cache'])
  946. # 拷贝assets
  947. print('copy oaid assets...')
  948. assetsPath = file_utils.get_full_path(sdkPath, 'assets')
  949. decomplieAssetsPath = file_utils.get_full_path(decompliePath, 'assets')
  950. if os.path.exists(assetsPath):
  951. ret = file_utils.copy_file_all_dir(assetsPath, decomplieAssetsPath)
  952. if ret:
  953. return ret
  954. # 拷贝jniLibs
  955. print('copy oaid jniLibs...')
  956. jniPath = file_utils.get_full_path(sdkPath, 'jniLibs')
  957. decomplieJniPath = file_utils.get_full_path(decompliePath, 'lib')
  958. abiFilters = []
  959. if os.path.exists(decomplieJniPath):
  960. for abi in os.listdir(decomplieJniPath):
  961. if abi == 'armeabi-v7a' or abi == 'armeabi':
  962. abiFilters.append(abi)
  963. else:
  964. abiFilters = ['armeabi-v7a']
  965. if os.path.exists(jniPath):
  966. ret = file_utils.copy_file_all_dir(
  967. jniPath, decomplieJniPath, False, abiFilters)
  968. if ret:
  969. return ret
  970. print('merge oaid AndroidManifest...')
  971. libManifest = file_utils.get_full_path(sdkPath, 'manifest.xml')
  972. if os.path.exists(libManifest):
  973. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  974. ret = xml_utils.merge_manifest_res(manifest, libManifest)
  975. if ret:
  976. return ret
  977. return packOaidJar(game, sdk, subChannel, config, oaidVersion)
  978. def generateNewRFile(game, sdk, subChannel, config):
  979. """
  980. 生成新的R文件
  981. """
  982. decompliePath = file_utils.get_decompile_path(
  983. game, sdk, subChannel, config['cache'])
  984. androidPlatforms = file_utils.get_android_compile_tool_path()
  985. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  986. decomplieResPath = file_utils.get_full_path(decompliePath, 'res')
  987. compliePath = file_utils.get_full_path(decompliePath, 'gen')
  988. if not os.path.exists(compliePath):
  989. os.makedirs(compliePath)
  990. # 生成R文件
  991. print('生成R文件 ...')
  992. if config['aapt2disable']:
  993. aapt = file_utils.get_aapt_path()
  994. ret = file_utils.get_exec_permission(aapt)
  995. if ret:
  996. return ret
  997. createRCmd = '"%s" p -f -m -J "%s" -S "%s" -I "%s" -M "%s"' % (
  998. aapt, compliePath, decomplieResPath, androidPlatforms, manifest)
  999. ret = file_utils.exec_format_cmd(createRCmd)
  1000. if ret:
  1001. return ret
  1002. else:
  1003. # compile
  1004. aapt = file_utils.get_aapt2_path()
  1005. ret = file_utils.get_exec_permission(aapt)
  1006. if ret:
  1007. return ret
  1008. print('compiled res ...')
  1009. complieResPath = os.path.join(compliePath, 'compiled')
  1010. complieResCmd = '"%s" compile --dir "%s" -o "%s"' % (
  1011. aapt, decomplieResPath, complieResPath)
  1012. file_utils.exec_format_cmd(complieResCmd)
  1013. # unzip
  1014. print('unzip compiled res ...')
  1015. unzipResPath = os.path.join(compliePath, 'aapt2_res')
  1016. with zipfile.ZipFile(complieResPath) as zf:
  1017. zf.extractall(unzipResPath)
  1018. print('create unzip %s' % unzipResPath)
  1019. # link
  1020. print('link res ...')
  1021. outApk = os.path.join(compliePath, 'res.apk')
  1022. linkResCmd = '"%s" link -o "%s" -I "%s" --manifest "%s" --java "%s" --auto-add-overlay' % (
  1023. aapt, outApk, androidPlatforms, manifest, compliePath)
  1024. for filename in os.listdir(unzipResPath):
  1025. linkResCmd += ' %s' % filename
  1026. print('link cmd len is %s' % len(linkResCmd))
  1027. ret = file_utils.exec_format_cmd(linkResCmd, unzipResPath)
  1028. if ret:
  1029. return ret
  1030. # 编译R文件
  1031. print('complie R.java ...')
  1032. packageName = xml_utils.get_package_name(manifest)
  1033. packagePath = file_utils.get_package_path(compliePath, packageName)
  1034. RSourceFile = os.path.join(packagePath, 'R.java')
  1035. complieRCmd = 'javac -source 1.8 -target 1.8 -encoding UTF-8 "%s"' % RSourceFile
  1036. ret = file_utils.exec_format_cmd(complieRCmd)
  1037. if ret:
  1038. return ret
  1039. # 生成dex
  1040. print('dex R.class ...')
  1041. outDex = os.path.join(compliePath, 'classes.dex')
  1042. if config['aapt2disable']:
  1043. dx = file_utils.get_dx_path()
  1044. dexCmd = '--dex --no-warning --output="%s" "%s"' % (
  1045. outDex, compliePath)
  1046. else:
  1047. dx = file_utils.get_d8_path()
  1048. clazz = os.path.join(packagePath, '*.class')
  1049. dexCmd = '--lib "%s" --output "%s" %s' % (
  1050. androidPlatforms, compliePath, clazz)
  1051. ret = file_utils.exec_jar_cmd(dx, dexCmd)
  1052. if ret:
  1053. return ret
  1054. # 反向dex生成smali
  1055. # 存放在out目录
  1056. print('baksmali classes.dex ...')
  1057. baksmaliPath = file_utils.get_baksmali_path()
  1058. outPath = file_utils.get_full_path(decompliePath, 'out')
  1059. ret = file_utils.exec_jar_cmd(
  1060. baksmaliPath, 'd "%s" -o "%s"' % (outDex, outPath))
  1061. if ret:
  1062. return ret
  1063. # 将生成的文件拷贝到目标目录
  1064. print('copy R.smali ...')
  1065. smaliPath = file_utils.get_full_path(decompliePath, 'smali')
  1066. file_utils.copy_file_all_dir(outPath, smaliPath)
  1067. return 0
  1068. def pack_jar(game, sdk, sub_channel, config):
  1069. """
  1070. 打包所有的jar
  1071. """
  1072. split_dex = config['splitDex']
  1073. decompile_path = file_utils.get_decompile_path(
  1074. game, sdk, sub_channel, config['cache'])
  1075. outPath = file_utils.get_full_path(decompile_path, 'gen')
  1076. if not os.path.exists(outPath):
  1077. os.makedirs(outPath)
  1078. if config['aapt2disable']:
  1079. dx = file_utils.get_dx_path()
  1080. dex_cmd = '--dex --no-warning --output="%s"' % outPath
  1081. else:
  1082. dx = file_utils.get_d8_path()
  1083. androidPlatforms = file_utils.get_android_compile_tool_path()
  1084. dex_cmd = '--lib "%s" --output "%s"' % (androidPlatforms, outPath)
  1085. # 找到所有lib依赖
  1086. sdk_path = file_utils.get_full_sdk_path(sdk)
  1087. libs = os.path.join(sdk_path, 'libs')
  1088. libConfig = os.path.join(libs, 'config.json')
  1089. # 存在配置文件
  1090. if os.path.exists(libConfig):
  1091. jsonText = file_utils.read_file(libConfig)
  1092. libConf = json.loads(jsonText)
  1093. if 'libConfig' in config and config['libConfig'] in libConf:
  1094. conf = config['libConfig']
  1095. libList = libConf[conf]
  1096. for jar in libList:
  1097. dex_cmd += ' ' + os.path.join(libs, jar)
  1098. elif 'default' in libConf:
  1099. libList = libConf['default']
  1100. for jar in libList:
  1101. dex_cmd += ' ' + os.path.join(libs, jar)
  1102. else:
  1103. for jar in os.listdir(libs):
  1104. if not jar.endswith('.jar'):
  1105. continue
  1106. dex_cmd += ' ' + os.path.join(libs, jar)
  1107. else:
  1108. for jar in os.listdir(libs):
  1109. if not jar.endswith('.jar'):
  1110. continue
  1111. dex_cmd += ' ' + os.path.join(libs, jar)
  1112. if 'refactorSdk' in config and config['refactorSdk']:
  1113. pass
  1114. else:
  1115. # multidex.jar
  1116. if split_dex:
  1117. print('getMultiDexPath ...')
  1118. dex_cmd += ' ' + file_utils.get_multidex_path()
  1119. # sdk实现类
  1120. dex_cmd += ' ' + os.path.join(sdk_path, '%s.jar' % sdk)
  1121. print('packaging all jar ...')
  1122. ret = file_utils.exec_jar_cmd(dx, dex_cmd)
  1123. if ret:
  1124. return ret
  1125. # 反向dex生成smali
  1126. # 存放在out目录
  1127. print('baksmali classes.dex ...')
  1128. outDex = os.path.join(outPath, 'classes.dex')
  1129. baksmaliPath = file_utils.get_baksmali_path()
  1130. outPath = file_utils.get_full_path(decompile_path, 'out')
  1131. ret = file_utils.exec_jar_cmd(baksmaliPath, 'd "%s" -o "%s"' % (outDex, outPath))
  1132. if ret:
  1133. return ret
  1134. # 将生成的文件拷贝到目标目录
  1135. print('copy all smali ...')
  1136. smaliPath = file_utils.get_full_path(decompile_path, 'smali')
  1137. ret = file_utils.copy_file_all_dir(outPath, smaliPath, True)
  1138. if ret:
  1139. return ret
  1140. return 0
  1141. def pack_log_jar(game, sdk, sub_channel, config, log_sdk):
  1142. """
  1143. 打包Log jar
  1144. """
  1145. decompliePath = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  1146. outPath = file_utils.get_full_path(decompliePath, 'gen')
  1147. if not os.path.exists(outPath):
  1148. os.makedirs(outPath)
  1149. if config['aapt2disable']:
  1150. dx = file_utils.get_dx_path()
  1151. dexCmd = '--dex --multi-dex --no-warning --output="%s"' % outPath
  1152. else:
  1153. dx = file_utils.get_d8_path()
  1154. androidPlatforms = file_utils.get_android_compile_tool_path()
  1155. dexCmd = '--lib "%s" --output "%s"' % (androidPlatforms, outPath)
  1156. # 找到所有lib依赖
  1157. if sdk == 'jm_beta_sdk' or sdk == 'beta_sdk':
  1158. sdk_path = file_utils.get_full_log_sdk_path(log_sdk, True)
  1159. elif sdk == 'qingshi':
  1160. sdk_path = file_utils.get_full_log_sdk_v2_path(log_sdk)
  1161. else:
  1162. sdk_path = file_utils.get_full_log_sdk_path(log_sdk)
  1163. libs = os.path.join(sdk_path, 'libs')
  1164. lib_config = os.path.join(libs, 'config.json')
  1165. # 存在配置文件
  1166. if os.path.exists(lib_config):
  1167. json_text = file_utils.read_file(lib_config)
  1168. lib_list = json.loads(json_text)
  1169. for jar in lib_list:
  1170. if not jar.endswith('.jar'):
  1171. continue
  1172. dexCmd += ' ' + os.path.join(libs, jar)
  1173. else:
  1174. for jar in os.listdir(libs):
  1175. if not jar.endswith('.jar'):
  1176. continue
  1177. dexCmd += ' ' + os.path.join(libs, jar)
  1178. # sdk实现类
  1179. print('packaging all log jar ...')
  1180. if sdk != 'qingshi':
  1181. dexCmd += ' ' + os.path.join(sdk_path, '%s.jar' % log_sdk)
  1182. ret = file_utils.exec_jar_cmd(dx, dexCmd)
  1183. if ret:
  1184. return ret
  1185. # 反向dex生成smali
  1186. # 存放在out目录
  1187. print('baksmali classes.dex ...')
  1188. outDex = os.path.join(outPath, 'classes.dex')
  1189. baksmaliPath = file_utils.get_baksmali_path()
  1190. outPath = file_utils.get_full_path(decompliePath, 'out')
  1191. ret = file_utils.exec_jar_cmd(
  1192. baksmaliPath, 'd "%s" -o "%s"' % (outDex, outPath))
  1193. if ret:
  1194. return ret
  1195. # 将生成的文件拷贝到目标目录
  1196. print('copy all log smali ...')
  1197. smaliPath = file_utils.get_full_path(decompliePath, 'smali')
  1198. ret = file_utils.copy_file_all_dir(outPath, smaliPath, True)
  1199. if ret:
  1200. return ret
  1201. return 0
  1202. def packOaidJar(game, sdk, subChannel, config, oaidVerion):
  1203. '''
  1204. 打包oaid jar
  1205. '''
  1206. decompliePath = file_utils.get_decompile_path(
  1207. game, sdk, subChannel, config['cache'])
  1208. outPath = file_utils.get_full_path(decompliePath, 'gen')
  1209. if not os.path.exists(outPath):
  1210. os.makedirs(outPath)
  1211. if config['aapt2disable']:
  1212. dx = file_utils.get_dx_path()
  1213. dexCmd = '--dex --multi-dex --no-warning --output="%s"' % outPath
  1214. else:
  1215. dx = file_utils.get_d8_path()
  1216. androidPlatforms = file_utils.get_android_compile_tool_path()
  1217. dexCmd = '--lib "%s" --output "%s"' % (androidPlatforms, outPath)
  1218. # 找到所有lib依赖
  1219. sdkPath = file_utils.getFullOaidSDKPath(oaidVerion)
  1220. libs = os.path.join(sdkPath, 'libs')
  1221. libConfig = os.path.join(libs, 'config.json')
  1222. # 存在配置文件
  1223. # if os.path.exists(libConfig):
  1224. # jsonText = file_utils.readFile(libConfig)
  1225. # libList = json.loads(jsonText)
  1226. # for jar in libList:
  1227. # if not jar.endswith('.jar'):
  1228. # continue
  1229. # dexCmd += ' ' + os.path.join(libs, jar)
  1230. # else:
  1231. # for jar in os.listdir(libs):
  1232. # if not jar.endswith('.jar'):
  1233. # continue
  1234. # dexCmd += ' ' + os.path.join(libs, jar)
  1235. # sdk实现类
  1236. print('packageing oaid jar ...')
  1237. dexCmd += ' ' + os.path.join(libs, 'miit_mdid_%s.jar' % oaidVerion)
  1238. ret = file_utils.exec_jar_cmd(dx, dexCmd)
  1239. if ret:
  1240. return ret
  1241. # 反向dex生成smali
  1242. # 存放在out目录
  1243. print('baksmali classes.dex ...')
  1244. outDex = os.path.join(outPath, 'classes.dex')
  1245. baksmaliPath = file_utils.get_baksmali_path()
  1246. outPath = file_utils.get_full_path(decompliePath, 'out')
  1247. ret = file_utils.exec_jar_cmd(
  1248. baksmaliPath, 'd "%s" -o "%s"' % (outDex, outPath))
  1249. if ret:
  1250. return ret
  1251. # 将生成的文件拷贝到目标目录
  1252. print('copy all log smali ...')
  1253. smaliPath = file_utils.get_full_path(decompliePath, 'smali')
  1254. ret = file_utils.copy_file_all_dir(outPath, smaliPath, True)
  1255. if ret:
  1256. return ret
  1257. return 0
  1258. def split_dex(game, sdk, sub_channel, config):
  1259. """
  1260. 分割dex
  1261. """
  1262. # 判断是否已经存在application
  1263. # 存在,则往原application添加内容
  1264. # 不存在,则拷贝一个默认的android.support.multidex.MultiDexApplication
  1265. print('add MultiDex support...')
  1266. decompile_path = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  1267. manifest = os.path.join(decompile_path, 'AndroidManifest.xml')
  1268. application = xml_utils.get_application_attr(manifest, 'name')
  1269. if application is None:
  1270. ret = xml_utils.change_application_attr(manifest, 'name', 'android.support.multidex.MultiDexApplication')
  1271. if ret:
  1272. return ret
  1273. else:
  1274. smaliPath = os.path.join(decompile_path, 'smali')
  1275. application_file = file_utils.get_package_path(smaliPath, application)
  1276. application_file += '.smali'
  1277. ret = change_application_dex(application_file)
  1278. if ret:
  1279. return ret
  1280. return split_smali(game, sdk, sub_channel, config, application)
  1281. def change_application_dex(file):
  1282. """
  1283. 修改application的smali文件,增加MultiDex操作
  1284. """
  1285. index = file_utils.get_application_smali_index(file)
  1286. file_utils.insert_application_smali(file, index)
  1287. return 0
  1288. def split_smali(game, sdk, sub_channel, config, application):
  1289. """
  1290. 如果函数上限超过限制,自动拆分smali,以便生成多个dex文件
  1291. """
  1292. print('splitSmali...')
  1293. decompliePath = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  1294. smaliPath = os.path.join(decompliePath, 'smali')
  1295. appPackage = None
  1296. if application:
  1297. appPackage = application[:application.rfind('.')]
  1298. appPackage = appPackage.replace('.', '/')
  1299. allFiles = []
  1300. allFiles = file_utils.list_files(smaliPath, allFiles)
  1301. # print('file count is %d' % len(allFiles))
  1302. # maxFuncNum = 65535
  1303. # 留一点空间,防止计算误差
  1304. maxFuncNum = 64000
  1305. currFucNum = 0
  1306. totalFucNum = 0
  1307. currDexIndex = 1
  1308. allRefs = []
  1309. # 保证Application等类在第一个classex.dex文件中
  1310. for f in allFiles:
  1311. f = f.replace('\\', '/')
  1312. if (appPackage and appPackage in f) or '/android/support/multidex' in f:
  1313. currFucNum += smali_utils.get_smali_method_count(f, allRefs)
  1314. totalFucNum = currFucNum
  1315. for f in allFiles:
  1316. f = f.replace('\\', '/')
  1317. if not f.endswith('.smali'):
  1318. continue
  1319. if (appPackage and appPackage in f) or '/android/support/multidex' in f:
  1320. continue
  1321. thisFucNum = smali_utils.get_smali_method_count(f, allRefs)
  1322. totalFucNum += thisFucNum
  1323. # print('%d # %d ==> %s' % (thisFucNum, currDexIndex, f))
  1324. # print('totalFucNum is %d' % totalFucNum)
  1325. if currFucNum + thisFucNum >= maxFuncNum:
  1326. currFucNum = thisFucNum
  1327. currDexIndex += 1
  1328. newDexPath = os.path.join(
  1329. decompliePath, 'smali_classes%d' % currDexIndex)
  1330. os.makedirs(newDexPath)
  1331. else:
  1332. currFucNum += thisFucNum
  1333. if currDexIndex > 1:
  1334. newDexPath = os.path.join(
  1335. decompliePath, 'smali_classes%d' % currDexIndex)
  1336. targetFile = newDexPath + f[len(smaliPath):]
  1337. file_utils.copy_file(f, targetFile, True)
  1338. return 0
  1339. def changeVersion(game, sdk, sub_channel, config):
  1340. """
  1341. 更改版本号
  1342. """
  1343. decompliePath = file_utils.get_decompile_path(
  1344. game, sdk, sub_channel, config['cache'])
  1345. yml = os.path.join(decompliePath, 'apktool.yml')
  1346. versionCode = None
  1347. versionName = None
  1348. targetSdkVersion = None
  1349. if 'versionCode' in config:
  1350. versionCode = config['versionCode']
  1351. if 'versionName' in config:
  1352. versionName = config['versionName']
  1353. if 'targetSdkVersion' in config:
  1354. targetSdkVersion = config['targetSdkVersion']
  1355. else:
  1356. targetSdkVersion = 26
  1357. print('changeVersion versionCode=%s,versionName=%s,targetSdkVersion=%s' %
  1358. (versionCode, versionName, targetSdkVersion))
  1359. return file_utils.changeVersion(yml, versionCode, versionName, targetSdkVersion)
  1360. def recomplie(game, sdk, subChannel, config):
  1361. '''
  1362. 回编译
  1363. '''
  1364. print('recomplie apk...')
  1365. apktoolPath = file_utils.get_apktool_path()
  1366. decompliePath = file_utils.get_decompile_path(
  1367. game, sdk, subChannel, config['cache'])
  1368. outApk = file_utils.getOutApkPath(game, sdk, subChannel, config['cache'])
  1369. useAppt2 = ' --use-aapt2'
  1370. if config['aapt2disable']:
  1371. useAppt2 = ''
  1372. return file_utils.exec_jar_cmd(apktoolPath, 'b -f "%s" -o "%s"%s' % (decompliePath, outApk, useAppt2))
  1373. def alignApk(game, sdk, subChannel, config):
  1374. '''
  1375. 对齐apk
  1376. '''
  1377. print('align apk...')
  1378. outApk = file_utils.getOutApkPath(game, sdk, subChannel, config['cache'])
  1379. alignApk = file_utils.getAlignApkPath(
  1380. game, sdk, subChannel, config['cache'])
  1381. alignapkTool = file_utils.get_zipalign_path()
  1382. if os.path.exists(alignApk):
  1383. os.remove(alignApk)
  1384. ret = file_utils.get_exec_permission(alignapkTool)
  1385. if ret:
  1386. return ret
  1387. # zipalign.exe -v -p 4 input.apk output.apk
  1388. return file_utils.exec_format_cmd('"%s" -f -p 4 "%s" "%s"' % (alignapkTool, outApk, alignApk))
  1389. def apk_signer_apk(game, sdk, sub_channel, config):
  1390. """
  1391. 签名apk
  1392. """
  1393. print('sign apk...')
  1394. print('game = %s, sdk = %s, subChannel = %s, ...' %
  1395. (game, sdk, sub_channel))
  1396. path = os.path.join(file_utils.get_current_path(), 'keystore', 'key.json')
  1397. jsonText = file_utils.read_file(path)
  1398. signConfig = json.loads(jsonText)
  1399. keystore = {}
  1400. for key in signConfig.keys():
  1401. print(key)
  1402. if game.find(key) > -1 or game == key:
  1403. if sdk in signConfig[key]:
  1404. keystore = signConfig[key][sdk]
  1405. break
  1406. else:
  1407. keystore = signConfig['default']
  1408. else:
  1409. keystore = signConfig['default']
  1410. # if game in signConfig:
  1411. # if sdk in signConfig[game]:
  1412. # keystore = signConfig[game][sdk]
  1413. # else:
  1414. # keystore = signConfig['default']
  1415. # else:
  1416. # keystore = signConfig['default']
  1417. print('storeFile is "%s"' % keystore['storeFile'])
  1418. apksigner = file_utils.get_apksigner_path()
  1419. alignApk = file_utils.getAlignApkPath(
  1420. game, sdk, sub_channel, config['cache'])
  1421. signedApk = file_utils.get_signed_apk_path(
  1422. game, sdk, sub_channel, config['cache'])
  1423. storeFile = os.path.join(file_utils.get_current_path(),
  1424. 'keystore', keystore['storeFile'])
  1425. # java -jar apksigner.jar sign --ks key.jks --ks-key-alias releasekey --ks-pass pass:pp123456 --key-pass pass:pp123456 --out output.apk input.apk
  1426. v2disable = ''
  1427. if 'v2disable' in config and config['v2disable']:
  1428. v2disable = ' --v2-signing-enabled=false'
  1429. return file_utils.exec_jar_cmd(apksigner,
  1430. 'sign%s --ks "%s" --ks-key-alias %s --ks-pass pass:%s --key-pass pass:%s --out "%s" "%s"' % (
  1431. v2disable, storeFile, keystore['keyAlias'], keystore['storePassword'],
  1432. keystore['keyPassword'], signedApk, alignApk))
  1433. def add_channel(game, sdk, sub_channel, config):
  1434. """
  1435. 添加渠道信息
  1436. """
  1437. if 'v2disable' in config and config['v2disable']:
  1438. return 0
  1439. walle = file_utils.getWallePath()
  1440. signedApk = file_utils.get_signed_apk_path(game, sdk, sub_channel, config['cache'])
  1441. walleApk = file_utils.getWalleApkPath(game, sdk, sub_channel, config['cache'])
  1442. properties = config['properties']
  1443. appid = ''
  1444. appkey = ''
  1445. host = ''
  1446. if 'appid' in properties:
  1447. appid = properties['appid']
  1448. if 'appkey' in properties:
  1449. appkey = properties['appkey']
  1450. if 'host' in properties:
  1451. host = properties['host']
  1452. return file_utils.exec_jar_cmd(walle, 'put -e version=%s,agent=%s,appid=%s,appkey=%s,host=%s "%s" "%s"' % (
  1453. config_utils.getDate(), properties['agent'], appid, appkey, host, signedApk, walleApk))
  1454. def clearTemp(game, sdk, sub_channel, config):
  1455. """
  1456. 清空中间产生的文件
  1457. """
  1458. print('clear temp...')
  1459. targetApkPath = file_utils.getTargetApkPath(game, sdk, config['cache'])
  1460. if os.path.exists(targetApkPath):
  1461. file_utils.delete_folder(targetApkPath)
  1462. decompliePath = file_utils.get_decompile_path(
  1463. game, sdk, sub_channel, config['cache'])
  1464. if os.path.exists(decompliePath):
  1465. file_utils.delete_folder(decompliePath)
  1466. random = config['random']
  1467. channelPath = file_utils.getChannelPath(game, random, sdk)
  1468. if os.path.exists(channelPath):
  1469. file_utils.delete_folder(channelPath)
  1470. print('clear temp end')
  1471. def packConsoleInput():
  1472. '''
  1473. 控制台打包
  1474. '''
  1475. if len(sys.argv) < 3:
  1476. print('argument is missing')
  1477. return 1
  1478. # 校验参数
  1479. game = sys.argv[1]
  1480. sdk = sys.argv[2]
  1481. # 可选参数,没有则默认打全部渠道
  1482. subChannel = None
  1483. if len(sys.argv) > 3:
  1484. subChannel = sys.argv[3]
  1485. return packConsole(game, sdk, subChannel)
  1486. def packConsole(game, sdk, config, subChannel):
  1487. """
  1488. 控制台打包
  1489. """
  1490. cache_game_apk_path = file_utils.get_cache_game_apk(game, config['random'], sdk)
  1491. print('cache game apk path %s' % cache_game_apk_path)
  1492. if not os.path.exists(cache_game_apk_path):
  1493. print('game "%s" not exists' % game)
  1494. return 1
  1495. if not os.path.exists(file_utils.get_full_sdk_path(sdk)):
  1496. print('sdk "%s" not exists' % sdk)
  1497. return 1
  1498. global startTime
  1499. startTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  1500. # 读取配置
  1501. random = config['random']
  1502. channelPath = file_utils.getChannelPath(game, random, sdk)
  1503. configPath = os.path.join(channelPath, 'config.json')
  1504. if not os.path.exists(configPath):
  1505. print('%s not exists' % configPath)
  1506. return 1
  1507. jsonText = file_utils.read_file(configPath)
  1508. config = json.loads(jsonText)
  1509. # 检查参数
  1510. if not config_utils.checkConfig(config):
  1511. return 1
  1512. # 处理参数
  1513. config_utils.replaceArgs(config)
  1514. successCount = 0
  1515. failureCount = 0
  1516. if type(config) == dict:
  1517. if subChannel is None or config['subChannel'] == subChannel:
  1518. ret = pack(game, sdk, config)
  1519. if ret:
  1520. failureCount += 1
  1521. else:
  1522. successCount += 1
  1523. else:
  1524. print('subChannel "%s" no found' % subChannel)
  1525. return 1
  1526. elif type(config) == list:
  1527. found = False
  1528. for itemConfig in config:
  1529. if subChannel is None or itemConfig['subChannel'] == subChannel:
  1530. found = True
  1531. ret = pack(game, sdk, itemConfig)
  1532. if ret:
  1533. failureCount += 1
  1534. else:
  1535. successCount += 1
  1536. if not found:
  1537. print('subChannel "%s" no found' % subChannel)
  1538. return 1
  1539. print('success %d, failure %d' % (successCount, failureCount))
  1540. subChannelPath = os.path.join(channelPath, subChannel)
  1541. print('------subChannelPath 目录清空:%s -------' % subChannelPath)
  1542. file_utils.delete_folder(subChannelPath)
  1543. return 0
  1544. def formatXml(game, sdk, subChannel, config):
  1545. decompliePath = file_utils.get_decompile_path(
  1546. game, sdk, subChannel, config['cache'])
  1547. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  1548. return xml_utils.formatXml(manifest)
  1549. def copy_v1_apk_2_out_dir(game, sdk, sub_channel, config):
  1550. walleApk = file_utils.getWalleApkPath(game, sdk, sub_channel, config['cache'])
  1551. releaseApkPath = ""
  1552. if 'outName' in config and 'outPath' in config:
  1553. if not os.path.exists(config['outPath']):
  1554. os.makedirs(config['outPath'])
  1555. releaseApkPath = os.path.join(config['outPath'], config['outName'] + '.apk')
  1556. elif 'outName' in config:
  1557. releaseApkPath = file_utils.getRenameApkPath(game, sdk, config['cache'], config['outName'])
  1558. print('------生成正式包路径 %s -------' % releaseApkPath)
  1559. file_utils.copy_file(walleApk, releaseApkPath)
  1560. def copy_v2_apk_2_out_dir(game, sdk, sub_channel, config):
  1561. signed_apk = file_utils.get_signed_apk_path(game, sdk, sub_channel, config['cache'])
  1562. release_apk_path = ""
  1563. if 'outName' in config and 'outPath' in config:
  1564. if not os.path.exists(config['outPath']):
  1565. os.makedirs(config['outPath'])
  1566. release_apk_path = os.path.join(config['outPath'], config['outName'] + '.apk')
  1567. elif 'outName' in config:
  1568. release_apk_path = file_utils.getRenameApkPath(game, sdk, config['cache'], config['outName'])
  1569. print('------生成正式包路径 %s -------' % release_apk_path)
  1570. file_utils.copy_file(signed_apk, release_apk_path)
  1571. def replace_hardware_accelerated(game, sdk, subChannel, config):
  1572. decompliePath = file_utils.get_decompile_path(game, sdk, subChannel, config['cache'])
  1573. manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
  1574. lines = open(manifest).readlines()
  1575. fp = open(manifest, "w")
  1576. isReplaced = False
  1577. for l in lines:
  1578. if isReplaced == False and l.find("android:hardwareAccelerated=") >= 0:
  1579. isReplace = True
  1580. l = re.sub("android:hardwareAccelerated=\"false\"",
  1581. "android:hardwareAccelerated=\"true\"", l)
  1582. fp.write(l)
  1583. fp.close()
  1584. pass
  1585. def remove_v2_old_abi(game, sdk, sub_channel, config):
  1586. print('remove v2 old abi...')
  1587. decompile_path = file_utils.get_decompile_path(game, sdk, sub_channel, config['cache'])
  1588. lib_path = os.path.join(decompile_path, 'lib')
  1589. abi_folders = os.listdir(lib_path)
  1590. for abi_folder in abi_folders:
  1591. abi_folder_path = os.path.join(lib_path, abi_folder)
  1592. abi_files = os.listdir(abi_folder_path)
  1593. for abi in abi_files:
  1594. if abi == 'libalicomphonenumberauthsdk_core.so':
  1595. abi_path = os.path.join(abi_folder_path, abi)
  1596. print(abi_path)
  1597. os.remove(abi_path)
  1598. if abi == 'libauth_number_product-2.12.1-log-online-standard-release_alijtca_plus.so':
  1599. abi_path = os.path.join(abi_folder_path, abi)
  1600. print(abi_path)
  1601. os.remove(abi_path)
  1602. if abi == 'libdolin-zap.so':
  1603. abi_path = os.path.join(abi_folder_path, abi)
  1604. print(abi_path)
  1605. os.remove(abi_path)
  1606. if abi == 'libmmkv.so':
  1607. abi_path = os.path.join(abi_folder_path, abi)
  1608. print(abi_path)
  1609. os.remove(abi_path)
  1610. if abi == 'libqsgamesdk.so':
  1611. abi_path = os.path.join(abi_folder_path, abi)
  1612. print(abi_path)
  1613. os.remove(abi_path)
  1614. if abi == 'libsecsdk.so':
  1615. abi_path = os.path.join(abi_folder_path, abi)
  1616. print(abi_path)
  1617. os.remove(abi_path)
  1618. def openFile(file, mode):
  1619. return open(file, mode, encoding='UTF-8')
  1620. def is_refactor_sdk(config) -> bool:
  1621. return 'refactorSdk' in config and config['refactorSdk']