Compare commits
1150 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ef6a2c58ff | |||
| 2aa41661a2 | |||
| e326f072d2 | |||
| f53cc18ab6 | |||
| 723a504d7c | |||
| dab48607e8 | |||
| 3ee69146bb | |||
| ca86a66b14 | |||
| c92bdd3014 | |||
| 0be23f26f2 | |||
| 6ce4592e5e | |||
| 92caedb011 | |||
| f796411fa8 | |||
| d45f185f77 | |||
| 10028dfebc | |||
| fa06795cef | |||
| c1eb324d79 | |||
| cdf9528583 | |||
| 5f5a621bd1 | |||
| b8d54dfa59 | |||
| b4f39d09e4 | |||
| a3aea6259c | |||
| 73e4c90956 | |||
| c1432159f3 | |||
| 45f47d98ba | |||
| 2e9638b8c5 | |||
| 7ea30c1d0e | |||
| 034e04944a | |||
| 99326596d5 | |||
| 1cc2b85816 | |||
| f4cd9419a4 | |||
| a24b9d92c7 | |||
| 8e7e83ad72 | |||
| cd810f0048 | |||
| fa050039cd | |||
| 935fb1149f | |||
| 951817455a | |||
| e71e7f6163 | |||
| 09be5e157d | |||
| 1f5e59fc1d | |||
| e58861afa4 | |||
| 44e51ecb0a | |||
| 794c17a1bb | |||
| 1b287962f0 | |||
| 8bdf98b9d8 | |||
| e1aeb61c9b | |||
| a39a70ac2d | |||
| 4fdcaaf591 | |||
| b4502638ff | |||
| 05502d56b1 | |||
| 90e1e8a40f | |||
| b10293da50 | |||
| 83cf0687e6 | |||
| f56b03716a | |||
| 61a41e6039 | |||
| 20ae9fe0ec | |||
| 74fdec9d72 | |||
| 3437265cc1 | |||
| 271993a876 | |||
| 3a8b7bb920 | |||
| fd85f3889d | |||
| 556ecea749 | |||
| 8a97844676 | |||
| f152296e7a | |||
| 4ccc789c7c | |||
| 747b02eb7a | |||
| a73c033c03 | |||
| 939db8c820 | |||
| 8601440d97 | |||
| 7a1fa90175 | |||
| 46722ba69d | |||
| 70d9d461bf | |||
| 91944df6a4 | |||
| ef86c1158c | |||
| 0f3b6ed34b | |||
| 8b50620ddc | |||
| 8b2a9eb6ca | |||
| 7297f5480e | |||
| 3bee8cc034 | |||
| 584a16e111 | |||
| 6460c7f8d6 | |||
| feb99c9f78 | |||
| 68ac809bcb | |||
| de207f66d9 | |||
| 054fcd2049 | |||
| 497fc998fe | |||
| 03f76453ab | |||
| 0a87bd354a | |||
| 1baceaef15 | |||
| 9719a7fa28 | |||
| 1718a66126 | |||
| b317ef3a39 | |||
| 8b0cd69ae6 | |||
| c7126e9836 | |||
| f3d01335a4 | |||
| 88e029b129 | |||
| 2bc72328c1 | |||
| 81179b1f72 | |||
| 9a7d4997c2 | |||
| 3b6ac881c2 | |||
| 6b5fb7d8bc | |||
| 1551b0a358 | |||
| 6540af8386 | |||
| 9badcdc382 | |||
| 0ba94fa56f | |||
| 52c1343ade | |||
| 7a0e633b79 | |||
| 9b68b05d7d | |||
| 9e7f6b0854 | |||
| cf20ad6fc2 | |||
| cb7bdba338 | |||
| f1fc06ca84 | |||
| 18f9fe7fcf | |||
| 18816a8a4e | |||
| 8d379501cb | |||
| 8f4c6abfd3 | |||
| a24d0a9618 | |||
| 8cdd66cd89 | |||
| 3fd34576e8 | |||
| 78d5cbcc42 | |||
| 803f2bef75 | |||
| 40c7e8f9e6 | |||
| b3c5ca6112 | |||
| 31067ea66d | |||
| 4e7626ff41 | |||
| e62822505e | |||
| cbc705d1eb | |||
| aa2e147a51 | |||
| 6249726839 | |||
| 8f4bc5a164 | |||
| eee459d08a | |||
| 81b4e40dbf | |||
| 261068e286 | |||
| 84364a7c66 | |||
| 3beb47a8be | |||
| ca76af4474 | |||
| bc33673533 | |||
| c5d038a173 | |||
| b1e492df1b | |||
| 9d9c213af7 | |||
| d3f97ea527 | |||
| 0a5fb4cb1d | |||
| 6905f7191a | |||
| bad7fb4922 | |||
| 250fa7eb7b | |||
| f0cd8567cb | |||
| f6dd35e4b8 | |||
| 2dc299e7f4 | |||
| 366e8ded14 | |||
| 8175742143 | |||
| fc858f1272 | |||
| 84b668714b | |||
| 5ea5346ee8 | |||
| c2eb0b267c | |||
| 7fb502e87e | |||
| 98726ddc3a | |||
| 75ff76acf4 | |||
| ba552812a3 | |||
| 83bfeb0abc | |||
| 70f1b7a678 | |||
| 455d53fee0 | |||
| 39e4b5bf55 | |||
| 40a729b6f8 | |||
| 9643176e06 | |||
| 1a70c33bef | |||
| 888ebe5f54 | |||
| cb02dbae57 | |||
| 2683d02dcd | |||
| ceb924e8f1 | |||
| bd91609a80 | |||
| 2fd74a4698 | |||
| e9e0d3b43e | |||
| 17e09ddad3 | |||
| 65427c55d6 | |||
| 7f99f75c6f | |||
| 548aea8d13 | |||
| a177137744 | |||
| 3c6443d78f | |||
| ba81ed9cb0 | |||
| 6a1cbd10c6 | |||
| 7e9ac0c4f1 | |||
| fe889639b3 | |||
| 848e43af28 | |||
| c7a3893fae | |||
| f7d633188c | |||
| e1e7d2d3d6 | |||
| 2b8a280768 | |||
| 6efe96eb0d | |||
| 3562fe9273 | |||
| 739ef44a8b | |||
| 879b42dbf2 | |||
| fae626bb98 | |||
| cebd639d78 | |||
| 17a99a1cda | |||
| 2a03683e1e | |||
| a579b3fe10 | |||
| 9c75dd18df | |||
| cdc9c86852 | |||
| fab1851436 | |||
| a6704e46a9 | |||
| e188f70eb6 | |||
| 02dd115886 | |||
| 5cbfc7b461 | |||
| b4742b5645 | |||
| 5ec25475ea | |||
| c58040ef83 | |||
| 75701b6875 | |||
| 2155a33689 | |||
| 68a9d5d771 | |||
| ebf6107faf | |||
| e4bc36a743 | |||
| 7a64251811 | |||
| 65409d75a7 | |||
| d40081d58b | |||
| f276e981ed | |||
| e50db66b47 | |||
| fc84022852 | |||
| b593f2f3ea | |||
| e782d0542c | |||
| 1a085cad98 | |||
| 1c33a0c4c5 | |||
| 3c4a7961c2 | |||
| 712f9b84cf | |||
| 2efb7b76cc | |||
| 5c4d93ce15 | |||
| 7addd92058 | |||
| 82c5898b9a | |||
| cced6b7035 | |||
| ae0b5b3738 | |||
| 6fdf9cbe5d | |||
| 009244c65d | |||
| 73a720bb9c | |||
| fd9df9904f | |||
| e75fb3a40d | |||
| 0bef1a2aa8 | |||
| 395eb641e5 | |||
| 9019242ffb | |||
| 9433bb72ca | |||
| 500f751152 | |||
| 9ebe3f4a0e | |||
| 4727f22b0f | |||
| 8c92fc9a42 | |||
| 2a7cb34218 | |||
| e1a42b49c1 | |||
| 5a825debf5 | |||
| e46b0a42b0 | |||
| eb0c442a5e | |||
| eb6460236b | |||
| ef051daffd | |||
| b6acb302d2 | |||
| 5cfc5a3971 | |||
| 04de97af16 | |||
| 6367f90589 | |||
| bc8f9d07bb | |||
| a3d693ddc1 | |||
| e205abd120 | |||
| 5da8fccef7 | |||
| c7e78142ee | |||
| 79cbb44d51 | |||
| dcde3db33a | |||
| 44fbc7a182 | |||
| 354c7d1f85 | |||
| d7a85edb76 | |||
| ceb9dc6707 | |||
| b0f20ee017 | |||
| cdf78f2bc5 | |||
| d3f0a8fe4a | |||
| 17acf1bd86 | |||
| 31a0bb24c7 | |||
| 13ff1f4343 | |||
| ec76be9d5e | |||
| 84d53616a0 | |||
| 2758216ae2 | |||
| c492f066ca | |||
| 897478e30e | |||
| a94d825ead | |||
| ba05e6137e | |||
| dc55342343 | |||
| 3ea96d27db | |||
| 48842c099b | |||
| 4f87cac46a | |||
| 52680b63b9 | |||
| f89defc78f | |||
| 46e9a161a4 | |||
| 8e602e8169 | |||
| c60df98577 | |||
| ad7db50336 | |||
| e40ef5292e | |||
| 94b844788c | |||
| 9c222baf91 | |||
| 0794606e57 | |||
| be34c486bf | |||
| fa7a5fef9b | |||
| 9e518d5414 | |||
| 2d17ecd438 | |||
| 56d6c28811 | |||
| 86b77e29e2 | |||
| 23b8b09834 | |||
| 30eb397c66 | |||
| 05bcc0f818 | |||
| 3f9434239f | |||
| 4caf7eabc0 | |||
| 0aee08bbb0 | |||
| 602dbff3c8 | |||
| d52cfd475f | |||
| 4512accb37 | |||
| 2d57c00149 | |||
| cae908da6a | |||
| 38f97673b8 | |||
| ed2bf89413 | |||
| 259d343e31 | |||
| 8e9dbafb4d | |||
| 7e737d7a46 | |||
| 50fd30d173 | |||
| 4c7310f71e | |||
| b3e7168922 | |||
| 261cc5b0eb | |||
| 60218eea97 | |||
| bc1945326a | |||
| 2fd12d56ed | |||
| cb28838b40 | |||
| 4cfd6952c0 | |||
| f5761e378e | |||
| 314144c384 | |||
| 81debc1cd8 | |||
| 9a2baf1d8c | |||
| 55ec26bd3d | |||
| 4c372eeb2b | |||
| c2f9e28edd | |||
| 65a8297fe0 | |||
| 1a48cca197 | |||
| 24984b5d67 | |||
| 619660e5e5 | |||
| c9c4a996dc | |||
| b8ae8b68dc | |||
| a9f4620d8b | |||
| 66abdb1eed | |||
| 1dc4be2d54 | |||
| a286f51801 | |||
| 27708da1bf | |||
| 3aa0e19b0f | |||
| 4d5627348a | |||
| 2aefeb5e53 | |||
| 728b663c7a | |||
| 36156cddc4 | |||
| 2b98702ceb | |||
| 2c2ab02398 | |||
| 8ae8c6d6fb | |||
| 1171424f19 | |||
| 3444922861 | |||
| 5821a519ee | |||
| 439a2353b0 | |||
| 8f8f3193dd | |||
| 5907b8b1a5 | |||
| ba5783417e | |||
| 56573deea1 | |||
| 892933888c | |||
| b3725baad0 | |||
| cf79735780 | |||
| ad059fe18d | |||
| 03fa2052da | |||
| d7d55b7341 | |||
| 6ea9a7de90 | |||
| 3bc65f42c7 | |||
| 854227304f | |||
| 62d34c6c06 | |||
| 69f0beff9c | |||
| 2a32859c48 | |||
| c6bdb4ee8d | |||
| cf5e981758 | |||
| 2bf246562b | |||
| c1cd25b89b | |||
| 2eb259055a | |||
| fe743590c9 | |||
| d3de1c238c | |||
| 931593d726 | |||
| 8f002fc804 | |||
| 10e0d0123e | |||
| b93cb06662 | |||
| 5471099e7b | |||
| 5a2f86be87 | |||
| 3d7ce17b07 | |||
| cf0e237529 | |||
| 60c84153e5 | |||
| f9a8efe084 | |||
| 6b48c546c4 | |||
| b1893718f6 | |||
| 7ad95d5f26 | |||
| 778b0e8f16 | |||
| ad847f6113 | |||
| 27778c2b31 | |||
| 484694cbdb | |||
| 969680a7ad | |||
| 6357e008dc | |||
| a570cfe32b | |||
| ccba561d47 | |||
| 0dcf86ce1c | |||
| 961d4ebb5c | |||
| 54b947504c | |||
| f5abd7e075 | |||
| 35cd97c751 | |||
| 147bc150f5 | |||
| ee7f102d34 | |||
| 7f0e59aba5 | |||
| 135b55f6f9 | |||
| 6986bd9a57 | |||
| 17782a500f | |||
| 64a64960ac | |||
| d4be850e68 | |||
| a6feb57f85 | |||
| 50fee01249 | |||
| 4ff12e91aa | |||
| 24b196f216 | |||
| 414064699a | |||
| d36b2f99ee | |||
| 704b73aef7 | |||
| 99878606d5 | |||
| e1cfccfcc0 | |||
| 4c2a46875d | |||
| 6ce64892e4 | |||
| 92e1c55913 | |||
| 72cfcd66b1 | |||
| 0cb65ab216 | |||
| d18731ccfe | |||
| b0a4aa66f6 | |||
| aad92e529e | |||
| 6e03e75110 | |||
| 91f79a5ff1 | |||
| cc53a1f3d6 | |||
| 25cd086298 | |||
| b27ecab969 | |||
| db1c0d954f | |||
| 03d20aed61 | |||
| d37929548e | |||
| 663891dd54 | |||
| 79d1c4fed4 | |||
| ecc8196701 | |||
| c2fb1a58db | |||
| 55998c3c4d | |||
| 83e44808cb | |||
| bfbc9900ed | |||
| 1735ba3312 | |||
| 1ef8fa5deb | |||
| d0a2868e5a | |||
| 49c2366a89 | |||
| cb7d985195 | |||
| bead0bded1 | |||
| cc92d5f639 | |||
| 84c281122e | |||
| bb4a35a6a9 | |||
| 71ae36fbf0 | |||
| 04864e059c | |||
| 7a47184af3 | |||
| 48e2831e96 | |||
| c1caa23b10 | |||
| 443cc6007d | |||
| 7d99923960 | |||
| 7342d0706f | |||
| c15c194feb | |||
| 3b6a5b5a20 | |||
| f9028ea8a5 | |||
| 8cd06a80ba | |||
| 6c80266abb | |||
| ca3c1fa8c2 | |||
| 2b7deaef2c | |||
| 42f1898bd1 | |||
| 0bdff3eac7 | |||
| a00f6660a1 | |||
| 67d1ad497f | |||
| f1bbf4e9fc | |||
| 00ff5e6a94 | |||
| 7f77a8fd63 | |||
| 7c1267148b | |||
| 2dbb7b67cb | |||
| c41db52b05 | |||
| 72f3a262ca | |||
| 2fbe6a4937 | |||
| c6fb63afe6 | |||
| 2e05320ddf | |||
| a3f86ab604 | |||
| 5d2efda925 | |||
| 4a30ac04b7 | |||
| 1097068393 | |||
| df88502c3d | |||
| b8df485a7e | |||
| a8a66a7b1e | |||
| a1548faeda | |||
| 34f452be6e | |||
| bef04854e3 | |||
| 757782e43b | |||
| 8a69f565a3 | |||
| be20d1fec6 | |||
| 7a71e457ef | |||
| 3af9fa0a10 | |||
| ff8b3efde9 | |||
| 161f63a664 | |||
| 3206e04639 | |||
| f1dea0f200 | |||
| d94a83a7c3 | |||
| 6bbc7104d9 | |||
| a2180196ee | |||
| a6dc4c7891 | |||
| fa7355c5c6 | |||
| 0140c10f15 | |||
| 796da0e673 | |||
| 743f78096a | |||
| 52d726b6f3 | |||
| bed4450900 | |||
| c2ab369d0c | |||
| 32a7f37b6a | |||
| b299199579 | |||
| 7091ea179d | |||
| dceb582bb1 | |||
| 6e2e9f7dcf | |||
| c27025269e | |||
| cf1411b412 | |||
| b167f5bb8b | |||
| 87d0fd9edb | |||
| b59a169e10 | |||
| 941e3985b0 | |||
| 127fb76c19 | |||
| 5f3028f795 | |||
| b596f04dba | |||
| 0bb96ecf12 | |||
| 60f21f6113 | |||
| 051000e4a8 | |||
| 14e8020147 | |||
| a99b1499a2 | |||
| 6a1c01556b | |||
| c41327640b | |||
| 7df5834ebc | |||
| ebafc2f98f | |||
| 92c9d81171 | |||
| 7d34a3972d | |||
| 90f1254c6c | |||
| 8b71d68749 | |||
| 17c0cf52b6 | |||
| 045be4ff09 | |||
| af7948fcb5 | |||
| e1c12d5007 | |||
| 8676b20fbb | |||
| 54db9fb910 | |||
| 0eaee1ae63 | |||
| e141dfb6b5 | |||
| b14b8c9f66 | |||
| b4b589f307 | |||
| 7a74bc0d04 | |||
| b826c0a9ad | |||
| a197b59200 | |||
| c25503d7f8 | |||
| 2c0449dcf6 | |||
| 59655daa3b | |||
| 1c36d7b923 | |||
| a51175620c | |||
| 7b95c265df | |||
| a11bb9c210 | |||
| 72227a5591 | |||
| f9f2eb4c05 | |||
| e9c57df5fb | |||
| 158c47d94b | |||
| 7616435098 | |||
| 69443ff457 | |||
| 6a257c0a9f | |||
| eddd56e53a | |||
| de6648867b | |||
| 567a6ceda5 | |||
| 59330bcd7e | |||
| 36803f24bc | |||
| 46458e2667 | |||
| d0aa6e1fe5 | |||
| 9bef919123 | |||
| 88a0603d50 | |||
| 106dbb3d8d | |||
| 4214d924a4 | |||
| c3b40f9264 | |||
| 69f00626a2 | |||
| c485b1f7f8 | |||
| 7186c73a64 | |||
| 88f9f65fb6 | |||
| 714573ec6b | |||
| a979445ffc | |||
| 3cf38eb3fc | |||
| 94ceca35bf | |||
| 2bd4eb2004 | |||
| 355e71e620 | |||
| 7d9520d97b | |||
| ce0957cea7 | |||
| c93169fe97 | |||
| 485dd96e93 | |||
| 9b0f0892ff | |||
| 9a04f3ae38 | |||
| 968d668afa | |||
| 85d19ed2bd | |||
| 28e490f8d4 | |||
| 298ae7f657 | |||
| d50f29b3dc | |||
| f167eff21c | |||
| 69d4f00807 | |||
| 904dc4fe2e | |||
| c870cc683d | |||
| deb29fd2e4 | |||
| 19f1bc947a | |||
| 60d1b47c66 | |||
| d67b845dfd | |||
| 6f1c7c7ded | |||
| 46e9118d73 | |||
| 8aa1557b7a | |||
| 6058c3f8c1 | |||
| d409e6f2a9 | |||
| a4d272c556 | |||
| 911d7c04ec | |||
| afc379d449 | |||
| 18feca49e2 | |||
| 792b19d40d | |||
| 108d05edea | |||
| d8882da17b | |||
| f120dfda15 | |||
| dd60ed7abd | |||
| d0b478c743 | |||
| defe69ba18 | |||
| 32d748efae | |||
| f194dc9bf6 | |||
| 075fbd77b2 | |||
| edb3e3713a | |||
| c70648e038 | |||
| 966f4ee57d | |||
| f90ced4c31 | |||
| 6bda4d80bf | |||
| 3ecb6b30c9 | |||
| 3c337b618c | |||
| 40a90bbcfa | |||
| e54b124252 | |||
| 18923efe23 | |||
| 5c5ad63cc6 | |||
| d5fd444ae5 | |||
| 4a22f70e30 | |||
| 9805bd4caa | |||
| 0690f13bea | |||
| da8faea4c8 | |||
| ff927bab09 | |||
| e3e5def3b6 | |||
| ba246585ad | |||
| f242a6a3bc | |||
| 0c89e76b39 | |||
| 1fa82e72f1 | |||
| b4e6b04e47 | |||
| 002f824f5c | |||
| 1aaf7f8de1 | |||
| 82ba19842c | |||
| 32ed1bf622 | |||
| 0d4838c536 | |||
| 11527b46f9 | |||
| 20c1957b59 | |||
| ed2630e016 | |||
| 8cc2ac2cad | |||
| 37745ca548 | |||
| 29edcdca4b | |||
| 92669d6974 | |||
| 351a64f592 | |||
| a29e56543b | |||
| 6db3e8c671 | |||
| 20c4d24698 | |||
| 114e185bcb | |||
| a293bff964 | |||
| 98b4d9f95d | |||
| 8489e87586 | |||
| 6f7ee2179d | |||
| ea6b442a48 | |||
| 12d26edd76 | |||
| 27053eecd7 | |||
| 151d5b9c1f | |||
| d35c558658 | |||
| baa4dc7a23 | |||
| 9b565c32d1 | |||
| 243dd26d73 | |||
| 263234fecb | |||
| 0ba598ee67 | |||
| 29430b9967 | |||
| 2038b16dce | |||
| 9ea793397b | |||
| 6061938129 | |||
| 62277aa525 | |||
| 1c118b06c9 | |||
| a41c315e36 | |||
| 40576e0012 | |||
| a582db52f4 | |||
| cb2656ad85 | |||
| da1c686d42 | |||
| b613fe2ba0 | |||
| 83e29b1cf3 | |||
| 5bbd23bf33 | |||
| 9f69b83b51 | |||
| 4f77781e24 | |||
| b23d589a29 | |||
| 7f16a69301 | |||
| 006da73737 | |||
| 3f998cdf75 | |||
| 3e94cd9d8c | |||
| 5922f92caf | |||
| f5f5909fde | |||
| 7e67357887 | |||
| d5750c6cb8 | |||
| b2983d5c96 | |||
| 5a19e46d26 | |||
| 8456a5a1d6 | |||
| b9329a092e | |||
| 6ecad9eebd | |||
| f32dd9efee | |||
| 48cbaf03b7 | |||
| 7f23cda97a | |||
| 49c1809aa2 | |||
| 173aa82134 | |||
| c57e8b2c76 | |||
| bb741013d4 | |||
| 5b014a5a1d | |||
| a85548ac33 | |||
| 77e689fec4 | |||
| fe942dcf73 | |||
| da3b700403 | |||
| fcd46cb2ea | |||
| e918b19e2e | |||
| afb8badc74 | |||
| 4e22a5c7bb | |||
| b5d2e02606 | |||
| 28afb4f14c | |||
| 165659a664 | |||
| 7b3d910b10 | |||
| 1e4a85719a | |||
| 4269cb37d2 | |||
| b7ce3e8c20 | |||
| 15a0240808 | |||
| 0aa68ea04b | |||
| 2d9b69fd1e | |||
| 48d6023e0d | |||
| 113ebb36e9 | |||
| d0c9bd8038 | |||
| 104586fb7f | |||
| 0612582a46 | |||
| 1bc5bb3ef6 | |||
| a3d0d91dd7 | |||
| 982e8f67bf | |||
| 0bb871bff2 | |||
| 0eb43d6552 | |||
| b4f29f4856 | |||
| 2719bff65f | |||
| 4fd68565d2 | |||
| b87972143d | |||
| 8241551438 | |||
| d7bb45f287 | |||
| 0cdec2a226 | |||
| dbb3078300 | |||
| 545c235b24 | |||
| 53d3cb320b | |||
| 38682f01a8 | |||
| a7d141efcc | |||
| 31c404021c | |||
| 631cec2fc6 | |||
| 13a76e8de7 | |||
| 1e98fa98c3 | |||
| be6eab0cae | |||
| 71ee8bfd29 | |||
| 66c9c02dc6 | |||
| 7880ee4aef | |||
| 6274d1f778 | |||
| 5e98813f92 | |||
| 1a30800fb4 | |||
| 454e6933f4 | |||
| e3072071b7 | |||
| 83a88326f0 | |||
| 27109a810f | |||
| 3d5bd424c5 | |||
| c7cd56e7be | |||
| 860769c44a | |||
| a83761b88d | |||
| a79fc9c0b1 | |||
| 877bd63d9d | |||
| bb9d0582c4 | |||
| df7e89e7e4 | |||
| a12593ea51 | |||
| 5ca0af4285 | |||
| 20bc38add4 | |||
| 89e72a0fea | |||
| efabaafa38 | |||
| fc25ad7ddb | |||
| 6b656cf446 | |||
| 26927661e7 | |||
| 15ba945751 | |||
| 8e0527b777 | |||
| b9dfa0a8a9 | |||
| c462973eb6 | |||
| b8cefd69c0 | |||
| 1c1537be8a | |||
| 1dad632c70 | |||
| 41600c7576 | |||
| 5f0074c88d | |||
| 907f2a2678 | |||
| 4a118bd51c | |||
| 4919b46e5d | |||
| 034a6662f9 | |||
| 3fb1c9f315 | |||
| aed4610afd | |||
| 345be8035a | |||
| 68c7b0ddaf | |||
| f39ce00152 | |||
| 0b6d1bd6df | |||
| dca7a44884 | |||
| d90cdf341e | |||
| 7828189ea0 | |||
| e4cd8da65c | |||
| 8cebbd3bbe | |||
| 63d9b354d4 | |||
| 254944fbfc | |||
| ec93080190 | |||
| ec638cb231 | |||
| 7c72623f90 | |||
| 2e58404e01 | |||
| 5eae896330 | |||
| 6c2dcc7d37 | |||
| d40e4e97c1 | |||
| 3164ed1b0e | |||
| b49fae0384 | |||
| 80544aff32 | |||
| 64235951c2 | |||
| f08fe7d855 | |||
| ff1a9e8694 | |||
| 2abf87628a | |||
| e835482abd | |||
| e78882e911 | |||
| b021d99f78 | |||
| 084781dc0a | |||
| ce83fed40d | |||
| 24d16a234f | |||
| 536af50a4f | |||
| 9eccc459d9 | |||
| 6e8310e4c9 | |||
| 35e79f938c | |||
| 10764ac3f4 | |||
| 2a6ecfa176 | |||
| 5b44c7f856 | |||
| 1e5e36a8c7 | |||
| 92dda8e64c | |||
| 27488e8084 | |||
| 72871e55c6 | |||
| 07c05b2191 | |||
| 89d2fb98fa | |||
| 6d1719b877 | |||
| 51599d5bb4 | |||
| aedaee8d3a | |||
| 82a859e820 | |||
| c1c655fcb0 | |||
| fabcce9a6c | |||
| 16feb963f6 | |||
| c7db58f6ea | |||
| 79ff887375 | |||
| e7ae608986 | |||
| 7ec4625d45 | |||
| 4f68f30576 | |||
| 135d717715 | |||
| 77c3131a69 | |||
| 7e74cbfbd1 | |||
| a2cd548d1e | |||
| 0a4d6122df | |||
| 23d1435ed2 | |||
| dd60900bcb | |||
| 0fbb0aa363 | |||
| 23539b9316 | |||
| a1460b07c6 | |||
| 02b6c2733b | |||
| 1d29d68aa2 | |||
| aa76a20065 | |||
| 0683a579c0 | |||
| f1194d434b | |||
| ec945919ba | |||
| e626e82945 | |||
| 6e238379f2 | |||
| 7a4ae83a2b | |||
| 46827b1489 | |||
| 59e80970ae | |||
| 762897521b | |||
| b8d74357b5 | |||
| 21c116ea5b | |||
| 2cf23b9a32 | |||
| 92a0d77885 | |||
| 1bc0b0e085 | |||
| 6b03098ac7 | |||
| bcd846024e | |||
| d98edc8f77 | |||
| a5129c809b | |||
| 3e8e5572d2 | |||
| faef2a5e4d | |||
| 3d88792d11 | |||
| 862b66f8e7 | |||
| f7fe7a5153 | |||
| 9aeb1624a6 | |||
| 15fad5635b | |||
| ec9c282618 | |||
| 7e1da213d5 | |||
| 8d9fd482b9 | |||
| bddde8c851 | |||
| b589c38eea | |||
| 5c3cdf227e | |||
| 838b775a3e | |||
| c87bf1e613 | |||
| 81dc17530f | |||
| 7af2b7c2d7 | |||
| b53f769a0d | |||
| f78570ce80 | |||
| 071376267a | |||
| 51c3d25f3a | |||
| cc6c31027a | |||
| f3b91b63ec | |||
| aadd2071b9 | |||
| fc7566d2c9 | |||
| 48b8c0d23e | |||
| c56826b29d | |||
| 28ec3ef5dc | |||
| 7f082b7a36 | |||
| c3b8538ac3 | |||
| f04b1c4300 | |||
| 1d7c8b894f | |||
| afd1232cea | |||
| 2b141e79cd | |||
| f6e452237a | |||
| 508dff3bae | |||
| 1259199e2c | |||
| 85fc2dda02 | |||
| d57a6879fb | |||
| c0f32124ad | |||
| b3a53f51b0 | |||
| 66175c7f20 | |||
| dc698ca2cc | |||
| 6d8c703f33 | |||
| f32e6b60d1 | |||
| f45d1ded17 | |||
| da9eac4ecd | |||
| b58d52709f | |||
| 3cde5cc39d | |||
| 50214e7461 | |||
| dc0994d084 | |||
| f79a45e533 | |||
| b704e47322 | |||
| bebda2de70 | |||
| dab9f850ba | |||
| e7073bf010 | |||
| c1ab9617ad | |||
| c6d9026333 | |||
| 42dae5c993 | |||
| a3af3dcf9b | |||
| 3e0887b5f9 | |||
| ba15462981 | |||
| c29066eb46 | |||
| 0464a859d2 | |||
| 962ff89833 | |||
| 74a40ebe97 | |||
| 686b454abe | |||
| 6d54ddea60 | |||
| d005403f65 | |||
| 8e907f5221 | |||
| 96bb953d9d | |||
| 78b581b376 | |||
| ef7edb4a9e | |||
| 4bf5ae40e2 | |||
| 22ebdc0e87 | |||
| 01bd1628cf | |||
| 7de88bc8ad | |||
| 1a01e2dd4d | |||
| 9e20c7082a | |||
| 74cb2f253b | |||
| cf41d2e4a7 | |||
| f232adaa98 | |||
| 713af4bf12 | |||
| f0f1906ffc | |||
| 3da6444ede | |||
| f149c56617 | |||
| 9915a18656 | |||
| 2173e5a91c | |||
| 4a6866d8fd | |||
| ddc324bcf1 | |||
| daba7e0d12 | |||
| 6203b80c4e | |||
| 416cbe7e82 | |||
| e28ce4d099 | |||
| d1f5ec6c2e | |||
| 166f44bb1d | |||
| c8a0420b21 | |||
| a8894cc464 | |||
| a3d7d9cb81 | |||
| b6d49c88db | |||
| 8572f8eaf4 | |||
| c533cd021f | |||
| 3eb1af7e23 | |||
| 97188a7d9c | |||
| e29ffa3d13 | |||
| 5b772a0537 | |||
| 82a8888676 | |||
| bf8630756a | |||
| 35fc381162 | |||
| f72342ac72 | |||
| 5a6e528c65 | |||
| 4eb52c91a4 | |||
| 77bc1594aa | |||
| 23267ec0ee | |||
| 1b1bd3264a | |||
| b954c1f664 | |||
| 707beb9672 | |||
| b2f5a19bde | |||
| e24d7f1045 | |||
| 142a64d261 | |||
| 2ef98fd050 | |||
| 2f3c387c16 | |||
| 83b97a9de9 | |||
| 97becbea2e | |||
| 8361609c70 | |||
| eb7d871e70 | |||
| d06ab34db1 | |||
| d59f604c7e | |||
| a8d9bb9180 | |||
| db90717617 | |||
| f916c7b8a5 | |||
| 4e410e3ea3 | |||
| 5a5fb7a5cc | |||
| 233a2172f1 | |||
| 6376973a61 | |||
| 5dd6d73603 | |||
| 5918b35793 | |||
| 10c3536b2b | |||
| fffef74480 | |||
| c5c2938089 | |||
| 32fe28f536 | |||
| fc4a751b2b | |||
| e364b7d3b0 | |||
| bc28e08b3f | |||
| 69b8155dcd | |||
| 16254bb578 | |||
| acc4a5b2aa | |||
| fddce1ebe3 | |||
| 7151cba40e | |||
| 6cff45eada | |||
| a05b4f7b65 | |||
| e5797a41b7 | |||
| 9f0191ce0a | |||
| 68a5c472c0 | |||
| 6c7e6d95ce | |||
| ec84bbb4f3 | |||
| 780a8649e3 | |||
| 9aaaf2204a | |||
| c7f608b9cb | |||
| 591885095b | |||
| 3bcdd37837 | |||
| 959c5e4cf5 | |||
| 7ecc8446ea | |||
| d3809bb699 | |||
| d5113a52fc | |||
| e2dd868705 | |||
| 41ae5b9b6b | |||
| b0470b3a41 | |||
| d371ae9dc5 | |||
| 00124a657d | |||
| 620cec08eb | |||
| b1205356c8 | |||
| e96d6829a4 | |||
| 0652da2300 | |||
| ebe3852132 | |||
| 1ae73277a9 | |||
| 97ec50f8a9 | |||
| 1997a8b296 | |||
| baae0e5bca | |||
| 4136bfab42 | |||
| 3d64d3c90e | |||
| 7d2835bb83 | |||
| 9ffaa97d70 | |||
| 363751a970 | |||
| c7218d9c0d | |||
| e9387e29c6 | |||
| 33b4d60882 | |||
| 86537b8f1e | |||
| c2e64e2a71 | |||
| 79af4945e3 | |||
| f83a50d4c5 | |||
| 1868488390 | |||
| 4dc71d2d76 | |||
| dca5565f45 | |||
| aa6294bfd4 | |||
| 77a6d3f295 | |||
| 10fd6d9aef | |||
| 37e6120768 | |||
| b9defd4a58 | |||
| 7f7938fdfa | |||
| 7c2f411a48 | |||
| 51c152ca5e | |||
| dc46ee4431 | |||
| da3ba76547 | |||
| 36a31f28f0 | |||
| 450a732f2e | |||
| b8c5dcf4b4 | |||
| 8ae5eacffe | |||
| bb9f7a33fb | |||
| 06f603e975 | |||
| 20c74a1727 | |||
| 5dd3ba43c9 | |||
| cd749fc1c9 | |||
| 6b7610bac8 | |||
| 041f48bdb5 | |||
| a1adfb336b | |||
| 35ff5af974 | |||
| 638f324cd2 | |||
| 62390f88e5 | |||
| 9428604613 | |||
| 610fc444af | |||
| e5d7b68a85 | |||
| 9e91a53e94 | |||
| fa553238bb | |||
| 0a579427f4 | |||
| 921bc29f73 | |||
| 2864fa0d91 | |||
| 9771fb7f25 | |||
| ec5bf05d42 | |||
| 7257f88993 | |||
| 79a5402e83 | |||
| abc899e822 | |||
| 4e96f00ae9 | |||
| 48106a8577 | |||
| dcdba2a9ad | |||
| 544c7a065f | |||
| cd3ed911d2 | |||
| e95b2a905c | |||
| e36209306e | |||
| af607bc64a | |||
| 450d81a4e3 | |||
| 75c69adc87 | |||
| 97b808fa81 | |||
| 512ae70b94 | |||
| 322a31fcac | |||
| 20b6c383e1 | |||
| e7ff3ab327 | |||
| 60b55bddab | |||
| 1898e594dd | |||
| 09f0704ad2 | |||
| a6cd047b24 | |||
| 37429a4993 | |||
| 47f2b1e62f | |||
| 4e5fe8c32d | |||
| 2fdf5421ad | |||
| 412e6aa0c5 | |||
| 1fdafeec4e | |||
| ac819893d4 | |||
| 118936845e | |||
| 4b1ab3453f | |||
| 53690ff46d | |||
| e9578bdeec |
@ -23,6 +23,10 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
// jumboMode = true
|
||||
javaMaxHeapSize "4g"
|
||||
@ -38,7 +42,7 @@ android {
|
||||
}
|
||||
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
abiFilters "armeabi-v7a"
|
||||
}
|
||||
|
||||
// 由于app只针对中文用户,所以仅保留zh资源,其他删掉
|
||||
@ -61,6 +65,15 @@ android {
|
||||
buildConfigField "String", "WEIBO_APPKEY", "\"${WEIBO_APPKEY}\""
|
||||
buildConfigField "String", "MTA_APPKEY", "\"${MTA_APPKEY}\""
|
||||
buildConfigField "String", "TD_APPID", "\"${TD_APPID}\""
|
||||
buildConfigField "String", "LETO_APPID", "\"${LETO_APPID}\""
|
||||
buildConfigField "String", "TTAD_APPID", "\"${TTAD_APPID}\""
|
||||
|
||||
buildConfigField "String", "MIPUSH_APPID", "\"${MIPUSH_APPID}\""
|
||||
buildConfigField "String", "MIPUSH_APPKEY", "\"${MIPUSH_APPKEY}\""
|
||||
buildConfigField "String", "MEIZUPUSH_APPID", "\"${MEIZUPUSH_APPID}\""
|
||||
buildConfigField "String", "MEIZUPUSH_APPKEY", "\"${MEIZUPUSH_APPKEY}\""
|
||||
|
||||
resValue "string", "huawei_push_appid", "appid=${HUAWEI_PUSH_APPID}"
|
||||
|
||||
/**
|
||||
* Build Time 供区分 jenkins 打包时间用
|
||||
@ -89,7 +102,7 @@ android {
|
||||
signingConfig signingConfigs.debug
|
||||
|
||||
buildConfigField "String", "EXPOSURE_REPO", "\"test\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E3\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E4\""
|
||||
|
||||
multiDexKeepProguard file("tinker_multidexkeep.pro")
|
||||
}
|
||||
@ -101,7 +114,7 @@ android {
|
||||
signingConfig signingConfigs.release
|
||||
|
||||
buildConfigField "String", "EXPOSURE_REPO", "\"exposure\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E3\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E4\""
|
||||
|
||||
multiDexKeepProguard file("tinker_multidexkeep.pro")
|
||||
}
|
||||
@ -117,16 +130,11 @@ android {
|
||||
publish {
|
||||
dimension "nonsense"
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "COMMENT_HOST", "\"${COMMENT_HOST}\""
|
||||
buildConfigField "String", "DATA_HOST", "\"${DATA_HOST}\""
|
||||
|
||||
buildConfigField "String", "SENSITIVE_API_HOST", "\"${SENSITIVE_API_HOST}\""
|
||||
|
||||
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
|
||||
buildConfigField "String", "MIPUSH_APPID", "\"${MIPUSH_APPID}\""
|
||||
buildConfigField "String", "MIPUSH_APPKEY", "\"${MIPUSH_APPKEY}\""
|
||||
buildConfigField "String", "MEIZUPUSH_APPID", "\"${MEIZUPUSH_APPID}\""
|
||||
buildConfigField "String", "MEIZUPUSH_APPKEY", "\"${MEIZUPUSH_APPKEY}\""
|
||||
|
||||
buildConfigField "String", "BUGLY_APPID", "\"${BUGLY_APPID}\""
|
||||
}
|
||||
// internal test dev host
|
||||
@ -135,17 +143,12 @@ android {
|
||||
versionNameSuffix "-debug"
|
||||
|
||||
buildConfigField "String", "API_HOST", "\"${DEV_API_HOST}\""
|
||||
buildConfigField "String", "COMMENT_HOST", "\"${DEV_COMMENT_HOST}\""
|
||||
buildConfigField "String", "DATA_HOST", "\"${DEV_DATA_HOST}\""
|
||||
|
||||
buildConfigField "String", "UMENG_APPKEY", "\"${DEBUG_UMENG_APPKEY}\""
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${DEBUG_UMENG_MESSAGE_SECRET}\""
|
||||
buildConfigField "String", "MIPUSH_APPID", "\"${DEBUG_MIPUSH_APPID}\""
|
||||
buildConfigField "String", "MIPUSH_APPKEY", "\"${DEBUG_MIPUSH_APPKEY}\""
|
||||
buildConfigField "String", "MEIZUPUSH_APPID", "\"${DEBUG_MEIZUPUSH_APPID}\""
|
||||
buildConfigField "String", "MEIZUPUSH_APPKEY", "\"${DEBUG_MEIZUPUSH_APPKEY}\""
|
||||
buildConfigField "String", "SENSITIVE_API_HOST", "\"${DEV_API_HOST}\""
|
||||
|
||||
buildConfigField "String", "BUGLY_APPID", "\"${DEBUG_BUGLY_APPID}\""
|
||||
buildConfigField "String", "UMENG_APPKEY", "\"${DEV_UMENG_APPKEY}\""
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${DEV_UMENG_MESSAGE_SECRET}\""
|
||||
buildConfigField "String", "BUGLY_APPID", "\"${DEV_BUGLY_APPID}\""
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,7 +172,7 @@ rebuildChannel {
|
||||
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs 'libs/aars'
|
||||
dirs 'libs', 'libs/aars'
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,6 +186,7 @@ dependencies {
|
||||
debugImplementation "com.facebook.stetho:stetho:${stetho}"
|
||||
debugImplementation "com.facebook.stetho:stetho-okhttp3:${stetho}"
|
||||
debugImplementation "com.squareup.okhttp3:logging-interceptor:${okHttp}"
|
||||
debugImplementation "com.gu.android:toolargetool:${toolargetool}"
|
||||
|
||||
implementation "androidx.core:core:${core}"
|
||||
implementation "androidx.fragment:fragment:${fragment}"
|
||||
@ -192,14 +196,14 @@ dependencies {
|
||||
implementation "androidx.annotation:annotation:${annotation}"
|
||||
implementation "androidx.constraintlayout:constraintlayout:${constraintLayout}"
|
||||
implementation "androidx.recyclerview:recyclerview:${recyclerView}"
|
||||
implementation "androidx.lifecycle:lifecycle-runtime:${lifeCycle}"
|
||||
implementation "androidx.lifecycle:lifecycle-extensions:${lifeCycle}"
|
||||
kapt "androidx.lifecycle:lifecycle-compiler:${lifeCycle}"
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifeCycle"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifeCycle"
|
||||
implementation "androidx.lifecycle:lifecycle-common-java8:$lifeCycle"
|
||||
implementation "androidx.room:room-runtime:${room}"
|
||||
implementation "androidx.room:room-rxjava2:${room}"
|
||||
implementation "androidx.core:core-ktx:${ktx}"
|
||||
implementation "androidx.viewpager2:viewpager2:${viewpager2}"
|
||||
kapt "androidx.room:room-compiler:${room}"
|
||||
kapt "androidx.databinding:databinding-compiler:${databinding}"
|
||||
|
||||
implementation "com.google.android.material:material:${material}"
|
||||
|
||||
@ -241,13 +245,13 @@ dependencies {
|
||||
// bugly with tinker support
|
||||
implementation "com.tencent.bugly:crashreport_upgrade:${buglyTinkerSupport}"
|
||||
|
||||
implementation 'com.google.android:flexbox:1.1.0'
|
||||
implementation "com.google.android:flexbox:${flexbox}"
|
||||
|
||||
implementation "pub.devrel:easypermissions:${easypermissions}"
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
implementation 'com.contrarywind:Android-PickerView:4.1.3'
|
||||
implementation "com.contrarywind:Android-PickerView:${pickerView}"
|
||||
|
||||
implementation "com.scwang.smartrefresh:SmartRefreshLayout:${smartRefreshLayout}"
|
||||
implementation "net.cachapa.expandablelayout:expandablelayout:${expandableLayout}"
|
||||
@ -260,30 +264,27 @@ dependencies {
|
||||
implementation "com.squareup.picasso:picasso:${picasso}"
|
||||
|
||||
// for video streaming
|
||||
implementation ("com.shuyu:gsyVideoPlayer-java:$gsyVideo",{
|
||||
implementation("com.shuyu:gsyVideoPlayer-java:$gsyVideo", {
|
||||
exclude module: "gsyvideoplayer-androidvideocache"
|
||||
})
|
||||
implementation "com.shuyu:gsyVideoPlayer-armv7a:$gsyVideo"
|
||||
implementation "com.shuyu:gsyVideoPlayer-x86:$gsyVideo"
|
||||
|
||||
implementation "com.github.wendux:DSBridge-Android:$dsBridge"
|
||||
implementation "com.shuyu:GSYVideoPlayer-exo2:$gsyVideo"
|
||||
|
||||
implementation "android.arch.work:work-runtime:${workManager}"
|
||||
|
||||
implementation "com.llew.huawei:verifier:1.0.6"
|
||||
implementation "com.llew.huawei:verifier:${verifier}"
|
||||
|
||||
implementation "com.github.tbruyelle:rxpermissions:${rxPermissions}"
|
||||
|
||||
implementation 'com.ethanhua:skeleton:1.1.1'
|
||||
implementation 'io.supercharge:shimmerlayout:2.1.0'
|
||||
implementation "com.tencent.mm.opensdk:wechat-sdk-android-without-mta:5.3.1"
|
||||
implementation 'com.walkud.rom.checker:RomChecker:1.0.0'
|
||||
implementation "com.ethanhua:skeleton:${skeleton}"
|
||||
implementation "io.supercharge:shimmerlayout:${shimmerlayout}"
|
||||
implementation "com.tencent.mm.opensdk:wechat-sdk-android-without-mta:${mta}"
|
||||
implementation "com.walkud.rom.checker:RomChecker:${romChecker}"
|
||||
|
||||
debugImplementation "com.github.nichbar.chucker:library:$chucker"
|
||||
releaseImplementation "com.github.nichbar.chucker:library-no-op:$chucker"
|
||||
implementation "com.bytedance.applog:RangersAppLog-Lite-cn:$bytedanceApplog"
|
||||
|
||||
implementation 'com.aliyun.dpa:oss-android-sdk:2.9.2'
|
||||
implementation "com.aliyun.dpa:oss-android-sdk:${oss}"
|
||||
|
||||
implementation "com.airbnb.android:lottie:$lottie"
|
||||
|
||||
|
||||
BIN
app/libs/AVMPSDK-external-release-5.4.1002.aar
Normal file
BIN
app/libs/AVMPSDK-external-release-5.4.1002.aar
Normal file
Binary file not shown.
BIN
app/libs/SecurityBodySDK-external-release-5.4.112-preInstall.aar
Normal file
BIN
app/libs/SecurityBodySDK-external-release-5.4.112-preInstall.aar
Normal file
Binary file not shown.
Binary file not shown.
@ -240,4 +240,18 @@
|
||||
-keep class com.shuyu.gsyvideoplayer.utils.** { *; }
|
||||
-dontwarn com.shuyu.gsyvideoplayer.utils.**
|
||||
-keep class tv.danmaku.ijk.** { *; }
|
||||
-dontwarn tv.danmaku.ijk.**
|
||||
-dontwarn tv.danmaku.ijk.**
|
||||
|
||||
#穿山甲
|
||||
-keep class com.bytedance.sdk.openadsdk.** { *; }
|
||||
-keep public interface com.bytedance.sdk.openadsdk.downloadnew.** {*;}
|
||||
-keep class com.pgl.sys.ces.* {*;}
|
||||
|
||||
-keep class com.gyf.immersionbar.* {*;}
|
||||
-dontwarn com.gyf.immersionbar.**
|
||||
|
||||
-keep class com.taobao.securityjni.**{*;}
|
||||
-keep class com.taobao.wireless.security.**{*;}
|
||||
-keep class com.ut.secbody.**{*;}
|
||||
-keep class com.taobao.dp.**{*;}
|
||||
-keep class com.alibaba.wireless.security.**{*;}
|
||||
@ -4,7 +4,6 @@ import android.app.Application;
|
||||
|
||||
import com.facebook.stetho.Stetho;
|
||||
import com.facebook.stetho.okhttp3.StethoInterceptor;
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
@ -18,18 +17,11 @@ import okhttp3.logging.HttpLoggingInterceptor;
|
||||
public class Injection {
|
||||
|
||||
public static boolean appInit(Application application) {
|
||||
|
||||
// init leakcanary
|
||||
if (LeakCanary.isInAnalyzerProcess(application)) {
|
||||
// This process is dedicated to LeakCanary for heap analysis.
|
||||
// You should not init your app in this process.
|
||||
return false;
|
||||
}
|
||||
LeakCanary.install(application);
|
||||
|
||||
// init stetho
|
||||
Stetho.initializeWithDefaults(application);
|
||||
|
||||
// 监控Bundle大小,预防溢出(需要调试的时候再开启吧!)
|
||||
// TooLargeTool.startLogging(application);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -36,13 +36,30 @@
|
||||
<uses-permission android:name="android.permission.READ_LOGS" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<!--可选,穿山甲提供“获取地理位置权限”和“不给予地理位置权限,开发者传入地理位置参数”两种方式上报用户位置,两种方式均可不选,添加位置权限或参数将帮助投放定位广告-->
|
||||
<!--请注意:无论通过何种方式提供给穿山甲用户地理位置,均需向用户声明地理位置权限将应用于穿山甲广告投放,穿山甲不强制获取地理位置信息-->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
|
||||
<!-- 如果有视频相关的广告且使用textureView播放,请务必添加,否则黑屏 -->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<uses-sdk tools:overrideLibrary="com.shuyu.gsyvideoplayer,
|
||||
com.shuyu.gsyvideoplayer.lib,
|
||||
com.shuyu.gsyvideoplayer.armv7a,
|
||||
com.shuyu.gsyvideoplayer.x86,
|
||||
com.shuyu.gsy.base,
|
||||
com.google.android.exoplayer2,
|
||||
tv.danmaku.ijk.media.exo2,
|
||||
shuyu.com.androidvideocache,
|
||||
pl.droidsonroids.gif" />
|
||||
pl.droidsonroids.gif,
|
||||
com.ledong.lib.minigame,
|
||||
com.ledong.lib.leto,
|
||||
com.leto.game.base.glide4,
|
||||
com.leto.game.ad.gdt,
|
||||
com.leto.game.fcm,
|
||||
com.leto.game.ad.toutiao" />
|
||||
|
||||
<!-- 去掉 SDK 一些流氓权限 -->
|
||||
<uses-permission
|
||||
@ -65,6 +82,7 @@
|
||||
android:largeHeap="true"
|
||||
android:resizeableActivity="true"
|
||||
android:theme="@style/AppCompatTheme.APP"
|
||||
tools:replace="android:allowBackup"
|
||||
tools:targetApi="n">
|
||||
|
||||
<!--android:launchMode = "singleTask"-->
|
||||
@ -113,6 +131,10 @@
|
||||
android:name="com.gh.gamecenter.ShellActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.history.HistoryApkListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.NewsDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -155,6 +177,7 @@
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar"
|
||||
android:name="com.gh.gamecenter.MessageDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
@ -185,6 +208,7 @@
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.CommentDetailActivity"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
@ -395,6 +419,7 @@
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar"
|
||||
android:name="com.gh.gamecenter.gamedetail.rating.RatingReplyActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
@ -456,8 +481,8 @@
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.HelpAndFeedbackActivity"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:screenOrientation="portrait" />
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.help.HelpDetailActivity"
|
||||
@ -478,10 +503,23 @@
|
||||
android:name=".gamedetail.myrating.MyRatingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.QaActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".qa.answer.draft.AnswerDraftActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!-- 使用小米/华为推送弹窗功能提高推送成功率-->
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.PushProxyActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@android:style/Theme.Translucent" />
|
||||
|
||||
<activity
|
||||
@ -544,7 +582,7 @@
|
||||
</receiver>
|
||||
|
||||
<!--魅族push应用定义消息receiver声明 -->
|
||||
<receiver android:name="com.gh.gamecenter.receiver.MeizuPushReceiver">
|
||||
<receiver android:name="com.gh.gamecenter.receiver.UmengMeizuPushReceiver">
|
||||
<intent-filter>
|
||||
<!-- 接收push消息 -->
|
||||
<action android:name="com.meizu.flyme.push.intent.MESSAGE" />
|
||||
@ -569,10 +607,47 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name="com.gh.base.GHUmengNotificationService" />
|
||||
<meta-data android:name="com.huawei.hms.client.appid" android:value="@string/huawei_push_appid"/>
|
||||
|
||||
<service
|
||||
android:name="com.gh.base.GHUmengNotificationService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<!--<service android:name = "com.gh.gamecenter.statistics.AppStaticService" />-->
|
||||
|
||||
<!-- 梦工厂配置 开始 -->
|
||||
<!--<meta-data
|
||||
android:name="MGC_APPID"
|
||||
android:value="1001276" />
|
||||
|
||||
<provider
|
||||
android:name="com.leto.game.base.provider.LetoFileProvider"
|
||||
android:authorities="${applicationId}.leto.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/leto_file_path"
|
||||
tools:replace="android:resource" />
|
||||
</provider>-->
|
||||
<!-- 梦工厂配置 结束 -->
|
||||
|
||||
<!-- 穿山甲配置 开始 -->
|
||||
<!--<provider
|
||||
android:name="com.bytedance.sdk.openadsdk.TTFileProvider"
|
||||
android:authorities="${applicationId}.TTFileProvider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<provider
|
||||
android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider"
|
||||
android:authorities="${applicationId}.TTMultiProvider"
|
||||
android:exported="false" />-->
|
||||
<!-- 穿山甲配置 结束 -->
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -2,16 +2,20 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<link rel="stylesheet" type="text/css" href="normalize.css">
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<link rel="stylesheet" type="text/css" href="video-js.min.css">
|
||||
<!-- <link rel="stylesheet" href="https://static-web.ghzs.com/website-static/lib/video-js.min.css">--> <!--在web页面播放视频-->
|
||||
<!--<link rel="stylesheet" type="text/css" href="https://resource.ghzs.com/css/halo_app.css">-->
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body style="overflow-x: hidden; word-break: break-all;">
|
||||
<div id="editor" contenteditable="false"></div>
|
||||
<script type="text/javascript" src="zepto.min.js"></script>
|
||||
<script type="text/javascript" src="rich_editor.js"></script>
|
||||
<script type="text/javascript" src="video.min.js"></script>
|
||||
<!--<script src="https://static-web.ghzs.com/website-static/lib/video.min.js"></script>--> <!--在web页面播放视频-->
|
||||
<!--<script type="text/javascript" src="content.js"></script>-->
|
||||
<!--<script type="text/javascript" src="https://resource.ghzs.com/js/halo_app.js"></script>-->
|
||||
</body>
|
||||
|
||||
1
app/src/main/assets/lottie/community_vote.json
Normal file
1
app/src/main/assets/lottie/community_vote.json
Normal file
File diff suppressed because one or more lines are too long
1
app/src/main/assets/lottie/double_click_guide.json
Normal file
1
app/src/main/assets/lottie/double_click_guide.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.6.4","fr":25,"ip":0,"op":35,"w":1080,"h":214,"nm":"点赞","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"椭圆形 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.588],"y":[0]},"t":17,"s":[15]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[468.04,73.68,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.659,0.659,0.333],"y":[0,0,0]},"t":10,"s":[50,50,100]},{"t":19,"s":[150,150,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[24,24],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":10,"op":1510,"st":10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"椭圆形 3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.588],"y":[0]},"t":27,"s":[15]},{"t":30,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[468.04,73.68,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.659,0.659,0.333],"y":[0,0,0]},"t":20,"s":[50,50,100]},{"t":28,"s":[140,140,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[24,24],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":20,"op":1520,"st":20,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"路径备份 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.602],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.663],"y":[0]},"t":24,"s":[100]},{"t":29,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[531.02,129.675,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.514,0.514,0.333],"y":[0,0,0]},"t":5,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.533,0.533,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.586,0.586,0.333],"y":[0,0,0]},"t":15,"s":[95,95,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.499,0.499,0.333],"y":[0,0,0]},"t":19,"s":[90,90,100]},{"t":24,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.33,-8.3],[3.89,0.27],[-4.4,-1.68],[-4.33,-0.67],[-4.08,9.32],[3.33,5.44],[3.39,4.6],[0.87,-3.7],[3.6,-0.86],[1.03,-0.21],[2.34,-0.53],[0.96,1.15],[4.22,5.48],[-1.18,-4.56]],"o":[[1.11,1.71],[-3.89,-0.27],[6.42,2.5],[4.33,0.66],[1.63,-5.32],[-3.34,-5.45],[-1.68,-2.1],[-0.71,3.14],[-3.43,0.95],[-0.57,0.08],[-3.86,1.12],[-3.23,-3.94],[-1.89,-2.28],[2.42,4.64]],"v":[[-5.387,9.698],[-10.717,8.498],[-12.327,15.628],[5.813,21.748],[23.313,11.778],[20.273,-1.202],[11.563,-13.962],[5.393,-12.362],[1.083,-13.722],[-2.087,-9.742],[-5.707,-11.752],[-8.777,-7.572],[-18.297,-20.542],[-23.827,-17.832]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"路径备份 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1500,"st":0,"bm":0}],"markers":[]}
|
||||
1
app/src/main/assets/lottie/follow.json
Normal file
1
app/src/main/assets/lottie/follow.json
Normal file
File diff suppressed because one or more lines are too long
1
app/src/main/assets/lottie/like.json
Normal file
1
app/src/main/assets/lottie/like.json
Normal file
File diff suppressed because one or more lines are too long
@ -617,3 +617,25 @@ RE.sendElementNameToNative = function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// android function to open link
|
||||
function customLinkgo(self) {
|
||||
var datas = self.dataset.datas
|
||||
// console.log(datas)
|
||||
window.OnLinkClickListener.onClick(datas)
|
||||
}
|
||||
|
||||
// 在web页面播放视频
|
||||
//RE.initArticleVideo = function(){
|
||||
// initArticleVideo()
|
||||
//}
|
||||
|
||||
function showNativeDialog(title, message, positive, negative, callback) {
|
||||
var jsCallbackCode = "(" + function (v) {
|
||||
window.onNativeDialogCallback(v);
|
||||
delete window.onNativeDialogCallback;
|
||||
}.toString() + ")";
|
||||
|
||||
window.onNativeDialogCallback = callback;
|
||||
window.NativeCallBack.showDialog(title, message, positive, negative, jsCallbackCode);
|
||||
}
|
||||
@ -1,16 +1,27 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.base.fragment.BaseFragment;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
@ -34,6 +45,8 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import butterknife.ButterKnife;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
@ -93,8 +106,8 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EventBus.getDefault().register(this);
|
||||
ButterKnife.bind(this);
|
||||
if (useEventBus()) EventBus.getDefault().register(this);
|
||||
if (useButterKnife()) ButterKnife.bind(this);
|
||||
mEntrance = getIntent().getStringExtra(KEY_ENTRANCE);
|
||||
if (TextUtils.isEmpty(mEntrance)) {
|
||||
mEntrance = Constants.ENTRANCE_UNKNOWN;
|
||||
@ -105,9 +118,18 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Override
|
||||
public void setContentView(View view) {
|
||||
if (BuildConfig.DEBUG || BuildConfig.BUILD_TIME != 0) {
|
||||
view = getRootViewWithEnvIndicator(view);
|
||||
}
|
||||
super.setContentView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
if (useEventBus()) EventBus.getDefault().unregister(this);
|
||||
mBaseHandler.removeCallbacksAndMessages(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
@ -124,21 +146,55 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
String icon,
|
||||
String shareTitle,
|
||||
String shareSummary,
|
||||
ShareUtils.ShareType shareType) {
|
||||
ShareUtils.ShareEntrance shareEntrance, String id) {
|
||||
ShareUtils.getInstance(this).showShareWindows(this,
|
||||
getWindow().getDecorView(),
|
||||
url,
|
||||
icon,
|
||||
shareTitle,
|
||||
shareSummary,
|
||||
shareType);
|
||||
if (shareType == ShareUtils.ShareType.game || shareType == ShareUtils.ShareType.plugin) {
|
||||
shareEntrance, id);
|
||||
if (shareEntrance == ShareUtils.ShareEntrance.game || shareEntrance == ShareUtils.ShareEntrance.plugin) {
|
||||
MtaHelper.onEvent("内容分享", "内容分享", shareTitle + shareSummary);
|
||||
} else {
|
||||
MtaHelper.onEvent("内容分享", "内容分享", shareTitle);
|
||||
}
|
||||
}
|
||||
|
||||
private View getRootViewWithEnvIndicator(View view) {
|
||||
RelativeLayout screenRootView = new RelativeLayout(this);
|
||||
screenRootView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
|
||||
|
||||
LinearLayout ll = new LinearLayout(this);
|
||||
TextView tv = new TextView(this);
|
||||
String envText = "正式环境";
|
||||
if (BuildConfig.FLAVOR.equals("internal")) {
|
||||
envText = "测试环境";
|
||||
}
|
||||
tv.setText(envText);
|
||||
tv.setGravity(Gravity.CENTER);
|
||||
tv.setTextColor(Color.WHITE);
|
||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
|
||||
tv.setBackground(ContextCompat.getDrawable(this, R.color.red));
|
||||
tv.measure(0, 0);
|
||||
tv.setAlpha(0.15F);
|
||||
int height = tv.getMeasuredHeight();
|
||||
int width = tv.getMeasuredWidth();
|
||||
tv.setPadding(DisplayUtils.dip2px(20), 0, DisplayUtils.dip2px(20), 0);
|
||||
ll.setTranslationX(DisplayUtils.dip2px(20));
|
||||
ll.setRotation(45);
|
||||
ll.addView(tv);
|
||||
ll.setPadding(0, (width - height) / 2, 0, (width - height) / 2);
|
||||
|
||||
screenRootView.addView(view);
|
||||
screenRootView.addView(ll);
|
||||
|
||||
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) ll.getLayoutParams();
|
||||
lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
|
||||
view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
|
||||
return screenRootView;
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(final EBShowDialog showDialog) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
|
||||
@ -178,6 +234,14 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (isFinishing()) {
|
||||
onFinish();
|
||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
||||
if (fragment.isAdded() && fragment instanceof BaseFragment) {
|
||||
((BaseFragment) fragment).onParentActivityFinish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -185,6 +249,13 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
/**
|
||||
* 此回调可用于确认当前 activity 已经执行了 finish() 方法并处于 isFinishing 状态
|
||||
*/
|
||||
protected void onFinish() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
@NonNull String[] permissions,
|
||||
@ -235,4 +306,22 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
return StringUtils.buildString(entrance, "+(", path, ")");
|
||||
}
|
||||
|
||||
protected boolean useEventBus() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean useButterKnife() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
Resources resources = super.getResources();
|
||||
if (resources.getConfiguration().fontScale != 1.0f) {
|
||||
Configuration configuration = resources.getConfiguration();
|
||||
configuration.fontScale = 1.0f;
|
||||
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.gh.base.adapter.FragmentAdapter;
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout;
|
||||
import com.gh.common.view.TabIndicatorView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
@ -45,7 +46,7 @@ public abstract class BaseActivity_TabLayout extends ToolBarActivity implements
|
||||
protected abstract void initTabTitleList(List<String> tabTitleList);
|
||||
|
||||
protected int provideIndicatorWidth() {
|
||||
return 65;
|
||||
return 20;
|
||||
}
|
||||
|
||||
protected View provideTabView(int position, String tabTitle) {
|
||||
@ -89,11 +90,14 @@ public abstract class BaseActivity_TabLayout extends ToolBarActivity implements
|
||||
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
|
||||
TabLayout.Tab tab = mTabLayout.getTabAt(i);
|
||||
if (tab == null) continue;
|
||||
View tabView = provideTabView(i, tab.getText() != null ? tab.getText().toString() : "");
|
||||
if (tabView == null) continue;
|
||||
String tabTitle = tab.getText() != null ? tab.getText().toString() : "";
|
||||
View tabView = provideTabView(i, tabTitle);
|
||||
if (tabView == null)
|
||||
tabView = BaseFragment_TabLayout.createDefaultTabCustomView(tabTitle);
|
||||
tab.setCustomView(tabView);
|
||||
}
|
||||
|
||||
BaseFragment_TabLayout.initTabStyle(mTabLayout, mCheckedIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -9,6 +9,7 @@ import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.widget.TextView
|
||||
import butterknife.OnClick
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
@ -16,6 +17,7 @@ import com.gh.common.view.RichEditor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.MyVideoEntity
|
||||
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity
|
||||
import com.gh.gamecenter.qa.editor.GameActivity
|
||||
import com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity
|
||||
import com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity
|
||||
@ -31,7 +33,9 @@ import kotterknife.bindView
|
||||
abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
|
||||
val mRichEditor by bindView<RichEditor>(R.id.rich_editor)
|
||||
val mDraftBtn by bindView<TextView>(R.id.draft_btn)
|
||||
|
||||
private val mEditorTextNumTv by bindView<TextView>(R.id.editorTextNumTv)
|
||||
private val mEditorFont by bindView<CheckableImageView>(R.id.editor_font)
|
||||
private val mEditorLink by bindView<CheckableImageView>(R.id.editor_link)
|
||||
private val mEditorParagraph by bindView<CheckableImageView>(R.id.editor_paragraph)
|
||||
@ -86,7 +90,12 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
// 防止个别手机在Js里无法获取粘贴内容
|
||||
mRichEditor.addJavascriptInterface(OnPasteListener(), "onPasteListener")
|
||||
mRichEditor.addJavascriptInterface(OnCursorChangeListener(), "OnCursorChangeListener")
|
||||
mRichEditor.addJavascriptInterface(OnEditorTextChangeListener(), "OnEditorTextChangeListener")
|
||||
mRichEditor.setInputEnabled(true)
|
||||
|
||||
mDraftBtn.text = if (this is AnswerEditActivity) {
|
||||
"回答草稿"
|
||||
} else "文章草稿"
|
||||
}
|
||||
|
||||
@OnClick(R.id.editor_image, R.id.editor_font, R.id.editor_link, R.id.editor_paragraph,
|
||||
@ -201,7 +210,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
}
|
||||
R.id.editor_link_game -> {
|
||||
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-游戏")
|
||||
startActivityForResult(GameActivity.getIntent(this, "插入游戏"), INSERT_GAME_CODE)
|
||||
startActivityForResult(GameActivity.getIntent(this, GameActivity.INSERT_GAME_TITLE), INSERT_GAME_CODE)
|
||||
}
|
||||
R.id.editor_link_video -> {
|
||||
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-视频")
|
||||
@ -251,6 +260,14 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private inner class OnEditorTextChangeListener {
|
||||
@JavascriptInterface
|
||||
fun onTextChange(count: Int) {
|
||||
val num = if (count > MAX_INPUT_TEXT_NUM) MAX_INPUT_TEXT_NUM - count else count
|
||||
mEditorTextNumTv.text = num.toString()
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun mtaEventName(): String
|
||||
|
||||
companion object {
|
||||
@ -266,5 +283,6 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
const val INSERT_ANSWER_CODE = 411
|
||||
const val INSERT_ARTICLE_CODE = 412
|
||||
const val INSERT_GAME_CODE = 413
|
||||
const val MAX_INPUT_TEXT_NUM = 10000
|
||||
}
|
||||
}
|
||||
@ -65,7 +65,9 @@ public class GHActivityLifecycleCallbacksImpl implements ActivityLifecycleCallba
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
AppManager.getInstance().finishActivity(activity);
|
||||
if (activity.isFinishing()) {
|
||||
AppManager.getInstance().finishActivity(activity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -12,11 +12,9 @@ import android.preference.PreferenceManager
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.text.htmlEncode
|
||||
import com.gh.common.notifier.Notifier
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.util.StringUtils
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.PushEntity
|
||||
import com.gh.gamecenter.entity.PushMessageEntity
|
||||
@ -97,7 +95,7 @@ class GHUmengNotificationService : UmengMessageService() {
|
||||
|
||||
// 用户未登录的情况下不生成消息中心通知,避免用户掉登录了还收到跳转至消息中心的通知
|
||||
if (data != null
|
||||
&& data.link?.target == "system"
|
||||
&& data.link?.link == "system"
|
||||
&& !UserManager.getInstance().isLoggedIn) {
|
||||
return
|
||||
}
|
||||
@ -132,7 +130,7 @@ class GHUmengNotificationService : UmengMessageService() {
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setTicker(pushData.body?.ticker)
|
||||
.setContentTitle(pushData.body?.title)
|
||||
.setContentText(pushData.body?.text)
|
||||
.setContentText(pushData.body?.text?.fromHtml())
|
||||
.setContentIntent(clickPendingIntent)
|
||||
.setDeleteIntent(deletePendingIntent)
|
||||
.build()
|
||||
|
||||
@ -3,7 +3,6 @@ package com.gh.base;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
@ -12,12 +11,10 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -52,6 +49,8 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
|
||||
@Nullable
|
||||
private PackageViewModel mPackageViewModel;
|
||||
|
||||
protected RelativeLayout mToolbarContainer;
|
||||
|
||||
protected Toolbar mToolbar;
|
||||
|
||||
protected TextView mTitleTv;
|
||||
@ -62,7 +61,6 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setStatusBarDarkMode(true, this);
|
||||
initToolbar();
|
||||
|
||||
@ -88,6 +86,7 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
|
||||
}
|
||||
|
||||
private void initToolbar() {
|
||||
mToolbarContainer = findViewById(R.id.normal_toolbar_container);
|
||||
mToolbar = findViewById(R.id.normal_toolbar);
|
||||
mTitleTv = findViewById(R.id.normal_title);
|
||||
if (mToolbar != null) {
|
||||
@ -239,7 +238,7 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.menu_download) {
|
||||
MtaHelper.onEvent("下载管理", "下载管理入口", getActivityNameInChinese());
|
||||
// MtaHelper.onEvent("下载管理", "下载管理入口", getActivityNameInChinese());
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(this, mEntrance);
|
||||
startActivity(intent);
|
||||
}
|
||||
@ -253,4 +252,11 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
|
||||
protected boolean showDownloadMenu() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideToolbar(boolean isHide) {
|
||||
if (mToolbarContainer != null) {
|
||||
mToolbarContainer.setVisibility(isHide ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,9 +9,20 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.gh.base.OnListClickListener;
|
||||
import com.gh.base.OnRequestCallBackListener;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler;
|
||||
import com.gh.common.syncpage.SyncDataEntity;
|
||||
import com.gh.common.syncpage.SyncPageRepository;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.eventbus.EBMiPush;
|
||||
import com.lightgame.OnTitleClickListener;
|
||||
@ -23,18 +34,14 @@ import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import kotlin.Pair;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
|
||||
@ -52,7 +59,7 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
protected boolean isEverPause;
|
||||
|
||||
@NonNull
|
||||
protected String mEntrance;
|
||||
protected String mEntrance = "";
|
||||
|
||||
protected final Handler mBaseHandler = new BaseFragment.BaseHandler(this);
|
||||
|
||||
@ -138,9 +145,55 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
} else {
|
||||
mCachedView = View.inflate(getContext(), getLayoutId(), null);
|
||||
}
|
||||
ButterKnife.bind(this, mCachedView);
|
||||
|
||||
if (useButterKnife()) {
|
||||
ButterKnife.bind(this, mCachedView);
|
||||
}
|
||||
|
||||
initView(mCachedView);
|
||||
|
||||
if (addSyncPageObserver()) {
|
||||
initSyncPageObserver();
|
||||
}
|
||||
}
|
||||
|
||||
private void initSyncPageObserver() {
|
||||
SyncPageRepository.INSTANCE.getSyncPageLiveData().observe(this, syncDataEntities -> {
|
||||
try {
|
||||
Utils.log("SyncPageRepository initSyncPageObserver->" + syncDataEntities);
|
||||
List<SyncDataEntity> readyRemoveList = new ArrayList<>();
|
||||
if (syncDataEntities == null || syncDataEntities.isEmpty()) return;
|
||||
RecyclerView.Adapter adapter = provideSyncAdapter();
|
||||
if (!(adapter instanceof ISyncAdapterHandler)) return;
|
||||
for (int i = 0; i < adapter.getItemCount(); i++) {
|
||||
Pair<String, Object> syncKey = ((ISyncAdapterHandler) adapter).getSyncData(i);
|
||||
if (syncKey == null) continue;
|
||||
for (SyncDataEntity syncDataEntity : syncDataEntities) {
|
||||
if (syncDataEntity.getSyncId().equals(syncKey.getFirst())) {
|
||||
boolean isSuccess = SyncPageRepository.INSTANCE.handleSyncData(syncKey.getSecond(), syncDataEntity);
|
||||
if (isSuccess) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("SyncPageRepository notify position->" + i);
|
||||
}
|
||||
adapter.notifyItemChanged(i);
|
||||
|
||||
if (syncDataEntity.getRemove()) {
|
||||
readyRemoveList.add(syncDataEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBaseHandler.postDelayed(() -> SyncPageRepository.removeSyncData(readyRemoveList), 2000);
|
||||
} catch (Exception e) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
throw e;
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 必须的有subscribe才能register
|
||||
@ -158,6 +211,13 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
return mCachedView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
mCachedView = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
@ -183,11 +243,7 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
try {
|
||||
Utils.toast(getContext(), msg);
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
Utils.toast(getContext(), msg);
|
||||
}
|
||||
|
||||
public void toastLong(@StringRes int msg) {
|
||||
@ -255,4 +311,20 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
return this;
|
||||
}
|
||||
|
||||
public void onParentActivityFinish() {
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected RecyclerView.Adapter provideSyncAdapter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean addSyncPageObserver() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean useButterKnife() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,28 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CheckedTextView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.base.adapter.FragmentAdapter;
|
||||
import com.gh.common.view.TabIndicatorView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.normal.NormalFragment;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.lightgame.view.NoScrollableViewPager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -46,7 +56,7 @@ public abstract class BaseFragment_TabLayout extends NormalFragment implements V
|
||||
protected abstract void initTabTitleList(List<String> tabTitleList);
|
||||
|
||||
protected int provideIndicatorWidth() {
|
||||
return 65;
|
||||
return 20;
|
||||
}
|
||||
|
||||
protected View provideTabView(int position, String tabTitle) {
|
||||
@ -94,11 +104,71 @@ public abstract class BaseFragment_TabLayout extends NormalFragment implements V
|
||||
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
|
||||
TabLayout.Tab tab = mTabLayout.getTabAt(i);
|
||||
if (tab == null) continue;
|
||||
View tabView = provideTabView(i, tab.getText() != null ? tab.getText().toString() : "");
|
||||
if (tabView == null) continue;
|
||||
String tabTitle = tab.getText() != null ? tab.getText().toString() : "";
|
||||
View tabView = provideTabView(i, tabTitle);
|
||||
if (tabView == null) tabView = createDefaultTabCustomView(tabTitle);
|
||||
tab.setCustomView(tabView);
|
||||
}
|
||||
|
||||
initTabStyle(mTabLayout, mCheckedIndex);
|
||||
}
|
||||
|
||||
public static void initTabStyle(TabLayout tabLayout, int currentItem) {
|
||||
// 默认选择addOnTabSelectedListener不会回调
|
||||
int tabCount = tabLayout.getTabCount();
|
||||
if (tabCount > 0) {
|
||||
TabLayout.Tab tab = tabLayout.getTabAt(currentItem);
|
||||
if (tab != null) updateTabStyle(tab, true);
|
||||
}
|
||||
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
updateTabStyle(tab, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
updateTabStyle(tab, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
updateTabStyle(tab, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void updateTabStyle(TabLayout.Tab tab, boolean isChecked) {
|
||||
View tabView = tab.getCustomView();
|
||||
if (tabView == null) {
|
||||
Utils.log("TabLayout->Tab样式不是通用样式,请检查");
|
||||
return;
|
||||
}
|
||||
|
||||
TextView tabTitle;
|
||||
if (tabView instanceof TextView) {
|
||||
tabTitle = (TextView) tabView;
|
||||
} else {
|
||||
tabTitle = tabView.findViewById(R.id.tab_title);
|
||||
}
|
||||
|
||||
if (tabTitle == null) {
|
||||
Utils.log("TabLayout->Tab样式不是通用样式,请检查");
|
||||
return;
|
||||
}
|
||||
tabTitle.setTypeface(isChecked ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
|
||||
}
|
||||
|
||||
// 如果不设置View的话,无法动态设置字体样式
|
||||
@NonNull
|
||||
public static View createDefaultTabCustomView(String title) {
|
||||
View view = LayoutInflater.from(HaloApp.getInstance().getApplication().getBaseContext()).inflate(R.layout.tab_item, null);
|
||||
View tabTitle = view.findViewById(R.id.tab_title);
|
||||
if (tabTitle instanceof CheckedTextView) {
|
||||
((CheckedTextView) tabTitle).setText(title);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.base.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.normal.NormalFragment
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
/**
|
||||
* 懒加载(支持多层嵌套)
|
||||
@ -12,10 +13,10 @@ abstract class BaseLazyFragment : NormalFragment() {
|
||||
|
||||
private var isViewCreated = false
|
||||
|
||||
private var isSupportVisible = false
|
||||
protected var isSupportVisible = false
|
||||
|
||||
/**
|
||||
* 用于分发可见时间的时候父获取 fragment 是否隐藏
|
||||
* 用于分发可见时间的时候获取 父fragment 是否隐藏
|
||||
*
|
||||
* @return true fragment 不可见, false 父 fragment 可见
|
||||
*/
|
||||
@ -104,7 +105,7 @@ abstract class BaseLazyFragment : NormalFragment() {
|
||||
isSupportVisible = visible
|
||||
|
||||
if (visible) {
|
||||
if (mIsFirstVisible) {
|
||||
if (mIsFirstVisible && view != null) {
|
||||
mIsFirstVisible = false
|
||||
onFragmentFirstVisible()
|
||||
}
|
||||
|
||||
107
app/src/main/java/com/gh/base/fragment/BaseLazyTabFragment.kt
Normal file
107
app/src/main/java/com/gh/base/fragment/BaseLazyTabFragment.kt
Normal file
@ -0,0 +1,107 @@
|
||||
package com.gh.base.fragment
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager.widget.PagerAdapter
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import butterknife.BindView
|
||||
import com.gh.base.adapter.FragmentAdapter
|
||||
import com.gh.common.view.TabIndicatorView
|
||||
import com.gh.gamecenter.R
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||
import com.lightgame.utils.Utils
|
||||
import com.lightgame.view.NoScrollableViewPager
|
||||
|
||||
abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeListener {
|
||||
|
||||
@BindView(R.id.fragment_tab_layout)
|
||||
lateinit var mTabLayout: TabLayout
|
||||
|
||||
@BindView(R.id.fragment_view_pager)
|
||||
lateinit var mViewPager: NoScrollableViewPager
|
||||
|
||||
@BindView(R.id.fragment_tab_indicator)
|
||||
lateinit var mTabIndicatorView: TabIndicatorView
|
||||
|
||||
var mFragmentsList: MutableList<Fragment> = arrayListOf()
|
||||
|
||||
var mTabTitleList: MutableList<String> = arrayListOf()
|
||||
|
||||
var mCheckedIndex = 0
|
||||
|
||||
abstract fun initFragmentList(fragments: MutableList<Fragment>)
|
||||
|
||||
abstract fun initTabTitleList(tabTitleList: MutableList<String>)
|
||||
|
||||
protected open fun provideIndicatorWidth(): Int {
|
||||
return 20
|
||||
}
|
||||
|
||||
protected open fun provideTabView(position: Int, tabTitle: String?): View? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.fragment_tablayout_viewpager
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
val fragments = childFragmentManager.fragments
|
||||
if (fragments != null) {
|
||||
for (fragment in fragments) {
|
||||
fragment.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (arguments != null) mCheckedIndex = requireArguments().getInt(PAGE_INDEX, 0)
|
||||
}
|
||||
|
||||
open fun providePagerAdapter(): PagerAdapter? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
super.onFragmentFirstVisible()
|
||||
|
||||
initFragmentList(mFragmentsList)
|
||||
initTabTitleList(mTabTitleList)
|
||||
|
||||
mViewPager.offscreenPageLimit = mFragmentsList.size
|
||||
mViewPager.addOnPageChangeListener(this)
|
||||
mViewPager.adapter = providePagerAdapter()
|
||||
?: FragmentAdapter(childFragmentManager, mFragmentsList, mTabTitleList)
|
||||
mViewPager.currentItem = mCheckedIndex
|
||||
mTabLayout.setupWithViewPager(mViewPager)
|
||||
mTabIndicatorView.setupWithTabLayout(mTabLayout)
|
||||
mTabIndicatorView.setupWithViewPager(mViewPager)
|
||||
mTabIndicatorView.setIndicatorWidth(provideIndicatorWidth())
|
||||
for (i in 0 until mTabLayout.tabCount) {
|
||||
val tab = mTabLayout.getTabAt(i) ?: continue
|
||||
val tabTitle = if (tab.text != null) tab.text.toString() else ""
|
||||
var tabView = provideTabView(i, tabTitle)
|
||||
if (tabView == null) tabView = BaseFragment_TabLayout.createDefaultTabCustomView(tabTitle)
|
||||
tab.customView = tabView
|
||||
}
|
||||
BaseFragment_TabLayout.initTabStyle(mTabLayout, mCheckedIndex)
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
|
||||
override fun onPageSelected(position: Int) {}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
|
||||
companion object {
|
||||
const val PAGE_INDEX = "PAGE_INDEX"
|
||||
}
|
||||
}
|
||||
@ -2,14 +2,28 @@ package com.gh.common
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.gh.common.AppExecutor.ioExecutor
|
||||
import com.gh.common.AppExecutor.lightWeightIoExecutor
|
||||
import com.gh.common.AppExecutor.uiExecutor
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
/**
|
||||
* APP 线程池管理类
|
||||
*
|
||||
* [ioExecutor] 是一个最大线程数固定的线程池,较为繁重的 IO 任务可以交给它
|
||||
* [uiExecutor] 是主线程的包裹,需要切换至主线程执行可以用它
|
||||
* [lightWeightIoExecutor] 是一个单线程的线程池,轻量级且需要保证同一线程的 IO 任务可以交给它
|
||||
*
|
||||
*/
|
||||
object AppExecutor {
|
||||
|
||||
@JvmStatic
|
||||
var ioExecutor = Executors.newSingleThreadExecutor()
|
||||
val uiExecutor by lazy { MainThreadExecutor() }
|
||||
@JvmStatic
|
||||
var uiExecutor = MainThreadExecutor()
|
||||
val lightWeightIoExecutor by lazy { Executors.newSingleThreadExecutor() }
|
||||
@JvmStatic
|
||||
val ioExecutor = Executors.newCachedThreadPool() // 用 by lazy 可能影响初始化速度
|
||||
|
||||
class MainThreadExecutor : Executor {
|
||||
private val mainThreadHandler = Handler(Looper.getMainLooper())
|
||||
@ -24,8 +38,12 @@ object AppExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnIoThread(f: () -> Unit) {
|
||||
AppExecutor.ioExecutor.execute(f)
|
||||
fun runOnIoThread(isLightWeightTask: Boolean = false, f: () -> Unit) {
|
||||
if (isLightWeightTask) {
|
||||
AppExecutor.lightWeightIoExecutor.execute(f)
|
||||
} else {
|
||||
AppExecutor.ioExecutor.execute(f)
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnUiThread(f: () -> Unit) {
|
||||
|
||||
@ -6,9 +6,12 @@ import android.webkit.JavascriptInterface
|
||||
import androidx.annotation.Keep
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.LoginActivity
|
||||
import com.gh.gamecenter.ViewImageActivity
|
||||
import com.gh.gamecenter.entity.Badge
|
||||
import com.gh.gamecenter.entity.MtaEvent
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -21,7 +24,6 @@ import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
import wendu.dsbridge.CompletionHandler
|
||||
|
||||
class DefaultJsApi(var context: Context) {
|
||||
|
||||
@ -76,6 +78,11 @@ class DefaultJsApi(var context: Context) {
|
||||
return HaloApp.getInstance().channel
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getAppVersion(msg: Any): String {
|
||||
return BuildConfig.VERSION_NAME
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun bindWechat(msg: Any, handler: CompletionHandler<Any>) {
|
||||
context.ifLogin("浏览器") {
|
||||
@ -144,9 +151,6 @@ class DefaultJsApi(var context: Context) {
|
||||
context?.startActivity(ViewImageActivity.getBase64ViewImageIntent(context, true))
|
||||
}
|
||||
|
||||
@Keep
|
||||
internal data class MtaEvent(var name: String = "", var key: String = "", var value: String = "")
|
||||
|
||||
@Keep
|
||||
internal data class ImageEvent(var imageList: ArrayList<String> = arrayListOf(), var position: Int = 0)
|
||||
|
||||
|
||||
228
app/src/main/java/com/gh/common/DefaultUrlHandler.kt
Normal file
228
app/src/main/java/com/gh/common/DefaultUrlHandler.kt
Normal file
@ -0,0 +1,228 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.DirectUtils.directToGameDetailVideoStreaming
|
||||
import com.gh.common.util.DirectUtils.directToGameVideo
|
||||
import com.gh.common.util.DirectUtils.directToVideoDetail
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
object DefaultUrlHandler {
|
||||
|
||||
@JvmStatic
|
||||
fun interceptUrl(context: Context, url: String, entrance: String): Boolean {
|
||||
val uri = Uri.parse(url)
|
||||
if ("ghzhushou" == uri.scheme) {
|
||||
Utils.log("url = $url")
|
||||
Utils.log("url = " + uri.scheme!!)
|
||||
val host = uri.host
|
||||
val path = uri.path
|
||||
var id = ""
|
||||
if (!TextUtils.isEmpty(path)) {
|
||||
id = path!!.substring(1)
|
||||
}
|
||||
val intent: Intent
|
||||
when (host) {
|
||||
"article" -> context.startActivity(NewsDetailActivity.getIntentById(context, id, entrance))
|
||||
|
||||
"game" -> GameDetailActivity.startGameDetailActivity(context, id, "libao" == uri.getQueryParameter("to"), entrance)
|
||||
|
||||
"column" -> SubjectActivity.startSubjectActivity(context, id, uri.getQueryParameter("name"), false, entrance)
|
||||
|
||||
"libao" -> context.startActivity(LibaoDetailActivity.getIntentById(context, id, entrance))
|
||||
|
||||
"qq" -> try {
|
||||
DirectUtils.directToQqConversation(context, id)
|
||||
} catch (e: Throwable) {
|
||||
Utils.toast(context, "请检查是否已经安装手机QQ")
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
"qqqun" -> {
|
||||
val key = uri.getQueryParameter("key")
|
||||
if (!DirectUtils.directToQqGroup(context, key)) {
|
||||
Utils.toast(context, "请检查是否已经安装手机QQ")
|
||||
}
|
||||
}
|
||||
|
||||
"inurl" -> {
|
||||
intent = Intent(context, WebActivity::class.java)
|
||||
intent.putExtra(EntranceUtils.KEY_URL, uri.getQueryParameter("url"))
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
"outurl" -> {
|
||||
intent = Intent()
|
||||
intent.action = Intent.ACTION_VIEW
|
||||
intent.data = Uri.parse(uri.getQueryParameter("url"))
|
||||
try {
|
||||
context.startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
Utils.toast(context, "请检查是否已经安装手机浏览器")
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
"question" -> DirectUtils.directToQuestionDetail(context, id, entrance, "文章链接")
|
||||
|
||||
"community" -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = id
|
||||
community.name = uri.getQueryParameter("name") ?: ""
|
||||
DirectUtils.directToCommunity(context, community)
|
||||
}
|
||||
|
||||
"community_column" -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = uri.getQueryParameter("community_id") ?: ""
|
||||
community.name = uri.getQueryParameter("community_name") ?: ""
|
||||
val columnId = uri.getQueryParameter("column_id") ?: ""
|
||||
DirectUtils.directToCommunityColumn(context, community, columnId, entrance, "文章链接")
|
||||
}
|
||||
|
||||
"answer" -> DirectUtils.directToAnswerDetail(context, id, entrance, "文章链接")
|
||||
|
||||
"communities" -> {
|
||||
// ghzhushou://communities/5a32405b2397ab000f688de3/articles/5c99d262c140b321564f04e3
|
||||
var communityId = ""
|
||||
var type = ""
|
||||
var typeId = ""
|
||||
val split = id.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
for (text in split) {
|
||||
if (TextUtils.isEmpty(communityId)) {
|
||||
communityId = text
|
||||
continue
|
||||
}
|
||||
if (TextUtils.isEmpty(type)) {
|
||||
type = text
|
||||
continue
|
||||
}
|
||||
if (TextUtils.isEmpty(typeId)) {
|
||||
typeId = text
|
||||
}
|
||||
}
|
||||
if ("articles" == type) {
|
||||
DirectUtils.directToCommunityArticle(
|
||||
context, typeId, communityId,
|
||||
entrance, "文章链接")
|
||||
}
|
||||
}
|
||||
EntranceUtils.HOST_UPLOAD_VIDEO -> {
|
||||
val titleParameter = uri.getQueryParameter("title")
|
||||
val title = if (titleParameter.isNullOrEmpty()) "" else "#$titleParameter#"
|
||||
val categoryId = uri.getQueryParameter("category_id") ?: ""
|
||||
val link = uri.getQueryParameter("link") ?: ""
|
||||
val linkEntity = VideoLinkEntity(title, categoryId, link)
|
||||
// if (!CheckLoginUtils.isLogin()) {
|
||||
// HaloApp.put(EntranceUtils.HOST_UPLOAD_VIDEO, linkEntity)
|
||||
// }
|
||||
CheckLoginUtils.checkLogin(context, null, true, EntranceUtils.ENTRANCE_BROWSER) {
|
||||
DirectUtils.directToVideoManager(context, linkEntity, EntranceUtils.ENTRANCE_BROWSER, "")
|
||||
}
|
||||
}
|
||||
EntranceUtils.HOST_USERHOME -> {
|
||||
val position = uri.getQueryParameter("position")
|
||||
DirectUtils.directToHomeActivity(context, id, if (position.isNullOrEmpty()) -1 else position.toInt(), entrance, "")
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_MORE -> {
|
||||
val referer = uri.getQueryParameter("referer") ?: ""
|
||||
val type = uri.getQueryParameter("type") ?: ""
|
||||
val act = uri.getQueryParameter("act") ?: ""
|
||||
val loaction = if (TextUtils.isEmpty(act)) id else VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.value
|
||||
directToVideoDetail(context, id, loaction, false, "", entrance, "", referer, type, act)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_SINGLE -> {
|
||||
val referer = uri.getQueryParameter("referer") ?: ""
|
||||
directToVideoDetail(context, id, VideoDetailContainerViewModel.Location.SINGLE_VIDEO.value,
|
||||
false, "", entrance, "", if (TextUtils.isEmpty(referer)) "" else referer)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_STREAMING_HOME -> {
|
||||
intent = Intent(context, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
intent.putExtra(MainActivity.SWITCH_TO_VIDEO, true)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_STREAMING_DESC -> {
|
||||
directToGameDetailVideoStreaming(context, id, entrance)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_COLLECTION -> {
|
||||
directToGameVideo(context, id, entrance, "")
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_CATEGORY -> {
|
||||
val title = uri.getQueryParameter("title")
|
||||
DirectUtils.directCategoryDirectory(context, id, title ?: "", entrance, "")
|
||||
}
|
||||
EntranceUtils.HOST_COLUMN_COLLECTION -> {
|
||||
val name = uri.getQueryParameter("name")
|
||||
DirectUtils.directToColumnCollection(context, id, -1, entrance, name ?: "")
|
||||
}
|
||||
EntranceUtils.HOST_COLUMN -> {
|
||||
DirectUtils.directToSubject(context, id, uri.getQueryParameter(EntranceUtils.KEY_NAME), entrance)
|
||||
}
|
||||
EntranceUtils.HOST_COMMUNITY_QUESTION_LABEL_DETAIL -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = uri.getQueryParameter("community_id") ?: ""
|
||||
community.name = uri.getQueryParameter("community_name") ?: ""
|
||||
val tag = uri.getQueryParameter("tag") ?: ""
|
||||
DirectUtils.directAskColumnLabelDetail(context, tag, community, entrance, "")
|
||||
}
|
||||
EntranceUtils.HOST_COMMUNITY_COLUMN_DETAIL -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = uri.getQueryParameter("community_id") ?: ""
|
||||
community.name = uri.getQueryParameter("community_name") ?: ""
|
||||
val columnId = uri.getQueryParameter("column_id") ?: ""
|
||||
DirectUtils.directAskColumnDetail(context, columnId, community, entrance, "")
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_BLOCK -> {
|
||||
val name = uri.getQueryParameter("name")
|
||||
?: ""
|
||||
val entity = SubjectRecommendEntity(link = id, name = name, text = name)
|
||||
DirectUtils.directToBlock(context, entity)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_SERVER_BLOCK -> {
|
||||
DirectUtils.directToGameServers(context, entrance = entrance, path = "")
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_AMWAY_BLOCK -> {
|
||||
DirectUtils.directToAmway(context, entrance = entrance, path = "")
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_HELP -> {
|
||||
val name = uri.getQueryParameter("name")
|
||||
?: ""
|
||||
DirectUtils.directToQa(context, name, id)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_HELP_COLLECTION -> {
|
||||
val name = uri.getQueryParameter("name")
|
||||
?: ""
|
||||
DirectUtils.directToQaCollection(context, name, id)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_UPLOAD -> {
|
||||
DirectUtils.directGameUpload(context,entrance = entrance, path = "")
|
||||
}
|
||||
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
return true
|
||||
}
|
||||
if ("http" != uri.scheme && "https" != uri.scheme) return true
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -1,133 +0,0 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.LibaoDetailActivity
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
object DefaultWebViewUrlHandler {
|
||||
|
||||
@JvmStatic
|
||||
fun interceptUrl(context: Context, url: String, entrance: String): Boolean {
|
||||
val uri = Uri.parse(url)
|
||||
if ("ghzhushou" == uri.scheme) {
|
||||
Utils.log("url = $url")
|
||||
Utils.log("url = " + uri.scheme!!)
|
||||
val host = uri.host
|
||||
val path = uri.path
|
||||
var id = ""
|
||||
if (!TextUtils.isEmpty(path)) {
|
||||
id = path!!.substring(1)
|
||||
}
|
||||
val intent: Intent
|
||||
when (host) {
|
||||
"article" -> context.startActivity(NewsDetailActivity.getIntentById(context, id, entrance))
|
||||
|
||||
"game" -> GameDetailActivity.startGameDetailActivity(context, id, entrance)
|
||||
|
||||
"column" -> SubjectActivity.startSubjectActivity(context, id, uri.getQueryParameter("name"), false, entrance)
|
||||
|
||||
"libao" -> context.startActivity(LibaoDetailActivity.getIntentById(context, id, entrance))
|
||||
|
||||
"qq" -> try {
|
||||
DirectUtils.directToQqConversation(context, id)
|
||||
} catch (e: Exception) {
|
||||
Utils.toast(context, "请检查是否已经安装手机QQ")
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
"qqqun" -> {
|
||||
val key = uri.getQueryParameter("key")
|
||||
if (!DirectUtils.directToQqGroup(context, key)) {
|
||||
Utils.toast(context, "请检查是否已经安装手机QQ")
|
||||
}
|
||||
}
|
||||
|
||||
"inurl" -> {
|
||||
intent = Intent(context, WebActivity::class.java)
|
||||
intent.putExtra(EntranceUtils.KEY_URL, uri.getQueryParameter("url"))
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
"outurl" -> {
|
||||
intent = Intent()
|
||||
intent.action = Intent.ACTION_VIEW
|
||||
intent.data = Uri.parse(uri.getQueryParameter("url"))
|
||||
try {
|
||||
context.startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
Utils.toast(context, "请检查是否已经安装手机浏览器")
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
"question" -> DirectUtils.directToQuestionDetail(context, id, entrance, "文章链接")
|
||||
|
||||
"community" -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = id
|
||||
community.name = uri.getQueryParameter("name")
|
||||
DirectUtils.directToCommunity(context, community)
|
||||
}
|
||||
|
||||
"answer" -> DirectUtils.directToAnswerDetail(context, id, entrance, "文章链接")
|
||||
|
||||
"communities" -> {
|
||||
// ghzhushou://communities/5a32405b2397ab000f688de3/articles/5c99d262c140b321564f04e3
|
||||
var communityId = ""
|
||||
var type = ""
|
||||
var typeId = ""
|
||||
val split = id.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
for (text in split) {
|
||||
if (TextUtils.isEmpty(communityId)) {
|
||||
communityId = text
|
||||
continue
|
||||
}
|
||||
if (TextUtils.isEmpty(type)) {
|
||||
type = text
|
||||
continue
|
||||
}
|
||||
if (TextUtils.isEmpty(typeId)) {
|
||||
typeId = text
|
||||
}
|
||||
}
|
||||
if ("articles" == type) {
|
||||
DirectUtils.directToCommunityArticle(
|
||||
context, typeId, communityId,
|
||||
entrance, "文章链接")
|
||||
}
|
||||
}
|
||||
EntranceUtils.HOST_UPLOAD_VIDEO -> {
|
||||
val titleParameter = uri.getQueryParameter("title")
|
||||
val title = if (titleParameter.isNullOrEmpty()) "" else "#$titleParameter#"
|
||||
val categoryId = uri.getQueryParameter("category_id") ?: ""
|
||||
val link = uri.getQueryParameter("link") ?: ""
|
||||
val linkEntity = VideoLinkEntity(title, categoryId, link)
|
||||
if (!CheckLoginUtils.isLogin()) {
|
||||
HaloApp.put(EntranceUtils.HOST_UPLOAD_VIDEO, linkEntity)
|
||||
}
|
||||
CheckLoginUtils.checkLogin(context, EntranceUtils.ENTRANCE_BROWSER) {
|
||||
DirectUtils.directToVideoManager(context, linkEntity, EntranceUtils.ENTRANCE_BROWSER, "")
|
||||
}
|
||||
}
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
return true
|
||||
}
|
||||
if ("http" != uri.scheme && "https" != uri.scheme) return true
|
||||
return false
|
||||
}
|
||||
}
|
||||
68
app/src/main/java/com/gh/common/FixedRateJobHelper.kt
Normal file
68
app/src/main/java/com/gh/common/FixedRateJobHelper.kt
Normal file
@ -0,0 +1,68 @@
|
||||
package com.gh.common
|
||||
|
||||
import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.loghub.LoghubUtils
|
||||
import com.gh.common.util.doOnMainProcessOnly
|
||||
import com.gh.common.videolog.VideoRecordUtils
|
||||
import com.gh.gamecenter.entity.TimeEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
object FixedRateJobHelper {
|
||||
private const val CHECKER_PERIOD: Long = 60 * 1000L
|
||||
private const val TIME_PERIOD: Long = 600 * 1000L
|
||||
private const val LOGHUB_PERIOD: Long = 120 * 1000L
|
||||
private const val EXPOSURE_PERIOD: Long = 300 * 1000L
|
||||
private const val REGION_SETTING_PERIOD: Long = 300 * 1000L
|
||||
private const val VIDEO_RECORD_PERIOD: Long = 60 * 1000L
|
||||
|
||||
private var mExecuteCount: Int = 0
|
||||
|
||||
var timeDeltaBetweenServerAndClient: Long = 0
|
||||
|
||||
@JvmStatic
|
||||
fun begin() {
|
||||
doOnMainProcessOnly {
|
||||
fixedRateTimer("Global-Fixed-Rate-Timer", initialDelay = 100, period = CHECKER_PERIOD) {
|
||||
// 时间校对,10分钟一次
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % TIME_PERIOD == 0L) {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api.time
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Response<TimeEntity>() {
|
||||
override fun onResponse(response: TimeEntity?) {
|
||||
val serverTime = response?.time
|
||||
serverTime?.let { timeDeltaBetweenServerAndClient = it * 1000 - System.currentTimeMillis() }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 提交曝光数据
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % EXPOSURE_PERIOD == 0L) {
|
||||
ExposureManager.commitSavedExposureEvents(true)
|
||||
}
|
||||
|
||||
// 提交普通 loghub 数据
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % LOGHUB_PERIOD == 0L) {
|
||||
LoghubUtils.commitSavedLoghubEvents()
|
||||
}
|
||||
|
||||
// 更新游戏屏蔽信息
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % REGION_SETTING_PERIOD == 0L) {
|
||||
RegionSettingHelper.getRegionSetting()
|
||||
}
|
||||
|
||||
// 提交视频浏览记录数据
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % VIDEO_RECORD_PERIOD == 0L) {
|
||||
VideoRecordUtils.commitVideoRecord()
|
||||
}
|
||||
|
||||
// ExposureUtils.logADownloadCompleteExposureEvent(GameEntity(id = mExecuteCount.toString(), name = "测试曝光上传"), platform = "", trace = null, downloadType = ExposureUtils.DownloadType.DOWNLOAD)
|
||||
mExecuteCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,7 @@ import com.gh.common.exposure.meta.MetaUtil
|
||||
import com.gh.common.util.edit
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.entity.AliasEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -35,33 +36,29 @@ object PushManager {
|
||||
|
||||
@JvmStatic
|
||||
fun init(channel: String) {
|
||||
//初始化友盟推送
|
||||
UMConfigure.init(mApplication,
|
||||
Config.UMENG_APPKEY, channel,
|
||||
UMConfigure.DEVICE_TYPE_PHONE,
|
||||
Config.UMENG_MESSAGE_SECRET)
|
||||
tryWithDefaultCatch {
|
||||
//初始化友盟推送
|
||||
UMConfigure.init(mApplication, Config.UMENG_APPKEY, channel, UMConfigure.DEVICE_TYPE_PHONE, Config.UMENG_MESSAGE_SECRET)
|
||||
|
||||
// 注册小米、华为和魅族通道
|
||||
MiPushRegistar.register(mApplication, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
|
||||
HuaWeiRegister.register(mApplication)
|
||||
MeizuRegister.register(mApplication, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
|
||||
//友盟推送
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
pushAgent.onAppStart() // 开启App统计
|
||||
runOnIoThread { registerDevice() }
|
||||
|
||||
//注册推送服务,每次调用register方法都会回调该接口
|
||||
registerDevice()
|
||||
// 注册小米、华为和魅族通道
|
||||
MiPushRegistar.register(mApplication, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
|
||||
HuaWeiRegister.register(mApplication)
|
||||
MeizuRegister.register(mApplication, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
|
||||
|
||||
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(mApplication).getString(SP_PUSH_ALIAS, "")
|
||||
mPreviousAlias = aliasInSp?.toObject()
|
||||
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(mApplication).getString(SP_PUSH_ALIAS, "")
|
||||
mPreviousAlias = aliasInSp?.toObject()
|
||||
|
||||
if (mPreviousAlias == null) {
|
||||
getAndSetAlias()
|
||||
if (mPreviousAlias == null) {
|
||||
getAndSetAlias()
|
||||
}
|
||||
|
||||
// 完全自定义处理(透传)
|
||||
pushAgent.setPushIntentServiceClass(GHUmengNotificationService::class.java)
|
||||
}
|
||||
|
||||
// 完全自定义处理(透传)
|
||||
pushAgent.setPushIntentServiceClass(GHUmengNotificationService::class.java)
|
||||
}
|
||||
|
||||
private fun registerDevice() {
|
||||
|
||||
@ -6,10 +6,11 @@ import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
/**
|
||||
* 统计用户在当前 Fragment 的停留时间,在 onViewDestroy 或 onDestroy 里获取 elapsedTime 即可,单位为秒
|
||||
* 统计用户在当前 Fragment/Activity 的停留时间,在 onViewDestroy 或 onDestroy 里获取 elapsedTime 即可,单位为秒
|
||||
*/
|
||||
class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) {
|
||||
|
||||
@ -113,7 +114,7 @@ class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) {
|
||||
}
|
||||
|
||||
object TimeElapsedThreadHolder {
|
||||
val threadService = Executors.newSingleThreadExecutor()
|
||||
val threadService: ExecutorService by lazy { Executors.newSingleThreadExecutor() }
|
||||
}
|
||||
|
||||
interface TimeoutCallback {
|
||||
|
||||
16
app/src/main/java/com/gh/common/annotation/SyncIgnore.java
Normal file
16
app/src/main/java/com/gh/common/annotation/SyncIgnore.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.gh.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 标记那些不需要检查的同步字段
|
||||
*
|
||||
* 同步字段冲突时使用
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SyncIgnore {
|
||||
}
|
||||
12
app/src/main/java/com/gh/common/annotation/SyncPage.java
Normal file
12
app/src/main/java/com/gh/common/annotation/SyncPage.java
Normal file
@ -0,0 +1,12 @@
|
||||
package com.gh.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SyncPage {
|
||||
String[] syncNames();
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.gh.common.avoidcallback;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
public class ActivityResultInfo {
|
||||
private int resultCode;
|
||||
private Intent data;
|
||||
|
||||
public ActivityResultInfo(int resultCode, Intent data) {
|
||||
this.resultCode = resultCode;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
||||
public int getResultCode() {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
public void setResultCode(int resultCode) {
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
public Intent getData() {
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Intent data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.gh.common.avoidcallback
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.SparseArray
|
||||
import androidx.fragment.app.Fragment
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.subjects.PublishSubject
|
||||
|
||||
class AvoidOnResultFragment : Fragment() {
|
||||
private val mSubjects = SparseArray<PublishSubject<ActivityResultInfo>>()
|
||||
private val mCallbacks = SparseArray<Callback>()
|
||||
|
||||
private var requestCode = 1000
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
retainInstance = true
|
||||
}
|
||||
|
||||
fun startForResult(intent: Intent): Observable<ActivityResultInfo> {
|
||||
val subject = PublishSubject.create<ActivityResultInfo>()
|
||||
return subject.doOnSubscribe {
|
||||
mSubjects.put(requestCode, subject)
|
||||
startActivityForResult(intent, requestCode)
|
||||
requestCode++
|
||||
}
|
||||
}
|
||||
|
||||
fun startForResult(intent: Intent, callback: Callback) {
|
||||
mCallbacks.put(requestCode, callback)
|
||||
startActivityForResult(intent, requestCode)
|
||||
requestCode++
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
val subject = mSubjects.get(requestCode)
|
||||
if (subject != null) {
|
||||
subject.onNext(ActivityResultInfo(resultCode, data))
|
||||
subject.onComplete()
|
||||
}
|
||||
mSubjects.remove(requestCode)
|
||||
val callback = mCallbacks.get(requestCode)
|
||||
callback?.onActivityResult(resultCode, data)
|
||||
mCallbacks.remove(requestCode)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.gh.common.avoidcallback
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import io.reactivex.Observable
|
||||
|
||||
|
||||
class AvoidOnResultManager {
|
||||
val TAG = "AvoidOnResultManager"
|
||||
private var mAvoidOnResultFragment: AvoidOnResultFragment
|
||||
|
||||
private constructor(activity: AppCompatActivity) {
|
||||
mAvoidOnResultFragment = getAvoidOnResultFragment(activity)
|
||||
}
|
||||
|
||||
private constructor(fragment: Fragment) : this(fragment.activity as AppCompatActivity)
|
||||
|
||||
companion object {
|
||||
fun getInstance(activity: AppCompatActivity): AvoidOnResultManager {
|
||||
return AvoidOnResultManager(activity)
|
||||
}
|
||||
|
||||
fun getInstance(fragment: Fragment): AvoidOnResultManager {
|
||||
return AvoidOnResultManager(fragment)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAvoidOnResultFragment(activity: AppCompatActivity): AvoidOnResultFragment {
|
||||
var avoidOnResultFragment = findAvoidOnResultFragment(activity)
|
||||
if (avoidOnResultFragment == null) {
|
||||
avoidOnResultFragment = AvoidOnResultFragment()
|
||||
val fragmentManager = activity.supportFragmentManager
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.add(avoidOnResultFragment, TAG)
|
||||
.commitAllowingStateLoss()
|
||||
fragmentManager.executePendingTransactions()
|
||||
}
|
||||
return avoidOnResultFragment
|
||||
}
|
||||
|
||||
private fun findAvoidOnResultFragment(activity: AppCompatActivity): AvoidOnResultFragment? {
|
||||
return activity.supportFragmentManager.findFragmentByTag(TAG) as? AvoidOnResultFragment
|
||||
}
|
||||
|
||||
fun startForResult(intent: Intent, callback: Callback) {
|
||||
mAvoidOnResultFragment.startForResult(intent, callback)
|
||||
}
|
||||
|
||||
fun startForResult(clazz: Class<*>, callback: Callback) {
|
||||
val intent = Intent(mAvoidOnResultFragment.activity, clazz)
|
||||
mAvoidOnResultFragment.startForResult(intent, callback)
|
||||
}
|
||||
|
||||
fun startForResult(intent: Intent): Observable<ActivityResultInfo> {
|
||||
return mAvoidOnResultFragment.startForResult(intent)
|
||||
}
|
||||
|
||||
fun startForResult(clazz: Class<*>): Observable<ActivityResultInfo> {
|
||||
val intent = Intent(mAvoidOnResultFragment.activity, clazz)
|
||||
return mAvoidOnResultFragment.startForResult(intent)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.gh.common.avoidcallback
|
||||
|
||||
import android.content.Intent
|
||||
|
||||
interface Callback {
|
||||
fun onActivityResult(resultCode: Int, data: Intent?)
|
||||
}
|
||||
@ -31,8 +31,7 @@ import io.reactivex.schedulers.Schedulers;
|
||||
public class Config {
|
||||
|
||||
public static final String API_HOST = BuildConfig.API_HOST;
|
||||
public static final String COMMENT_HOST = BuildConfig.COMMENT_HOST;
|
||||
public static final String DATA_HOST = BuildConfig.DATA_HOST;
|
||||
public static final String SENSITIVE_API_HOST = BuildConfig.SENSITIVE_API_HOST;
|
||||
|
||||
/**
|
||||
* 需要配置的请使用{@link PreferenceManager#getDefaultSharedPreferences(Context)}
|
||||
@ -50,6 +49,8 @@ public class Config {
|
||||
public static final String UMENG_APPKEY = BuildConfig.UMENG_APPKEY;
|
||||
public static final String UMENG_MESSAGE_SECRET = BuildConfig.UMENG_MESSAGE_SECRET;
|
||||
public static final String BUGLY_APPID = BuildConfig.BUGLY_APPID;
|
||||
public static final String LETO_APPID = BuildConfig.LETO_APPID;
|
||||
public static final String TTAD_APPID = BuildConfig.TTAD_APPID;
|
||||
// http://www.ghzs666.com/article/${articleId}.html
|
||||
public static final String URL_ARTICLE = "http://www.ghzs666.com/article/"; // ghzs/ghzs666 统一
|
||||
public static final String PATCHES = "patches";
|
||||
@ -235,6 +236,10 @@ public class Config {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isGameDomeSwitchOpen() {
|
||||
return getSettings() != null && getSettings().getGameDomeSwitch().equals("on");
|
||||
}
|
||||
|
||||
public static void fixHideFunction() {
|
||||
SharedPreferences preferences = PreferenceManager.
|
||||
getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
|
||||
@ -249,7 +254,7 @@ public class Config {
|
||||
public static void getGhzsSettings() {
|
||||
String channel = HaloApp.getInstance().getChannel();
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
|
||||
.getApi().getSettings(PackageUtils.getVersionName(), channel)
|
||||
.getSensitiveApi().getSettings(PackageUtils.getVersionName(), channel)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<SettingsEntity>() {
|
||||
|
||||
@ -28,10 +28,23 @@ public class Constants {
|
||||
public static final String XPOSED_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
|
||||
|
||||
public static final String EB_QUIT_LOGIN = "quit_login";
|
||||
|
||||
// 用于避免历史下载掺和到普通下载状态的 ID 修饰符
|
||||
public static final String GAME_ID_DIVIDER = ":";
|
||||
// 用于避免历史下载影响到部分依赖名字作为数据更新条件的修饰符
|
||||
public static final String GAME_NAME_DECORATOR = " ";
|
||||
|
||||
// 游戏详情进入时的自定义栏目标签是否已经默认展开过一次的标记
|
||||
public static final String SP_HAS_EXPANDED_GAME_DETAIL_TAGS = "has_expanded_game_detail_tags";
|
||||
// 游戏详情进入时的自定义栏目标签是否已经显示过一次展开更多的浮窗提示
|
||||
public static final String SP_HAS_SHOWN_EXPANDED_GAME_DETAIL_TAGS_HINT = "has_shown_expanded_game_detail_tags_hint";
|
||||
|
||||
// 最近显示的弹窗信息
|
||||
public static final String SP_LAST_OPENING_ID = "last_opening_dialog_id";
|
||||
public static final String SP_LAST_OPENING_TIME = "last_opening_dialog_time";
|
||||
|
||||
// 新用户首次启动光环的时间
|
||||
public static final String SP_INITIAL_USAGE_TIME = "initial_usage_time";
|
||||
|
||||
//引导设置 “通知管理” 引导弹窗
|
||||
public static final String SP_SHOWED_NOTIFICATION_LOGIN = "show_notification_login_hint";
|
||||
@ -44,12 +57,40 @@ public class Constants {
|
||||
public static final String SP_SHOWED_NOTIFICATION_NEW_VERSION = "show_notification_new_version";
|
||||
// 今天是否已经触发了 “通知管理” 引导弹窗
|
||||
public static final String SP_IS_SHOWED_NOTIFICATION_TODAY = "show_is_notification_today";
|
||||
// 标记安装的游戏为已玩过弹窗,最多取消2次 (https://gitlab.ghzs.com/pm/halo-app-issues/issues/722 调整为版本相关) (不是常量了也放这里好像有点奇怪)
|
||||
// v4.0.0已废弃,标记安装的游戏为已玩过弹窗,最多取消2次 (https://gitlab.ghzs.com/pm/halo-app-issues/issues/722 调整为版本相关) (不是常量了也放这里好像有点奇怪)
|
||||
public static final String SP_MARK_INSTALLED_GAME = "mark_installed_game" + PackageUtils.getVersionName();
|
||||
// 标记安装的游戏为已玩过弹窗(个人主页最多弹一次)
|
||||
public static final String SP_MARK_INSTALLED_GAME_USER_HOME = "mark_installed_game_user_home" + PackageUtils.getVersionName();
|
||||
// 标记安装的游戏为已玩过弹窗(我的游戏最多弹一次)
|
||||
public static final String SP_MARK_INSTALLED_GAME_MY_GAME = "mark_installed_game_my_game" + PackageUtils.getVersionName();
|
||||
//视频详情滑动引导
|
||||
public static final String SP_SHOW_SLIDE_GUIDE = "show_slide_guide";
|
||||
//视频详情点击引导
|
||||
public static final String SP_SHOW_CLICK_GUIDE = "show_click_guide";
|
||||
//视频详情双击点赞引导
|
||||
public static final String SP_SHOW_DOUBLE_CLICK_GUIDE = "show_double_click_guide";
|
||||
//顶部视频声音状态,重启恢复
|
||||
public static final String SP_TOP_VIDEO_VOICE = "top_video_voice";
|
||||
//我的光环提醒设置已读
|
||||
public static final String SP_ADDONS_FUNCS_HAVE_READ = "addons_funcs_have_read";
|
||||
//视频非wifi提醒只提醒一次,重启恢复
|
||||
public static final String SP_NON_WIFI_TIPS = "non_wifi_tips";
|
||||
//首页视频最新tab提示
|
||||
public static final String SP_HOME_NEW_VIDEO_TIPS = "home_new_video";
|
||||
//游戏设备弹窗提示
|
||||
public static final String SP_DEVICE_REMIND = "device_remind";
|
||||
//是否是第一次弹出游戏设备弹窗提示
|
||||
public static final String SP_FIRST_DEVICE_REMIND = "first_device_remind";
|
||||
//游戏设备弹窗不再提示
|
||||
public static final String SP_NO_REMIND_AGAIN = "no_remind_again";
|
||||
//游戏详情过滤标签数据
|
||||
public static final String SP_FILTER_TAGS = "filter_tags";
|
||||
//实名认证弹窗分类数据
|
||||
public static final String SP_AUTH_DIALOG = "auth_dialog";
|
||||
//顶部视频进度保存,重启恢复
|
||||
public static final String SP_TOP_VIDEO_SCHEDULE = "top_video_schedule";
|
||||
//我的光环小红点提示
|
||||
public static final String SP_GH_RED_POINT_REMIND = "gh_red_point_remind";
|
||||
|
||||
//手机号码匹配规则
|
||||
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
|
||||
@ -84,13 +125,18 @@ public class Constants {
|
||||
public static final int COMMENT_CD = 60 * 1000;
|
||||
//我的光环功能分组 cd间隔
|
||||
public static final int ADDONS_CD = 10 * 60 * 1000;
|
||||
//已收录包名更新 cd间隔
|
||||
public static final int PACKAGES_CD = 60 * 1000;
|
||||
|
||||
public static final String[] REPORT_LIST = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息", "违法有害信息", "其它"};
|
||||
|
||||
public static final String ENTRANCE_UNKNOWN = "(unknown)";
|
||||
|
||||
public static final String DEFAULT_TEXT_WRAPPER = "###";
|
||||
|
||||
|
||||
// 触发了安装事件的标记
|
||||
public static final String MARK_ALREADY_TRIGGERED_INSTALLATION = "triggered_installation";
|
||||
|
||||
// 标记下载重试标记(值为任务已下载大小,为空表示需要重试)
|
||||
public static final String MARK_RETRY_DOWNLOAD = "retry_download";
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.common.databind;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
@ -13,12 +14,19 @@ import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.BindingAdapter;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.OnViewClickListener;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.CertificationDialog;
|
||||
import com.gh.common.dialog.ReserveDialogFragment;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DataUtils;
|
||||
@ -36,10 +44,10 @@ import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PermissionHelper;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.common.view.DownloadDialog;
|
||||
import com.gh.common.view.DownloadProgressBar;
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
@ -52,6 +60,7 @@ import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.entity.ServerCalendarEntity;
|
||||
import com.gh.gamecenter.entity.TagStyleEntity;
|
||||
import com.gh.gamecenter.entity.TestEntity;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.gh.gamecenter.qa.entity.CommunityVideoEntity;
|
||||
@ -62,15 +71,10 @@ import com.lightgame.utils.Utils;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.BindingAdapter;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
/**
|
||||
* Created by khy on 12/02/18.
|
||||
*/
|
||||
@ -92,6 +96,26 @@ public class BindingAdapters {
|
||||
view.setTextSize(number);
|
||||
}
|
||||
|
||||
@BindingAdapter("setTypeface")
|
||||
public static void setTypeface(TextView view, String type) {
|
||||
if (type == null) return;
|
||||
|
||||
switch (type) {
|
||||
case "bold":
|
||||
view.setTypeface(null, Typeface.BOLD);
|
||||
break;
|
||||
case "italic":
|
||||
view.setTypeface(null, Typeface.ITALIC);
|
||||
break;
|
||||
case "bold_italic":
|
||||
view.setTypeface(null, Typeface.BOLD_ITALIC);
|
||||
break;
|
||||
default:
|
||||
view.setTypeface(null, Typeface.NORMAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"addDetailKaiFuView", "addDetailKaiFuViewListener", "isReadyPatch"})
|
||||
public static void addDetailKaiFuView(LinearLayout view, List<ServerCalendarEntity> list
|
||||
, OnViewClickListener listener, Boolean isReadyPatch) {
|
||||
@ -198,6 +222,17 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("textColorFromString")
|
||||
public static void textColorFromString(TextView tv, String hexString) {
|
||||
if (TextUtils.isEmpty(hexString)) return;
|
||||
|
||||
try {
|
||||
tv.setTextColor(Color.parseColor(hexString));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("visibleGone")
|
||||
public static void showHide(View view, Boolean show) {
|
||||
if (show != null && show) {
|
||||
@ -207,6 +242,40 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("goneIf")
|
||||
public static void goneIf(View view, Boolean gone) {
|
||||
if (gone != null && gone) {
|
||||
view.setVisibility(View.GONE);
|
||||
} else {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lazy 的 paddingTop
|
||||
*/
|
||||
@BindingAdapter("lazyPaddingTop")
|
||||
public static void lazyPaddingTop(View view, int paddingTopInDp) {
|
||||
view.setPadding(view.getPaddingLeft(), DisplayUtils.dip2px(paddingTopInDp), view.getPaddingRight(), view.getPaddingBottom());
|
||||
}
|
||||
|
||||
/**
|
||||
* lazy 的 paddingBottom
|
||||
*/
|
||||
@BindingAdapter("lazyPaddingBottom")
|
||||
public static void lazyPaddingBottom(View view, int paddingBottomInDp) {
|
||||
view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), DisplayUtils.dip2px(paddingBottomInDp));
|
||||
}
|
||||
|
||||
@BindingAdapter("visibleInvisible")
|
||||
public static void visibleInvisible(View view, Boolean show) {
|
||||
if (show != null && show) {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
view.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("messageUnread")
|
||||
public static void setMessageUnread(TextView view, int unreadCount) {
|
||||
if (unreadCount < 100) {
|
||||
@ -358,17 +427,26 @@ public class BindingAdapters {
|
||||
case PLUGIN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
ApkEntity apk = gameEntity.getApk().get(0);
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
apk,
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(v.getContext(), gameEntity, apk,
|
||||
() -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
entrance, location + gameEntity.getName(), traceEvent);
|
||||
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
|
||||
DownloadDialog.showDownloadDialog(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
traceEvent,
|
||||
entrance,
|
||||
location + ":" + gameEntity.getName());
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
case LAUNCH_OR_OPEN:
|
||||
@ -376,8 +454,12 @@ public class BindingAdapters {
|
||||
DataUtils.onGameLaunchEvent(v.getContext(), gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), location);
|
||||
PackageUtils.launchApplicationByPackageName(v.getContext(), gameEntity.getApk().get(0).getPackageName());
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
entrance, location + gameEntity.getName(), traceEvent);
|
||||
DownloadDialog.showDownloadDialog(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
traceEvent,
|
||||
entrance,
|
||||
location + ":" + gameEntity.getName());
|
||||
}
|
||||
break;
|
||||
case INSTALL_PLUGIN:
|
||||
@ -416,9 +498,15 @@ public class BindingAdapters {
|
||||
}
|
||||
break;
|
||||
case H5_GAME:
|
||||
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
|
||||
LinkEntity linkEntity = gameEntity.getH5Link();
|
||||
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), "play".equals(linkEntity.getType())));
|
||||
boolean isPlay = "play".equals(linkEntity.getType()); // 是否为开始玩
|
||||
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
|
||||
|
||||
if (isPlay) {
|
||||
HistoryHelper.insertGameEntity(gameEntity);
|
||||
}
|
||||
|
||||
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), isPlay));
|
||||
progressBar.getContext().startActivity(i);
|
||||
break;
|
||||
}
|
||||
@ -455,7 +543,7 @@ public class BindingAdapters {
|
||||
}
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity, PluginLocation.only_game);
|
||||
switch (status) {
|
||||
@ -511,6 +599,23 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
/*private static void download(DownloadProgressBar progressBar, GameEntity gameEntity, ExposureEvent traceEvent, @Nullable String entrance, @Nullable String location, View v) {
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
ApkEntity apk = gameEntity.getApk().get(0);
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
apk,
|
||||
() -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
});
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
entrance, location + gameEntity.getName(), traceEvent);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
private static void updateReservation(DownloadProgressBar progressBar, GameEntity gameEntity) {
|
||||
// 显示预约
|
||||
@ -546,10 +651,7 @@ public class BindingAdapters {
|
||||
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity.getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(progressBar.getContext(), gameEntity.getName(), apkEntity.getPlatform(), entrance, "下载开始", method);
|
||||
|
||||
ExposureUtils.DownloadType downloadType = ExposureUtils.getDownloadType(apkEntity, method);
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, downloadType);
|
||||
|
||||
|
||||
DownloadManager.createDownload(progressBar.getContext(),
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
@ -557,7 +659,7 @@ public class BindingAdapters {
|
||||
entrance,
|
||||
location + gameEntity.getName(),
|
||||
isSubscribe,
|
||||
downloadExposureEvent);
|
||||
traceEvent);
|
||||
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setDownloadType("插件化".equals(method) ?
|
||||
@ -567,27 +669,36 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"gameLabelList", "subjectTag"})
|
||||
public static void setGameLabelList(LinearLayout layout, GameEntity gameEntity, String subjectTag) {
|
||||
if (gameEntity == null) return;
|
||||
if (gameEntity.getTest() != null) {
|
||||
layout.removeAllViews();
|
||||
View testView = LayoutInflater.from(layout.getContext()).inflate(R.layout.game_test_label, null);
|
||||
TextView testType = testView.findViewById(R.id.test_type);
|
||||
TextView testTime = testView.findViewById(R.id.test_time);
|
||||
testType.setText(gameEntity.getTest().getType());
|
||||
testType.setBackgroundColor(ContextCompat.getColor(layout.getContext(), R.color.tag_yellow));
|
||||
@BindingAdapter("gameLabelList")
|
||||
public static void setGameLabelList(LinearLayout layout, List<TagStyleEntity> tagStyle) {
|
||||
GameViewUtils.setLabelList(layout.getContext(), layout, tagStyle);
|
||||
}
|
||||
|
||||
if (gameEntity.getTest().getStart() == 0) {
|
||||
testTime.setVisibility(View.GONE);
|
||||
// 包含测试开服标签
|
||||
@BindingAdapter("setGameTags")
|
||||
public static void setGameTags(LinearLayout layout, GameEntity gameEntity) {
|
||||
try {
|
||||
ArrayList<TagStyleEntity> tagStyle = new ArrayList<>();
|
||||
TestEntity test = gameEntity.getTest();
|
||||
if (test != null) {
|
||||
TagStyleEntity typeTag = new TagStyleEntity();
|
||||
typeTag.setName(test.getType() != null ? test.getType() : "");
|
||||
typeTag.setBackground("FFF3E0");
|
||||
typeTag.setColor("FA8500");
|
||||
tagStyle.add(typeTag);
|
||||
|
||||
TagStyleEntity timeTag = new TagStyleEntity();
|
||||
timeTag.setName(GameViewUtils.getGameTestDate(test.getStart()));
|
||||
timeTag.setBackground("E0FFF9");
|
||||
timeTag.setColor("00A887");
|
||||
tagStyle.add(timeTag);
|
||||
} else {
|
||||
testTime.setText(GameViewUtils.getGameTestDate(gameEntity.getTest().getStart()));
|
||||
tagStyle = gameEntity.getTagStyle();
|
||||
}
|
||||
layout.addView(testView);
|
||||
} else {
|
||||
GameViewUtils.setLabelList(layout.getContext(), layout, gameEntity.getTag(), subjectTag, gameEntity.getTagStyle());
|
||||
GameViewUtils.setLabelList(layout.getContext(), layout, tagStyle);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@BindingAdapter("isRefreshing")
|
||||
@ -597,14 +708,15 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"setGameName", "isShowPlatform"})
|
||||
public static void setGameName(TextView view, GameEntity game, boolean isShowPlatform) {
|
||||
@BindingAdapter({"setGameName", "isShowPlatform", "isShowSuffix"})
|
||||
public static void setGameName(TextView view, GameEntity game, boolean isShowPlatform, @Nullable Boolean isShowSuffix) {
|
||||
if (isShowSuffix == null) isShowSuffix = true; // 默认显示
|
||||
if (isShowPlatform && game.getApk().size() > 0) {
|
||||
view.setText(String.format("%s - %s", game.getName(),
|
||||
view.setText(String.format("%s - %s", !isShowSuffix ? game.getNameWithoutSuffix() : game.getName(),
|
||||
PlatformUtils.getInstance(view.getContext()).getPlatformName(
|
||||
game.getApk().get(0).getPlatform())));
|
||||
} else {
|
||||
view.setText(game.getName());
|
||||
view.setText(!isShowSuffix ? game.getNameWithoutSuffix() : game.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ abstract class BaseTrackableDialogFragment : BaseDialogFragment() {
|
||||
|
||||
abstract fun getEvent(): String
|
||||
abstract fun getKey(): String
|
||||
open fun getValue(): String = ""
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
private val mIsCanceledByClickOutsideOfDialog = AtomicBoolean(true)
|
||||
@ -47,6 +48,9 @@ abstract class BaseTrackableDialogFragment : BaseDialogFragment() {
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), value)
|
||||
} else {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), value)
|
||||
if (getValue().isNotEmpty()) {
|
||||
MtaHelper.onEvent(getEvent(), value, getValue())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
196
app/src/main/java/com/gh/common/dialog/CertificationDialog.kt
Normal file
196
app/src/main/java/com/gh/common/dialog/CertificationDialog.kt
Normal file
@ -0,0 +1,196 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.CheckBox
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.common.avoidcallback.AvoidOnResultManager
|
||||
import com.gh.common.avoidcallback.Callback
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.GsonUtils
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.UserInfoEditActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.AuthDialogEntity
|
||||
import com.gh.gamecenter.entity.AuthDialogLevel
|
||||
import com.gh.gamecenter.entity.DeviceDialogEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.user.UserViewModel
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.fragment.user.UserInfoEditFragment
|
||||
import com.lightgame.utils.AppManager
|
||||
import com.tencent.bugly.beta.tinker.TinkerManager.getApplication
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.HttpException
|
||||
|
||||
class CertificationDialog(context: Context, private val authDialogEntity: AuthDialogEntity, val gameId: String, val listener: DialogUtils.ConfirmListener) :
|
||||
Dialog(context, R.style.GhAlertDialog) {
|
||||
|
||||
private lateinit var view: View
|
||||
private lateinit var detailedDesTv: TextView
|
||||
private lateinit var noRemindAgainCb: CheckBox
|
||||
private lateinit var actionLeftTv: TextView
|
||||
private lateinit var actionRightTv: TextView
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
view = LayoutInflater.from(context).inflate(R.layout.dialog_sertification, null)
|
||||
setContentView(view)
|
||||
detailedDesTv = view.findViewById(R.id.detailedDesTv)
|
||||
noRemindAgainCb = view.findViewById(R.id.noRemindAgainCb)
|
||||
actionLeftTv = view.findViewById(R.id.actionLeftTv)
|
||||
actionRightTv = view.findViewById(R.id.actionRightTv)
|
||||
|
||||
detailedDesTv.paint.flags = Paint.UNDERLINE_TEXT_FLAG
|
||||
detailedDesTv.paint.isAntiAlias = true
|
||||
|
||||
detailedDesTv.setOnClickListener {
|
||||
context.startActivity(WebActivity.getIntentByUrl(context, authDialogEntity.link))
|
||||
}
|
||||
|
||||
when (authDialogEntity.level) {
|
||||
AuthDialogLevel.MUST_PASS.value -> {
|
||||
actionLeftTv.text = "暂不下载"
|
||||
actionRightTv.text = "去实名认证"
|
||||
noRemindAgainCb.visibility = View.GONE
|
||||
actionLeftTv.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
actionRightTv.setOnClickListener {
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
gotoAuthPage()
|
||||
} else {
|
||||
gotoLoginPage()
|
||||
}
|
||||
}
|
||||
}
|
||||
AuthDialogLevel.ALWAYS_HINT.value -> {
|
||||
actionLeftTv.text = "去实名认证"
|
||||
actionRightTv.text = "继续下载"
|
||||
noRemindAgainCb.visibility = View.GONE
|
||||
actionLeftTv.setOnClickListener {
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
gotoAuthPage()
|
||||
} else {
|
||||
gotoLoginPage()
|
||||
}
|
||||
}
|
||||
actionRightTv.setOnClickListener {
|
||||
listener.onConfirm()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
AuthDialogLevel.OPTIONAL_HINT.value -> {
|
||||
actionLeftTv.text = "去实名认证"
|
||||
actionRightTv.text = "继续下载"
|
||||
noRemindAgainCb.visibility = View.VISIBLE
|
||||
actionLeftTv.setOnClickListener {
|
||||
if (noRemindAgainCb.isChecked) {
|
||||
SPUtils.setBoolean(gameId, true)
|
||||
}
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
gotoAuthPage()
|
||||
} else {
|
||||
gotoLoginPage()
|
||||
}
|
||||
}
|
||||
actionRightTv.setOnClickListener {
|
||||
if (noRemindAgainCb.isChecked) {
|
||||
SPUtils.getBoolean(gameId, true)
|
||||
}
|
||||
listener.onConfirm()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//跳转登录页面
|
||||
private fun gotoLoginPage() {
|
||||
CheckLoginUtils.checkLogin(AppManager.getInstance().currentActivity() as AppCompatActivity,
|
||||
null, true, "实名认证弹窗") {
|
||||
if (UserManager.getInstance().isAuth) {
|
||||
listener.onConfirm()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//跳转实名认证页面
|
||||
private fun gotoAuthPage() {
|
||||
AvoidOnResultManager.getInstance(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
.startForResult(UserInfoEditActivity.getIntent(context, UserViewModel.TYPE_ID_CARD), object : Callback {
|
||||
override fun onActivityResult(resultCode: Int, data: Intent?) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val isAuthSuccess = data.getBooleanExtra(UserInfoEditFragment.AUTH_SUCCESS, false)
|
||||
if (isAuthSuccess) {
|
||||
listener.onConfirm()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun showCertificationDialog(context: Context, game: GameEntity, listener: DialogUtils.ConfirmListener) {
|
||||
//1.先判断是否登录 是执行2 否执行3
|
||||
//2.判断是否实名认证 是终止 否执行3
|
||||
//3.判断是否需要弹出认证弹窗接口
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
if (UserManager.getInstance().isAuth) {//已实名认证
|
||||
listener.onConfirm()
|
||||
} else {
|
||||
authDialog(context, game, listener)
|
||||
}
|
||||
} else {
|
||||
authDialog(context, game, listener)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun authDialog(context: Context, game: GameEntity, listener: DialogUtils.ConfirmListener) {
|
||||
var authDialog: AuthDialogEntity? = null
|
||||
if (game.authDialog != null) {
|
||||
authDialog = game.authDialog
|
||||
}
|
||||
if (authDialog == null) {
|
||||
val datas = SPUtils.getString(Constants.SP_AUTH_DIALOG)
|
||||
val type = object : TypeToken<List<AuthDialogEntity>>() {}.type
|
||||
val authDialogs = GsonUtils.gson.fromJson<List<AuthDialogEntity>>(datas, type)
|
||||
if (!authDialogs.isNullOrEmpty()) {
|
||||
authDialog = authDialogs.find { it.gameCategory == game.category }
|
||||
}
|
||||
}
|
||||
val isCloseAuthDialog = SPUtils.getBoolean(game.id, false)
|
||||
if (authDialog != null && (authDialog.level != AuthDialogLevel.OPTIONAL_HINT.value || !isCloseAuthDialog)) {
|
||||
val dialog = CertificationDialog(context, authDialog, game.id, listener)
|
||||
dialog.show()
|
||||
} else {
|
||||
listener.onConfirm()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
233
app/src/main/java/com/gh/common/dialog/DeviceRemindDialog.kt
Normal file
233
app/src/main/java/com/gh/common/dialog/DeviceRemindDialog.kt
Normal file
@ -0,0 +1,233 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Message
|
||||
import android.preference.PreferenceManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.DeviceDialogEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.fragment.SettingsFragment.AUTO_INSTALL_SP_KEY
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.android.synthetic.main.dialog_device_remind.view.*
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
* 设备提醒弹窗
|
||||
*/
|
||||
class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val gameEntity: GameEntity) : Dialog(context, R.style.GhAlertDialog) {
|
||||
private lateinit var view: View
|
||||
private var currentPage = 0
|
||||
private var mSlideLooperInterval = 3000L
|
||||
private lateinit var mLooperHandle: LooperHandle
|
||||
private lateinit var mAdapter: BannerAdapter
|
||||
private var mDatas: ArrayList<String> = ArrayList()
|
||||
private val mSlideLooperKey = 100
|
||||
private var disposable: Disposable? = null
|
||||
private val dataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
if (downloadEntity.status == DownloadStatus.done && downloadEntity.name == gameEntity.name) {
|
||||
val sp = PreferenceManager.getDefaultSharedPreferences(getContext())
|
||||
val autoInstall = sp.getBoolean(AUTO_INSTALL_SP_KEY, true)
|
||||
if (autoInstall) {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun showDeviceRemindDialog(context: Context, gameEntity: GameEntity) {
|
||||
val datas = SPUtils.getString(Constants.SP_DEVICE_REMIND)
|
||||
if (datas.isNotEmpty()) {
|
||||
val type = object : TypeToken<List<DeviceDialogEntity>>() {}.type
|
||||
val entitys = GsonUtils.gson.fromJson<List<DeviceDialogEntity>>(datas, type)
|
||||
//1.判断设备是否匹配
|
||||
val entity = entitys.find { it.manufacturer.toLowerCase().startsWith(Build.MANUFACTURER.toLowerCase()) }
|
||||
?: return
|
||||
//2.判断游戏不含剔除标签
|
||||
gameEntity.tagStyle.forEach {
|
||||
if (entity.excludeTags.contains(it.name)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
//3.不再弹出提示判断
|
||||
val isNoRemindAgain = SPUtils.getBoolean(Constants.SP_NO_REMIND_AGAIN, false)
|
||||
if (isNoRemindAgain) return
|
||||
|
||||
val dialog = DeviceRemindDialog(context, entity, gameEntity)
|
||||
dialog.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
view = LayoutInflater.from(context).inflate(R.layout.dialog_device_remind, null)
|
||||
setContentView(view)
|
||||
mDatas.addAll(entity.gallery)
|
||||
view.titleTv.text = entity.title
|
||||
view.contentTv.text = entity.content
|
||||
|
||||
view.bannerView.apply {
|
||||
orientation = ViewPager2.ORIENTATION_HORIZONTAL
|
||||
mAdapter = BannerAdapter()
|
||||
val recyclerView = getChildAt(0) as RecyclerView
|
||||
recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_NEVER
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
super.onPageSelected(position)
|
||||
currentPage = position
|
||||
slideIndicator(currentPage % mDatas.size)
|
||||
}
|
||||
})
|
||||
recyclerView.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
|
||||
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
|
||||
val isStop = e.action == MotionEvent.ACTION_DOWN || e.action == MotionEvent.ACTION_MOVE
|
||||
if (isStop) mAdapter.stopScroll() else mAdapter.startScroll()
|
||||
return false
|
||||
}
|
||||
})
|
||||
adapter = mAdapter
|
||||
mLooperHandle = LooperHandle(mAdapter)
|
||||
currentPage = (adapter as BannerAdapter).getActualFirstPositionInCenter()
|
||||
setCurrentItem(currentPage, false)
|
||||
if (mDatas.size > 1) {
|
||||
addIndicator()
|
||||
slideIndicator(currentPage % mDatas.size)
|
||||
autoPlay()
|
||||
}
|
||||
}
|
||||
val isFirst = SPUtils.getBoolean(Constants.SP_FIRST_DEVICE_REMIND, false)
|
||||
if (!isFirst) {
|
||||
view.cancelTv.isEnabled = false
|
||||
view.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_round_f5f5f5)
|
||||
disposable = countDownTimer(3) { finish, time ->
|
||||
if (finish) {
|
||||
view.cancelTv.isEnabled = true
|
||||
view.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_blue_oval)
|
||||
view.cancelTv.text = "我知道了"
|
||||
view.cancelTv.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
} else {
|
||||
view.cancelTv.text = "我知道了(${time}S)"
|
||||
}
|
||||
}
|
||||
|
||||
SPUtils.setBoolean(Constants.SP_FIRST_DEVICE_REMIND, true)
|
||||
} else {
|
||||
view.noRemindAgainCb.visibility = View.VISIBLE
|
||||
view.cancelTv.text = "我知道了"
|
||||
view.cancelTv.isEnabled = true
|
||||
view.cancelTv.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
view.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_blue_oval)
|
||||
}
|
||||
view.cancelTv.setOnClickListener {
|
||||
SPUtils.setBoolean(Constants.SP_NO_REMIND_AGAIN, view.noRemindAgainCb.isChecked)
|
||||
dismiss()
|
||||
}
|
||||
DownloadManager.getInstance(context).addObserver(dataWatcher)
|
||||
}
|
||||
|
||||
private fun addIndicator() {
|
||||
view.indicatorLl.removeAllViews()
|
||||
mDatas.forEach { _ ->
|
||||
val indicatorView = ImageView(context).apply {
|
||||
setImageResource(R.drawable.selector_device_remind_indicator)
|
||||
val params = LinearLayout.LayoutParams(DisplayUtils.dip2px(8F), LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
params.leftMargin = DisplayUtils.dip2px(1F)
|
||||
params.rightMargin = DisplayUtils.dip2px(1F)
|
||||
layoutParams = params
|
||||
}
|
||||
view.indicatorLl.addView(indicatorView)
|
||||
}
|
||||
}
|
||||
|
||||
private fun slideIndicator(position: Int) {
|
||||
for (i in 0 until view.indicatorLl.childCount) {
|
||||
val childAt = view.indicatorLl.getChildAt(i)
|
||||
childAt.isSelected = i == position
|
||||
}
|
||||
}
|
||||
|
||||
private fun autoPlay() {
|
||||
mAdapter.startScroll()
|
||||
}
|
||||
|
||||
inner class BannerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return object : RecyclerView.ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_device_remind_banner, parent, false)) {}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = if (mDatas.size == 1) mDatas.size else Int.MAX_VALUE
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val data = mDatas[position % mDatas.size]
|
||||
val view = holder.itemView as SimpleDraweeView
|
||||
ImageUtils.display(view, data)
|
||||
}
|
||||
|
||||
fun getActualFirstPositionInCenter(): Int {
|
||||
if (mDatas.size == 1) return 0
|
||||
var index = itemCount / 2
|
||||
if (index % mDatas.size != 0) {
|
||||
index -= (index % mDatas.size)
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
fun scrollToNextPage() {
|
||||
currentPage++
|
||||
view.bannerView.setCurrentItem(currentPage, true)
|
||||
}
|
||||
|
||||
fun startScroll() {
|
||||
mLooperHandle.removeMessages(mSlideLooperKey)
|
||||
mLooperHandle.sendEmptyMessageDelayed(mSlideLooperKey, mSlideLooperInterval)
|
||||
}
|
||||
|
||||
fun stopScroll() {
|
||||
mLooperHandle.removeMessages(mSlideLooperKey)
|
||||
}
|
||||
}
|
||||
|
||||
class LooperHandle(val mAdapter: BannerAdapter) : Handler() {
|
||||
private val mWeakReference: WeakReference<BannerAdapter> = WeakReference(mAdapter)
|
||||
override fun handleMessage(msg: Message?) {
|
||||
val adapter = mWeakReference.get()
|
||||
adapter?.scrollToNextPage()
|
||||
adapter?.startScroll()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
if (disposable != null && !disposable!!.isDisposed) {
|
||||
disposable!!.dispose()
|
||||
disposable = null
|
||||
}
|
||||
DownloadManager.getInstance(context).removeObserver(dataWatcher)
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,7 @@ import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.text.HtmlCompat
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
@ -18,7 +19,10 @@ import com.gh.gamecenter.entity.GameEntity
|
||||
import kotlinx.android.synthetic.main.dialog_game_off_service.*
|
||||
|
||||
// 游戏关闭下载弹窗
|
||||
class GameOffServiceDialogFragment : BaseTrackableDialogFragment() {
|
||||
class GameOffServiceDialogFragment
|
||||
// : BaseTrackableDialogFragment()
|
||||
:BaseDialogFragment() {
|
||||
|
||||
private var mDialog: GameEntity.Dialog? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
@ -38,11 +42,11 @@ class GameOffServiceDialogFragment : BaseTrackableDialogFragment() {
|
||||
topMargin = DisplayUtils.dip2px(12f)
|
||||
}
|
||||
siteTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
|
||||
siteTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme))
|
||||
siteTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme_font))
|
||||
siteTv.text = site.text
|
||||
siteTv.paintFlags = siteTv.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
||||
siteTv.setOnClickListener {
|
||||
MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
|
||||
// MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
|
||||
DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)")
|
||||
dismiss()
|
||||
}
|
||||
@ -52,13 +56,13 @@ class GameOffServiceDialogFragment : BaseTrackableDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEvent(): String {
|
||||
return "游戏下载状态按钮"
|
||||
}
|
||||
|
||||
override fun getKey(): String {
|
||||
return "查看详情弹窗"
|
||||
}
|
||||
// override fun getEvent(): String {
|
||||
// return "游戏下载状态按钮"
|
||||
// }
|
||||
//
|
||||
// override fun getKey(): String {
|
||||
// return "查看详情弹窗"
|
||||
// }
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
|
||||
@ -37,7 +37,7 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
titleTv.text = mNotificationHint?.title
|
||||
|
||||
contentContainer.removeAllViews()
|
||||
for (item in mNotificationHint?.content!!) {
|
||||
for (item in mNotificationHint?.content ?: arrayListOf()) {
|
||||
val tv = TextView(context)
|
||||
|
||||
tv.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
|
||||
@ -14,7 +14,9 @@ import androidx.lifecycle.MutableLiveData
|
||||
import butterknife.BindView
|
||||
import butterknife.ButterKnife
|
||||
import butterknife.OnClick
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.history.HistoryHelper
|
||||
import com.gh.common.repository.ReservationRepository
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
@ -28,7 +30,9 @@ import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
|
||||
// 预约弹窗
|
||||
class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
class ReserveDialogFragment
|
||||
: BaseDialogFragment() {
|
||||
// : BaseTrackableDialogFragment() {
|
||||
|
||||
@BindView(R.id.reserve_hint_tv)
|
||||
lateinit var reserveHintTv: TextView
|
||||
@ -49,6 +53,7 @@ class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
private var mSuccessCallback: SuccessCallback? = null
|
||||
|
||||
private var mGame: GameEntity? = null
|
||||
private var mGameId: String = ""
|
||||
private var mGameName: String = ""
|
||||
|
||||
@ -62,13 +67,13 @@ class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
return inflater.inflate(R.layout.dialog_reserve_game, null)
|
||||
}
|
||||
|
||||
override fun getEvent(): String {
|
||||
return "预约游戏"
|
||||
}
|
||||
|
||||
override fun getKey(): String {
|
||||
return "预约功能操作"
|
||||
}
|
||||
// override fun getEvent(): String {
|
||||
// return "预约游戏"
|
||||
// }
|
||||
//
|
||||
// override fun getKey(): String {
|
||||
// return "预约功能操作"
|
||||
// }
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@SuppressLint("SetTextI18n")
|
||||
@ -86,6 +91,7 @@ class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
if (it.success) {
|
||||
showSuccessDialog(it.withMobile, it.boundWechat)
|
||||
mSuccessCallback?.onSuccess()
|
||||
HistoryHelper.insertGameEntity(mGame!!)
|
||||
}
|
||||
}
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
@ -106,7 +112,7 @@ class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
} else {
|
||||
customizableBtn.text = dialogConfig?.text
|
||||
customizableBtn.setOnClickListener {
|
||||
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击跳转按钮")
|
||||
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击跳转按钮")
|
||||
DirectUtils.directToLinkPage(
|
||||
requireContext(),
|
||||
dialogConfig!!.toLinkEntity(),
|
||||
@ -124,7 +130,7 @@ class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
fun onClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.reserve_without_mobile_btn -> {
|
||||
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击无手机号预约")
|
||||
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击无手机号预约")
|
||||
mViewModel.reserve(gameId = mGameId, gameName = mGameName)
|
||||
}
|
||||
|
||||
@ -135,12 +141,12 @@ class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
return
|
||||
}
|
||||
|
||||
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击立即预约")
|
||||
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击立即预约")
|
||||
mViewModel.reserve(gameId = mGameId, gameName = mGameName, mobile = mobile)
|
||||
}
|
||||
|
||||
R.id.close_btn -> {
|
||||
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击关闭")
|
||||
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击关闭")
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
@ -149,6 +155,7 @@ class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(gameEntity: GameEntity, successCallback: SuccessCallback) = ReserveDialogFragment().apply {
|
||||
this.mGame = gameEntity
|
||||
this.mGameId = gameEntity.id
|
||||
this.mGameName = gameEntity.name ?: ""
|
||||
this.mSuccessCallback = successCallback
|
||||
@ -185,7 +192,7 @@ class ReserveViewModel(application: Application) : AndroidViewModel(application)
|
||||
reservation.postValue(Reservation(success = true, withMobile = mobile.isNotEmpty(), boundWechat = boundWechat))
|
||||
ReservationRepository.addReservationToMemoryAndRefresh(gameId)
|
||||
|
||||
MtaHelper.onEvent("预约游戏", "预约", gameName)
|
||||
// MtaHelper.onEvent("预约游戏", "预约", gameName)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
|
||||
@ -8,12 +8,13 @@ import com.gh.common.util.MtaHelper
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
open class TrackableDialog(context: Context,
|
||||
themeResId: Int,
|
||||
private var mEvent: String,
|
||||
private var mKey: String,
|
||||
private var mCancelValue: String? = null,
|
||||
private var mKeyBackValue: String? = null,
|
||||
private var mLogShowEvent: Boolean = true)
|
||||
themeResId: Int,
|
||||
private var mEvent: String,
|
||||
private var mKey: String,
|
||||
private var mValue: String? = null,
|
||||
private var mCancelValue: String? = null,
|
||||
private var mKeyBackValue: String? = null,
|
||||
private var mLogShowEvent: Boolean = true)
|
||||
: Dialog(context, themeResId) {
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
@ -25,6 +26,9 @@ open class TrackableDialog(context: Context,
|
||||
setOnCancelListener {
|
||||
if (mIsCanceledByClickOutsideOfDialog.get()) {
|
||||
MtaHelper.onEvent(mEvent, mKey, mCancelValue ?: "点击空白")
|
||||
if (!mValue.isNullOrEmpty()) {
|
||||
MtaHelper.onEvent(mEvent, "点击空白", mValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +36,9 @@ open class TrackableDialog(context: Context,
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
|
||||
mIsCanceledByClickOutsideOfDialog.set(false)
|
||||
MtaHelper.onEvent(mEvent, mKey, mKeyBackValue ?: "点击返回")
|
||||
if (mValue != null) {
|
||||
MtaHelper.onEvent(mEvent, "点击返回", mValue)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
@ -41,6 +48,9 @@ open class TrackableDialog(context: Context,
|
||||
super.show()
|
||||
if (mLogShowEvent) {
|
||||
MtaHelper.onEvent(mEvent, mKey, "出现弹窗")
|
||||
if (!mValue.isNullOrEmpty()) {
|
||||
MtaHelper.onEvent(mEvent, "出现弹窗", mValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ data class ExposureEntity(
|
||||
@SerializedName("game_id")
|
||||
val gameId: String? = "",
|
||||
val gameName: String? = "",
|
||||
val gameVersion: String? = "",
|
||||
val sequence: Int? = 0,
|
||||
val platform: String? = "",
|
||||
val downloadType: String? = "",
|
||||
|
||||
@ -4,9 +4,11 @@ import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.exposure.meta.Meta
|
||||
import com.gh.common.exposure.meta.MetaUtil
|
||||
import com.gh.common.exposure.time.TimeUtil
|
||||
import com.gh.common.util.getFirstElementDividedByDivider
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import java.util.*
|
||||
@ -26,9 +28,14 @@ data class ExposureEvent(
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>? = null, event: ExposureType = ExposureType.EXPOSURE): ExposureEvent {
|
||||
if (gameEntity?.getApk()?.size == 1) {
|
||||
gameEntity.gameVersion = gameEntity.getApk().elementAtOrNull(0)?.version ?: ""
|
||||
}
|
||||
return ExposureEvent(
|
||||
payload = ExposureEntity(gameId = gameEntity?.id,
|
||||
gameName = gameEntity?.name,
|
||||
payload = ExposureEntity(
|
||||
gameId = gameEntity?.id?.getFirstElementDividedByDivider(Constants.GAME_ID_DIVIDER),
|
||||
gameName = gameEntity?.name?.removeSuffix(Constants.GAME_NAME_DECORATOR),
|
||||
gameVersion = gameEntity?.gameVersion,
|
||||
sequence = gameEntity?.sequence,
|
||||
platform = gameEntity?.platform,
|
||||
downloadType = gameEntity?.downloadType,
|
||||
|
||||
@ -26,6 +26,10 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
|
||||
visibleState?.let { commitExposure(it) }
|
||||
throttleBus?.clear()
|
||||
}
|
||||
|
||||
override fun onFragmentViewDestroyed(fm: FragmentManager, f: Fragment) {
|
||||
fragment.fragmentManager?.unregisterFragmentLifecycleCallbacks(this)
|
||||
}
|
||||
}, false)
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ import com.gh.loghub.LoghubHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
/**
|
||||
* A handful tool for committing logs to aliyun loghub.
|
||||
@ -17,7 +16,7 @@ import kotlin.concurrent.fixedRateTimer
|
||||
* 如何简单地统计列表中每个 item 的曝光事件?
|
||||
*
|
||||
* 1. Adapter 实现 IExposable 接口,在 BindView 阶段更新 ExposureEvent,ExposureEvent 供 getEventByPosition(pos) 方法获取用
|
||||
* 2. 构建一个 ExposureListener 并作为入参添加至 recyclerview 的 Scroll 回调中
|
||||
* 2. 构建一个 ExposureListener 并作为入参添加至 recyclerview 的 onScroll 回调中
|
||||
* 3. 没了
|
||||
*/
|
||||
object ExposureManager {
|
||||
@ -25,31 +24,24 @@ object ExposureManager {
|
||||
private const val ENDPOINT = "cn-qingdao.log.aliyuncs.com"
|
||||
private const val PROJECT = "ghzs"
|
||||
private const val STORE_SIZE = 100
|
||||
private const val STORE_FORCE_UPLOAD_PERIOD = 300 * 1000L
|
||||
private const val LOG_STORE = BuildConfig.EXPOSURE_REPO
|
||||
|
||||
private val loghubHelper = LoghubHelper.getInstance()
|
||||
|
||||
// exposureCache 用来过滤掉具有相同 id 的曝光事件,避免重复发送事件
|
||||
private val exposureSet = hashSetOf<ExposureEvent>()
|
||||
private val exposureExecutor = Executors.newSingleThreadExecutor()
|
||||
private val exposureCache = FixedSizeLinkedHashSet<String>(300)
|
||||
private val exposureSet by lazy { hashSetOf<ExposureEvent>() }
|
||||
private val exposureExecutor by lazy { Executors.newSingleThreadExecutor() }
|
||||
private val exposureCache by lazy { FixedSizeLinkedHashSet<String>(300) }
|
||||
private val exposureDao by lazy { ExposureDatabase.buildDatabase(HaloApp.getInstance().application).logHubEventDao() }
|
||||
|
||||
@JvmStatic
|
||||
fun init() {
|
||||
TimeUtil.init()
|
||||
|
||||
loghubHelper.init(HaloApp.getInstance().application, ENDPOINT, PROJECT, LOG_STORE) { TimeUtil.currentTimeMillis() }
|
||||
|
||||
exposureExecutor.execute {
|
||||
val eventList = exposureDao.getAll()
|
||||
exposureSet.addAll(eventList)
|
||||
}
|
||||
|
||||
fixedRateTimer(name = "ExposureManager-Store-Checker", initialDelay = 500, period = STORE_FORCE_UPLOAD_PERIOD) {
|
||||
commitSavedExposureEvents(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import android.text.TextUtils
|
||||
import com.g00fy2.versioncompare.Version
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.gamecenter.entity.ApkEntity
|
||||
@ -15,6 +18,12 @@ object ExposureUtils {
|
||||
traceEvent: ExposureEvent?,
|
||||
downloadType: DownloadType): ExposureEvent {
|
||||
val gameEntity = entity.clone()
|
||||
gameEntity.id = if (entity.id.contains(Constants.GAME_ID_DIVIDER)) {
|
||||
entity.id.split(Constants.GAME_ID_DIVIDER).toTypedArray()[0]
|
||||
} else {
|
||||
entity.id
|
||||
}
|
||||
gameEntity.gameVersion = entity.getApk().elementAtOrNull(0)?.version ?: gameEntity.gameVersion
|
||||
gameEntity.platform = platform
|
||||
gameEntity.downloadType = downloadType.toString()
|
||||
val exposureEvent = ExposureEvent.createEvent(gameEntity = gameEntity,
|
||||
@ -43,29 +52,30 @@ object ExposureUtils {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getDownloadType(apkEntity: ApkEntity, method: String) : DownloadType {
|
||||
return if ("更新" == method) {
|
||||
if (PackageUtils.isSignature(HaloApp.getInstance().application, apkEntity.packageName)) {
|
||||
DownloadType.PLUGIN_UPDATE
|
||||
fun getDownloadType(apkEntity: ApkEntity, gameId: String): DownloadType {
|
||||
return if (PackageUtils.isInstalled(HaloApp.getInstance().application, apkEntity.packageName)) {
|
||||
if (PackageUtils.isSignedByGh(HaloApp.getInstance().application, apkEntity.packageName)) {
|
||||
if (PackageUtils.isCanUpdate(apkEntity, gameId)) {
|
||||
DownloadType.PLUGIN_UPDATE
|
||||
} else {
|
||||
if (Version(apkEntity.version).isHigherThan(PackageUtils.getVersionByPackage(apkEntity.packageName))) {
|
||||
DownloadType.UPDATE
|
||||
} else {
|
||||
DownloadType.DOWNLOAD
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DownloadType.UPDATE
|
||||
if (!TextUtils.isEmpty(apkEntity.ghVersion)) {
|
||||
DownloadType.PLUGIN_DOWNLOAD
|
||||
} else {
|
||||
DownloadType.UPDATE
|
||||
}
|
||||
}
|
||||
} else if ("插件化" == method) {
|
||||
DownloadType.PLUGIN_DOWNLOAD
|
||||
} else {
|
||||
DownloadType.DOWNLOAD
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getUpdateType(apkEntity: ApkEntity) : DownloadType {
|
||||
return if (PackageUtils.isSignature(HaloApp.getInstance().application, apkEntity.packageName)) {
|
||||
DownloadType.PLUGIN_UPDATE
|
||||
} else {
|
||||
DownloadType.UPDATE
|
||||
}
|
||||
}
|
||||
|
||||
enum class DownloadType {
|
||||
DOWNLOAD,
|
||||
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
package com.gh.common.exposure.time
|
||||
|
||||
import com.gh.gamecenter.entity.TimeEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
class Corrector {
|
||||
|
||||
companion object {
|
||||
const val TIME_CORRECTOR_ADJUST_PERIOD: Long = 600000
|
||||
}
|
||||
|
||||
var delta: Long = 0
|
||||
|
||||
init {
|
||||
fixedRateTimer("TimeUtil-Corrector-Checker", initialDelay = 0, period = TIME_CORRECTOR_ADJUST_PERIOD) {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api.time
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Response<TimeEntity>() {
|
||||
override fun onResponse(response: TimeEntity?) {
|
||||
val serverTime = response?.time
|
||||
serverTime?.let { delta = it * 1000 - System.currentTimeMillis() }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,23 +1,15 @@
|
||||
package com.gh.common.exposure.time
|
||||
|
||||
import com.gh.common.FixedRateJobHelper
|
||||
|
||||
object TimeUtil {
|
||||
|
||||
private lateinit var corrector: Corrector
|
||||
|
||||
fun init() {
|
||||
corrector = Corrector()
|
||||
}
|
||||
|
||||
fun currentTimeMillis(): Long {
|
||||
return corrector.delta + System.currentTimeMillis()
|
||||
return FixedRateJobHelper.timeDeltaBetweenServerAndClient + System.currentTimeMillis()
|
||||
}
|
||||
|
||||
fun currentTime(): Int {
|
||||
return if (::corrector.isInitialized) {
|
||||
((corrector.delta + System.currentTimeMillis()) / 1000).toInt()
|
||||
} else {
|
||||
(System.currentTimeMillis() / 1000).toInt()
|
||||
}
|
||||
return ((FixedRateJobHelper.timeDeltaBetweenServerAndClient + System.currentTimeMillis()) / 1000).toInt()
|
||||
}
|
||||
|
||||
}
|
||||
21
app/src/main/java/com/gh/common/filter/RegionSetting.kt
Normal file
21
app/src/main/java/com/gh/common/filter/RegionSetting.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package com.gh.common.filter
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
@Keep
|
||||
data class RegionSetting(
|
||||
@SerializedName("game_mirror")
|
||||
var mirrorGameIdSet: HashSet<String>,
|
||||
@SerializedName("game_block")
|
||||
var filterGameIdSet: HashSet<String>,
|
||||
@SerializedName("channel_control")
|
||||
var channelControl: ChannelControl) {
|
||||
|
||||
@Keep
|
||||
data class ChannelControl(
|
||||
@SerializedName("game_category")
|
||||
var gameCategory: String,
|
||||
@SerializedName("effect")
|
||||
var effect: Boolean)
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
package com.gh.common.filter
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.functions.Function
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
object RegionSettingHelper {
|
||||
|
||||
private var mChannelControl: RegionSetting.ChannelControl? = null
|
||||
private var mFilterGameIdSet: HashSet<String>? = hashSetOf()
|
||||
private var mDisplayMirrorIfoGameIdSet: HashSet<String>? = hashSetOf()
|
||||
|
||||
private const val SP_SETTING = "region_setting"
|
||||
|
||||
fun shouldThisGameDisplayMirrorInfo(gameId: String): Boolean {
|
||||
return mDisplayMirrorIfoGameIdSet?.contains(gameId) ?: false
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun shouldThisGameBeFiltered(gameId: String?): Boolean {
|
||||
return mFilterGameIdSet?.contains(gameId) ?: false
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun filterGame(list: List<GameEntity>?): ArrayList<GameEntity> {
|
||||
if (list == null) return arrayListOf()
|
||||
|
||||
if (mFilterGameIdSet?.isEmpty() == true) {
|
||||
if (list is ArrayList) return list
|
||||
}
|
||||
|
||||
val listCopy: ArrayList<GameEntity> = if (list is ArrayList) list else ArrayList(list)
|
||||
listCopy.removeAll { mFilterGameIdSet?.contains(it.id) ?: false }
|
||||
return listCopy
|
||||
}
|
||||
|
||||
@JvmField
|
||||
var filterGame = Function { list: List<GameEntity> ->
|
||||
filterGame(list)
|
||||
list
|
||||
}
|
||||
|
||||
fun shouldGameOfThisCategoryUseMirrorInfo(category: String) : Boolean {
|
||||
return if (mChannelControl == null || mChannelControl?.effect == false || !isUserUsedLessThan24Hours()) {
|
||||
false
|
||||
} else {
|
||||
mChannelControl?.gameCategory == category
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun getRegionSetting() {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.sensitiveApi
|
||||
.getRegionSetting(HaloApp.getInstance().channel)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<RegionSetting>() {
|
||||
override fun onSuccess(data: RegionSetting) {
|
||||
updateSettingsInMemory(data)
|
||||
SPUtils.setString(SP_SETTING, data.toJson())
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
SPUtils.getString(SP_SETTING).toObject<RegionSetting>()?.let {
|
||||
updateSettingsInMemory(it)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun updateSettingsInMemory(data: RegionSetting) {
|
||||
mFilterGameIdSet = data.filterGameIdSet
|
||||
mDisplayMirrorIfoGameIdSet = data.mirrorGameIdSet
|
||||
mChannelControl = data.channelControl
|
||||
}
|
||||
|
||||
/**
|
||||
* 该用户是否是使用了不到 24 小时的新用户
|
||||
*/
|
||||
private fun isUserUsedLessThan24Hours(): Boolean {
|
||||
val initialUsageTime = SPUtils.getLong(Constants.SP_INITIAL_USAGE_TIME, 0)
|
||||
return !(initialUsageTime == 0L || System.currentTimeMillis() - initialUsageTime > 86400000)
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,7 +15,7 @@ import com.gh.gamecenter.room.converter.*
|
||||
import com.gh.gamecenter.room.dao.*
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 5, exportSchema = false)
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 6, exportSchema = false)
|
||||
@TypeConverters(CountConverter::class,
|
||||
CommunityConverter::class,
|
||||
TimeConverter::class,
|
||||
@ -23,7 +23,8 @@ import com.halo.assistant.HaloApp
|
||||
ThumbnailConverter::class,
|
||||
TagStyleListConverter::class,
|
||||
StringArrayListConverter::class,
|
||||
CommunityVideoConverter::class)
|
||||
CommunityVideoConverter::class,
|
||||
UserConverter::class)
|
||||
|
||||
abstract class HistoryDatabase : RoomDatabase() {
|
||||
|
||||
@ -54,11 +55,20 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_5_6: Migration = object : Migration(5, 6) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("Alter TABLE MyVideoEntity add title TEXT NOT NULL DEFAULT ''")
|
||||
database.execSQL("Alter TABLE MyVideoEntity add commentCount INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("Alter TABLE MyVideoEntity add user TEXT NOT NULL DEFAULT ''")
|
||||
}
|
||||
}
|
||||
|
||||
val instance by lazy {
|
||||
Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE")
|
||||
.addMigrations(MIGRATION_2_3)
|
||||
.addMigrations(MIGRATION_3_4)
|
||||
.addMigrations(MIGRATION_4_5)
|
||||
.addMigrations(MIGRATION_5_6)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,9 +4,7 @@ import com.gh.common.runOnIoThread
|
||||
import com.gh.common.util.clearHtmlFormatCompletely
|
||||
import com.gh.common.util.removeInsertedContent
|
||||
import com.gh.common.util.removeVideoContent
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.HistoryGameEntity
|
||||
import com.gh.gamecenter.entity.NewsEntity
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.qa.entity.AnswerDetailEntity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
|
||||
@ -24,11 +22,32 @@ object HistoryHelper {
|
||||
runOnIoThread { HistoryDatabase.instance.articleDao().addArticle(articleEntity) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun insertGameEntity(gameEntity: GameEntity) {
|
||||
val historyGameEntity = convertGameEntityToHistoryGameEntity(gameEntity)
|
||||
runOnIoThread { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun insertGameEntity(updateEntity: GameUpdateEntity) {
|
||||
val historyGameEntity = convertGameUpdateEntityToHistoryGameEntity(updateEntity)
|
||||
runOnIoThread { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) }
|
||||
}
|
||||
|
||||
private fun convertGameUpdateEntityToHistoryGameEntity(updateEntity: GameUpdateEntity): HistoryGameEntity{
|
||||
val historyGame = HistoryGameEntity()
|
||||
|
||||
historyGame.orderTag = System.currentTimeMillis()
|
||||
historyGame.id = updateEntity.id
|
||||
historyGame.brief = updateEntity.brief
|
||||
historyGame.des = ""
|
||||
historyGame.icon = updateEntity.icon
|
||||
historyGame.name = updateEntity.name
|
||||
historyGame.tagStyle = updateEntity.tagStyle
|
||||
historyGame.tag = updateEntity.tag
|
||||
return historyGame
|
||||
}
|
||||
|
||||
private fun convertGameEntityToHistoryGameEntity(gameEntity: GameEntity): HistoryGameEntity {
|
||||
val historyGame = HistoryGameEntity()
|
||||
|
||||
@ -70,6 +89,11 @@ object HistoryHelper {
|
||||
runOnIoThread { HistoryDatabase.instance.answerDao().deleteAnswer(AnswerEntity().apply { primaryKey = answerId }) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun deleteVideoEntity(videoId: String) {
|
||||
runOnIoThread { HistoryDatabase.instance.videoHistoryDao().deleteVideo(MyVideoEntity().apply { id = videoId }) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun emptyDatabase() {
|
||||
runOnIoThread { HistoryDatabase.instance.clearAllTables() }
|
||||
|
||||
@ -4,6 +4,7 @@ import android.app.Activity
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.runOnIoThread
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
@ -128,7 +129,7 @@ object ImManager {
|
||||
@JvmStatic
|
||||
fun sendFeedbackMessage(message: String) {
|
||||
val fromToMessage = IMMessage.createTxtMessage(message)
|
||||
HaloApp.getInstance().mainExecutor.execute {
|
||||
runOnIoThread {
|
||||
tryWithDefaultCatch {
|
||||
IMChat.getInstance().sendMessage(fromToMessage, object : ChatListener {
|
||||
override fun onProgress(p0: Int) {}
|
||||
|
||||
@ -10,6 +10,7 @@ import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.util.doOnMainProcessOnly
|
||||
import com.gh.gamecenter.R
|
||||
import com.m7.imkfsdk.chat.ChatActivity
|
||||
import com.m7.imkfsdk.utils.Utils
|
||||
@ -25,51 +26,53 @@ class ImReceiver : BroadcastReceiver() {
|
||||
var notificationManager: NotificationManager? = null
|
||||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
intent?.let {
|
||||
if (intent.action == IMChatManager.NEW_MSG_ACTION) {
|
||||
notificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
// 判断 ImActivity 是否在最顶端
|
||||
if (CurrentActivityHolder.getCurrentActivity() is ChatActivity) {
|
||||
ImManager.showFloatingWindow()
|
||||
ImManager.updateShouldShowFloatingWindowDot(false)
|
||||
} else {
|
||||
val contentIntent = Intent(Utils.getApp(), ChatActivity::class.java)
|
||||
|
||||
contentIntent.putExtra("PeerId", "")
|
||||
contentIntent.putExtra("type", "peedId")
|
||||
|
||||
contentIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
val resultPendingIntent = PendingIntent.getActivity(
|
||||
Utils.getApp(),
|
||||
0,
|
||||
contentIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
// 新的通知
|
||||
val builder = NotificationCompat.Builder(Utils.getApp(), "Halo_IM")
|
||||
val notification = builder.setTicker("您有新的消息")
|
||||
.setDefaults(Notification.DEFAULT_ALL)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setContentIntent(resultPendingIntent)
|
||||
.setContentTitle("光环助手客服回复")
|
||||
.setContentText("您有新的消息")
|
||||
.setAutoCancel(true)
|
||||
.build()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel("Halo_IM", "Halo_IM", NotificationManager.IMPORTANCE_DEFAULT)
|
||||
notificationManager?.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
if (notification != null) {
|
||||
notificationManager?.notify(NOTIFICATION_ID, notification)
|
||||
context?.doOnMainProcessOnly {
|
||||
intent?.let {
|
||||
if (intent.action == IMChatManager.NEW_MSG_ACTION) {
|
||||
notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
// 判断 ImActivity 是否在最顶端
|
||||
if (CurrentActivityHolder.getCurrentActivity() is ChatActivity) {
|
||||
ImManager.showFloatingWindow()
|
||||
ImManager.updateShouldShowFloatingWindowDot(false)
|
||||
} else {
|
||||
val contentIntent = Intent(Utils.getApp(), ChatActivity::class.java)
|
||||
|
||||
contentIntent.putExtra("PeerId", "")
|
||||
contentIntent.putExtra("type", "peedId")
|
||||
|
||||
contentIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
val resultPendingIntent = PendingIntent.getActivity(
|
||||
Utils.getApp(),
|
||||
0,
|
||||
contentIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
// 新的通知
|
||||
val builder = NotificationCompat.Builder(Utils.getApp(), "Halo_IM")
|
||||
val notification = builder.setTicker("您有新的消息")
|
||||
.setDefaults(Notification.DEFAULT_ALL)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setContentIntent(resultPendingIntent)
|
||||
.setContentTitle("光环助手客服回复")
|
||||
.setContentText("您有新的消息")
|
||||
.setAutoCancel(true)
|
||||
.build()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel("Halo_IM", "Halo_IM", NotificationManager.IMPORTANCE_DEFAULT)
|
||||
notificationManager?.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
if (notification != null) {
|
||||
notificationManager?.notify(NOTIFICATION_ID, notification)
|
||||
ImManager.showFloatingWindow()
|
||||
}
|
||||
}
|
||||
} else if (intent.action == IMChatManager.FINISH_ACTION) {
|
||||
ImManager.dismissFloatingWindow()
|
||||
}
|
||||
} else if (intent.action == IMChatManager.FINISH_ACTION) {
|
||||
ImManager.dismissFloatingWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,16 +6,13 @@ import com.aliyun.sls.android.sdk.model.LogGroup
|
||||
import com.gh.loghub.LoghubHelper
|
||||
import org.json.JSONObject
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
object LoghubUtils {
|
||||
|
||||
private const val STORE_SIZE = 100
|
||||
private const val STORE_FORCE_UPLOAD_INTERVAL = 120 * 1000L
|
||||
|
||||
private lateinit var mApplication: Application
|
||||
|
||||
private val loghubEventSet = hashSetOf<LoghubEvent>()
|
||||
private val loghubEventSet by lazy { hashSetOf<LoghubEvent>() }
|
||||
private val loghubEventExecutor by lazy { Executors.newSingleThreadExecutor() }
|
||||
private val loghubEventDao by lazy { LoghubDatabase.buildDatabase(mApplication).logHubEventDao() }
|
||||
|
||||
@ -27,10 +24,6 @@ object LoghubUtils {
|
||||
val eventList = loghubEventDao.getAll()
|
||||
loghubEventSet.addAll(eventList)
|
||||
}
|
||||
|
||||
fixedRateTimer(name = "Loghub-Event-Checker", initialDelay = 1000, period = STORE_FORCE_UPLOAD_INTERVAL) {
|
||||
commitSavedLoghubEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -54,7 +47,7 @@ object LoghubUtils {
|
||||
LoghubHelper.getInstance().uploadLogGroup(logGroup, logStore)
|
||||
}
|
||||
|
||||
private fun commitSavedLoghubEvents() {
|
||||
fun commitSavedLoghubEvents() {
|
||||
loghubEventExecutor.execute {
|
||||
if (loghubEventSet.isEmpty()) return@execute
|
||||
|
||||
@ -75,8 +68,16 @@ object LoghubUtils {
|
||||
}
|
||||
|
||||
val log = Log()
|
||||
log.PutContent("current time ", event.time)
|
||||
log.PutContent("content", event.content)
|
||||
// 特殊处理,以下logStore不需要用content包裹数据
|
||||
if (event.logStore == "collection" || event.logStore == "common" || event.logStore == "halo-api-device-installed") {
|
||||
val contentJson = JSONObject(event.content)
|
||||
for (key in contentJson.keys()) {
|
||||
log.PutContent(key, contentJson.get(key).toString())
|
||||
}
|
||||
} else {
|
||||
log.PutContent("current time ", event.time)
|
||||
log.PutContent("content", event.content)
|
||||
}
|
||||
logGroupHashMap[event.logStore]?.PutLog(log)
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.repository
|
||||
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.util.ApkActiveUtils
|
||||
import com.gh.common.util.RandomUtils
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
@ -15,7 +16,8 @@ object RemenkapaiRepository {
|
||||
@JvmStatic
|
||||
fun getRemenkapai(size: Int): Observable<List<GameEntity>> {
|
||||
return if (remenkapaiList.isEmpty()) {
|
||||
RetrofitManager.getInstance(getApplication()).api.remenkapai
|
||||
RetrofitManager.getInstance(getApplication()).sensitiveApi.remenkapai
|
||||
.map(RegionSettingHelper.filterGame)
|
||||
.map { gameList -> filterEntityWithoutApk(gameList) }
|
||||
.map { pickRandomSizeEntity(size) }
|
||||
.map(ApkActiveUtils.filterMapperList)
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
package com.gh.common.syncpage
|
||||
|
||||
interface ISyncAdapterHandler {
|
||||
|
||||
/**
|
||||
* @param position position to query
|
||||
* @return Pair first: item sync id
|
||||
* Pair second: item data entity
|
||||
*/
|
||||
fun getSyncData(position: Int): Pair<String, Any>?
|
||||
|
||||
}
|
||||
43
app/src/main/java/com/gh/common/syncpage/SyncDataEntity.kt
Normal file
43
app/src/main/java/com/gh/common/syncpage/SyncDataEntity.kt
Normal file
@ -0,0 +1,43 @@
|
||||
package com.gh.common.syncpage
|
||||
|
||||
import androidx.annotation.Keep
|
||||
|
||||
@Keep
|
||||
data class SyncDataEntity(
|
||||
/**
|
||||
* 标识一条数据的唯一ID
|
||||
*
|
||||
* 与[ISyncAdapterHandler.getSyncData]返回的Pair first一致
|
||||
*/
|
||||
val syncId: String,
|
||||
|
||||
/**
|
||||
* 需要同步的字段名
|
||||
*
|
||||
* 与@SyncPage注解的值一致
|
||||
*/
|
||||
val syncFieldName: String?,
|
||||
|
||||
/**
|
||||
* 需要同步的具体内容
|
||||
*/
|
||||
val syncFieldValue: Any?,
|
||||
|
||||
/**
|
||||
* 同步完一次是否自动删除
|
||||
*/
|
||||
val remove: Boolean = true,
|
||||
|
||||
/**
|
||||
* 是否需要查询同步实体的父级字段
|
||||
*
|
||||
* 由于反射可能会导致较大的性能消耗,默认关闭,具体按实际情况开启
|
||||
*/
|
||||
val checkInherited: Boolean = false,
|
||||
|
||||
/**
|
||||
* 是否需要查询同步实体的嵌套实体内容
|
||||
*
|
||||
* 由于反射可能会导致较大的性能消耗,默认关闭,具体按实际情况开启
|
||||
*/
|
||||
val checkFieldEntity: Boolean = false)
|
||||
@ -0,0 +1,20 @@
|
||||
package com.gh.common.syncpage
|
||||
|
||||
object SyncFieldConstants {
|
||||
|
||||
// 是否点赞
|
||||
const val ANSWER_VOTE = "ANSWER_VOTE"
|
||||
const val ARTICLE_VOTE = "ARTICLE_VOTE"
|
||||
|
||||
// 赞同数量
|
||||
const val ANSWER_VOTE_COUNT = "ANSWER_VOTE_COUNT"
|
||||
const val ARTICLE_VOTE_COUNT = "ARTICLE_VOTE_COUNT"
|
||||
|
||||
// 评论数量
|
||||
const val ANSWER_COMMENT_COUNT = "ANSWER_COMMENT_COUNT"
|
||||
const val ARTICLE_COMMENT_COUNT = "ARTICLE_COMMENT_COUNT"
|
||||
|
||||
// 回答数量
|
||||
const val ANSWER_COUNT = "ANSWER_COUNT"
|
||||
|
||||
}
|
||||
154
app/src/main/java/com/gh/common/syncpage/SyncPageRepository.kt
Normal file
154
app/src/main/java/com/gh/common/syncpage/SyncPageRepository.kt
Normal file
@ -0,0 +1,154 @@
|
||||
package com.gh.common.syncpage
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.annotation.SyncIgnore
|
||||
import com.gh.common.annotation.SyncPage
|
||||
import com.gh.common.util.debugOnly
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.tryCatchInRelease
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import java.lang.reflect.Field
|
||||
|
||||
/**
|
||||
* 页面之间实现数据同步(主要是单个字段的同步)
|
||||
*
|
||||
* 实现思路:
|
||||
* 1.把需要同步的数据以一个特殊ID作为唯一标识,并存于一个全局的仓库
|
||||
* 2.利用LiveData进行页面回调,再通过[ISyncAdapterHandler.getSyncData]找到需要被同步的数据
|
||||
* 3.最后利用反射进行数据替换,具体请见[SyncPageRepository.replaceSyncData]
|
||||
*
|
||||
* 具体的接入方式(以列表为例):
|
||||
* 1.通过[SyncPageRepository.postSyncData]提交同步数据
|
||||
* 2.在Fragment重写[BaseFragment.addSyncPageObserver]开启同步事件监听
|
||||
* 3.在Fragment重写[BaseFragment.provideSyncAdapter]提供获取数据的来源
|
||||
* - [BaseFragment.provideSyncAdapter]提供的Adapter必须实现[ISyncAdapterHandler]接口
|
||||
*
|
||||
*/
|
||||
object SyncPageRepository {
|
||||
|
||||
// 只有在新增操作时,才需要进行页面刷新
|
||||
val syncPageLiveData = MutableLiveData<List<SyncDataEntity>>()
|
||||
|
||||
val syncDataList = ArrayList<SyncDataEntity>()
|
||||
|
||||
// size: 防止删除刚刚添加的数据
|
||||
@JvmStatic
|
||||
fun clearSyncData() {
|
||||
tryCatchInRelease {
|
||||
synchronized(syncDataList) {
|
||||
if (syncDataList.size > 0) {
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository clearSyncData 存在" + syncDataList.size + "条数据尚未处理,即将删除")
|
||||
}
|
||||
syncDataList.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun removeSyncData(list: List<SyncDataEntity>) {
|
||||
tryCatchInRelease {
|
||||
synchronized(syncDataList) {
|
||||
for (syncDataEntity in list) {
|
||||
val remove = syncDataList.remove(syncDataEntity)
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository removeSyncData ->" + syncDataEntity.syncId +
|
||||
", fieldName->" + syncDataEntity.syncFieldName +
|
||||
", remove->" + remove)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository removeSyncData ->" + syncDataList.size)
|
||||
}
|
||||
}
|
||||
|
||||
// 提交同步数据
|
||||
fun postSyncData(entity: SyncDataEntity) {
|
||||
tryCatchInRelease {
|
||||
synchronized(syncDataList) {
|
||||
// 检查是否存在重复操作
|
||||
for (syncDataEntity in syncDataList) {
|
||||
if (syncDataEntity.syncId == entity.syncId && syncDataEntity.syncFieldName == entity.syncFieldName) {
|
||||
syncDataList.remove(syncDataEntity)
|
||||
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository postSyncData 存在重复操作->" + entity.toJson())
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
syncDataList.add(entity)
|
||||
syncPageLiveData.postValue(syncDataList)
|
||||
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository postSyncData->" + entity.toJson())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun handleSyncData(rawData: Any, syncData: SyncDataEntity): Boolean {
|
||||
val fields = if (syncData.checkInherited) {
|
||||
getAllFieldsList(rawData::class.java)
|
||||
} else rawData::class.java.declaredFields.toList()
|
||||
|
||||
var isNeedNotify = false
|
||||
for (field in fields) {
|
||||
isNeedNotify = replaceSyncData(field, rawData, syncData)
|
||||
if (isNeedNotify) break
|
||||
}
|
||||
|
||||
if (!isNeedNotify) {
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository sync failure-> " + syncData.syncFieldName)
|
||||
}
|
||||
}
|
||||
|
||||
return isNeedNotify
|
||||
}
|
||||
|
||||
private fun replaceSyncData(field: Field, extractObject: Any, syncData: SyncDataEntity): Boolean {
|
||||
field.getAnnotation(SyncPage::class.java)?.syncNames?.forEach { syncName ->
|
||||
if (syncName == syncData.syncFieldName && field.getAnnotation(SyncIgnore::class.java) == null) {
|
||||
field.isAccessible = true
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository sync success-> " + syncData.syncFieldName + ", fieldName->" + field.name + ", fieldValue->" + field.get(extractObject))
|
||||
}
|
||||
field.set(extractObject, syncData.syncFieldValue)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if (syncData.checkFieldEntity) {
|
||||
// 递归查询
|
||||
val pkgName = field.type.getPackage()?.name ?: return false
|
||||
if (pkgName.contains(HaloApp.getInstance().application.packageName) && field.getAnnotation(SyncIgnore::class.java) == null) {
|
||||
field.isAccessible = true
|
||||
val extractEntityObject = field.get(extractObject) ?: return false
|
||||
field.type.declaredFields.forEach {
|
||||
if (replaceSyncData(it, extractEntityObject, syncData)) return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 包括父类 Field 对象
|
||||
private fun getAllFieldsList(cls: Class<*>?): List<Field> {
|
||||
if (cls == null) return arrayListOf()
|
||||
val allFields = arrayListOf<Field>()
|
||||
var currentClass = cls
|
||||
while (currentClass != null) {
|
||||
val declaredFields = currentClass.declaredFields
|
||||
allFields.addAll(declaredFields)
|
||||
currentClass = currentClass.superclass
|
||||
}
|
||||
return allFields
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
package com.gh.common.syncpage.example
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.constant.ItemViewType
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.baselist.ListAdapter
|
||||
import com.gh.gamecenter.databinding.CommunityAnswerItemBinding
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.qa.answer.CommunityAnswerItemViewHolder
|
||||
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.Questions
|
||||
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
|
||||
|
||||
class ExampleAdapter(context: Context) : ListAdapter<AnswerEntity>(context), ISyncAdapterHandler {
|
||||
|
||||
override fun areItemsTheSame(oldItem: AnswerEntity?, newItem: AnswerEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if (position == itemCount - 1) return ItemViewType.ITEM_FOOTER
|
||||
return ItemViewType.ITEM_BODY
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val view: View
|
||||
return when (viewType) {
|
||||
ItemViewType.ITEM_FOOTER -> {
|
||||
view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)
|
||||
FooterViewHolder(view)
|
||||
}
|
||||
else -> {
|
||||
view = mLayoutInflater.inflate(R.layout.community_answer_item, parent, false)
|
||||
CommunityAnswerItemViewHolder(CommunityAnswerItemBinding.bind(view))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (mEntityList.isNotEmpty()) mEntityList.size + FOOTER_ITEM_COUNT else 0
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (getItemViewType(position)) {
|
||||
ItemViewType.ITEM_BODY -> {
|
||||
val answer = mEntityList[position]
|
||||
if ("community_article" == answer.type) {
|
||||
val questions = Questions()
|
||||
questions.title = answer.articleTitle
|
||||
answer.questions = questions
|
||||
}
|
||||
|
||||
val answerViewHolder = holder as CommunityAnswerItemViewHolder
|
||||
val binding = answerViewHolder.binding
|
||||
answerViewHolder.bindAnswerItem(answer, "", getPath())
|
||||
binding.title.setOnClickListener {
|
||||
if ("community_article" == answer.type) {
|
||||
mContext.startActivity(ArticleDetailActivity.getIntent(mContext, UserManager.getInstance().community, answer.id!!, "", getPath()))
|
||||
} else {
|
||||
val questions = answer.questions
|
||||
mContext.startActivity(QuestionsDetailActivity.getIntent(mContext, questions.id, "", getPath()))
|
||||
}
|
||||
}
|
||||
|
||||
answerViewHolder.itemView.setOnClickListener {
|
||||
if ("community_article" == answer.type) {
|
||||
mContext.startActivity(ArticleDetailActivity.getIntent(mContext, UserManager.getInstance().community, answer.id!!, "", getPath()))
|
||||
} else {
|
||||
mContext.startActivity(AnswerDetailActivity.getIntent(mContext, answer.id, "", getPath()))
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemViewType.ITEM_FOOTER -> {
|
||||
val footerViewHolder = holder as FooterViewHolder
|
||||
footerViewHolder.initItemPadding()
|
||||
footerViewHolder.initFooterViewHolder(mIsLoading, mIsNetworkError, mIsOver, R.string.ask_loadover_hint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyncData(position: Int): Pair<String, AnswerEntity>? {
|
||||
if (position >= mEntityList.size) return null
|
||||
val entity = mEntityList[position]
|
||||
return Pair(entity.id ?: "", entity)
|
||||
}
|
||||
|
||||
fun getPath(): String {
|
||||
return "问答-推荐-按时间"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package com.gh.common.syncpage.example
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.view.VerticalItemDecoration
|
||||
import com.gh.gamecenter.baselist.ListFragment
|
||||
import com.gh.gamecenter.baselist.NormalListViewModel
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.Observable
|
||||
|
||||
class ExampleFragment : ListFragment<AnswerEntity, NormalListViewModel<AnswerEntity>>() {
|
||||
|
||||
private var mAdapter: ExampleAdapter? = null
|
||||
|
||||
override fun provideListAdapter(): ExampleAdapter {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = ExampleAdapter(requireContext())
|
||||
}
|
||||
return mAdapter!!
|
||||
}
|
||||
|
||||
override fun getItemDecoration(): RecyclerView.ItemDecoration {
|
||||
return VerticalItemDecoration(context, 8F, false)
|
||||
}
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<MutableList<AnswerEntity>> {
|
||||
return RetrofitManager.getInstance(context).api.getCommunitiesRecommendNewest(UserManager.getInstance().community.id, page)
|
||||
}
|
||||
|
||||
override fun provideListViewModel(): NormalListViewModel<AnswerEntity> {
|
||||
val factory = NormalListViewModel.Factory(HaloApp.getInstance().application, this)
|
||||
return ViewModelProviders.of(this, factory).get(NormalListViewModel::class.java) as NormalListViewModel<AnswerEntity>
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
// SyncPageRepository.syncPageLiveData.observe(this, Observer {
|
||||
// it ?: return@Observer
|
||||
// val adapter = mListRv.adapter
|
||||
// if (adapter !is ISyncAdapterHandler) return@Observer
|
||||
// for(position in 0 until adapter.itemCount) {
|
||||
// val syncKey = adapter.getSyncData(position)
|
||||
// for (syncDataEntity in it) {
|
||||
// if (syncDataEntity.syncId == syncKey?.first) {
|
||||
// val isSuccess = SyncPageRepository.handleSyncData(syncKey.second, syncDataEntity)
|
||||
// if (isSuccess) adapter.notifyItemChanged(position)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
|
||||
return mListRv.adapter
|
||||
}
|
||||
|
||||
override fun addSyncPageObserver(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
14
app/src/main/java/com/gh/common/util/AntiBotHelper.kt
Normal file
14
app/src/main/java/com/gh/common/util/AntiBotHelper.kt
Normal file
@ -0,0 +1,14 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.alibaba.wireless.security.jaq.avmp.IJAQAVMPSignComponent
|
||||
import com.alibaba.wireless.security.open.SecurityGuardManager
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
object AntiBotHelper {
|
||||
@JvmStatic
|
||||
val manager by lazy {
|
||||
SecurityGuardManager.getInstance(HaloApp.getInstance().application).getInterface(IJAQAVMPSignComponent::class.java).apply {
|
||||
this.initialize()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,17 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.avoidcallback.Callback;
|
||||
import com.gh.gamecenter.LoginActivity;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Created by khy on 28/06/17.
|
||||
*/
|
||||
@ -32,6 +36,28 @@ public class CheckLoginUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkLogin(final Context context, Bundle nextToBundle, boolean isTriggerNextStep, String entrance, OnLoginListener listener) {
|
||||
if (!isLogin()) {
|
||||
if (listener != null) Utils.toast(context, "需要登录");
|
||||
LogUtils.login("dialog", null, entrance);
|
||||
LogUtils.login("activity", null, entrance);
|
||||
|
||||
// 有可能App未启动
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
bundle.putString(EntranceUtils.KEY_TO, LoginActivity.class.getName());
|
||||
EntranceUtils.jumpActivity(context, nextToBundle, bundle, (resultCode, data) -> {
|
||||
if (isTriggerNextStep && listener != null && isLogin()) {
|
||||
listener.onLogin();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (listener != null) {
|
||||
listener.onLogin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isLogin() {
|
||||
return !TextUtils.isEmpty(UserManager.getInstance().getToken());
|
||||
}
|
||||
|
||||
@ -72,11 +72,6 @@ object CommentHelper {
|
||||
videoId: String? = null,
|
||||
listener: OnCommentCallBackListener? = null) {
|
||||
val dialogOptions = ArrayList<String>()
|
||||
|
||||
if (commentEntity.me == null || !commentEntity.me?.isCommentOwner!!) {
|
||||
dialogOptions.add("回复")
|
||||
}
|
||||
|
||||
dialogOptions.add("复制")
|
||||
dialogOptions.add("投诉")
|
||||
|
||||
@ -97,18 +92,6 @@ object CommentHelper {
|
||||
when (it) {
|
||||
"管理" -> showControlDialog(context, answerId, articleId, communityId, commentEntity, commentEntity.me!!)
|
||||
|
||||
"回复" -> {
|
||||
context.ifLogin("回答详情-评论-回复") {
|
||||
if (listener != null) {
|
||||
listener.onCommentCallback(commentEntity)
|
||||
} else if (!TextUtils.isEmpty(commentEntity.id)) {
|
||||
context.startActivity(MessageDetailActivity.getMessageDetailIntent(context, commentEntity, commentEntity.id))
|
||||
} else {
|
||||
Utils.toast(context, "缺少关键属性")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"复制" -> copyText(commentEntity.content, context)
|
||||
|
||||
"投诉" -> {
|
||||
|
||||
@ -13,9 +13,7 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.gamecenter.CommentDetailActivity;
|
||||
import com.gh.gamecenter.MessageDetailActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.OnCommentCallBackListener;
|
||||
import com.gh.gamecenter.adapter.viewholder.CommentViewHolder;
|
||||
import com.gh.gamecenter.entity.CommentEntity;
|
||||
import com.gh.gamecenter.entity.MeEntity;
|
||||
@ -35,6 +33,7 @@ import java.lang.ref.WeakReference;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -53,8 +52,12 @@ public class CommentUtils {
|
||||
public static void setCommentTime(TextView textView, long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
|
||||
try {
|
||||
long today = format.parse(format.format(new Date())).getTime();
|
||||
long day = time * 1000;
|
||||
String year = String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
|
||||
format.applyPattern("yyyy");
|
||||
String currentYear = format.format(day);
|
||||
format.applyPattern("yyyyMMdd");
|
||||
long today = format.parse(format.format(new Date())).getTime();
|
||||
if (day >= today && day < today + 86400 * 1000) {
|
||||
long min = new Date().getTime() / 1000 - day / 1000;
|
||||
int hour = (int) (min / (60 * 60));
|
||||
@ -70,6 +73,13 @@ public class CommentUtils {
|
||||
} else if (day >= today - 86400 * 1000 && day < today) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText("昨天 ");
|
||||
} else if (day >= today - 86400 * 1000 * 7 && day < today - 86400 * 1000) {
|
||||
format.applyPattern("HH:mm");
|
||||
long days = (today - day) / 86400000 + 1;
|
||||
textView.setText(String.format(Locale.getDefault(), "%d天前 ", days));
|
||||
} else if (day < today - 86400 * 1000 * 7 && year.equals(currentYear)) {
|
||||
format.applyPattern("MM-dd");
|
||||
textView.setText(format.format(day));
|
||||
} else {
|
||||
format.applyPattern("yyyy-MM-dd");
|
||||
textView.setText(format.format(day));
|
||||
@ -85,8 +95,6 @@ public class CommentUtils {
|
||||
public static void showReportDialog(final CommentEntity commentEntity,
|
||||
final Context context,
|
||||
final boolean showConversation,
|
||||
final OnCommentCallBackListener listener,
|
||||
final String newsId,
|
||||
final String patch) {
|
||||
final Dialog dialog = new Dialog(context);
|
||||
|
||||
@ -96,11 +104,6 @@ public class CommentUtils {
|
||||
container.setPadding(0, DisplayUtils.dip2px(context, 12), 0, DisplayUtils.dip2px(context, 12));
|
||||
|
||||
List<String> dialogType = new ArrayList<>();
|
||||
|
||||
if (commentEntity.getMe() == null || !commentEntity.getMe().isCommentOwner()) {
|
||||
dialogType.add("回复");
|
||||
}
|
||||
|
||||
dialogType.add("复制");
|
||||
dialogType.add("投诉");
|
||||
|
||||
@ -126,17 +129,6 @@ public class CommentUtils {
|
||||
public void onClick(View v) {
|
||||
dialog.cancel();
|
||||
switch (reportTv.getText().toString()) {
|
||||
case "回复":
|
||||
CheckLoginUtils.checkLogin(context, patch + "-回复", () -> {
|
||||
if (listener != null) {
|
||||
listener.onCommentCallback(commentEntity);
|
||||
} else if (!TextUtils.isEmpty(newsId)) {
|
||||
context.startActivity(MessageDetailActivity.getMessageDetailIntent(context, commentEntity, newsId));
|
||||
} else {
|
||||
Utils.toast(context, "缺少关键属性");
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "复制":
|
||||
copyText(commentEntity.getContent(), context);
|
||||
break;
|
||||
@ -218,13 +210,13 @@ public class CommentUtils {
|
||||
public static void postVote(final Context context, final CommentEntity commentEntity,
|
||||
final TextView commentLikeCountTv, final ImageView commentLikeIv,
|
||||
final OnVoteListener listener) {
|
||||
if (commentLikeCountTv.getCurrentTextColor() == ContextCompat.getColor(context, R.color.theme)) {
|
||||
Utils.toast(context, "已经点过赞啦!");
|
||||
if (commentLikeCountTv.getCurrentTextColor() == ContextCompat.getColor(context, R.color.theme_font)) {
|
||||
ToastUtils.INSTANCE.showToast("已经点过赞啦!");
|
||||
return;
|
||||
}
|
||||
commentEntity.setVote(commentEntity.getVote() + 1);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.theme));
|
||||
commentLikeIv.setImageResource(R.drawable.vote_icon_select);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.theme_font));
|
||||
commentLikeIv.setImageResource(R.drawable.comment_vote_select);
|
||||
commentLikeCountTv.setText(NumberUtils.transSimpleCount(commentEntity.getVote()));
|
||||
commentLikeCountTv.setVisibility(View.VISIBLE);
|
||||
|
||||
@ -242,7 +234,7 @@ public class CommentUtils {
|
||||
|
||||
commentEntity.setVote(commentEntity.getVote() - 1);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.hint));
|
||||
commentLikeIv.setImageResource(R.drawable.vote_icon_unselect);
|
||||
commentLikeIv.setImageResource(R.drawable.comment_vote_unselect);
|
||||
commentLikeCountTv.setText(NumberUtils.transSimpleCount(commentEntity.getVote()));
|
||||
if (commentEntity.getVote() == 0) {
|
||||
commentLikeCountTv.setVisibility(View.GONE);
|
||||
@ -256,7 +248,7 @@ public class CommentUtils {
|
||||
try {
|
||||
String detail = new JSONObject(exception.response().errorBody().string()).getString("detail");
|
||||
if ("voted".equals(detail)) {
|
||||
Utils.toast(context, "已经点过赞啦!");
|
||||
ToastUtils.INSTANCE.showToast("已经点过赞啦!");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
@ -284,13 +276,13 @@ public class CommentUtils {
|
||||
entrance = "社区文章详情-评论-点赞";
|
||||
}
|
||||
CheckLoginUtils.checkLogin(context, entrance, () -> {
|
||||
if (commentLikeCountTv.getCurrentTextColor() == ContextCompat.getColor(context, R.color.theme)) {
|
||||
Utils.toast(context, "已经点过赞啦!");
|
||||
if (commentLikeCountTv.getCurrentTextColor() == ContextCompat.getColor(context, R.color.theme_font)) {
|
||||
ToastUtils.INSTANCE.showToast("已经点过赞啦!");
|
||||
return;
|
||||
}
|
||||
commentEntity.setVote(commentEntity.getVote() + 1);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.theme));
|
||||
commentLikeIv.setImageResource(R.drawable.vote_icon_select);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.theme_font));
|
||||
commentLikeIv.setImageResource(R.drawable.comment_vote_select);
|
||||
commentLikeCountTv.setText(NumberUtils.transSimpleCount(commentEntity.getVote()));
|
||||
commentLikeCountTv.setVisibility(View.VISIBLE);
|
||||
|
||||
@ -307,7 +299,7 @@ public class CommentUtils {
|
||||
public void postFailed(Throwable e) {
|
||||
commentEntity.setVote(commentEntity.getVote() - 1);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.hint));
|
||||
commentLikeIv.setImageResource(R.drawable.vote_icon_unselect);
|
||||
commentLikeIv.setImageResource(R.drawable.comment_vote_unselect);
|
||||
commentLikeCountTv.setText(NumberUtils.transSimpleCount(commentEntity.getVote()));
|
||||
if (commentEntity.getVote() == 0) {
|
||||
commentLikeCountTv.setVisibility(View.GONE);
|
||||
@ -321,7 +313,7 @@ public class CommentUtils {
|
||||
try {
|
||||
String detail = new JSONObject(exception.response().errorBody().string()).getString("detail");
|
||||
if ("voted".equals(detail)) {
|
||||
Utils.toast(context, "已经点过赞啦!");
|
||||
ToastUtils.INSTANCE.showToast("已经点过赞啦!");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
@ -340,14 +332,22 @@ public class CommentUtils {
|
||||
public static void setCommentUserView(Context mContext, CommentViewHolder holder, CommentEntity entity) {
|
||||
MeEntity userDataEntity = entity.getMe();
|
||||
holder.commentLikeCountTv.setTextColor(ContextCompat.getColor(mContext, R.color.hint));
|
||||
holder.commentLikeIv.setImageResource(R.drawable.vote_icon_unselect);
|
||||
holder.commentLikeIv.setImageResource(R.drawable.comment_vote_unselect);
|
||||
|
||||
if (userDataEntity == null || !userDataEntity.isCommentOwner()) {
|
||||
holder.replyLine.setVisibility(View.VISIBLE);
|
||||
holder.commentReply.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.replyLine.setVisibility(View.GONE);
|
||||
holder.commentReply.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (entity.getVote() == 0) {
|
||||
holder.commentLikeCountTv.setVisibility(View.GONE);
|
||||
} else { // 检查是否已点赞
|
||||
if (userDataEntity != null && (userDataEntity.isCommentVoted())) {
|
||||
holder.commentLikeCountTv.setTextColor(ContextCompat.getColor(mContext, R.color.theme));
|
||||
holder.commentLikeIv.setImageResource(R.drawable.vote_icon_select);
|
||||
holder.commentLikeCountTv.setTextColor(ContextCompat.getColor(mContext, R.color.theme_font));
|
||||
holder.commentLikeIv.setImageResource(R.drawable.comment_vote_select);
|
||||
}
|
||||
holder.commentLikeCountTv.setVisibility(View.VISIBLE);
|
||||
holder.commentLikeCountTv.setText(NumberUtils.transSimpleCount(entity.getVote()));
|
||||
@ -367,10 +367,11 @@ public class CommentUtils {
|
||||
UserInfoEntity userInfo = UserManager.getInstance().getUserInfoEntity();
|
||||
if (userDataEntity != null && userDataEntity.isCommentOwner() && userInfo != null) {
|
||||
if (entity.getMe() != null && entity.getMe().isContentOwner()) {
|
||||
holder.commentUserNameTv.setText(userInfo.getName() + "(作者)");
|
||||
holder.commentAuthorTv.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.commentUserNameTv.setText(userInfo.getName());
|
||||
holder.commentAuthorTv.setVisibility(View.GONE);
|
||||
}
|
||||
holder.commentUserNameTv.setText(userInfo.getName());
|
||||
if (userInfo.getAuth() != null) {
|
||||
ImageUtils.display(holder.commentUserBadgeIv, userInfo.getAuth().getIcon());
|
||||
} else {
|
||||
@ -379,10 +380,11 @@ public class CommentUtils {
|
||||
ImageUtils.displayIcon(holder.commentUserIconDv, userInfo.getIcon());
|
||||
} else {
|
||||
if (entity.getMe() != null && entity.getMe().isContentOwner()) {
|
||||
holder.commentUserNameTv.setText(entity.getUser().getName() + "(作者)");
|
||||
holder.commentAuthorTv.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.commentUserNameTv.setText(entity.getUser().getName());
|
||||
holder.commentAuthorTv.setVisibility(View.GONE);
|
||||
}
|
||||
holder.commentUserNameTv.setText(entity.getUser().getName());
|
||||
if (entity.getUser().getAuth() != null) {
|
||||
ImageUtils.display(holder.commentUserBadgeIv, entity.getUser().getAuth().getIcon());
|
||||
} else {
|
||||
@ -431,7 +433,7 @@ public class CommentUtils {
|
||||
ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cmb.setText(copyContent);
|
||||
|
||||
Utils.toast(context, "复制成功");
|
||||
ToastUtils.INSTANCE.showToast("复制成功");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import android.graphics.BitmapFactory
|
||||
import android.graphics.Matrix
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.entity.SettingsEntity
|
||||
import com.github.piasy.biv.metadata.ImageInfoExtractor
|
||||
import com.halo.assistant.HaloApp
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
@ -26,11 +27,16 @@ object CompressImageUtils {
|
||||
* 压缩图片并保存到目标文件
|
||||
* 该压缩方法是同步执行 请勿在主线程执行
|
||||
* 返回源文件的三种情况:小于特定值,图片类型为GIF,压缩失败
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* 关于压缩格式问题:
|
||||
* 1.图片详情对动态Webp/静态Webp的判断存在问题,导致部分静态Webp图片误判为动态Webp而直接委托Fresco处理,出现无法缩放问题
|
||||
* 2.为了解决上述问题,如果压缩是检测到是动态Webp时直接压缩为JPEG,这样就能解决图片详情无法缩放问题(todo 这样会导致动态Webp无法播放)
|
||||
*/
|
||||
@Throws(Exception::class)
|
||||
fun compressImageAndSaveToFile(imageFile: File, compressGif: Boolean): File {
|
||||
val imageType = ImageInfoExtractor.getImageType(imageFile)
|
||||
// 小于某一个设定的值时,直接返回原图
|
||||
if (imageFile.length() < getImageSetting().processLimitSize) {
|
||||
if (imageType != ImageInfoExtractor.TYPE_ANIMATED_WEBP && imageFile.length() < getImageSetting().processLimitSize) {
|
||||
return imageFile
|
||||
}
|
||||
|
||||
@ -49,7 +55,7 @@ object CompressImageUtils {
|
||||
} else if (options.outMimeType.contains("gif") && !compressGif) { // gif直接返回原图
|
||||
return imageFile
|
||||
} else {
|
||||
Bitmap.CompressFormat.WEBP
|
||||
Bitmap.CompressFormat.JPEG
|
||||
}
|
||||
|
||||
fileOutputStream = FileOutputStream(cacheDir)
|
||||
@ -165,6 +171,7 @@ object CompressImageUtils {
|
||||
enum class CompressType {
|
||||
// 0: 短边等比压缩至1280 H:长边 W:短边
|
||||
LIMIT_SHORT,
|
||||
|
||||
// 1: 取长边等比压缩至1280 H:短边 W: 长边
|
||||
LIMIT_LONG
|
||||
}
|
||||
@ -3,17 +3,18 @@ package com.gh.common.util;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.NewsDetailEntity;
|
||||
import com.gh.gamecenter.manager.DataCollectionManager;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import kotlin.text.StringsKt;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/12/9.
|
||||
* 数据收集 工具类(data.ghzs666.com)
|
||||
@ -33,8 +34,8 @@ public class DataCollectionUtils {
|
||||
// 上传下载数据(开始、完成)
|
||||
public static void uploadDownload(Context context, DownloadEntity downloadEntity, String status) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("game", downloadEntity.getName());
|
||||
map.put("game_id", downloadEntity.getGameId());
|
||||
map.put("game", StringsKt.removeSuffix(downloadEntity.getName(), Constants.GAME_NAME_DECORATOR));
|
||||
map.put("game_id", downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER));
|
||||
if (downloadEntity.isPluggable()) {
|
||||
map.put("method", "插件化");
|
||||
map.put("btn_status", "插件化");
|
||||
@ -169,24 +170,4 @@ public class DataCollectionUtils {
|
||||
map.put("type", args[2]);
|
||||
DataCollectionManager.onEvent(context, "concern", map);
|
||||
}
|
||||
|
||||
//上传推荐位数据
|
||||
public static void uploadPosition(Context context, String... args) {
|
||||
if (args.length < 3) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("page", args[0]);
|
||||
map.put("location", args[1]);
|
||||
map.put("name", args[2]);
|
||||
DataCollectionManager.onEvent(context, "position", map);
|
||||
}
|
||||
|
||||
//上传应用列表
|
||||
public static void uploadAppList(Context context, JSONArray applist) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("applist", applist);
|
||||
DataCollectionManager.onEvent(context, "applist", map);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,8 +2,7 @@ package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.common.loghub.LoghubUtils;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
@ -14,12 +13,6 @@ import org.json.JSONObject;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/12/8.
|
||||
* 日志上传工具类
|
||||
@ -68,12 +61,7 @@ public class DataLogUtils {
|
||||
params.put("time", String.valueOf(Utils.getTime(context)));
|
||||
params.put("content", new JSONObject(map).toString());
|
||||
|
||||
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
|
||||
new JSONObject(params).toString());
|
||||
RetrofitManager.getInstance(context).getData().postLog(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>());
|
||||
LoghubUtils.log(new JSONObject(params), "common", true);
|
||||
}
|
||||
|
||||
// 网络错误
|
||||
|
||||
@ -3,19 +3,16 @@ package com.gh.common.util;
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gid.GidCallback;
|
||||
import com.gh.gid.GidHelper;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.tencent.bugly.crashreport.CrashReport;
|
||||
import com.tencent.stat.MtaSDkException;
|
||||
@ -126,11 +123,18 @@ public class DataUtils {
|
||||
public static void getGid() {
|
||||
GidHelper.getInstance().registerDevice(new GidCallback() {
|
||||
@Override
|
||||
public void onSuccess(String s) {
|
||||
Utils.log("Gid", s);
|
||||
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit().putString(Constants.DEVICE_KEY, s).apply();
|
||||
public void onSuccess(String gid) {
|
||||
Utils.log("Gid", gid);
|
||||
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit().putString(Constants.DEVICE_KEY, gid).apply();
|
||||
|
||||
String originalGid = HaloApp.getInstance().getGid();
|
||||
HaloApp.getInstance().setGid(gid);
|
||||
|
||||
// 避免重复调用
|
||||
if (!TextUtils.isEmpty(gid) && !gid.equals(originalGid)) {
|
||||
GameSubstituteRepositoryHelper.updateSubstitutableGames();
|
||||
}
|
||||
|
||||
HaloApp.getInstance().setGid(s);
|
||||
// 避免初始化顺序问题导致 MetaUtil 一直持有空的 gid
|
||||
MetaUtil.INSTANCE.refreshMeta();
|
||||
}
|
||||
@ -197,36 +201,36 @@ public class DataUtils {
|
||||
|
||||
// 游戏下载
|
||||
public static void onGameDownloadEvent(Context context, String gameName, String platform, String entrance, String status, String method) {
|
||||
Map<String, Object> kv = new HashMap<>();
|
||||
|
||||
platform = PlatformUtils.getInstance(HaloApp.getInstance().getApplication()).getPlatformName(platform);
|
||||
|
||||
kv.put("版本", platform);
|
||||
kv.put("用户机型", Build.MODEL);
|
||||
kv.put("设备IMEI", Util_System_Phone_State.getDeviceId(HaloApp.getInstance().getApplication()));
|
||||
kv.put("网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
kv.put("光环助手版本", BuildConfig.VERSION_NAME);
|
||||
kv.put("位置", entrance);
|
||||
kv.put("类型", method);
|
||||
kv.put("厂商", Build.MANUFACTURER);
|
||||
kv.put("Android版本", Build.VERSION.RELEASE);
|
||||
onEvent(context, "游戏下载", gameName, kv);
|
||||
|
||||
Map<String, Object> kv2 = new HashMap<>();
|
||||
kv2.put("状态", status);
|
||||
kv2.put("位置", entrance);
|
||||
|
||||
if (status.equals("开始")) {
|
||||
kv2.put("版本", entrance + "-开始");
|
||||
kv2.put("游戏分平台", gameName + "-" + platform + "-开始");
|
||||
kv2.put("光环助手版本", BuildConfig.VERSION_NAME + "-开始");
|
||||
} else {
|
||||
kv2.put("版本", platform);
|
||||
kv2.put("游戏分平台", gameName + "-" + platform);
|
||||
kv2.put("光环助手版本", BuildConfig.VERSION_NAME);
|
||||
}
|
||||
|
||||
onEvent(context, "游戏下载位置", gameName, kv2);
|
||||
// Map<String, Object> kv = new HashMap<>();
|
||||
//
|
||||
// platform = PlatformUtils.getInstance(HaloApp.getInstance().getApplication()).getPlatformName(platform);
|
||||
//
|
||||
// kv.put("版本", platform);
|
||||
// kv.put("用户机型", Build.MODEL);
|
||||
// kv.put("设备IMEI", Util_System_Phone_State.getDeviceId(HaloApp.getInstance().getApplication()));
|
||||
// kv.put("网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
// kv.put("光环助手版本", BuildConfig.VERSION_NAME);
|
||||
// kv.put("位置", entrance);
|
||||
// kv.put("类型", method);
|
||||
// kv.put("厂商", Build.MANUFACTURER);
|
||||
// kv.put("Android版本", Build.VERSION.RELEASE);
|
||||
// onEvent(context, "游戏下载", gameName, kv);
|
||||
//
|
||||
// Map<String, Object> kv2 = new HashMap<>();
|
||||
// kv2.put("状态", status);
|
||||
// kv2.put("位置", entrance);
|
||||
//
|
||||
// if (status.equals("开始")) {
|
||||
// kv2.put("版本", entrance + "-开始");
|
||||
// kv2.put("游戏分平台", gameName + "-" + platform + "-开始");
|
||||
// kv2.put("光环助手版本", BuildConfig.VERSION_NAME + "-开始");
|
||||
// } else {
|
||||
// kv2.put("版本", platform);
|
||||
// kv2.put("游戏分平台", gameName + "-" + platform);
|
||||
// kv2.put("光环助手版本", BuildConfig.VERSION_NAME);
|
||||
// }
|
||||
//
|
||||
// onEvent(context, "游戏下载位置", gameName, kv2);
|
||||
}
|
||||
|
||||
// 游戏更新
|
||||
|
||||
@ -13,6 +13,7 @@ import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
/**
|
||||
* Created by khy on 27/06/17.
|
||||
@ -22,6 +23,7 @@ import com.lightgame.download.DownloadEntity;
|
||||
public class DetailDownloadUtils {
|
||||
|
||||
public static void detailInitDownload(DetailViewHolder viewHolder, boolean isCheck) {
|
||||
String downloadAddWord = viewHolder.gameEntity.getDownloadAddWord();
|
||||
|
||||
if (viewHolder.gameEntity != null
|
||||
&& Config.isShowDownload(viewHolder.gameEntity.getId())
|
||||
@ -34,10 +36,11 @@ public class DetailDownloadUtils {
|
||||
|
||||
if (viewHolder.gameEntity.isReservable()) {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(viewHolder.gameEntity.getId())) {
|
||||
if (TextUtils.isEmpty(viewHolder.downloadAddWord)) {
|
||||
|
||||
if (TextUtils.isEmpty(downloadAddWord)) {
|
||||
viewHolder.mDownloadPb.setText(String.format("预约" + "《%s》", viewHolder.gameEntity.getName()));
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(String.format("预约" + "《%s》%s", viewHolder.gameEntity.getName(), viewHolder.downloadAddWord));
|
||||
viewHolder.mDownloadPb.setText(String.format("预约" + "《%s》%s", viewHolder.gameEntity.getName(), downloadAddWord));
|
||||
}
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.RESERVABLE);
|
||||
} else {
|
||||
@ -49,10 +52,10 @@ public class DetailDownloadUtils {
|
||||
|
||||
if (viewHolder.gameEntity.getApk().isEmpty() || viewHolder.gameEntity.getDownloadOffStatus() != null) {
|
||||
LinkEntity h5LinkEntity = viewHolder.gameEntity.getH5Link();
|
||||
|
||||
|
||||
if (h5LinkEntity != null) {
|
||||
if ("play".equals(h5LinkEntity.getType())) {
|
||||
String defaultString = String.format("开始玩" + "《%s》", viewHolder.gameEntity.getName());
|
||||
String defaultString = String.format("开始玩" + "《%s》", viewHolder.gameEntity.getName());
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(h5LinkEntity.getText()) ? defaultString : h5LinkEntity.getText());
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(h5LinkEntity.getText()) ? "查看" : h5LinkEntity.getText());
|
||||
@ -60,35 +63,39 @@ public class DetailDownloadUtils {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.H5_GAME);
|
||||
} else {
|
||||
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "查看详情" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "查看详情" : viewHolder.gameEntity.getDownloadOffText());
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE_WITH_HINT);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "暂无下载" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "暂无下载" : viewHolder.gameEntity.getDownloadOffText());
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (viewHolder.gameEntity.getApk().size() == 1) {
|
||||
String status = GameUtils.getDownloadBtnText(viewHolder.context, viewHolder.gameEntity, PluginLocation.only_game);
|
||||
switch (status) {
|
||||
case "插件化":
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.PLUGIN);
|
||||
break;
|
||||
case "打开":
|
||||
case "启动":
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.LAUNCH_OR_OPEN);
|
||||
break;
|
||||
default:
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NORMAL);
|
||||
break;
|
||||
if (viewHolder.context.getString(R.string.pluggable).equals(status)) {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.PLUGIN);
|
||||
} else if (viewHolder.context.getString(R.string.launch).equals(status)) {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.LAUNCH_OR_OPEN);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NORMAL);
|
||||
}
|
||||
|
||||
String downloadText;
|
||||
if (viewHolder.isNewsDetail) {
|
||||
viewHolder.mDownloadPb.setText(status);
|
||||
} else if (TextUtils.isEmpty(viewHolder.downloadAddWord)) {
|
||||
viewHolder.mDownloadPb.setText(String.format(status + "《%s》", viewHolder.gameEntity.getName()));
|
||||
downloadText = status;
|
||||
} else if (viewHolder.context.getString(R.string.pluggable).equals(status)) {
|
||||
downloadText = "升级" + (TextUtils.isEmpty(downloadAddWord) ? "" : "至" + downloadAddWord) + getDownloadSizeText(viewHolder);
|
||||
} else if (viewHolder.context.getString(R.string.launch).equals(status)) {
|
||||
downloadText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord);
|
||||
} else if (viewHolder.context.getString(R.string.attempt).equals(status)) {
|
||||
downloadText = status + getDownloadSizeText(viewHolder);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(String.format(status + "《%s》%s", viewHolder.gameEntity.getName(), viewHolder.downloadAddWord));
|
||||
downloadText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : downloadAddWord) + getDownloadSizeText(viewHolder);
|
||||
}
|
||||
viewHolder.mDownloadPb.setText(downloadText);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText("选择下载你的版本" + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord) + " >");
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NORMAL);
|
||||
}
|
||||
if (isCheck && viewHolder.gameEntity.getApk().size() == 1) {
|
||||
String url = viewHolder.gameEntity.getApk().get(0).getUrl();
|
||||
@ -100,6 +107,10 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static String getDownloadSizeText(DetailViewHolder viewHolder) {
|
||||
return String.format("(%s)", viewHolder.gameEntity.getApk().get(0).getSize());
|
||||
}
|
||||
|
||||
public static void detailInvalidate(DetailViewHolder viewHolder) {
|
||||
viewHolder.mDownloadPb.setProgress((int) (viewHolder.downloadEntity.getPercent() * 10));
|
||||
DownloadEntity downloadEntity = viewHolder.downloadEntity;
|
||||
@ -128,7 +139,7 @@ public class DetailDownloadUtils {
|
||||
case done:
|
||||
viewHolder.mDownloadPb.setText(R.string.install);
|
||||
if (downloadEntity.isPluggable()
|
||||
&& PackagesManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
|
||||
&& PackagesManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_PLUGIN);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_NORMAL);
|
||||
@ -143,6 +154,4 @@ public class DetailDownloadUtils {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -269,18 +269,21 @@ public class DeviceUtils {
|
||||
|
||||
// 只能获取WiFi的IpAddress
|
||||
public static String getCurrentIpAddress() {
|
||||
String ipAddress;
|
||||
WifiManager wifiManager = (WifiManager) HaloApp.getInstance().
|
||||
getApplication().
|
||||
getApplicationContext().
|
||||
getSystemService(Context.WIFI_SERVICE);
|
||||
int address = wifiManager.getDhcpInfo().ipAddress;
|
||||
ipAddress = ((address & 0xFF)
|
||||
+ "." + ((address >> 8) & 0xFF)
|
||||
+ "." + ((address >> 16) & 0xFF)
|
||||
+ "." + ((address >> 24) & 0xFF));
|
||||
return ipAddress;
|
||||
String ipAddress = "0.0.0.0";
|
||||
try {
|
||||
WifiManager wifiManager = (WifiManager) HaloApp.getInstance().
|
||||
getApplication().
|
||||
getApplicationContext().
|
||||
getSystemService(Context.WIFI_SERVICE);
|
||||
int address = wifiManager.getDhcpInfo().ipAddress;
|
||||
ipAddress = ((address & 0xFF)
|
||||
+ "." + ((address >> 8) & 0xFF)
|
||||
+ "." + ((address >> 16) & 0xFF)
|
||||
+ "." + ((address >> 24) & 0xFF));
|
||||
return ipAddress;
|
||||
} catch (Exception e) {
|
||||
return ipAddress;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.CountDownTimer;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
@ -28,23 +29,24 @@ import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchy;
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.TrackableDialog;
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.common.view.FixLinearLayoutManager;
|
||||
import com.gh.common.view.LimitHeightLinearLayout;
|
||||
import com.gh.common.view.MaxHeightNestedScrollView;
|
||||
import com.gh.gamecenter.AboutActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.adapter.viewholder.PrivacyPolicyItemViewHolder;
|
||||
import com.gh.gamecenter.databinding.ImprintContentItemBinding;
|
||||
import com.gh.gamecenter.databinding.PrivacyItemBinding;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.entity.TrackableEntity;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.halo.assistant.fragment.SettingsFragment;
|
||||
@ -52,9 +54,16 @@ import com.lightgame.adapter.BaseRecyclerAdapter;
|
||||
import com.lightgame.utils.AppManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class DialogUtils {
|
||||
|
||||
public static Dialog showWaitDialog(Context context, String msg) {
|
||||
@ -185,7 +194,7 @@ public class DialogUtils {
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> Utils.toast(context, "当前使用移动网络下载,请注意流量消耗"), 500);
|
||||
callBack.onResponse(false);
|
||||
} else {
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "出现弹窗提示");
|
||||
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "出现弹窗提示");
|
||||
showDownloadDialog(context,
|
||||
() -> callBack.onResponse(false),
|
||||
() -> callBack.onResponse(true));
|
||||
@ -200,7 +209,7 @@ public class DialogUtils {
|
||||
String mb = size.toUpperCase().replaceAll("MB", "").trim();
|
||||
Float i = Float.valueOf(mb);
|
||||
if (NetworkUtils.isWifiOr4GConnected(context) && i <= 50) {
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> Utils.toast(context, "当前使用移动网络下载,请注意流量消耗"),500);
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> Utils.toast(context, "当前使用移动网络下载,请注意流量消耗"), 500);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -241,16 +250,16 @@ public class DialogUtils {
|
||||
Context finalContext = context;
|
||||
allowOnce.setOnClickListener(v -> {
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
Utils.toast(HaloApp.getInstance().getApplication(), "已使用移动网络下载,请注意流量消耗");
|
||||
Utils.toast(finalContext, "已使用移动网络下载,请注意流量消耗");
|
||||
}, 500);
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "本次允许");
|
||||
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "本次允许");
|
||||
});
|
||||
wifiAuto.setOnClickListener(v -> {
|
||||
cancelListener.onCancel();
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "连上WiFi后自动下载");
|
||||
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "连上WiFi后自动下载");
|
||||
});
|
||||
allowAlways.setOnClickListener(v -> {
|
||||
PreferenceManager
|
||||
@ -261,11 +270,11 @@ public class DialogUtils {
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
// 显示了弹窗以后,即便下面这个 toast 放在 listener.onConfirm 后调用也是显示 listener.onConfirm 里的 toast
|
||||
// 喷了,延时包治疑难杂症
|
||||
Utils.toast(HaloApp.getInstance().getApplication(), "已使用移动网络下载,请注意流量消耗");
|
||||
Utils.toast(finalContext, "已使用移动网络下载,请注意流量消耗");
|
||||
}, 500);
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "总是允许");
|
||||
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "总是允许");
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
@ -646,9 +655,9 @@ public class DialogUtils {
|
||||
Button negativeBtn = alertDialog.getButton(android.app.AlertDialog.BUTTON_NEGATIVE);
|
||||
|
||||
positiveBtn.setTextSize(13);
|
||||
positiveBtn.setTextColor(ContextCompat.getColor(context, R.color.theme));
|
||||
positiveBtn.setTextColor(ContextCompat.getColor(context, R.color.theme_font));
|
||||
negativeBtn.setTextSize(13);
|
||||
negativeBtn.setTextColor(ContextCompat.getColor(context, R.color.theme));
|
||||
negativeBtn.setTextColor(ContextCompat.getColor(context, R.color.theme_font));
|
||||
if (mesage != null) {
|
||||
mesage.setGravity(Gravity.CENTER);
|
||||
mesage.setTextSize(24);
|
||||
@ -878,19 +887,24 @@ public class DialogUtils {
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
AtomicBoolean isCanceledByClickOutsideOfDialog = new AtomicBoolean(true);
|
||||
|
||||
final Dialog dialog = new Dialog(activityContext, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
|
||||
final Dialog dialog = new Dialog(activityContext, R.style.GhAlertDialog);
|
||||
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_privacy_policy, null);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.getDecorView().setPadding(0, 0, 0, 0);
|
||||
window.setBackgroundDrawableResource(android.R.color.transparent);
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.horizontalMargin = 0;
|
||||
params.width = context.getResources().getDisplayMetrics().widthPixels;
|
||||
params.height = context.getResources().getDisplayMetrics().heightPixels;
|
||||
params.width = context.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(40);
|
||||
int height = context.getResources().getDisplayMetrics().heightPixels - DisplayUtils.dip2px(120);
|
||||
int maxHeight = DisplayUtils.dip2px(546);
|
||||
if (height > maxHeight) {
|
||||
params.height = maxHeight;
|
||||
} else {
|
||||
params.height = height;
|
||||
}
|
||||
window.setAttributes(params);
|
||||
}
|
||||
|
||||
@ -898,6 +912,7 @@ public class DialogUtils {
|
||||
TextView bottomContent = contentView.findViewById(R.id.bottom_content);
|
||||
TextView topContent = contentView.findViewById(R.id.top_content);
|
||||
TextView allowButton = contentView.findViewById(R.id.allow_button);
|
||||
TextView disallowButton = contentView.findViewById(R.id.disallow_button);
|
||||
TextView linkContent = contentView.findViewById(R.id.link_content);
|
||||
RecyclerView permissions = contentView.findViewById(R.id.permissions_content);
|
||||
|
||||
@ -938,7 +953,7 @@ public class DialogUtils {
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setColor(ContextCompat.getColor(activityContext, R.color.text_1383EB));
|
||||
ds.setColor(ContextCompat.getColor(activityContext, R.color.theme_font));
|
||||
ds.setUnderlineText(false);
|
||||
}
|
||||
|
||||
@ -954,7 +969,7 @@ public class DialogUtils {
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setColor(ContextCompat.getColor(activityContext, R.color.text_1383EB));
|
||||
ds.setColor(ContextCompat.getColor(activityContext, R.color.theme_font));
|
||||
ds.setUnderlineText(false);
|
||||
}
|
||||
|
||||
@ -968,17 +983,19 @@ public class DialogUtils {
|
||||
title.setText(entity.getTitle());
|
||||
linkContent.setText(skipText);
|
||||
linkContent.setMovementMethod(new LinkMovementMethod());
|
||||
allowButton.setText("我知道了");
|
||||
topContent.setText(entity.getTopContent());
|
||||
bottomContent.setText(entity.getBottomContent());
|
||||
|
||||
allowButton.setOnClickListener(view -> {
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击我知道了");
|
||||
callback.onCallback();
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击同意");
|
||||
});
|
||||
|
||||
dialog.setOnDismissListener(d -> {
|
||||
callback.onCallback();
|
||||
disallowButton.setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
showPrivacyPolicyDisallowDialog(activityContext, entity, callback);
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "不同意并退出App");
|
||||
});
|
||||
|
||||
dialog.setOnCancelListener(cd -> {
|
||||
@ -997,6 +1014,38 @@ public class DialogUtils {
|
||||
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "出现弹窗");
|
||||
|
||||
try {
|
||||
dialog.setCancelable(false);
|
||||
dialog.show();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void showPrivacyPolicyDisallowDialog(Context context,
|
||||
@NonNull PrivacyPolicyEntity entity,
|
||||
EmptyCallback callback) {
|
||||
final Context activityContext = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(activityContext, R.style.DialogWindowTransparent);
|
||||
|
||||
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_disallow_privacy_policy, null);
|
||||
View backButton = contentView.findViewById(R.id.back_button);
|
||||
View reviewButton = contentView.findViewById(R.id.review_button);
|
||||
|
||||
backButton.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "退出提示弹窗", "退出应用");
|
||||
dialog.dismiss();
|
||||
AppManager.getInstance().appExit(activityContext);
|
||||
});
|
||||
reviewButton.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "退出提示弹窗", "再次查看");
|
||||
dialog.dismiss();
|
||||
showPrivacyPolicyDialog(activityContext, entity, callback);
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setCancelable(false);
|
||||
dialog.setContentView(contentView);
|
||||
try {
|
||||
dialog.show();
|
||||
} catch (Exception ignored) {
|
||||
@ -1056,6 +1105,7 @@ public class DialogUtils {
|
||||
R.style.GhAlertDialog,
|
||||
trackableEntity.getEvent(),
|
||||
trackableEntity.getKey(),
|
||||
trackableEntity.getValue(),
|
||||
trackableEntity.getCancelValue(),
|
||||
trackableEntity.getKeyBackValue(),
|
||||
trackableEntity.getLogShowEvent());
|
||||
@ -1150,6 +1200,174 @@ public class DialogUtils {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static void showDownloadMutexDialog(Context context) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_downlaod_mutex, null);
|
||||
TextView positive = contentView.findViewById(R.id.dialog_positive);
|
||||
|
||||
CountDownTimer timer = new CountDownTimer(6000, 1000) {
|
||||
public void onTick(long millisUntilFinished) {
|
||||
positive.setText(("我知道了(" + millisUntilFinished / 1000 + ")"));
|
||||
}
|
||||
|
||||
public void onFinish() {
|
||||
dialog.dismiss();
|
||||
}
|
||||
};
|
||||
timer.start();
|
||||
|
||||
positive.setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showVersionNumberDialog(Context context, GameEntity gameEntity, @NonNull ConfirmListener listener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
if (!gameEntity.isShowVersionNumber()) {
|
||||
listener.onConfirm();
|
||||
} else {
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_version_number, null);
|
||||
|
||||
TextView contentTv = contentView.findViewById(R.id.contentTv);
|
||||
TextView cancelTv = contentView.findViewById(R.id.cancelTv);
|
||||
TextView continueTv = contentView.findViewById(R.id.continueTv);
|
||||
|
||||
contentTv.setText(gameEntity.getVersionNumberString());
|
||||
cancelTv.setOnClickListener(v -> dialog.dismiss());
|
||||
continueTv.setOnClickListener(v -> {
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
public static void showImprintDialog(Context context, GameEntity gameEntity, String titleName) {
|
||||
context = checkDialogContext(context);
|
||||
Dialog dialog = new Dialog(context, R.style.full_dialog);
|
||||
View inflate = LayoutInflater.from(context).inflate(R.layout.imprint_dialog, null);
|
||||
dialog.setContentView(inflate);
|
||||
dialog.show();
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
WindowManager.LayoutParams params;
|
||||
if (window != null) {
|
||||
params = window.getAttributes();
|
||||
params.width = (int) (context.getResources().getDisplayMetrics().widthPixels * 0.9);
|
||||
window.setAttributes(params);
|
||||
window.setBackgroundDrawableResource(R.drawable.full_dialog_background);
|
||||
}
|
||||
|
||||
inflate.findViewById(R.id.imprint_close).setOnClickListener(v -> dialog.dismiss());
|
||||
LinearLayout content = inflate.findViewById(R.id.imprint_content);
|
||||
((TextView) inflate.findViewById(R.id.imprint_title)).setText(titleName);
|
||||
View head = LayoutInflater.from(context).inflate(R.layout.imprint_content_item, null);
|
||||
content.addView(head, LinearLayout.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(30));
|
||||
LimitHeightLinearLayout imprintContainer = inflate.findViewById(R.id.imprint_container);
|
||||
imprintContainer.setLimitHeight((int) (context.getResources().getDisplayMetrics().heightPixels * 0.8));
|
||||
|
||||
ArrayList<ApkEntity> list = gameEntity.getApk();
|
||||
SettingsEntity settings = Config.getSettings();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ApkEntity apk = gameEntity.getApk().get(i);
|
||||
if (settings != null && settings.getGameDownloadBlackList().contains(apk.getPackageName())) {
|
||||
continue;
|
||||
}
|
||||
View item = LayoutInflater.from(context).inflate(R.layout.imprint_content_item, null);
|
||||
ImprintContentItemBinding bind = DataBindingUtil.bind(item);
|
||||
bind.setApk(apk);
|
||||
bind.setPlatformName(PlatformUtils.getInstance(context).getPlatformName(apk.getPlatform()));
|
||||
content.addView(item, LinearLayout.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(40));
|
||||
}
|
||||
|
||||
|
||||
// close line
|
||||
View view = new View(context);
|
||||
view.setBackgroundColor(context.getResources().getColor(R.color.text_5d5d5d));
|
||||
view.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(1)));
|
||||
content.addView(view);
|
||||
}
|
||||
|
||||
public static void showKaifuRemindDialog(Context context, String content, String gameName) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new TrackableDialog(context, R.style.GhAlertDialog, "开服说明弹窗", "弹窗", gameName, null, null, true);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_kaifu_remind, null);
|
||||
|
||||
TextView contentTv = contentView.findViewById(R.id.contentTv);
|
||||
MaxHeightNestedScrollView scrollView = contentView.findViewById(R.id.scrollView);
|
||||
contentTv.setText(Html.fromHtml(content));
|
||||
TextView ok = contentView.findViewById(R.id.dialog_ok);
|
||||
scrollView.setScrollChangedListener((l, t, oldl, oldt) -> {
|
||||
MtaHelper.onEvent("开服说明弹窗", "滑动内容", gameName);
|
||||
});
|
||||
ok.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("开服说明弹窗", "弹窗", "点击我知道了");
|
||||
MtaHelper.onEvent("开服说明弹窗", "点击我知道了", gameName);
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showPluggableNeverRemindDialog(Context context, String nameAndPlatform, @NonNull ConfirmListener listener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_pluggable_never_remind, null);
|
||||
|
||||
View cancelBtn = contentView.findViewById(R.id.cancel);
|
||||
View confirmBtn = contentView.findViewById(R.id.confirm);
|
||||
TextView contentTv = contentView.findViewById(R.id.content);
|
||||
|
||||
contentTv.setText(("助手首页将不再提示《" + nameAndPlatform + "》的所有插件化消息,确定吗?"));
|
||||
|
||||
cancelBtn.setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
confirmBtn.setOnClickListener(v -> {
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context may be is application context
|
||||
* @return activity context
|
||||
@ -1163,6 +1381,7 @@ public class DialogUtils {
|
||||
return context;
|
||||
}
|
||||
|
||||
// currentActivity 是否存在 isDestroyed 的情况?
|
||||
return AppManager.getInstance().currentActivity();
|
||||
}
|
||||
|
||||
|
||||
@ -6,11 +6,17 @@ import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.base.ToolBarActivity
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.exposure.ExposureEvent
|
||||
import com.gh.common.exposure.ExposureEvent.Companion.createEvent
|
||||
import com.gh.common.exposure.ExposureManager.log
|
||||
import com.gh.common.exposure.ExposureTraceUtils.appendTrace
|
||||
import com.gh.common.exposure.ExposureType
|
||||
import com.gh.common.util.EntranceUtils.*
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.amway.AmwayActivity
|
||||
@ -21,6 +27,7 @@ import com.gh.gamecenter.eventbus.EBReuse
|
||||
import com.gh.gamecenter.eventbus.EBSkip
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment
|
||||
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
|
||||
import com.gh.gamecenter.game.upload.GameSubmissionActivity
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.mygame.PlayedGameActivity
|
||||
@ -124,32 +131,45 @@ object DirectUtils {
|
||||
when (linkEntity.type) {
|
||||
"article", "news", "文章" -> {
|
||||
NewsUtils.statNewsViews(context, linkEntity.link) // 统计阅读量
|
||||
context.startActivity(NewsDetailActivity.getIntentById(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path)))
|
||||
directToArticle(context, linkEntity.link
|
||||
?: "", BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
}
|
||||
|
||||
"game", "游戏" -> {
|
||||
if (exposureEvent != null) {
|
||||
GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path), exposureEvent)
|
||||
directToGameDetail(context, linkEntity.link
|
||||
?: "", BaseActivity.mergeEntranceAndPath(entrance, path), traceEvent = exposureEvent)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
directToGameDetail(context, linkEntity.link
|
||||
?: "", BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
}
|
||||
}
|
||||
|
||||
"column", "游戏专题" -> SubjectActivity.startSubjectActivity(context, linkEntity.link, linkEntity.text, false, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
"column", "游戏专题" -> directToSubject(context, linkEntity.link
|
||||
?: "", linkEntity.text, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
|
||||
"question", "社区问题" -> context.startActivity(QuestionsDetailActivity.getIntent(context, linkEntity.link, entrance, path))
|
||||
"question", "社区问题" -> directToQuestionDetail(context, linkEntity.link
|
||||
?: "", entrance, path)
|
||||
|
||||
"answer", "社区回答" -> context.startActivity(AnswerDetailActivity.getIntent(context, linkEntity.link, entrance, path))
|
||||
"answer", "社区回答" -> directToAnswerDetail(context, linkEntity.link ?: "", entrance, path)
|
||||
|
||||
"community", "问答社区" -> directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
|
||||
|
||||
"community_article", "社区文章" -> context.startActivity(ArticleDetailActivity.getIntent(context, linkEntity.community!!, linkEntity.link!!, entrance, path))
|
||||
"community_article", "社区文章" -> directToCommunityArticle(context, linkEntity.community!!, linkEntity.link!!, entrance, path)
|
||||
|
||||
"community_column", "社区专题" -> directToCommunityColumn(context, linkEntity.community, linkEntity.link!!, entrance, path)
|
||||
|
||||
"community_special_column" -> context.startActivity(AskColumnDetailActivity.getIntentByColumnId(context, linkEntity.link, linkEntity.community!!, entrance, path))
|
||||
"community_special_column" -> directAskColumnDetail(context, linkEntity.link
|
||||
?: "", linkEntity.community!!, entrance, path)
|
||||
|
||||
"web", "inurl", "web链接" -> directToWebView(context, url = linkEntity.link!!, entrance = BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
"web", "inurl", "web链接" -> {
|
||||
when {
|
||||
linkEntity.link!!.contains("v.douyin") && PackageHelper.localPackageNameSet.contains("com.ss.android.ugc.aweme") -> {
|
||||
directDouyin(context, "1402577827140941")
|
||||
}
|
||||
else -> directToWebView(context, url = linkEntity.link!!, entrance = BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
}
|
||||
}
|
||||
|
||||
"qq", "QQ" -> directToQqConversation(context, linkEntity.link)
|
||||
|
||||
@ -159,37 +179,28 @@ object DirectUtils {
|
||||
|
||||
"tag" -> context.startActivity(TagsActivity.getIntent(context, linkEntity.text!!, linkEntity.title, entrance, path))
|
||||
|
||||
"all_community_article" -> {
|
||||
context.startActivity(SimpleArticleListActivity.getIntent(
|
||||
context,
|
||||
linkEntity.link ?: "",
|
||||
entrance,
|
||||
path))
|
||||
}
|
||||
"all_community_article" -> directSimpleArticleList(context, linkEntity.link
|
||||
?: "", entrance, path)
|
||||
|
||||
"category", "分类" -> {
|
||||
context.startActivity(CategoryDirectoryActivity.getIntent(context, linkEntity.link!!, linkEntity.text!!))
|
||||
}
|
||||
"category", "分类" -> directCategoryDirectory(context, linkEntity.link!!, linkEntity.text!!)
|
||||
|
||||
"block", "版块" -> {
|
||||
context.startActivity(BlockActivity.getIntent(context, SubjectRecommendEntity(
|
||||
directToBlock(context, SubjectRecommendEntity(
|
||||
link = linkEntity.link,
|
||||
text = linkEntity.text,
|
||||
name = linkEntity.name,
|
||||
display = linkEntity.display ?: Display())))
|
||||
display = linkEntity.display ?: Display()))
|
||||
}
|
||||
|
||||
"column_collection", "专题合集" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
|
||||
|
||||
"server" -> {
|
||||
context.startActivity(GameServersActivity.getIntent(context, entrance, path))
|
||||
}
|
||||
"server", "game_server", "开服表" -> directToGameServers(context, entrance, path)
|
||||
|
||||
"top_game_comment" -> directToAmway(context, null, entrance, path)
|
||||
|
||||
"wechat_bind" -> context.startActivity(WebActivity.getBindWechatIntent(context))
|
||||
|
||||
"video", "video_stream" -> directToVideoDetail(context,
|
||||
"video", "video_stream", "视频" -> directToVideoDetail(context,
|
||||
videoId = linkEntity.link!!,
|
||||
fromLocation = VideoDetailContainerViewModel.Location.VIDEO_CHOICENESS.value,
|
||||
entrance = entrance,
|
||||
@ -197,6 +208,27 @@ object DirectUtils {
|
||||
|
||||
"game_video" -> directToGameVideo(context, linkEntity.link ?: "", entrance, path)
|
||||
|
||||
"libao", "礼包" -> directToGiftDetail(context, linkEntity.link ?: "", entrance)
|
||||
|
||||
"feedback" -> directToFeedback(context, linkEntity.name, linkEntity.text, entrance)
|
||||
|
||||
"qa", "Q&A" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "")
|
||||
|
||||
"qa_collection", "Q&A合集" -> directToQaCollection(context, linkEntity.text
|
||||
?: "", linkEntity.link
|
||||
?: "")
|
||||
|
||||
"anliwall", "安利墙" -> directToAmway(context, fixedTopAmwayCommentId = null, entrance = entrance, path = path)
|
||||
|
||||
"game_detail_comment" -> directToGameDetail(context, linkEntity.link ?: "", entrance)
|
||||
|
||||
"game_upload", "游戏投稿" -> directGameUpload(context, entrance, path)
|
||||
|
||||
//"h5_game_center" -> directLetoGameCenter(context)
|
||||
|
||||
"" -> {
|
||||
// do nothing
|
||||
}
|
||||
else -> {
|
||||
if (unknownCallback != null) {
|
||||
unknownCallback.invoke()
|
||||
@ -207,11 +239,45 @@ object DirectUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至QA
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToQa(context: Context, text: String, id: String) {
|
||||
// context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaId = id))
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, QaActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_NAVIGATION_TITLE, text)
|
||||
bundle.putString(KEY_QA_ID, id)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至QA合集
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToQaCollection(context: Context, text: String, id: String) {
|
||||
// context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaCollectionId = id))
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, QaActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_NAVIGATION_TITLE, text)
|
||||
bundle.putString(KEY_QA_COLLECTION_ID, id)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至专题合集
|
||||
*/
|
||||
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String) {
|
||||
context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance))
|
||||
@JvmStatic
|
||||
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String, columnName: String = "") {
|
||||
// context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance, columnName))
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, ColumnCollectionDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_COLLECTION_ID,id)
|
||||
bundle.putString(KEY_COLUMNNAME,columnName)
|
||||
bundle.putInt(KEY_POSITION,position)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -234,6 +300,21 @@ object DirectUtils {
|
||||
context.startActivity(UserHomeActivity.getIntent(context, userId ?: "", entrance, path))
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至个人主页
|
||||
* @param position 定位到某个tab 0游戏评论 1问答 2视频
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToHomeActivity(context: Context, userId: String?, position: Int, entrance: String? = null, path: String? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_USER_ID, userId)
|
||||
bundle.putString(KEY_TO, UserHomeActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putInt(KEY_POSITION, position)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 回到首页
|
||||
*/
|
||||
@ -246,11 +327,20 @@ object DirectUtils {
|
||||
* 跳转到游戏详情
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameDetail(context: Context, id: String, entrance: String? = null, autoDownload: Boolean? = null) {
|
||||
fun directToGameDetail(context: Context, id: String, entrance: String? = null, autoDownload: Boolean? = null, scrollToLibao: Boolean = false, traceEvent: ExposureEvent? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, GameDetailActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
if (scrollToLibao) {
|
||||
bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_TRENDES)
|
||||
bundle.putBoolean(KEY_SCROLL_TO_LIBAO, scrollToLibao)
|
||||
}
|
||||
if (traceEvent != null) {
|
||||
val clickEvent = createEvent(GameEntity(id), traceEvent.source, appendTrace(traceEvent), ExposureType.CLICK)
|
||||
log(clickEvent)
|
||||
bundle.putParcelable(KEY_TRACE_EVENT, clickEvent)
|
||||
}
|
||||
bundle.putBoolean(KEY_AUTO_DOWNLOAD, autoDownload ?: false)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
@ -289,12 +379,21 @@ object DirectUtils {
|
||||
// 反馈
|
||||
@JvmStatic
|
||||
fun directToFeedback(context: Context, content: String? = null, entrance: String? = null) {
|
||||
directToFeedback(context, content, null, entrance)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToFeedback(context: Context, content: String? = null, hintType: String? = null, entrance: String? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, SuggestionActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_CONTENT, content)
|
||||
bundle.putString(KEY_SUGGEST_HINT_TYPE, KEY_PLUGIN)
|
||||
bundle.putSerializable(EntranceUtils.KEY_SUGGESTTYPE, SuggestType.gameQuestion)
|
||||
if (TextUtils.isEmpty(hintType)) {
|
||||
bundle.putString(KEY_SUGGEST_HINT_TYPE, KEY_PLUGIN)
|
||||
} else {
|
||||
bundle.putString(KEY_SUGGEST_HINT_TYPE, hintType)
|
||||
}
|
||||
bundle.putSerializable(KEY_SUGGESTTYPE, SuggestType.gameQuestion)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -384,6 +483,9 @@ object DirectUtils {
|
||||
@JvmStatic
|
||||
fun directToExternalBrowser(context: Context, url: String) {
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
if (context !is AppCompatActivity){
|
||||
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
context.startActivity(browserIntent)
|
||||
}
|
||||
|
||||
@ -404,7 +506,11 @@ object DirectUtils {
|
||||
chatType = "wpa"
|
||||
}
|
||||
val str = "mqqwpa://im/chat?chat_type=$chatType&uin=$qq&version=1&src_type=web"
|
||||
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(str)))
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(str))
|
||||
if (context !is AppCompatActivity){
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
} else {
|
||||
// 没有安装QQ 复制账号
|
||||
Util_System_ClipboardManager.setText(context, qq)
|
||||
@ -415,16 +521,24 @@ object DirectUtils {
|
||||
// 跳转 QQ 群
|
||||
@JvmStatic
|
||||
fun directToQqGroup(context: Context, groupNumber: String? = null): Boolean {
|
||||
val intent = Intent()
|
||||
intent.data = Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D$groupNumber")
|
||||
// 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
try {
|
||||
context.startActivity(intent)
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
// 未安装手Q或安装的版本不支持
|
||||
if (ShareUtils.isQQClientAvailable(context)) {
|
||||
val intent = Intent()
|
||||
intent.data = Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D$groupNumber")
|
||||
// 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
return try {
|
||||
if (context !is AppCompatActivity){
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}else{
|
||||
Utils.toast(context, "请安装QQ客户端")
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -484,6 +598,17 @@ object DirectUtils {
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToCommunityArticle(context: Context, community: CommunityEntity?, articleId: String?, entrance: String?, path: String?) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_TO, ArticleDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_COMMUNITY_ARTICLE_ID, articleId)
|
||||
bundle.putParcelable(KEY_COMMUNITY_DATA, community)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到社区专题
|
||||
*/
|
||||
@ -502,7 +627,7 @@ object DirectUtils {
|
||||
* @param fromLocation 可见 [VideoDetailContainerViewModel.Location]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null, path: String? = "", referer: String = "") {
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null, path: String? = "", referer: String = "", type: String = "", act: String = "") {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
@ -513,12 +638,19 @@ object DirectUtils {
|
||||
bundle.putString(KEY_LOCATION, fromLocation)
|
||||
bundle.putBoolean(KEY_SHOW_COMMENT, showComment)
|
||||
bundle.putString(KEY_REFERER, referer)
|
||||
bundle.putString(KEY_TYPE, type)
|
||||
bundle.putString(KEY_ACTIVITY_NAME, act)
|
||||
jumpActivity(context, bundle)
|
||||
} else {
|
||||
DialogUtils.showLowSystemVersionDialog(context)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null, path: String? = "", referer: String = "") {
|
||||
directToVideoDetail(context, videoId, fromLocation, showComment, gameId, entrance, path, referer, "", "")
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至安利墙
|
||||
* @param fixedTopAmwayCommentId 需要置顶的安利Id
|
||||
@ -567,4 +699,126 @@ object DirectUtils {
|
||||
// context.startActivity(GameVideoActivity.getIntent(context, gameId, entrance, path))
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directDouyin(context: Context, userId: String) {
|
||||
if (PackageHelper.localPackageNameSet.contains("com.ss.android.ugc.aweme")) {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("snssdk1128://user/profile/$userId"))
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转梦工厂小游戏
|
||||
*/
|
||||
/*@JvmStatic
|
||||
fun directLetoGameCenter(context: Context) {
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
UserManager.getInstance().userInfoEntity?.run {
|
||||
MgcAccountManager.syncAccount(context, if (idCard != null) idCard!!.name else name, mobile, name, icon, true,
|
||||
object : SyncUserInfoListener {
|
||||
override fun onSuccess(data: LoginResultBean?) {}
|
||||
|
||||
override fun onFail(code: String?, message: String?) {}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
MgcAccountManager.exitAccount(context, object : SyncUserInfoListener {
|
||||
override fun onSuccess(data: LoginResultBean?) {}
|
||||
|
||||
override fun onFail(code: String?, message: String?) {}
|
||||
})
|
||||
}
|
||||
Leto.getInstance().startGameCenter(context)
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 跳转分类
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directCategoryDirectory(context: Context, categoryId: String, categoryTitle: String, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, CategoryDirectoryActivity::class.java.name)
|
||||
bundle.putString(KEY_CATEGORY_ID, categoryId)
|
||||
bundle.putString(KEY_CATEGORY_TITLE, categoryTitle)
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到问题标签详情
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directAskColumnLabelDetail(context: Context, tag: String, community: CommunityEntity, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, AskColumnDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_ASK_TAG, tag)
|
||||
bundle.putParcelable(KEY_COMMUNITY_DATA, community)
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到专栏详情
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directAskColumnDetail(context: Context, columnId: String, community: CommunityEntity, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, AskColumnDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_COLUMN_ID, columnId)
|
||||
bundle.putParcelable(KEY_COMMUNITY_DATA, community)
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到板块
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToBlock(context: Context, blockData: SubjectRecommendEntity) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, BlockActivity::class.java.name)
|
||||
bundle.putParcelable(KEY_BLOCK_DATA, blockData)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到开服表
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameServers(context: Context, entrance: String, path: String) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameServersActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, ToolBarActivity.mergeEntranceAndPath(entrance, path))
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到游戏上传
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directGameUpload(context: Context, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameSubmissionActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 社区文章
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directSimpleArticleList(context: Context, sortType: String, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, SimpleArticleListActivity::class.java.name)
|
||||
bundle.putString(KEY_TYPE, sortType)
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,7 @@ import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
@ -205,6 +206,13 @@ public class DisplayUtils {
|
||||
public static void setStatusBarColor(Activity activity, int color, boolean lightStatusBar) {
|
||||
Window window = activity.getWindow();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (!isMiuiOs()) {
|
||||
//取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
//需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
}
|
||||
|
||||
window.setStatusBarColor(ContextCompat.getColor(activity, color));
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
@ -237,6 +245,42 @@ public class DisplayUtils {
|
||||
return (resourceId > 0 && hasSoftKeys(context)) ? resources.getDimensionPixelSize(resourceId) : 0;
|
||||
}
|
||||
|
||||
//判断导航栏是否显示
|
||||
public static boolean isNavigationBarShow(Activity activity) {
|
||||
ViewGroup vp = (ViewGroup) activity.getWindow().getDecorView();
|
||||
for (int i = 0; i < vp.getChildCount(); i++) {
|
||||
View child = vp.getChildAt(i);
|
||||
if (child.getId() != -1 && "navigationBarBackground".equals(activity.getResources().getResourceEntryName(child.getId())) && child.getMeasuredHeight() != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int getScreenWidth() {
|
||||
WindowManager manager = (WindowManager) HaloApp.getInstance().getApplication().getSystemService(Context.WINDOW_SERVICE);
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
manager.getDefaultDisplay().getMetrics(metrics);
|
||||
return metrics.widthPixels;
|
||||
}
|
||||
|
||||
public static int getScreenHeight() {
|
||||
WindowManager manager = (WindowManager) HaloApp.getInstance().getApplication().getSystemService(Context.WINDOW_SERVICE);
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
manager.getDefaultDisplay().getMetrics(metrics);
|
||||
return metrics.heightPixels;
|
||||
}
|
||||
|
||||
public static int getToastOffset() {
|
||||
int i = Resources.getSystem().getIdentifier("toast_y_offset", "dimen", "android");
|
||||
return HaloApp.getInstance().getApplication().getResources().getDimensionPixelSize(i);
|
||||
}
|
||||
|
||||
public static int getToastDefaultGravity() {
|
||||
int i = Resources.getSystem().getIdentifier("config_toastDefaultGravity", "integer", "android");
|
||||
return HaloApp.getInstance().getApplication().getResources().getInteger(i);
|
||||
}
|
||||
|
||||
public static boolean hasSoftKeys(Context context) {
|
||||
if (!(context instanceof Activity)) return false;
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
@ -18,8 +19,12 @@ object DownloadHelper {
|
||||
* @param block 成功添加下载任务后执行的代码块
|
||||
*/
|
||||
fun createABrandNewDownloadTaskQuietly(gameId: String? = "", packageName: String? = "", block: () -> Unit) {
|
||||
if (RegionSettingHelper.shouldThisGameBeFiltered(gameId)) {
|
||||
return
|
||||
}
|
||||
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.api
|
||||
.sensitiveApi
|
||||
.getGameDigest(gameId)
|
||||
.map(ApkActiveUtils.filterMapper)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@ -8,13 +8,21 @@ import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.CertificationDialog;
|
||||
import com.gh.common.dialog.DeviceRemindDialog;
|
||||
import com.gh.common.dialog.ReserveDialogFragment;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.common.view.DownloadDialog;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
@ -32,12 +40,9 @@ import com.lightgame.utils.Utils;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* todo 下载判断不能以按钮文案为判断条件,否则按钮文案修改时又要修改判断逻辑
|
||||
*/
|
||||
public class DownloadItemUtils {
|
||||
|
||||
// 更新下载进度条
|
||||
@ -125,20 +130,27 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadBtn.setTextColor(Color.WHITE);
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_pause_dn);
|
||||
}
|
||||
if (gameEntity.isLibaoExists()) {
|
||||
holder.gameLibaoIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.gameLibaoIcon.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
|
||||
boolean isShowPlatform) {
|
||||
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game);
|
||||
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, false, null);
|
||||
}
|
||||
|
||||
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
|
||||
boolean isShowPlatform, PluginLocation pluginLocation) {
|
||||
boolean isShowPlatform, boolean hideDownloadBtnIfNoAvailableContent) {
|
||||
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, hideDownloadBtnIfNoAvailableContent, null);
|
||||
}
|
||||
|
||||
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
|
||||
boolean isShowPlatform, String briefStyle) {
|
||||
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, false, briefStyle);
|
||||
}
|
||||
|
||||
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
|
||||
boolean isShowPlatform, PluginLocation pluginLocation,
|
||||
boolean hideDownloadBtnIfNoAvailableContent,
|
||||
@Nullable String briefStyle) {
|
||||
|
||||
// 控制是否显示下载按钮
|
||||
if (!Config.isShowDownload(gameEntity.getId()) || context.getString(R.string.app_name).equals(gameEntity.getName())) {
|
||||
@ -147,17 +159,9 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadBtn.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (gameEntity.isLibaoExists()) {
|
||||
holder.gameLibaoIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.gameLibaoIcon.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// 显示预约
|
||||
if (gameEntity.isReservable()) {
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
updateItemViewStatus(holder, false, briefStyle);
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
|
||||
holder.gameDownloadBtn.setText("预约");
|
||||
holder.gameDownloadBtn.setTextColor(Color.WHITE);
|
||||
@ -171,14 +175,12 @@ public class DownloadItemUtils {
|
||||
}
|
||||
|
||||
if (gameEntity.getApk().isEmpty()
|
||||
|| gameEntity.getDownloadOffStatus() != null) {
|
||||
|| gameEntity.getDownloadOffStatus() != null) {
|
||||
LinkEntity h5LinkEntity = gameEntity.getH5Link();
|
||||
String offStatus = gameEntity.getDownloadOffStatus();
|
||||
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
|
||||
|
||||
updateItemViewStatus(holder, false, briefStyle);
|
||||
|
||||
if (h5LinkEntity != null) {
|
||||
if ("play".equals(h5LinkEntity.getType())) {
|
||||
holder.gameDownloadBtn.setText("开始玩");
|
||||
@ -195,20 +197,23 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadBtn.setText("暂无");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.button_gray));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.news_detail_comment);
|
||||
if (hideDownloadBtnIfNoAvailableContent) {
|
||||
holder.gameDownloadBtn.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
}
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
updateNormalItem(context, holder, gameEntity, isShowPlatform, pluginLocation);
|
||||
updateNormalItem(context, holder, gameEntity, isShowPlatform, pluginLocation, briefStyle);
|
||||
} else {
|
||||
updatePluginItem(context, holder, gameEntity, isShowPlatform, pluginLocation);
|
||||
updatePluginItem(context, holder, gameEntity, isShowPlatform, pluginLocation, briefStyle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 更新正常的条目,只有一个apk包
|
||||
static void updateNormalItem(Context context, GameViewHolder holder, GameEntity gameEntity,
|
||||
boolean isShowPlatform, PluginLocation pluginLocation) {
|
||||
boolean isShowPlatform, PluginLocation pluginLocation, String briefStyle) {
|
||||
|
||||
final ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
|
||||
final ApkEntity apkEntity = gameEntity.getApk().get(0);
|
||||
@ -224,14 +229,12 @@ public class DownloadItemUtils {
|
||||
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, holder.gameDownloadBtn, pluginLocation);
|
||||
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
updateItemViewStatus(holder, false, briefStyle);
|
||||
}
|
||||
|
||||
// 更新插件的条目,有多个apk包
|
||||
private static void updatePluginItem(Context context, GameViewHolder holder, GameEntity gameEntity,
|
||||
boolean isShowPlatform, PluginLocation pluginLocation) {
|
||||
boolean isShowPlatform, PluginLocation pluginLocation, String briefStyle) {
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, holder.gameDownloadBtn, pluginLocation);
|
||||
|
||||
ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
|
||||
@ -250,18 +253,14 @@ public class DownloadItemUtils {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
updateItemViewStatus(holder, false, briefStyle);
|
||||
}
|
||||
|
||||
// 更改进度条和提示文本的状态
|
||||
public static void changeStatus(Context context, GameViewHolder holder, DownloadEntity downloadEntity,
|
||||
boolean isShowPlatform, boolean isNormal) {
|
||||
holder.gameDes.setVisibility(View.GONE);
|
||||
holder.gameProgressbar.setVisibility(View.VISIBLE);
|
||||
holder.gameInfo.setVisibility(View.VISIBLE);
|
||||
|
||||
updateItemViewStatus(holder, true, null);
|
||||
|
||||
String platform = PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
|
||||
|
||||
@ -334,15 +333,38 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadBtn.setText(R.string.install);
|
||||
holder.gameDownloadBtn.setTextColor(Color.WHITE);
|
||||
if (downloadEntity.isPluggable()
|
||||
&& PackagesManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
&& PackagesManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.download_button_pluggable_style);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.download_button_normal_style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateItemViewStatus(GameViewHolder holder, boolean hasDownload, @Nullable String briefStyle) {
|
||||
if (hasDownload) {
|
||||
if (holder.gameRating != null) holder.gameRating.setVisibility(View.GONE);
|
||||
holder.gameDes.setVisibility(View.GONE);
|
||||
holder.gameProgressbar.setVisibility(View.VISIBLE);
|
||||
holder.gameInfo.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
if (briefStyle != null && briefStyle.contains("star")) {
|
||||
if (holder.gameRating != null) holder.gameRating.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
if (holder.gameRating != null) holder.gameRating.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(briefStyle) || briefStyle.contains("brief")) {
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.gameDes.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setOnClickListener(final Context context,
|
||||
final TextView downloadBtn,
|
||||
final GameEntity gameEntity,
|
||||
@ -420,11 +442,19 @@ public class DownloadItemUtils {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (gameEntity.getApk().size() == 0 && gameEntity.getH5Link() != null) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
|
||||
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), "play".equals(gameEntity.getH5Link().getType()));
|
||||
|
||||
LinkEntity linkEntity = gameEntity.getH5Link();
|
||||
|
||||
boolean isPlay = "play".equals(linkEntity.getType()); // 是否为开始玩
|
||||
if (isPlay) {
|
||||
HistoryHelper.insertGameEntity(gameEntity);
|
||||
}
|
||||
|
||||
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), isPlay);
|
||||
context.startActivity(i);
|
||||
});
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
@ -449,7 +479,16 @@ public class DownloadItemUtils {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(context, () -> {
|
||||
DownloadDialog.getInstance(context).showPopupWindow(v, gameEntity, entrance, location, traceEvent);
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
|
||||
DownloadDialog.showDownloadDialog(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
traceEvent,
|
||||
entrance,
|
||||
location);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -480,19 +519,38 @@ public class DownloadItemUtils {
|
||||
if (str.equals(context.getString(R.string.download))) {
|
||||
// 先弹下载弹窗(如果需要的话)
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
});
|
||||
|
||||
DataLogUtils.uploadGameLog(context, gameEntity.getId(), gameEntity.getName(), entrance);
|
||||
} else if (str.equals(context.getString(R.string.pluggable))) {
|
||||
} else if (str.equals(context.getString(R.string.attempt))) {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
DataLogUtils.uploadGameLog(context, gameEntity.getId(), gameEntity.getName(), entrance);
|
||||
} else if (str.contains("化")) {
|
||||
if (entrance.contains("我的游戏")) {
|
||||
MtaHelper.onEvent("我的游戏_启动", "插件化", gameEntity.getName());
|
||||
}
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> plugin(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
if (gameEntity.getPluggableCollection() != null) {
|
||||
DownloadDialog.showDownloadDialog(context, gameEntity, traceEvent, entrance, location);
|
||||
} else {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> plugin(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
});
|
||||
}
|
||||
} else if (str.equals(context.getString(R.string.install))) {
|
||||
install(context, gameEntity, position, adapter);
|
||||
} else if (str.equals(context.getString(R.string.launch))) {
|
||||
@ -528,14 +586,13 @@ public class DownloadItemUtils {
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), entrance, "下载开始", "下载");
|
||||
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, gameEntity.getApk().get(0).getPlatform(), traceEvent, ExposureUtils.DownloadType.DOWNLOAD);
|
||||
|
||||
DownloadManager.createDownload(context, gameEntity, context.getString(R.string.download), entrance, location, isSubscribe, downloadExposureEvent);
|
||||
DownloadManager.createDownload(context, gameEntity, context.getString(R.string.download), entrance, location, isSubscribe, traceEvent);
|
||||
Utils.toast(context, gameEntity.getName() + "已加入下载队列");
|
||||
|
||||
downloadBtn.setText(R.string.downloading);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
|
||||
DeviceRemindDialog.Companion.showDeviceRemindDialog(context, gameEntity);
|
||||
} else {
|
||||
Utils.toast(context, msg);
|
||||
}
|
||||
@ -548,9 +605,7 @@ public class DownloadItemUtils {
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), entrance, "下载开始", "插件化");
|
||||
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, gameEntity.getApk().get(0).getPlatform(), traceEvent, ExposureUtils.DownloadType.PLUGIN_DOWNLOAD);
|
||||
|
||||
DownloadManager.createDownload(context, gameEntity, "插件化", entrance, location, isSubscribe, downloadExposureEvent);
|
||||
DownloadManager.createDownload(context, gameEntity, "插件化", entrance, location, isSubscribe, traceEvent);
|
||||
Utils.toast(context, gameEntity.getName() + "已加入下载队列");
|
||||
|
||||
downloadBtn.setText(R.string.downloading);
|
||||
@ -575,6 +630,8 @@ public class DownloadItemUtils {
|
||||
gameEntity.getEntryMap().remove(apkEntity.getPlatform());
|
||||
}
|
||||
adapter.notifyItemChanged(position);
|
||||
} else if (PackageUtils.isCanPluggable(apkEntity)) {
|
||||
DialogUtils.showPluginDialog(context, () -> context.startActivity(PackageUtils.getUninstallIntent(context, path)));
|
||||
} else {
|
||||
PackageUtils.launchSetup(context, downloadEntity);
|
||||
}
|
||||
@ -584,13 +641,9 @@ public class DownloadItemUtils {
|
||||
//更新
|
||||
private static void update(Context context, GameEntity gameEntity, String entrance, String location, boolean isSubscribe, @Nullable ExposureEvent traceEvent) {
|
||||
ApkEntity apkEntity = gameEntity.getApk().get(0);
|
||||
|
||||
ExposureUtils.DownloadType downloadType = ExposureUtils.getUpdateType(apkEntity);
|
||||
|
||||
DataUtils.onGameUpdateEvent(context, gameEntity.getName(), apkEntity.getPlatform(), "下载开始");
|
||||
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity
|
||||
.getPlatform(), traceEvent, downloadType);
|
||||
DownloadManager.createDownload(context, gameEntity, "更新", entrance, location, isSubscribe, downloadExposureEvent);
|
||||
DownloadManager.createDownload(context, gameEntity, "更新", entrance, location, isSubscribe, traceEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -88,30 +88,33 @@ object DownloadNotificationHelper {
|
||||
else -> builder.setSortKey("C")
|
||||
}
|
||||
|
||||
val notification = builder.build()
|
||||
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
|
||||
tryCatchInRelease {
|
||||
val notification = builder.build() // 可能会抛出异常
|
||||
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
|
||||
|
||||
if (entity.status == DownloadStatus.delete
|
||||
|| entity.status == DownloadStatus.cancel
|
||||
|| entity.status == DownloadStatus.hijack
|
||||
|| entity.status == DownloadStatus.notfound
|
||||
|| entity.status == DownloadStatus.overflow
|
||||
|| (entity.status == DownloadStatus.done // 触发安装事件以后也 cancel 掉通知
|
||||
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty())) {
|
||||
requireUpdateNotificationGroupDelay = true
|
||||
notificationManager.cancel(entity.path, DOWNLOAD_NOTIFICATION_ID)
|
||||
} else {
|
||||
if (entity.status != DownloadStatus.downloading) {
|
||||
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
|
||||
if (entity.status == DownloadStatus.delete
|
||||
|| entity.status == DownloadStatus.cancel
|
||||
|| entity.status == DownloadStatus.hijack
|
||||
|| entity.status == DownloadStatus.notfound
|
||||
|| entity.status == DownloadStatus.overflow
|
||||
|| (entity.status == DownloadStatus.done // 触发安装事件以后也 cancel 掉通知
|
||||
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty())) {
|
||||
requireUpdateNotificationGroupDelay = true
|
||||
notificationManager.cancel(entity.path, DOWNLOAD_NOTIFICATION_ID)
|
||||
} else {
|
||||
val time = mNotifyMap[entity.path]
|
||||
val curTime = System.currentTimeMillis()
|
||||
if (time == null || curTime - time > 2000) {
|
||||
mNotifyMap[entity.path] = curTime
|
||||
if (entity.status != DownloadStatus.downloading) {
|
||||
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
|
||||
} else {
|
||||
val time = mNotifyMap[entity.path]
|
||||
val curTime = System.currentTimeMillis()
|
||||
if (time == null || curTime - time > 2000) {
|
||||
mNotifyMap[entity.path] = curTime
|
||||
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (requireUpdateNotificationGroupDelay) {
|
||||
// 虽然运行到这里时 notification 已经被 cancel 了,但在下面的 notificationManager.getActiveNotifications 里它有可能还是 active 状态,
|
||||
// 这里延时 100 ms 避免出现所有的任务都取消了以后依旧有一条 notification group 常驻
|
||||
|
||||
262
app/src/main/java/com/gh/common/util/DownloadObserver.kt
Normal file
262
app/src/main/java/com/gh/common/util/DownloadObserver.kt
Normal file
@ -0,0 +1,262 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.preference.PreferenceManager
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.exposure.ExposureUtils
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.SuggestionActivity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBShowDialog
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.suggest.SuggestType
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.halo.assistant.fragment.SettingsFragment
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import com.lightgame.download.FileUtils
|
||||
import com.lightgame.utils.AppManager
|
||||
import com.lightgame.utils.Util_System_Phone_State
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
object DownloadObserver {
|
||||
|
||||
private val mApplication = HaloApp.getInstance().application
|
||||
|
||||
// 如果在WIFI状态下,下载自动暂停,则再重试一遍
|
||||
@JvmStatic
|
||||
fun initObserver() {
|
||||
val dataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
val gameId = downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER)
|
||||
val downloadManager = DownloadManager.getInstance(HaloApp.getInstance().application)
|
||||
|
||||
if (downloadEntity.status != DownloadStatus.downloading) {
|
||||
LogUtils.uploadDownloadEvent(downloadEntity)
|
||||
}
|
||||
|
||||
if (DownloadStatus.hijack == downloadEntity.status) {
|
||||
// 链接被劫持
|
||||
processHijack(downloadEntity)
|
||||
val nameAndPlatform = (downloadEntity.name + ":"
|
||||
+ PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
|
||||
// MtaHelper.onEvent("下载劫持",
|
||||
// "游戏名字", nameAndPlatform,
|
||||
// "网络状态", DeviceUtils.getNetwork(mApplication))
|
||||
return
|
||||
} else if (DownloadStatus.notfound == downloadEntity.status) {
|
||||
// 404 Not Found
|
||||
// 删除任务
|
||||
downloadEntity.status = DownloadStatus.cancel
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
Utils.toast(mApplication, "该链接已失效!请联系管理员。")
|
||||
|
||||
// MtaHelper.onEventWithBasicDeviceInfo("下载失败弹窗",
|
||||
// "游戏", downloadEntity.name,
|
||||
// "平台", downloadEntity.platform)
|
||||
|
||||
DialogUtils.showAlertDialog(AppManager.getInstance().currentActivity(), "下载失败", "下载链接已失效,建议提交反馈", "立即反馈", "取消", {
|
||||
SuggestionActivity.startSuggestionActivity(AppManager.getInstance().currentActivity(),
|
||||
SuggestType.gameQuestion, "notfound",
|
||||
StringUtils.buildString(downloadEntity.name, ",问题反馈:下载链接失效"),
|
||||
SimpleGameEntity(gameId, downloadEntity.name, ""))
|
||||
}, null)
|
||||
return
|
||||
} else if (DownloadStatus.neterror == downloadEntity.status || DownloadStatus.timeout == downloadEntity.status) {
|
||||
if (downloadEntity.meta[Constants.MARK_RETRY_DOWNLOAD].isNullOrEmpty()
|
||||
&& NetworkUtils.isWifiConnected(HaloApp.getInstance().application)) {
|
||||
downloadEntity.meta[Constants.MARK_RETRY_DOWNLOAD] = downloadEntity.progress.toString()
|
||||
downloadManager.updateDownloadEntity(downloadEntity)
|
||||
downloadManager.startDownload(downloadEntity.url)
|
||||
debugOnly {
|
||||
Utils.log("DownloadObserver", "下载重试->" + downloadEntity.toJson())
|
||||
}
|
||||
} else {
|
||||
Utils.toast(mApplication, "网络不稳定,下载任务已暂停")
|
||||
DataLogUtils.uploadNeterrorLog(mApplication, downloadEntity)
|
||||
|
||||
// MtaHelper.onEventWithBasicDeviceInfo("下载自动暂停",
|
||||
// "游戏", downloadEntity.name,
|
||||
// "平台", downloadEntity.platform)
|
||||
debugOnly {
|
||||
Utils.log("DownloadObserver", "下载自动暂停->" + downloadEntity.toJson())
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DownloadStatus.done == downloadEntity.status) {
|
||||
if (downloadEntity.name.contains(mApplication.getString(R.string.app_name))) {
|
||||
MtaHelper.onEvent("软件更新", "下载完成")
|
||||
tryWithDefaultCatch {
|
||||
// 会有 ActivityNotFoundException 异常,catch 掉不管了
|
||||
mApplication.startActivity(PackageUtils.getInstallIntent(mApplication, downloadEntity.path, true))
|
||||
}
|
||||
DataLogUtils.uploadUpgradeLog(mApplication, "install") //上传更新安装数据
|
||||
} else {
|
||||
statDoneEvent(downloadEntity)
|
||||
|
||||
val platform = PlatformUtils.getInstance(mApplication)
|
||||
.getPlatformName(downloadEntity.platform)
|
||||
if (platform != null) {
|
||||
when {
|
||||
downloadEntity.isPluggable -> // 弹出插件化提示框
|
||||
EventBus.getDefault().post(EBShowDialog(BaseActivity.PLUGGABLE, downloadEntity.path))
|
||||
downloadEntity.isPlugin -> Utils.toast(mApplication, downloadEntity.name + " - " + platform + " - 下载完成")
|
||||
else -> Utils.toast(mApplication, downloadEntity.name + " - 下载完成")
|
||||
}
|
||||
} else {
|
||||
Utils.toast(mApplication, downloadEntity.name + " - 下载完成")
|
||||
}
|
||||
if (!downloadEntity.isPluggable) {
|
||||
// 是否是自动安装
|
||||
if (PreferenceManager.getDefaultSharedPreferences(mApplication).getBoolean(SettingsFragment.AUTO_INSTALL_SP_KEY, true)) {
|
||||
if (FileUtils.isEmptyFile(downloadEntity.path)) {
|
||||
Utils.toast(mApplication, R.string.install_failure_hint)
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
} else {
|
||||
if (PackageUtils.isCanLaunchSetup(mApplication, downloadEntity.path)) {
|
||||
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
|
||||
tryWithDefaultCatch {
|
||||
mApplication.startActivity(PackageUtils.getInstallIntent(mApplication, downloadEntity.path))
|
||||
}
|
||||
} else {
|
||||
// 弹出卸载提示框
|
||||
EventBus.getDefault().post(EBShowDialog(BaseActivity.PLUGGABLE, downloadEntity.path))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 统计下载完成
|
||||
uploadData(gameId, downloadEntity.platform)
|
||||
}
|
||||
|
||||
// 下载过程分析统计
|
||||
val pm = mApplication.packageManager
|
||||
val packageInfo = pm.getPackageArchiveInfo(downloadEntity.path, PackageManager.GET_ACTIVITIES)
|
||||
if (packageInfo == null) {
|
||||
// MtaHelper.onEventWithBasicDeviceInfo("解析包错误分析",
|
||||
// "游戏名字", downloadEntity.name + ":" + PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
|
||||
//
|
||||
// MtaHelper.onEventWithBasicDeviceInfo("解析包错误_新",
|
||||
// "游戏", downloadEntity.name + ":" + PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadEntity.status == DownloadStatus.done) {
|
||||
EventBus.getDefault().post(EBDownloadStatus("done", "", "", "", downloadEntity.packageName, ""))
|
||||
}
|
||||
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
|
||||
// 如果已下载大小发生变化,表示成功恢复下载,则重置重试标记
|
||||
if (downloadEntity.status == DownloadStatus.downloading &&
|
||||
downloadEntity.progress.toString() != downloadEntity.meta[Constants.MARK_RETRY_DOWNLOAD]) {
|
||||
downloadEntity.meta[Constants.MARK_RETRY_DOWNLOAD] = ""
|
||||
downloadManager.updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加观察者
|
||||
DownloadManager.getInstance(mApplication).addObserver(dataWatcher)
|
||||
|
||||
}
|
||||
|
||||
// 统计下载完成事件
|
||||
private fun statDoneEvent(downloadEntity: DownloadEntity) {
|
||||
var type: ExposureUtils.DownloadType
|
||||
val platform = PlatformUtils.getInstance(HaloApp.getInstance().application).getPlatformName(downloadEntity.platform)
|
||||
|
||||
val kv1 = HashMap<String, Any>()
|
||||
kv1["版本"] = platform
|
||||
kv1["状态"] = "下载完成"
|
||||
kv1["用户机型"] = Build.MODEL
|
||||
kv1["设备IMEI"] = Util_System_Phone_State.getDeviceId(HaloApp.getInstance().application)
|
||||
kv1["网络状态"] = DeviceUtils.getNetwork(HaloApp.getInstance().application)
|
||||
kv1["光环助手版本"] = BuildConfig.VERSION_NAME
|
||||
if (downloadEntity.isUpdate) {
|
||||
type = ExposureUtils.DownloadType.UPDATE
|
||||
if (downloadEntity.isPlugin) {
|
||||
type = ExposureUtils.DownloadType.PLUGIN_UPDATE
|
||||
}
|
||||
DataUtils.onEvent(mApplication, "游戏更新", downloadEntity.name, kv1)
|
||||
} else {
|
||||
type = ExposureUtils.DownloadType.DOWNLOAD
|
||||
}
|
||||
|
||||
// val kv2 = HashMap<String, Any>()
|
||||
// kv2["版本"] = downloadEntity.platform
|
||||
// kv2["状态"] = "下载完成"
|
||||
// kv2["位置"] = downloadEntity.entrance ?: "null"
|
||||
// kv2["游戏分平台"] = downloadEntity.name + "-" + platform
|
||||
// kv2["光环助手版本"] = BuildConfig.VERSION_NAME
|
||||
// DataUtils.onEvent(mApplication, "游戏下载位置", downloadEntity.name, kv2)
|
||||
|
||||
if (downloadEntity.isPluggable) {
|
||||
val kv3 = HashMap<String, Any>()
|
||||
kv3["下载"] = "下载完成"
|
||||
kv3["版本"] = downloadEntity.platform
|
||||
kv3["位置"] = downloadEntity.entrance ?: "null"
|
||||
type = ExposureUtils.DownloadType.PLUGIN_DOWNLOAD
|
||||
DataUtils.onEvent(mApplication, "插件化", downloadEntity.name, kv3)
|
||||
|
||||
// MtaHelper.onEvent(
|
||||
// "插件化_新",
|
||||
// "位置", downloadEntity.entrance,
|
||||
// "游戏", downloadEntity.name + "-" + downloadEntity.platform,
|
||||
// "操作", "下载完成",
|
||||
// "网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().application))
|
||||
}
|
||||
|
||||
ExposureUtils.logADownloadCompleteExposureEvent(
|
||||
GameEntity(id = downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER),
|
||||
mName = downloadEntity.name.removeSuffix(Constants.GAME_NAME_DECORATOR),
|
||||
gameVersion = downloadEntity.versionName ?: ""),
|
||||
downloadEntity.platform,
|
||||
downloadEntity.exposureTrace,
|
||||
type)
|
||||
|
||||
DataCollectionUtils.uploadDownload(mApplication, downloadEntity, "完成")
|
||||
}
|
||||
|
||||
private fun processHijack(downloadEntity: DownloadEntity) {
|
||||
// 删除任务
|
||||
downloadEntity.status = DownloadStatus.cancel
|
||||
DownloadManager.getInstance(mApplication).cancel(downloadEntity.url)
|
||||
// 弹出提示框
|
||||
EventBus.getDefault().post(EBShowDialog(BaseActivity.DOWNLOAD_HIJACK))
|
||||
// 记录链接被劫持
|
||||
DataCollectionUtils.uploadHijack(mApplication, downloadEntity)
|
||||
// 上传劫持log
|
||||
DataLogUtils.uploadHijack(mApplication, downloadEntity)
|
||||
}
|
||||
|
||||
// 统计下载
|
||||
private fun uploadData(id: String, platform: String?) {
|
||||
val params = HashMap<String, String>()
|
||||
params["game"] = id
|
||||
params["platform"] = platform ?: ""
|
||||
val body = RequestBody.create(MediaType.parse("application/json"),
|
||||
JSONObject(params).toString())
|
||||
RetrofitManager.getInstance(mApplication).api.postDownload(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(Response())
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,11 +4,15 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.gh.common.avoidcallback.AvoidOnResultManager;
|
||||
import com.gh.common.avoidcallback.Callback;
|
||||
import com.gh.gamecenter.MainActivity;
|
||||
import com.gh.gamecenter.NormalActivity;
|
||||
import com.gh.gamecenter.SplashScreenActivity;
|
||||
import com.gh.gamecenter.normal.NormalFragment;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 2017/4/25
|
||||
@ -18,11 +22,13 @@ import com.gh.gamecenter.normal.NormalFragment;
|
||||
public class EntranceUtils {
|
||||
|
||||
public static final String KEY_TO = "to";
|
||||
public static final String KEY_NEXT_TO = "next_to";
|
||||
public static final String KEY_NEWSID = "newsId";
|
||||
public static final String KEY_GAMEID = "gameId";
|
||||
public static final String KEY_ID = "id";
|
||||
public static final String KEY_URL = "url";
|
||||
public static final String KEY_GAMENAME = "gameName";
|
||||
public static final String KEY_PACKAGE_MD5 = "package_md5";
|
||||
public static final String HOST_ARTICLE = "article";
|
||||
public static final String HOST_UPLOAD_VIDEO = "upload_video";//上传视频
|
||||
public static final String HOST_VIDEO_SINGLE = "video_single";//指定视频-不能划动
|
||||
@ -30,7 +36,18 @@ public class EntranceUtils {
|
||||
public static final String HOST_VIDEO_STREAMING_HOME = "video_streaming_home";//视频流-首页
|
||||
public static final String HOST_VIDEO_STREAMING_DESC = "video_streaming_desc";//视频流-游戏介绍进入
|
||||
public static final String HOST_VIDEO_COLLECTION = "video_collection";//视频合集
|
||||
public static final String HOST_USERHOME = "userhome";//个人主页
|
||||
public static final String HOST_VIDEO = "video";
|
||||
public static final String HOST_CATEGORY = "category";//分类
|
||||
public static final String HOST_COLUMN_COLLECTION = "column_collection";//专题合集
|
||||
public static final String HOST_COMMUNITY_QUESTION_LABEL_DETAIL = "community_question_label_detail";//问题标签详情
|
||||
public static final String HOST_COMMUNITY_COLUMN_DETAIL = "community_column_detail";//专栏详情
|
||||
public static final String HOST_BLOCK = "block";//板块
|
||||
public static final String HOST_SERVER_BLOCK = "server";//开服表板块
|
||||
public static final String HOST_AMWAY_BLOCK = "amway";//安利墙板块
|
||||
public static final String HOST_HELP = "help";//Q&A
|
||||
public static final String HOST_HELP_COLLECTION = "help_collection";//Q&A合集
|
||||
public static final String HOST_GAME_UPLOAD = "game_upload";//游戏上传
|
||||
public static final String HOST_COMMUNITY_ARTICLE = "community_article";
|
||||
public static final String HOST_COMMUNITY_COLUMN = "community_column";
|
||||
public static final String HOST_GAME = "game";
|
||||
@ -80,6 +97,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_OLDERUSER = "isOldUser";
|
||||
public static final String KEY_SEARCHKEY = "searchKey";
|
||||
public static final String KEY_HINT = "hint";
|
||||
public static final String KEY_GAME = "game";
|
||||
public static final String KEY_GAME_ICON_URL = "gameIconUrl";
|
||||
public static final String KEY_SHARECONTENT = "shareContent";
|
||||
public static final String KEY_SUGGESTTYPE = "suggestType";
|
||||
@ -107,6 +125,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_CATEGORY_INIT_TITLE = "category_init_title";
|
||||
public static final String KEY_BLOCK_DATA = "blockData";
|
||||
public static final String KEY_ASK_TAG = "askTag";
|
||||
public static final String KEY_SCROLL_TO_LIBAO = "libao";
|
||||
public static final String KEY_ASK_COLUMN_TAG = "askColumnTag";
|
||||
public static final String KEY_COMMUNITY_ID = "community_id";
|
||||
public static final String KEY_COMMUNITY_NAME = "community_name";
|
||||
@ -131,6 +150,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_DIRECT_COMMENT = "directComment";
|
||||
public static final String KEY_SORT = "sort";
|
||||
public static final String KEY_AMWAY = "amway";
|
||||
public static final String KEY_SKIP_SUCCESS_PAGE = "skipSuccessPage";
|
||||
public static final String KEY_COLLECTION_ID = "collectionId";
|
||||
public static final String KEY_NAVIGATION_TITLE = "navigationTitle";
|
||||
public static final String KEY_IMAGE_CROP_RATIO = "imageCropRatio";
|
||||
@ -140,8 +160,18 @@ public class EntranceUtils {
|
||||
public static final String KEY_IS_HOME_VIDEO = "isHomeVideo";
|
||||
public static final String KEY_IS_HOME = "isHome";
|
||||
public static final String KEY_WEB_SHARE = "webShare";
|
||||
public static final String KEY_ACTIVITY_NAME = "activityName";//活动名称
|
||||
public static final String KEY_REQUIRE_REDIRECT = "require_redirect"; // 标记需要再跳转
|
||||
public static final String KEY_COLUMNNAME = "columnName";
|
||||
public static final String KEY_QA_ID = "qaId";
|
||||
public static final String KEY_QA_COLLECTION_ID = "qaCollectionId";
|
||||
public static final String KEY_SHOW_EDIT_DRAFT = "showEditDraft";
|
||||
public static final String KEY_ARTICLE_OPEN_IN_NEW_PAGE = "openArticleInNewPage";
|
||||
public static final String KEY_ONLY_CREATE_DRAFT = "onlyCreateDraft";
|
||||
public static final String KEY_KAIFU_SELECT_TIME = "kaifuSelectTime";
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
//TODO 把其他类似的跳转启动逻辑也处理掉
|
||||
if (RunningUtils.isRunning(context)
|
||||
@ -164,4 +194,34 @@ public class EntranceUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void jumpActivity(Context context, Bundle nextToBundle, Bundle bundle, Callback callback) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
//TODO 把其他类似的跳转启动逻辑也处理掉
|
||||
if (RunningUtils.isRunning(context)
|
||||
&& MainActivity.class.getName().equals(RunningUtils.getBaseActivity(context))) {
|
||||
// 应用正在运行,前台或后台
|
||||
String to = bundle.getString(KEY_TO);
|
||||
Class<?> clazz = ClassUtils.forName(to);
|
||||
if (clazz == null) clazz = MainActivity.class;
|
||||
if (NormalFragment.class.isAssignableFrom(clazz)) { // 兼容NormalFragment
|
||||
NormalActivity.startFragmentNewTask(context, (Class<? extends NormalFragment>) clazz, bundle);
|
||||
} else {
|
||||
Intent intent1 = new Intent(context, clazz);
|
||||
//TODO:添加FLAG_ACTIVITY_NEW_TASK会导致一跳转页面callback就被调用
|
||||
//intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent1.putExtras(bundle);
|
||||
|
||||
AvoidOnResultManager.Companion.getInstance((AppCompatActivity) context)
|
||||
.startForResult(intent1, callback);
|
||||
}
|
||||
} else {
|
||||
// 应用未在运行
|
||||
if (nextToBundle != null) {
|
||||
bundle.putBundle(KEY_NEXT_TO, nextToBundle);
|
||||
}
|
||||
context.startActivity(SplashScreenActivity.getSplashScreenIntent(context, bundle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,10 @@ object ErrorHelper {
|
||||
customizedHandler: (code: Int) -> Boolean) {
|
||||
val errorEntity = errorString?.toObject<ErrorEntity>()
|
||||
|
||||
if (customizedHandler(errorEntity?.code ?: 0)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (errorEntity == null) {
|
||||
Utils.toast(context, R.string.post_failure_hint)
|
||||
return
|
||||
@ -33,11 +37,7 @@ object ErrorHelper {
|
||||
return
|
||||
}
|
||||
|
||||
if (customizedHandler(errorEntity.code ?: 0)) {
|
||||
return
|
||||
} else {
|
||||
handleError(context, showHighPriorityHint, errorEntity)
|
||||
}
|
||||
handleError(context, showHighPriorityHint, errorEntity)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,10 +115,11 @@ object ErrorHelper {
|
||||
403074 -> Utils.toast(context, "该微信号(${errorEntity.data?.nickname})已绑定")
|
||||
403078 -> Utils.toast(context, "已点赞")
|
||||
403072 -> Utils.toast(context, R.string.comment_failed_userblocked)
|
||||
403082 -> Utils.toast(context, "作者已关闭评论")
|
||||
|
||||
403020 -> if (showHighPriorityHint) {
|
||||
DialogUtils.showAlertDialog(context,
|
||||
"限制提醒",
|
||||
"提醒",
|
||||
"提问过于频繁,请先休息一下哦",
|
||||
"知道了", null, null, null)
|
||||
} else {
|
||||
|
||||
@ -3,16 +3,18 @@ package com.gh.common.util
|
||||
import android.animation.Animator
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.text.Editable
|
||||
import android.text.Html
|
||||
import android.text.Spanned
|
||||
import android.text.TextWatcher
|
||||
import android.os.Build
|
||||
import android.text.*
|
||||
import android.text.style.ClickableSpan
|
||||
import android.text.style.ImageSpan
|
||||
import android.text.style.URLSpan
|
||||
import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
@ -21,10 +23,15 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.DefaultUrlHandler
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.view.CenterImageSpan
|
||||
import com.gh.common.view.CustomLinkMovementMethod
|
||||
import com.gh.common.view.ExpandTextView
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
@ -35,6 +42,7 @@ import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import java.net.URI
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
@ -190,6 +198,28 @@ inline fun <reified T : Any> T.toJson(): String {
|
||||
return GsonUtils.toJson(this)
|
||||
}
|
||||
|
||||
fun String.insert(index: Int, string: String): String {
|
||||
return this.substring(0, index) + string + this.substring(index, this.length)
|
||||
}
|
||||
|
||||
/**
|
||||
* TextView 内部处理 ul li ol 得跟 Android 版本走,这里换成专属的标签手动处理
|
||||
*/
|
||||
fun String.replaceUnsupportedHtmlTag(): String {
|
||||
return this.replace("<ul", "<hul")
|
||||
.replace("</ul>", "</hul>")
|
||||
.replace("<li", "<hli")
|
||||
.replace("</li>", "</hli>")
|
||||
.replace("<ol", "<hol")
|
||||
.replace("</ol>", "</hol>")
|
||||
}
|
||||
|
||||
fun String.containHtmlTag(): Boolean {
|
||||
val pattern = Pattern.compile("<(\"[^\"]*\"|'[^']*'|[^'\">])*>")
|
||||
val matcher = pattern.matcher(this)
|
||||
return matcher.find()
|
||||
}
|
||||
|
||||
/**
|
||||
* 在限定 interval 里只触发一次 action
|
||||
*/
|
||||
@ -222,6 +252,29 @@ inline fun tryWithDefaultCatch(action: (() -> Unit)) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 只在正式版本进行 try catch 操作
|
||||
*
|
||||
* 对于个别偶发的异常尽量不要做暴力的 try catch 处理
|
||||
*/
|
||||
inline fun tryCatchInRelease(action: (() -> Unit)) {
|
||||
try {
|
||||
action.invoke()
|
||||
} catch (e: Throwable) {
|
||||
if (BuildConfig.DEBUG) throw e
|
||||
else e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 debug 状态下抛出异常
|
||||
*/
|
||||
fun throwExceptionInDebug(message: String = "", predicate: Boolean = true) {
|
||||
if (predicate && BuildConfig.DEBUG) {
|
||||
throw RuntimeException(message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String related
|
||||
*/
|
||||
@ -261,11 +314,18 @@ fun String.subStringIfPossible(length: Int): String {
|
||||
}
|
||||
}
|
||||
|
||||
fun String.getFirstElementDividedByDivider(divider: String): String {
|
||||
if (this.contains(divider)) {
|
||||
return this.split(divider.toRegex()).toTypedArray()[0]
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun String.copyTextAndToast(toastText: String = "复制成功") {
|
||||
val application = HaloApp.getInstance().application
|
||||
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
cmb.text = this
|
||||
Utils.toast(application, toastText)
|
||||
ToastUtils.showToast(toastText)
|
||||
}
|
||||
|
||||
fun Map<String, String>.createRequestBody(): RequestBody {
|
||||
@ -390,7 +450,7 @@ fun FragmentActivity.checkStoragePermissionBeforeAction(action: (() -> Unit)) {
|
||||
fun TextView.setTextWithHighlightedTextWrappedInsideWrapper(text: CharSequence,
|
||||
wrapper: String = Constants.DEFAULT_TEXT_WRAPPER,
|
||||
@ColorRes
|
||||
highlightColorId: Int = R.color.theme,
|
||||
highlightColorId: Int = R.color.theme_font,
|
||||
copyClickedText: Boolean = false,
|
||||
highlightedTextClickListener: (() -> Unit)? = null) {
|
||||
TextHelper.highlightTextThatIsWrappedInsideWrapper(this, text, wrapper, highlightColorId, object : SimpleCallback<String> {
|
||||
@ -418,8 +478,77 @@ fun TextView.setTextChangedListener(action: (s: CharSequence, start: Int, before
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截 TextView 中的 Url Span,用应用内页面的形式打开链接
|
||||
* @param shrankText 未展开时的文字
|
||||
* @param expandedText 展开后的文字
|
||||
*/
|
||||
fun ExpandTextView.setTextWithInterceptingInternalUrl(shrankText: CharSequence, expandedText: CharSequence) {
|
||||
var shrankSsb = shrankText.interceptUrlSpanAndRoundImageSpan()
|
||||
var expandedSsb = expandedText.interceptUrlSpanAndRoundImageSpan()
|
||||
|
||||
// 去掉旧版本 Android 系统 [Html.FROM_HTML_MODE_LEGACY] 产生的两个换行符 (丑陋的代码)
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
while (shrankSsb.contains("\n\n")) {
|
||||
val index = shrankSsb.indexOf("\n\n", 0, true)
|
||||
shrankSsb = SpannableStringBuilder(shrankSsb.subSequence(0, index)).append(shrankSsb.subSequence(index + "\n".length, shrankSsb.length))
|
||||
}
|
||||
while (expandedSsb.contains("\n\n")) {
|
||||
val index = expandedSsb.indexOf("\n\n", 0, true)
|
||||
expandedSsb = SpannableStringBuilder(expandedSsb.subSequence(0, index)).append(expandedSsb.subSequence(index + "\n".length, expandedSsb.length))
|
||||
}
|
||||
}
|
||||
|
||||
// 去掉多余的 P 标签换行
|
||||
if (expandedSsb.endsWith("\n", true)) {
|
||||
expandedSsb = SpannableStringBuilder((expandedSsb.subSequence(0, expandedSsb.length - "\n".length)))
|
||||
}
|
||||
|
||||
movementMethod = CustomLinkMovementMethod.getInstance()
|
||||
|
||||
shrankSsb = TextHelper.updateSpannableStringWithHighlightedSpan(context, shrankSsb, highlightedTextClickListener = null)
|
||||
expandedSsb = TextHelper.updateSpannableStringWithHighlightedSpan(context, expandedSsb, highlightedTextClickListener = null)
|
||||
setShrankTextAndExpandedText(shrankSsb, expandedSsb)
|
||||
}
|
||||
|
||||
fun CharSequence.interceptUrlSpanAndRoundImageSpan(): SpannableStringBuilder {
|
||||
return SpannableStringBuilder.valueOf(this).apply {
|
||||
getSpans(0, length, URLSpan::class.java).forEach {
|
||||
setSpan(
|
||||
object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = ContextCompat.getColor(HaloApp.getInstance().application, R.color.theme_font)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
if (!DefaultUrlHandler.interceptUrl(widget.context, it.url, "")) {
|
||||
widget.context.startActivity(WebActivity.getIntent(widget.context, it.url, true))
|
||||
}
|
||||
}
|
||||
},
|
||||
getSpanStart(it),
|
||||
getSpanEnd(it),
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
removeSpan(it)
|
||||
}
|
||||
|
||||
getSpans(0, length, ImageSpan::class.java).forEach {
|
||||
setSpan(
|
||||
CenterImageSpan(it.drawable),
|
||||
getSpanStart(it),
|
||||
getSpanEnd(it),
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
removeSpan(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.toColor(): Int {
|
||||
return HaloApp.getInstance().application.resources.getColor(this)
|
||||
return ContextCompat.getColor(HaloApp.getInstance().application, this)
|
||||
}
|
||||
|
||||
fun Int.toResString(): String {
|
||||
@ -437,6 +566,35 @@ fun SimpleDraweeView.display(url: String) {
|
||||
ImageUtils.display(this, url)
|
||||
}
|
||||
|
||||
/**
|
||||
* Process related
|
||||
*/
|
||||
fun Context.doOnMainProcessOnly(callback: EmptyCallback) {
|
||||
doOnMainProcessOnly { callback.onCallback() }
|
||||
}
|
||||
|
||||
inline fun Context.doOnMainProcessOnly(f: () -> Unit) {
|
||||
val processName = PackageUtils.obtainProcessName(this)
|
||||
if (processName == null || BuildConfig.APPLICATION_ID == processName) {
|
||||
f.invoke()
|
||||
} else {
|
||||
tryWithDefaultCatch {
|
||||
Utils.log("Block one useless sub process method call from ${Thread.currentThread().stackTrace[3].methodName} -> ${Thread.currentThread().stackTrace[2].methodName}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun doOnMainProcessOnly(f: () -> Unit) {
|
||||
val processName = PackageUtils.obtainProcessName(HaloApp.getInstance().application)
|
||||
if (processName == null || BuildConfig.APPLICATION_ID == processName) {
|
||||
f.invoke()
|
||||
} else {
|
||||
tryWithDefaultCatch {
|
||||
Utils.log("Block one useless sub process method call from ${Thread.currentThread().stackTrace[3].methodName} -> ${Thread.currentThread().stackTrace[2].methodName}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试用包裹
|
||||
*/
|
||||
@ -456,15 +614,15 @@ inline fun testChannelOnly(f: () -> Unit) {
|
||||
* 倒计时,单位s
|
||||
*/
|
||||
inline fun countDownTimer(
|
||||
millisUntilFinish: Long,
|
||||
crossinline block: (finish: Boolean, millisUntilFinished: Long) -> Unit
|
||||
timeInSeconds: Long,
|
||||
crossinline block: (finish: Boolean, remainingTime: Long) -> Unit
|
||||
): Disposable {
|
||||
var subscribe: Disposable? = null
|
||||
subscribe = Observable.interval(0, 1000, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
if (it < millisUntilFinish) {
|
||||
block.invoke(false, millisUntilFinish - it)
|
||||
if (it < timeInSeconds) {
|
||||
block.invoke(false, timeInSeconds - it)
|
||||
} else {
|
||||
block.invoke(true, 0)
|
||||
if (subscribe != null && !subscribe!!.isDisposed) {
|
||||
@ -522,4 +680,30 @@ fun LottieAnimationView.doOnAnimationEnd(action: () -> Unit) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查内容是否一致
|
||||
* @return true:相同 false:不同
|
||||
*/
|
||||
fun List<String>?.checkSameFromStringArray(check2: List<String>?): Boolean {
|
||||
if (this == check2) {
|
||||
return true
|
||||
}
|
||||
if (this == null && check2 == null) {
|
||||
return true
|
||||
}
|
||||
if (this == null || check2 == null) {
|
||||
return false
|
||||
}
|
||||
if (this.size != check2.size) {
|
||||
return false
|
||||
}
|
||||
for (tag in this) {
|
||||
if (!check2.contains(tag)) return false
|
||||
}
|
||||
for (tag in check2) {
|
||||
if (!this.contains(tag)) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
183
app/src/main/java/com/gh/common/util/ExtraTagHandler.kt
Normal file
183
app/src/main/java/com/gh/common/util/ExtraTagHandler.kt
Normal file
@ -0,0 +1,183 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.text.Editable
|
||||
import android.text.Html.TagHandler
|
||||
import android.text.Spanned
|
||||
import android.text.style.BulletSpan
|
||||
import android.text.style.LeadingMarginSpan
|
||||
import android.util.Log
|
||||
import org.xml.sax.XMLReader
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Implements support for ordered (`<ol>`) and unordered (`<ul>`) lists in to Android TextView.
|
||||
*
|
||||
*
|
||||
* This can be used as follows:<br></br>
|
||||
* `textView.setText(Html.fromHtml("<ul><li>item 1</li><li>item 2</li></ul>", null, new HtmlListTagHandler()));`
|
||||
*
|
||||
*
|
||||
* Implementation based on code by Juha Kuitunen (https://bitbucket.org/Kuitsi/android-textview-html-list),
|
||||
* released under Apache License v2.0. Refactored & improved by Matthias Stevens (InThePocket.mobi).
|
||||
*
|
||||
*
|
||||
* **Known issues:**
|
||||
* * The indentation on nested `<ul>`s isn't quite right (TODO fix this)
|
||||
* * the `start` attribute of `<ol>` is not supported. Doing so is tricky because
|
||||
* [Html.TagHandler.handleTag] does not expose tag attributes.
|
||||
* The only way to do it would be to use reflection to access the attribute information kept by the XMLReader
|
||||
* (see: http://stackoverflow.com/a/24534689/1084488).
|
||||
*
|
||||
* https://bitbucket.org/Kuitsi/android-textview-html-list/src/master/app/src/main/java/fi/iki/kuitsi/listtest/MyTagHandler.java
|
||||
*
|
||||
*/
|
||||
class ExtraTagHandler : TagHandler {
|
||||
/**
|
||||
* Keeps track of lists (ol, ul). On bottom of Stack is the outermost list
|
||||
* and on top of Stack is the most nested list
|
||||
*/
|
||||
private val lists = Stack<ListTag>()
|
||||
|
||||
/**
|
||||
* @see android.text.Html.TagHandler.handleTag
|
||||
*/
|
||||
override fun handleTag(opening: Boolean, tag: String, output: Editable, xmlReader: XMLReader) {
|
||||
if (UL_TAG.equals(tag, ignoreCase = true)) {
|
||||
if (opening) { // handle <ul>
|
||||
lists.push(Ul())
|
||||
} else { // handle </ul>
|
||||
lists.pop()
|
||||
}
|
||||
} else if (OL_TAG.equals(tag, ignoreCase = true)) {
|
||||
if (opening) { // handle <ol>
|
||||
lists.push(Ol()) // use default start index of 1
|
||||
} else { // handle </ol>
|
||||
lists.pop()
|
||||
}
|
||||
} else if (LI_TAG.equals(tag, ignoreCase = true)) {
|
||||
if (opening) { // handle <li>
|
||||
lists.peek().openItem(output)
|
||||
} else { // handle </li>
|
||||
lists.peek().closeItem(output, lists.size)
|
||||
}
|
||||
} else {
|
||||
Log.d("TagHandler", "Found an unsupported tag $tag")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract super class for [Ul] and [Ol].
|
||||
*/
|
||||
private abstract class ListTag {
|
||||
/**
|
||||
* Opens a new list item.
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
open fun openItem(text: Editable) {
|
||||
if (text.length > 0 && text[text.length - 1] != '\n') {
|
||||
text.append("\n")
|
||||
}
|
||||
val len = text.length
|
||||
text.setSpan(this, len, len, Spanned.SPAN_MARK_MARK)
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes a list item.
|
||||
*
|
||||
* @param text
|
||||
* @param indentation
|
||||
*/
|
||||
fun closeItem(text: Editable, indentation: Int) {
|
||||
if (text.length > 0 && text[text.length - 1] != '\n') {
|
||||
text.append("\n")
|
||||
}
|
||||
val replaces = getReplaces(text, indentation)
|
||||
val len = text.length
|
||||
val listTag = getLast(text)
|
||||
val where = text.getSpanStart(listTag)
|
||||
text.removeSpan(listTag)
|
||||
if (where != len) {
|
||||
for (replace in replaces) {
|
||||
text.setSpan(replace, where, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun getReplaces(text: Editable?, indentation: Int): Array<Any>
|
||||
|
||||
/**
|
||||
* Note: This knows that the last returned object from getSpans() will be the most recently added.
|
||||
*
|
||||
* @see Html
|
||||
*/
|
||||
private fun getLast(text: Spanned): ListTag? {
|
||||
val listTags = text.getSpans(0, text.length, ListTag::class.java)
|
||||
return if (listTags.size == 0) {
|
||||
null
|
||||
} else listTags[listTags.size - 1]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing the unordered list (`<ul>`) HTML tag.
|
||||
*/
|
||||
private class Ul : ListTag() {
|
||||
override fun getReplaces(text: Editable?, indentation: Int): Array<Any> {
|
||||
// Nested BulletSpans increases distance between BULLET_SPAN and text, so we must prevent it.
|
||||
var bulletMargin = INDENT_PX
|
||||
if (indentation > 1) {
|
||||
bulletMargin = INDENT_PX - BULLET_SPAN.getLeadingMargin(true)
|
||||
if (indentation > 2) {
|
||||
// This get's more complicated when we add a LeadingMarginSpan into the same line:
|
||||
// we have also counter it's effect to BulletSpan
|
||||
bulletMargin -= (indentation - 2) * LIST_ITEM_INDENT_PX
|
||||
}
|
||||
}
|
||||
return arrayOf(
|
||||
LeadingMarginSpan.Standard(LIST_ITEM_INDENT_PX * (indentation - 1)),
|
||||
BulletSpan(bulletMargin)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing the ordered list (`<ol>`) HTML tag.
|
||||
*/
|
||||
private class Ol
|
||||
/**
|
||||
* Creates a new `<ul>` with start index of 1.
|
||||
*/ @JvmOverloads constructor(private var nextIdx: Int = 1) : ListTag() {
|
||||
override fun openItem(text: Editable) {
|
||||
super.openItem(text)
|
||||
text.append(Integer.toString(nextIdx++)).append(". ")
|
||||
}
|
||||
|
||||
override fun getReplaces(text: Editable?, indentation: Int): Array<Any> {
|
||||
var numberMargin = LIST_ITEM_INDENT_PX * (indentation - 1)
|
||||
if (indentation > 2) {
|
||||
// Same as in ordered lists: counter the effect of nested Spans
|
||||
numberMargin -= (indentation - 2) * LIST_ITEM_INDENT_PX
|
||||
}
|
||||
return arrayOf(LeadingMarginSpan.Standard(numberMargin))
|
||||
}
|
||||
/**
|
||||
* Creates a new `<ul>` with given start index.
|
||||
*
|
||||
* @param nextIdx
|
||||
*/
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val OL_TAG = "hol"
|
||||
private const val UL_TAG = "hul"
|
||||
private const val LI_TAG = "hli"
|
||||
|
||||
/**
|
||||
* List indentation in pixels. Nested lists use multiple of this.
|
||||
*/
|
||||
private const val INDENT_PX = 10
|
||||
private const val LIST_ITEM_INDENT_PX = INDENT_PX * 2
|
||||
private val BULLET_SPAN = BulletSpan(INDENT_PX)
|
||||
}
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
/**
|
||||
* 首页补充游戏库辅助类
|
||||
*/
|
||||
object GameRepositoryHelper {
|
||||
|
||||
private const val KEY_GAME_REPOSITORY = "game_repository"
|
||||
|
||||
var gameCollectionList: List<SubjectEntity> = arrayListOf()
|
||||
|
||||
init {
|
||||
loadSavedRepository()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取游戏补充库
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getGameRepository(context: Context) {
|
||||
|
||||
RetrofitManager.getInstance(context)
|
||||
.api
|
||||
.reserveColumns
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Response<List<SubjectEntity>>() {
|
||||
override fun onResponse(response: List<SubjectEntity>?) {
|
||||
super.onResponse(response)
|
||||
|
||||
updateGameRepository(response)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新内存中的游戏库(即从 SP 中再读一次)
|
||||
*/
|
||||
@JvmStatic
|
||||
fun refreshGameRepository() = loadSavedRepository()
|
||||
|
||||
private fun loadSavedRepository() {
|
||||
gameCollectionList = SPUtils.getString(KEY_GAME_REPOSITORY).toObject() ?: arrayListOf()
|
||||
}
|
||||
|
||||
fun updateGameRepository(subjects: List<SubjectEntity>?) {
|
||||
|
||||
if (subjects == null) return
|
||||
|
||||
SPUtils.setString(KEY_GAME_REPOSITORY, subjects.toJson())
|
||||
|
||||
gameCollectionList = subjects
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 从补充游戏库相应的专题中取出一个与其它游戏都不相同的游戏,为空时即为游戏用完或不存在该相应专题
|
||||
* @param collectionId 补充游戏库相应专题 ID
|
||||
* @param gameIdList 该专题里已经包含的游戏 ID 列表
|
||||
*/
|
||||
fun getOneUniqueGame(collectionId: String?, gameIdList: HashSet<String>): GameEntity? {
|
||||
collectionId?.let {
|
||||
val collection = gameCollectionList.find { it.id == collectionId }
|
||||
collection?.let {
|
||||
val game = collection.data?.find { game -> isThisGameUnique(game, gameIdList) }
|
||||
game?.let {
|
||||
collection.data?.remove(game)
|
||||
// 产品说要记录补充专题的曝光数,所以这个游戏附带了所在专题的名字
|
||||
game.subjectName = collection.name
|
||||
return game
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun isThisGameUnique(game: GameEntity, gameIdList: HashSet<String>): Boolean {
|
||||
// 若该补充游戏已经存在关联关系,判定为非唯一
|
||||
for (relatedId in game.relatedGameIds!!) {
|
||||
gameIdList.contains(relatedId)
|
||||
return false
|
||||
}
|
||||
for (apk in game.getApk()) {
|
||||
// 检查本地是否已安装该游戏,已过滤那部分框架服务的包名
|
||||
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return !gameIdList.contains(game.id) && !TextUtils.isEmpty(game.id)
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,194 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
/**
|
||||
* 首页补充游戏库辅助类
|
||||
*/
|
||||
object GameSubstituteRepositoryHelper {
|
||||
|
||||
private const val KEY_GAME_REPOSITORY = "game_substitute_repository"
|
||||
|
||||
private var mSubstitutableGameIdSet = hashSetOf<String>()
|
||||
private var mApi = RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
private val mSensitiveApi = RetrofitManager.getInstance(HaloApp.getInstance().application).sensitiveApi
|
||||
private var mApplicationContext = HaloApp.getInstance().application
|
||||
|
||||
var gameCollectionList: List<SubjectEntity> = arrayListOf()
|
||||
|
||||
init {
|
||||
loadSavedRepository()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取游戏补充库
|
||||
*/
|
||||
@JvmStatic
|
||||
fun updateGameSubstituteRepository() {
|
||||
mSensitiveApi.reserveColumns
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Response<List<SubjectEntity>>() {
|
||||
override fun onResponse(response: List<SubjectEntity>?) {
|
||||
super.onResponse(response)
|
||||
|
||||
updateGameRepository(response)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@SuppressLint("CheckResult")
|
||||
fun updateSubstitutableGames() {
|
||||
mApplicationContext.doOnMainProcessOnly {
|
||||
val single = if (UserManager.getInstance().isLoggedIn) {
|
||||
mApi.getIdListOfPlayedGames(UserManager.getInstance().userId, Utils.getTime(mApplicationContext))
|
||||
} else {
|
||||
mApi.getIdListOfDownloadedGames(HaloApp.getInstance().gid, Utils.getTime(mApplicationContext))
|
||||
}
|
||||
single.subscribeOn(Schedulers.io()).subscribe(object : BiResponse<List<String>>() {
|
||||
override fun onSuccess(data: List<String>) {
|
||||
mSubstitutableGameIdSet = data.toHashSet()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新内存中的游戏库(即从 SP 中再读一次)
|
||||
*/
|
||||
@JvmStatic
|
||||
fun refreshRepositoryFromLocal() = loadSavedRepository()
|
||||
|
||||
private fun loadSavedRepository() {
|
||||
gameCollectionList = SPUtils.getString(KEY_GAME_REPOSITORY).toObject() ?: arrayListOf()
|
||||
}
|
||||
|
||||
private fun updateGameRepository(subjects: List<SubjectEntity>?) {
|
||||
if (subjects == null) return
|
||||
|
||||
SPUtils.setString(KEY_GAME_REPOSITORY, subjects.toJson())
|
||||
|
||||
gameCollectionList = subjects
|
||||
}
|
||||
|
||||
/**
|
||||
* 从补充游戏库相应的专题中取出一个与其它游戏都不相同的游戏,为空时即为游戏用完或不存在该相应专题
|
||||
* @param collectionId 补充游戏库相应专题 ID
|
||||
* @param gameIdList 该专题里已经包含的游戏 ID 列表
|
||||
*/
|
||||
private fun getOneUniqueGame(collectionId: String?, gameIdList: HashSet<String>): GameEntity? {
|
||||
collectionId?.let {
|
||||
val collection = gameCollectionList.find { it.id == collectionId }
|
||||
collection?.let {
|
||||
val game = collection.data?.find { game -> isThisGameUnique(game, gameIdList) }
|
||||
game?.let {
|
||||
collection.data?.remove(game)
|
||||
// 产品说要记录补充专题的曝光数,所以这个游戏附带了所在专题的名字
|
||||
game.subjectName = collection.name
|
||||
return game
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换游戏,包括 已安装,历史下载,历史已安装等类型
|
||||
*/
|
||||
fun replaceGames(gameList: MutableList<GameEntity>,
|
||||
alreadyDisplayedGameIdSet: HashSet<String>,
|
||||
relatedCollectionId: String,
|
||||
shouldLogReplaceEvent: Boolean) {
|
||||
val positionOfTheGameToReplaceList = arrayListOf<Int>()
|
||||
|
||||
// 标记需要替换的已安装游戏
|
||||
for ((index, game) in gameList.withIndex()) {
|
||||
|
||||
// 是大图形式的游戏时不标记替换
|
||||
if ((index == 0 && !gameList[0].image.isNullOrEmpty())) {
|
||||
continue
|
||||
}
|
||||
|
||||
var isThisPositionLabeled = false
|
||||
|
||||
// 从 游戏ID 判断当前游戏是否需要被替换
|
||||
if (mSubstitutableGameIdSet.contains(game.id)) {
|
||||
positionOfTheGameToReplaceList.add(index)
|
||||
isThisPositionLabeled = true
|
||||
}
|
||||
|
||||
// 检查是否已安装该游戏里同包名的 APK
|
||||
if (!isThisPositionLabeled) {
|
||||
for (apk in game.getApk()) {
|
||||
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
|
||||
// 将该位置的游戏标记为需要替换
|
||||
positionOfTheGameToReplaceList.add(index)
|
||||
isThisPositionLabeled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 若此游戏所包含的 apk 没有已安装,那么再检查是否已安装有预设相关包名
|
||||
if (!isThisPositionLabeled) {
|
||||
var relatedPackageList = arrayListOf<String>()
|
||||
for (entity in PackageHelper.relatedPackageList) {
|
||||
if (entity.gameId == game.id) {
|
||||
relatedPackageList = ArrayList(entity.packages!!)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for (packageName in relatedPackageList) {
|
||||
if (PackageHelper.validLocalPackageNameSet.contains(packageName)) {
|
||||
positionOfTheGameToReplaceList.add(index)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (positionOfTheGameToReplaceList.isNotEmpty()) {
|
||||
if (shouldLogReplaceEvent) {
|
||||
MtaHelper.onEvent("首页_加载", "启动光环", "替换游戏")
|
||||
}
|
||||
for (position in positionOfTheGameToReplaceList) {
|
||||
val replacingGame = getOneUniqueGame(relatedCollectionId, alreadyDisplayedGameIdSet)
|
||||
replacingGame?.let {
|
||||
gameList[position] = replacingGame
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isThisGameUnique(game: GameEntity, gameIdList: HashSet<String>): Boolean {
|
||||
// 判断该游戏是否出现在已安装列表
|
||||
if (mSubstitutableGameIdSet.contains(game.id)) return false
|
||||
|
||||
// 该补充游戏是否已经存在关联关系
|
||||
for (relatedId in game.relatedGameIds!!) {
|
||||
if (gameIdList.contains(relatedId)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for (apk in game.getApk()) {
|
||||
// 检查本地是否已安装该游戏,已过滤那部分框架服务的包名
|
||||
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return !gameIdList.contains(game.id) && !TextUtils.isEmpty(game.id)
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,12 +5,12 @@ import android.graphics.Color;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.ApkLink;
|
||||
import com.gh.gamecenter.entity.GameCollectionEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
@ -19,8 +19,11 @@ import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
|
||||
public class GameUtils {
|
||||
|
||||
@ -53,13 +56,13 @@ public class GameUtils {
|
||||
String status = getDownloadBtnText(context, gameEntity, pluginLocation);
|
||||
downloadBtn.setTextColor(Color.WHITE);
|
||||
downloadBtn.setText(status);
|
||||
if ("插件化".equals(status)) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
} else if ("打开".equals(status) || "启动".equals(status)) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.detail_download_open_style);
|
||||
downloadBtn.setTextColor(ContextCompat.getColor(context, R.color.theme));
|
||||
if (context.getString(R.string.pluggable).equals(status)) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.download_button_pluggable_style);
|
||||
String pluginDesc = gameEntity.getPluginDesc();
|
||||
if (pluginDesc.length() > 3) pluginDesc = pluginDesc.substring(0, 3);
|
||||
downloadBtn.setText((pluginDesc + "化"));
|
||||
} else {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
downloadBtn.setBackgroundResource(R.drawable.download_button_normal_style);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +70,10 @@ public class GameUtils {
|
||||
* 获取下载按钮文案
|
||||
*/
|
||||
public static String getDownloadBtnText(Context context, GameEntity gameEntity, PluginLocation pluginLocation) {
|
||||
if (gameEntity.getApk().size() > 1) {
|
||||
return context.getString(R.string.expand);
|
||||
}
|
||||
|
||||
int doneCount = 0; // 下载完成数量
|
||||
int pluginCount = 0; // 可插件化数量
|
||||
int updateCount = 0; // 可更新数量
|
||||
@ -103,7 +110,7 @@ public class GameUtils {
|
||||
gh_id = PackageUtils.getMetaData(context, apkEntity.getPackageName(), "gh_id");
|
||||
if (gameEntity.getTag() != null && gameEntity.getTag().size() != 0
|
||||
&& !TextUtils.isEmpty(apkEntity.getGhVersion())
|
||||
&& !PackageUtils.isSignature(context, apkEntity.getPackageName())
|
||||
&& !PackageUtils.isSignedByGh(context, apkEntity.getPackageName())
|
||||
&& apkEntity.isShowPlugin(pluginLocation)) {
|
||||
pluginCount++;
|
||||
} else if (gh_id == null || gh_id.equals(gameEntity.getId())) {
|
||||
@ -118,18 +125,59 @@ public class GameUtils {
|
||||
} else if (updateCount != 0) {
|
||||
return context.getString(R.string.update);
|
||||
} else if (installCount != 0) {
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
return context.getString(R.string.launch);
|
||||
} else {
|
||||
return context.getString(R.string.open);
|
||||
}
|
||||
return context.getString(R.string.launch);
|
||||
} else if (gameEntity.getVersionNumber().contains("无版号") && Config.isGameDomeSwitchOpen()) {
|
||||
return context.getString(R.string.attempt);
|
||||
} else {
|
||||
return context.getString(R.string.download);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取GameUpdateEntity
|
||||
* 获取简单的下载按钮文案,只需要知道是否已下载,是否已安装
|
||||
*/
|
||||
public static String getSimpleDownloadBtnText(Context context, GameEntity gameEntity) {
|
||||
int doneCount = 0; // 下载完成数量
|
||||
int installCount = 0; // 已安装数量
|
||||
|
||||
DownloadEntity downloadEntity;
|
||||
Object gh_id;
|
||||
apkFor:
|
||||
for (ApkEntity apkEntity : gameEntity.getApk()) {
|
||||
// filter by packageName
|
||||
SettingsEntity settings = Config.getSettings();
|
||||
if (settings != null && gameEntity.getApk().size() > 1) {
|
||||
for (String pkgName : settings.getGameDownloadBlackList()) {
|
||||
if (pkgName.equals(apkEntity.getPackageName())) {
|
||||
continue apkFor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
downloadEntity = DownloadManager.getInstance(context).getDownloadEntityByUrl(apkEntity.getUrl());
|
||||
if (downloadEntity != null) {
|
||||
if (downloadEntity.getStatus().equals(DownloadStatus.done)) {
|
||||
doneCount++;
|
||||
}
|
||||
}
|
||||
if (PackagesManager.INSTANCE.isInstalled(apkEntity.getPackageName())) {
|
||||
gh_id = PackageUtils.getMetaData(context, apkEntity.getPackageName(), "gh_id");
|
||||
if (gh_id == null || gh_id.equals(gameEntity.getId())) {
|
||||
installCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (doneCount != 0) {
|
||||
return context.getString(R.string.install);
|
||||
} else if (installCount != 0) {
|
||||
return context.getString(R.string.launch);
|
||||
} else {
|
||||
return context.getString(R.string.download);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取GameUpdateEntity(插件化)
|
||||
*/
|
||||
public static GameUpdateEntity getGameUpdateEntity(GameEntity gameEntity, ApkEntity apkEntity) {
|
||||
GameUpdateEntity gameUpdateEntity = new GameUpdateEntity();
|
||||
@ -150,7 +198,50 @@ public class GameUtils {
|
||||
gameUpdateEntity.setPlugin(apkEntity.getPlugin());
|
||||
gameUpdateEntity.setDownload(gameEntity.getDownload());
|
||||
gameUpdateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
gameUpdateEntity.setPluginDesc(gameEntity.getPluginDesc());
|
||||
|
||||
GameCollectionEntity pluggableCollection = getPluggableCollectionFromGameEntity(gameEntity, apkEntity.getPackageName());
|
||||
if (pluggableCollection != null) {
|
||||
gameUpdateEntity.setPluggableCollection(pluggableCollection);
|
||||
}
|
||||
return gameUpdateEntity;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GameCollectionEntity getPluggableCollectionFromGameEntity(GameEntity gameEntity, String targetPkg) {
|
||||
// 添加插件化包所在的合集
|
||||
for (GameCollectionEntity collectionEntity : gameEntity.getCollection()) {
|
||||
if (collectionEntity.getPackages().contains(targetPkg)) {
|
||||
ArrayList<ApkEntity> saveApkEntity = new ArrayList<>();
|
||||
for (String pkg : collectionEntity.getPackages()) {
|
||||
for (ApkEntity apk : gameEntity.getApk()) {
|
||||
if (pkg.equals(apk.getPackageName())) {
|
||||
saveApkEntity.add(apk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<ApkLink> apkLinks = gameEntity.getApkLink();
|
||||
if (apkLinks != null) {
|
||||
for (ApkLink apkLink : apkLinks) {
|
||||
if (apkLink.getCollection().equals(collectionEntity.getId())) {
|
||||
ApkEntity element = new ApkEntity();
|
||||
element.setApkLink(apkLink);
|
||||
if (saveApkEntity.size() > apkLink.getSort()) {
|
||||
saveApkEntity.add(apkLink.getSort(), element);
|
||||
} else {
|
||||
saveApkEntity.add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectionEntity.setSaveApkEntity(saveApkEntity);
|
||||
return collectionEntity;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -10,6 +10,9 @@ import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.TagStyleEntity;
|
||||
|
||||
@ -21,8 +24,6 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
/**
|
||||
* @author 温冠超
|
||||
* @email 294299195@qq.com
|
||||
@ -32,21 +33,17 @@ import androidx.core.content.ContextCompat;
|
||||
*/
|
||||
public class GameViewUtils {
|
||||
|
||||
public static void setLabelList(Context context, LinearLayout labelLayout, List<String> tag, String tagType, List<TagStyleEntity> tagStyle) {
|
||||
public static void setLabelList(Context context, LinearLayout labelLayout, List<TagStyleEntity> tagStyle) {
|
||||
labelLayout.removeAllViews();
|
||||
if (tag == null || tag.isEmpty()) {
|
||||
labelLayout.addView(getGameTagView(context, "官方版", 0, tagType, null));
|
||||
if (tagStyle == null || tagStyle.isEmpty()) {
|
||||
// 没有数据的话默认不显示
|
||||
// TagStyleEntity tagEntity = new TagStyleEntity();
|
||||
// tagEntity.setName("官方版");
|
||||
// labelLayout.addView(getNewGameTagView(context, tagEntity, 0));
|
||||
} else {
|
||||
for (int i = 0, size = tag.size(); i < size; i++) {
|
||||
View view;
|
||||
if (i == size - 1) {
|
||||
view = getGameTagView(context, tag.get(i), 0, tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
|
||||
} else {
|
||||
view = getGameTagView(context, tag.get(i), DisplayUtils.dip2px(context, 8), tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
|
||||
}
|
||||
if (view != null) {
|
||||
labelLayout.addView(view);
|
||||
}
|
||||
for (int i = 0, size = tagStyle.size(); i < size; i++) {
|
||||
View view = getNewGameTagView(context, tagStyle.get(i), i == size - 1 ? 0 : DisplayUtils.dip2px(context, 8));
|
||||
labelLayout.addView(view);
|
||||
if (labelLayout.getChildCount() == 3) {
|
||||
break;
|
||||
}
|
||||
@ -76,6 +73,32 @@ public class GameViewUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// 新的游戏标签样式 version>=4.0.0
|
||||
private static TextView getNewGameTagView(Context context, TagStyleEntity tagEntity, int rightMargin) {
|
||||
// 参数不全,用旧样式实现
|
||||
if (TextUtils.isEmpty(tagEntity.getBackground())) {
|
||||
return getGameTagView(context, tagEntity.getName(), rightMargin, "type", tagEntity);
|
||||
}
|
||||
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
|
||||
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
lparams.rightMargin = rightMargin;
|
||||
TextView tag = new TextView(context);
|
||||
tag.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
|
||||
tag.setSingleLine(true);
|
||||
tag.setText(tagEntity.getName());
|
||||
tag.setLayoutParams(lparams);
|
||||
tag.setPadding(
|
||||
DisplayUtils.dip2px(context, 4),
|
||||
0,
|
||||
DisplayUtils.dip2px(context, 4),
|
||||
DisplayUtils.dip2px(context, 1));
|
||||
|
||||
tag.setTextColor(Color.parseColor("#" + tagEntity.getColor()));
|
||||
tag.setBackground(DrawableView.getServerDrawable(Color.parseColor("#" + tagEntity.getBackground())));
|
||||
return tag;
|
||||
}
|
||||
|
||||
private static TextView getGameTagView(Context context, String tagStr, int rightMargin, String tagType, TagStyleEntity tagEntity) {
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
|
||||
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
|
||||
@ -22,6 +22,12 @@ object GsonUtils {
|
||||
return gson.fromJson(json.toString(), type)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun <T> fromJsonList(json: String): List<T> {
|
||||
val type = object : TypeToken<List<T>>() {}.type
|
||||
return gson.fromJson(json, type)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun toJson(any: Any?): String {
|
||||
return gson.toJson(any)
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import com.contrarywind.adapter.WheelAdapter;
|
||||
|
||||
/**
|
||||
* 注意:选择后的数据其实是dates的position,需要在回调时对返回的date数据进行转换
|
||||
*
|
||||
* 例子请见:
|
||||
* {@link com.gh.gamecenter.servers.add.AddKaiFuActivity}
|
||||
*/
|
||||
public class HaloWheelViewAdapter implements WheelAdapter {
|
||||
private int[] dates;
|
||||
|
||||
|
||||
public HaloWheelViewAdapter(int[] dates) {
|
||||
this.dates = dates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int index) {
|
||||
return dates[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemsCount() {
|
||||
return dates.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
try {
|
||||
return (int) o;
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
app/src/main/java/com/gh/common/util/HomePluggableHelper.kt
Normal file
50
app/src/main/java/com/gh/common/util/HomePluggableHelper.kt
Normal file
@ -0,0 +1,50 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.HomePluggableFilterEntity
|
||||
import com.gh.gamecenter.room.AppDatabase
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
object HomePluggableHelper {
|
||||
|
||||
private val mHomePluggableFilterDao = AppDatabase.getInstance(HaloApp.getInstance().application).homePluggableFilterDao()
|
||||
|
||||
@JvmStatic
|
||||
fun setHomePluggableFilterData(gameEntity: GameEntity, isNever: Boolean) {
|
||||
val apkList = gameEntity.getApk()
|
||||
if (apkList.isNotEmpty()) {
|
||||
val apk = apkList.first()
|
||||
val tag = if (isNever) "never" else apk.version ?: ""
|
||||
mHomePluggableFilterDao.addData(HomePluggableFilterEntity(pkgName = apk.packageName, tag = tag, active = isNever))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showHomePluggable(gameEntity: GameEntity): Boolean {
|
||||
val apkList = gameEntity.getApk()
|
||||
if (apkList.isNotEmpty()) {
|
||||
val apk = apkList.first()
|
||||
val filterData = mHomePluggableFilterDao.getDataByPkgName(apk.packageName)
|
||||
if (filterData?.active == true) {
|
||||
val filterTag = filterData.tag
|
||||
return filterTag != "never" && apk.version != filterTag
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getPermanentInactivePluggablePackage() = mHomePluggableFilterDao.getDataByTag("never")
|
||||
|
||||
@JvmStatic
|
||||
fun activationFilterData() {
|
||||
val filterList = mHomePluggableFilterDao.getDataByActive(false)
|
||||
|
||||
if (filterList != null) {
|
||||
for (entity in filterList) {
|
||||
entity.active = true
|
||||
}
|
||||
mHomePluggableFilterDao.addData(filterList)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -32,4 +32,39 @@ public class HtmlUtils {
|
||||
|
||||
return htmlStr.trim(); //返回文本字符串
|
||||
}
|
||||
|
||||
/**
|
||||
* 去除html代码及文本
|
||||
*/
|
||||
public static String stripHtmlCode(String htmlStr) {
|
||||
if (TextUtils.isEmpty(htmlStr)) return "";
|
||||
|
||||
String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
|
||||
String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
|
||||
String regEx_html = "<[^>]+>[\\s\\S]*?<\\/[^>]+>"; //定义HTML标签的正则表达式
|
||||
String regEx_html_single = "<[^>]+>"; //定义HTML单标签的正则表达式
|
||||
String regEx_blank = "\\s+"; //定义空白字符的正则表达式
|
||||
|
||||
Pattern p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
|
||||
Matcher m_script = p_script.matcher(htmlStr);
|
||||
htmlStr = m_script.replaceAll(""); //过滤script标签
|
||||
|
||||
Pattern p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
|
||||
Matcher m_style = p_style.matcher(htmlStr);
|
||||
htmlStr = m_style.replaceAll(""); //过滤style标签
|
||||
|
||||
Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
|
||||
Matcher m_html = p_html.matcher(htmlStr);
|
||||
htmlStr = m_html.replaceAll(""); //过滤html标签
|
||||
|
||||
Pattern p_html_single = Pattern.compile(regEx_html_single, Pattern.CASE_INSENSITIVE);
|
||||
Matcher m_html_single = p_html_single.matcher(htmlStr);
|
||||
htmlStr = m_html_single.replaceAll(""); //过滤html单标签
|
||||
|
||||
Pattern p_blank = Pattern.compile(regEx_blank, Pattern.CASE_INSENSITIVE);
|
||||
Matcher m_blank = p_blank.matcher(htmlStr);
|
||||
htmlStr = m_blank.replaceAll(" ");//过滤空白字符
|
||||
|
||||
return htmlStr.trim(); //返回文本字符串
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,12 +16,14 @@ import com.facebook.drawee.controller.ControllerListener
|
||||
import com.facebook.drawee.drawable.ScalingUtils
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.facebook.imagepipeline.core.ImagePipeline
|
||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
||||
import com.facebook.imagepipeline.image.ImageInfo
|
||||
import com.facebook.imagepipeline.request.ImageRequest
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
|
||||
@ -236,7 +238,7 @@ object ImageUtils {
|
||||
fun display(view: SimpleDraweeView?, url: String?) {
|
||||
url?.let {
|
||||
// 图片是以 gif 结尾的就
|
||||
if (it.endsWith(".gif")) {
|
||||
if (it.endsWith(".gif") && view?.getTag(R.id.tag_show_gif) != false) {
|
||||
if (view?.tag == url) return@let
|
||||
|
||||
val controller = Fresco.newDraweeControllerBuilder()
|
||||
@ -323,6 +325,14 @@ object ImageUtils {
|
||||
draweeView.setImageURI("res:///" + res)
|
||||
}
|
||||
|
||||
//预加载图片
|
||||
@JvmStatic
|
||||
fun prefetchToDiskCache(url: String){
|
||||
val imagePipeline = Fresco.getImagePipeline()
|
||||
val imageRequest = ImageRequest.fromUri(url)
|
||||
imagePipeline.prefetchToDiskCache(imageRequest, HaloApp.getInstance().application)
|
||||
}
|
||||
|
||||
public interface OnImageloadListener {
|
||||
fun onLoadFinal(imageInfo: ImageInfo?)
|
||||
}
|
||||
|
||||
@ -67,8 +67,8 @@ public class InstallUtils {
|
||||
String installVersion = PackageUtils.getVersionByPackage(packageName);
|
||||
if (!TextUtils.isEmpty(installVersion) && downloadEntity != null &&
|
||||
installVersion.equals(downloadEntity.getVersionName())) {
|
||||
if (!downloadEntity.isPluggable() || PackageUtils.isSignature(context, packageName)) {
|
||||
EventBus.getDefault().post(new EBPackage("安装", packageName));
|
||||
if (!downloadEntity.isPluggable() || PackageUtils.isSignedByGh(context, packageName)) {
|
||||
EventBus.getDefault().post(new EBPackage("安装", packageName, installVersion));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,7 +85,7 @@ public class InstallUtils {
|
||||
keys.add(packageName);
|
||||
} else if (!list.contains(packageName)) {
|
||||
keys.add(packageName);
|
||||
EventBus.getDefault().post(new EBPackage("卸载", packageName));
|
||||
EventBus.getDefault().post(new EBPackage("卸载", packageName, ""));
|
||||
}
|
||||
}
|
||||
for (String key : keys) {
|
||||
|
||||
@ -11,8 +11,6 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.LibaoDetailAdapter;
|
||||
@ -37,6 +35,7 @@ import org.json.JSONObject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
@ -151,76 +150,76 @@ public class LibaoUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public static void setLiBaoBtnStatus(final TextView libaoBtn, String status, Context context) {
|
||||
public static void setLiBaoBtnStatusRound(final TextView libaoBtn, String status, Context context) {
|
||||
libaoBtn.setTextColor(Color.WHITE);
|
||||
if (TextUtils.isEmpty(status)) return;
|
||||
switch (status) {
|
||||
case "ling":
|
||||
libaoBtn.setText(R.string.libao_ling);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
case "tao":
|
||||
libaoBtn.setText(R.string.libao_tao);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
case "coming":
|
||||
libaoBtn.setText(R.string.libao_coming);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme));
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "used_up":
|
||||
libaoBtn.setText(R.string.libao_used_up);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme));
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "finish":
|
||||
libaoBtn.setText(R.string.libao_finish);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_gray);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_round_gray);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.button_gray));
|
||||
break;
|
||||
case "linged":
|
||||
libaoBtn.setText(R.string.libao_linged);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme));
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "taoed":
|
||||
libaoBtn.setText(R.string.libao_taoed);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme));
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "copy":
|
||||
libaoBtn.setText(R.string.libao_copy);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
case "repeatLing":
|
||||
libaoBtn.setText(R.string.libao_repeat_ling);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme));
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "repeatLinged":
|
||||
libaoBtn.setText(R.string.libao_repeat_ling);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
case "repeatTao":
|
||||
libaoBtn.setText(R.string.libao_repeat_tao);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme));
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "repeatTaoed":
|
||||
libaoBtn.setText(R.string.libao_repeat_tao);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
case "unshelve":
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_gray);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_round_gray);
|
||||
libaoBtn.setText(R.string.libao_unshelve);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.button_gray));
|
||||
break;
|
||||
case "check":
|
||||
libaoBtn.setText(R.string.libao_check);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
default:
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_gray);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_round_gray);
|
||||
libaoBtn.setText("异常");
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.button_gray));
|
||||
break;
|
||||
@ -230,7 +229,7 @@ public class LibaoUtils {
|
||||
public static void initLibaoBtn(final Context context, final TextView libaoBtn, final LibaoEntity libaoEntity,
|
||||
final boolean isInstallRequired, final LibaoDetailAdapter adapter, final String entrance) {
|
||||
String status = libaoEntity.getStatus();
|
||||
setLiBaoBtnStatus(libaoBtn, status, context);
|
||||
setLiBaoBtnStatusRound(libaoBtn, status, context);
|
||||
|
||||
libaoBtn.setOnClickListener(v -> {
|
||||
String btnStatus = libaoBtn.getText().toString();
|
||||
|
||||
@ -283,7 +283,7 @@ public class LogUtils {
|
||||
|
||||
uploadToReservation(object);
|
||||
}
|
||||
|
||||
|
||||
private static void uploadToCommunity(JSONObject object) {
|
||||
uploadToCommunity(object, false);
|
||||
}
|
||||
@ -419,4 +419,89 @@ public class LogUtils {
|
||||
}
|
||||
uploadVideoStreaming(object);
|
||||
}
|
||||
|
||||
private static void uploadShare(JSONObject object) {
|
||||
Meta meta = MetaUtil.INSTANCE.getMeta();
|
||||
JSONObject metaObject = new JSONObject();
|
||||
try {
|
||||
metaObject.put("android_id", meta.getAndroid_id());
|
||||
metaObject.put("android_sdk", meta.getAndroid_sdk());
|
||||
metaObject.put("android_version", meta.getAndroid_version());
|
||||
metaObject.put("appVersion", meta.getAppVersion());
|
||||
metaObject.put("channel", meta.getChannel());
|
||||
metaObject.put("gid", meta.getGid());
|
||||
metaObject.put("imei", meta.getImei());
|
||||
metaObject.put("mac", meta.getMac());
|
||||
metaObject.put("manufacturer", meta.getManufacturer());
|
||||
metaObject.put("model", meta.getModel());
|
||||
metaObject.put("network", meta.getNetwork());
|
||||
metaObject.put("os", meta.getOs());
|
||||
metaObject.put("userId", meta.getUserId());
|
||||
|
||||
object.put("event", "SHARE");
|
||||
object.put("meta", metaObject);
|
||||
object.put("timestamp", System.currentTimeMillis() / 1000);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->" + object.toString());
|
||||
}
|
||||
|
||||
LoghubUtils.log(object, "event", false);
|
||||
}
|
||||
|
||||
public static void uploadShareEnter(String entrance, String url, String title, String summary, String resourceId) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
try {
|
||||
object.put("action", "entrance_source");
|
||||
payloadObject.put("entrance", entrance);
|
||||
payloadObject.put("url", url);
|
||||
payloadObject.put("title", title);
|
||||
payloadObject.put("summary", summary);
|
||||
payloadObject.put("resource_id", resourceId);
|
||||
object.put("payload", payloadObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploadShare(object);
|
||||
}
|
||||
|
||||
public static void uploadShareType(String shareType, String entrance, String url, String title, String summary, String resourceId) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
try {
|
||||
object.put("action", "share_type");
|
||||
payloadObject.put("share_type", shareType);
|
||||
payloadObject.put("entrance", entrance);
|
||||
payloadObject.put("url", url);
|
||||
payloadObject.put("title", title);
|
||||
payloadObject.put("summary", summary);
|
||||
payloadObject.put("resource_id", resourceId);
|
||||
object.put("payload", payloadObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploadShare(object);
|
||||
}
|
||||
|
||||
public static void uploadShareResult(String shareType, String entrance, String shareResult, String url, String title, String summary, String resourceId) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
try {
|
||||
object.put("action", "share_result");
|
||||
payloadObject.put("share_type", shareType);
|
||||
payloadObject.put("entrance", entrance);
|
||||
payloadObject.put("share_result", shareResult);
|
||||
payloadObject.put("url", url);
|
||||
payloadObject.put("title", title);
|
||||
payloadObject.put("summary", summary);
|
||||
payloadObject.put("resource_id", resourceId);
|
||||
object.put("payload", payloadObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploadShare(object);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user