Compare commits
1110 Commits
v3.7.1
...
v4.0.0-bug
| Author | SHA1 | Date | |
|---|---|---|---|
| 0dcf86ce1c | |||
| 961d4ebb5c | |||
| 54b947504c | |||
| ee7f102d34 | |||
| 135b55f6f9 | |||
| 17782a500f | |||
| 64a64960ac | |||
| d4be850e68 | |||
| 414064699a | |||
| 99878606d5 | |||
| e1cfccfcc0 | |||
| 4c2a46875d | |||
| 6ce64892e4 | |||
| 92e1c55913 | |||
| b0a4aa66f6 | |||
| aad92e529e | |||
| 6e03e75110 | |||
| cc53a1f3d6 | |||
| 25cd086298 | |||
| b27ecab969 | |||
| db1c0d954f | |||
| 03d20aed61 | |||
| c2fb1a58db | |||
| 55998c3c4d | |||
| 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 | |||
| 3c4cc4ff7f | |||
| 150d640977 | |||
| a3599af9d1 | |||
| 1ac1196b20 | |||
| 6c5e863a5b | |||
| 15376a5e13 | |||
| eaf5b24044 | |||
| f05c6540f1 | |||
| 25dd3ca4df | |||
| 6281b4f510 | |||
| 2cbc0b0e17 | |||
| f18a0ef72c | |||
| 98fb4fc412 | |||
| 73c995c31f | |||
| 60dcafe0c1 | |||
| c118d7e4ad | |||
| babc55739b | |||
| df8790c6ff | |||
| 30ccdcd750 | |||
| 79d23bb203 | |||
| b2c5e6551b | |||
| ec49d7f20a | |||
| 5a35d13d70 | |||
| dcfa4fdaaf | |||
| 43324ca44e | |||
| 8e778e8172 | |||
| 928a98831e | |||
| 3dc678bc27 | |||
| d2b19a128d | |||
| cc75cb497d | |||
| 4840c5c604 | |||
| 347cfdb72d | |||
| 06ec87ba6d | |||
| 1206800a3d | |||
| d4763468c1 | |||
| 9c1a186a28 | |||
| bd9b914c18 | |||
| d40a57bcaa | |||
| 1892758288 | |||
| ca2e26756a | |||
| ed5696f4bd | |||
| cee34e7d76 | |||
| 54decbade3 | |||
| 11167670f8 | |||
| 37c7629cf0 | |||
| 947236f85d | |||
| eafa13ec76 | |||
| 7258812537 | |||
| e0a82f5050 | |||
| e0e7cbd2a3 | |||
| 554ec20493 | |||
| 31c3ed3bc5 | |||
| 466b690ac0 | |||
| 0420557f47 | |||
| c0edbf1a57 | |||
| 374610dbc0 | |||
| 080ac5f1d5 | |||
| 9dc967087d | |||
| 80a238253d | |||
| d7b7f11ebf | |||
| 9abb14e37f | |||
| 5fbb93cbee | |||
| 20b75ff046 | |||
| 73374017a5 | |||
| 73c3d5cd4d | |||
| 01a02a000f | |||
| 8998f1323f | |||
| bb77cf4624 | |||
| 772705ed0f | |||
| 6e2f568ad3 | |||
| df20c8235e | |||
| 4882cc5203 | |||
| 4fa6a41681 | |||
| f77e9d4949 | |||
| 1bc167fe7b | |||
| 98213ad3ee | |||
| 0b101d693d | |||
| 8655822d88 | |||
| 386923d16e | |||
| 013536b147 | |||
| 880eef90fb | |||
| 61e3784991 | |||
| 0664d92e62 | |||
| aab99b0c29 | |||
| 2e6ca9c524 | |||
| 0a402e4e92 | |||
| 7e75cd7859 | |||
| e3522d4160 | |||
| c9d0b813b6 | |||
| 3a7e28fac2 | |||
| 9aca24c02b | |||
| 9c818e1470 | |||
| 614ed0e7e2 | |||
| 55b1d43e73 | |||
| 25526f3666 | |||
| 773f2e798d | |||
| 58b5ec4eb9 | |||
| 007cef39a7 | |||
| ba1a702ea1 | |||
| 56d8b58f72 | |||
| f53c8377e6 | |||
| cfb1d86e8e | |||
| 8f0caa0949 | |||
| 8ef13cb4ff | |||
| e6d4f60d4f | |||
| e67f85c084 | |||
| 5318693650 | |||
| 3bf242b145 | |||
| 0ba82a334e | |||
| 0a385bb720 | |||
| 7658fd2a4f | |||
| e40e655bfa | |||
| cfa000bf88 | |||
| 12c35cebc4 | |||
| 92089e60ce | |||
| 141a6df8ab | |||
| 7719e9763d | |||
| 8d3307986d | |||
| d0b7ec39a7 | |||
| cfd198b4ab | |||
| a557c12c6d | |||
| 6b777d4ec8 | |||
| 882dd95190 | |||
| 7764bd29c8 | |||
| 08730f1ce9 | |||
| f9c15d3427 | |||
| 8e8668036e | |||
| cc65eed48d | |||
| 29f4e547a1 | |||
| 419003ae23 | |||
| 0519872d81 | |||
| e9b52bb70b | |||
| 681ea201c3 | |||
| a5466bb6ad | |||
| 3a3998ae84 | |||
| 7e27502430 | |||
| 8956885f1c | |||
| caeb0a1362 | |||
| cc094889b8 | |||
| 839386c5f4 | |||
| 6c5de65278 | |||
| 3aadac942c | |||
| dca9b49d75 | |||
| 8e764dc22a | |||
| 383cf4941e | |||
| 05510a8588 | |||
| eb611a9ff1 | |||
| 15aa3713e6 | |||
| 7d11713c49 | |||
| 66ff610078 | |||
| f351761d9e | |||
| 6bb5e18253 | |||
| c44e8cffcc | |||
| 39d4c35504 | |||
| d42b57f385 | |||
| 2142a1676e | |||
| b0fa41bded | |||
| 28f552ca19 | |||
| da0b256054 | |||
| 8b477c357a | |||
| 650075488d | |||
| 8cff41defa | |||
| 6519eca511 | |||
| 85d8463972 | |||
| c762a7c755 | |||
| 142859fd39 | |||
| d7f84ff3c8 | |||
| 6c4545e364 | |||
| a3d9f12414 | |||
| 412d2ff9dc | |||
| 65f8440637 | |||
| f06359f5c3 | |||
| 433088116e | |||
| c93e55f306 | |||
| e613066ed3 | |||
| 9aabfde5b0 | |||
| 9f4c9431b9 | |||
| 74f64d9782 | |||
| d79b3f10e8 | |||
| b29d32c8f2 | |||
| b8ec93c6a1 | |||
| dad3c9aee7 | |||
| 833e0406f0 | |||
| 3d6b556dfd | |||
| ad0a5525f0 | |||
| a012c3e3de | |||
| 6c2d489940 | |||
| 0ea56b01eb | |||
| f65c226657 | |||
| 006b82381b | |||
| 059414b9f8 | |||
| 93c1105346 | |||
| 7ca92e8b7f | |||
| eeb7415086 | |||
| 9a288e8870 | |||
| 351fefd57b | |||
| 4915cdc3ba | |||
| 9d044a4001 | |||
| 8e465c17dd | |||
| fa73ac790c | |||
| 899f442f14 | |||
| 698af5d584 | |||
| 66dea77546 | |||
| eed2eed992 | |||
| 913c0027a6 | |||
| a7884325c8 | |||
| a7caa063ef | |||
| ee99895cba | |||
| cf7a14e80a | |||
| 07a64d118a | |||
| 72329d0222 | |||
| 16e85e9222 | |||
| dd11883eab | |||
| be70ce8551 | |||
| d428c46957 | |||
| 516b956269 | |||
| 8bb90f4d4c | |||
| 2f9e9fe976 | |||
| bf2271ac06 | |||
| f279564e02 | |||
| 386eafa0bc | |||
| 619b5a3cc3 | |||
| d0391c779d | |||
| fc9d3f2e91 | |||
| 42c7123d2d | |||
| 8e66f80360 | |||
| b80fab06ad | |||
| 943c359c22 | |||
| 8631045874 | |||
| 5991a90353 | |||
| 8534455344 | |||
| 1a21fceeb7 | |||
| 274739c885 | |||
| 5134fa19be | |||
| 7342e94bdc | |||
| 28bf579518 | |||
| 9e490ef349 | |||
| 548206792e | |||
| c87d7f9c28 | |||
| cfe1584fc3 | |||
| 137a95f5ab | |||
| 6ab8b24353 | |||
| 1515cc1ddd | |||
| abfd4834ef | |||
| 03032a0dbd | |||
| 75545a5929 | |||
| 1425a95bc8 | |||
| 23674a1c55 | |||
| caf0a8d5f5 | |||
| b11928528c | |||
| cf9bd70c6c | |||
| c6ab68e9b4 | |||
| 899da43682 | |||
| 1825f713b3 | |||
| 760bc9b63c | |||
| 4974c105bf | |||
| 9c910ce6de | |||
| fcd1c2d418 | |||
| 5c0c227c3b | |||
| a69669a7ca | |||
| 166e2e341a | |||
| 8cb689cc99 | |||
| 1dd5c5fd40 | |||
| 92719c538e | |||
| 3448dfddef | |||
| b190b31afa | |||
| 083a62ed9d | |||
| 5f0bfd1184 | |||
| 15bb7d654c | |||
| f42278b91f | |||
| aa23d515c6 | |||
| b3417749ed | |||
| 4c33977568 | |||
| 1ecd83b6af | |||
| b202302a7e | |||
| 7450edd177 | |||
| 4c7ab844e8 | |||
| fd6581671d | |||
| 71cc0962d3 | |||
| 9c70d802b5 | |||
| ed6bec0cfc | |||
| 36834cfec7 | |||
| 7dfaf45dc2 | |||
| 5efddb05b3 | |||
| f46122787c | |||
| 1b8cde1c91 | |||
| 1694603cd0 | |||
| 4243f37126 | |||
| 63e0b9887c | |||
| 201efd9628 | |||
| c7c29b7ca8 | |||
| 0b3fd3a123 | |||
| 99e988a0d9 | |||
| eaa3b81e31 | |||
| dbbf9a846e | |||
| af8b336434 | |||
| ce84c0f9c9 | |||
| 0f8d9cd5d3 | |||
| cb70e12632 | |||
| a5ad403614 | |||
| e674a8313a | |||
| 1cef4bb53d | |||
| 3851aeb790 | |||
| 7680e2e125 | |||
| f674aa4a79 | |||
| be1533a5df | |||
| eca3bdd4e5 | |||
| c885579516 | |||
| 341d849e29 | |||
| 2bb5c79c38 | |||
| fa26e1a17b | |||
| 8ed76089eb | |||
| 678418da0b | |||
| 1c11fc4469 | |||
| 78f277fd6d | |||
| 5520fd7122 | |||
| cb6ce2e14f | |||
| 80933e82eb | |||
| e32dce2ef9 | |||
| e252a9ebf8 | |||
| 08936a22c8 | |||
| 3fea57d05f | |||
| 52ae5fc451 | |||
| 045dea265d | |||
| 501282f243 | |||
| 998cf70723 | |||
| 1a10fcac71 | |||
| ee5862eddd | |||
| c1527ec37e | |||
| eb112b358e | |||
| b860ab912a | |||
| b14ee68882 | |||
| 44065fcb06 | |||
| ec5305b76f | |||
| ddfb651d6a | |||
| 8a828a3250 | |||
| 31f5795e27 | |||
| dbde817b59 | |||
| 83e251492d | |||
| 5fa22c7f5d | |||
| b4ad18c806 | |||
| 61eb35cf31 | |||
| 07e54d5b5e | |||
| e0c27f721c | |||
| d2bf6bb211 | |||
| e2681494db | |||
| ac1d078681 | |||
| 624d9c1e2d | |||
| 892cc3cdde | |||
| fd7b9263bf | |||
| a9428ddb3b | |||
| 319f526e0f | |||
| 4755542933 | |||
| f221e20169 | |||
| a149666d3a | |||
| 0ff428b61a | |||
| cfedc72955 | |||
| 16de588c30 | |||
| 779d907397 | |||
| f91e2e41b6 | |||
| a04e4874f3 | |||
| d303b67e35 | |||
| 31c0c43d14 | |||
| fafb73d03c | |||
| e4ee4d9efe | |||
| 3a043b2704 | |||
| 8c9c7309a5 | |||
| 09330e9cbf | |||
| 08ad62dc70 | |||
| 464482a507 | |||
| d449b1266f | |||
| 6d0c4b18d6 | |||
| a83d1b5761 | |||
| 99d564278e | |||
| 482f45d43f | |||
| 21335a843a | |||
| d02a527b36 | |||
| 75883e11d8 |
@ -23,6 +23,10 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
// jumboMode = true
|
||||
javaMaxHeapSize "4g"
|
||||
@ -118,7 +122,6 @@ android {
|
||||
dimension "nonsense"
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "COMMENT_HOST", "\"${COMMENT_HOST}\""
|
||||
buildConfigField "String", "DATA_HOST", "\"${DATA_HOST}\""
|
||||
|
||||
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
|
||||
@ -136,7 +139,6 @@ android {
|
||||
|
||||
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}\""
|
||||
@ -183,6 +185,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 +195,18 @@ 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-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}"
|
||||
// kapt "androidx.databinding:databinding-compiler:${databinding}"
|
||||
|
||||
implementation "com.google.android.material:material:${material}"
|
||||
|
||||
@ -207,6 +214,7 @@ dependencies {
|
||||
|
||||
implementation "com.facebook.fresco:fresco:${fresco}"
|
||||
implementation "com.facebook.fresco:animated-gif:${fresco}"
|
||||
implementation "com.facebook.fresco:animated-drawable:${fresco}"
|
||||
|
||||
implementation "com.squareup.okhttp3:okhttp:${okHttp}"
|
||||
|
||||
@ -240,13 +248,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}"
|
||||
@ -259,39 +267,48 @@ dependencies {
|
||||
implementation "com.squareup.picasso:picasso:${picasso}"
|
||||
|
||||
// for video streaming
|
||||
implementation "com.shuyu:gsyVideoPlayer-java:$gsyVideo"
|
||||
implementation "com.shuyu:gsyVideoPlayer-armv7a:$gsyVideo"
|
||||
implementation "com.shuyu:gsyVideoPlayer-x86:$gsyVideo"
|
||||
implementation ("com.shuyu:gsyVideoPlayer-java:$gsyVideo",{
|
||||
exclude module: "gsyvideoplayer-androidvideocache"
|
||||
})
|
||||
implementation "com.shuyu:GSYVideoPlayer-exo2:$gsyVideo"
|
||||
|
||||
implementation "com.github.wendux:DSBridge-Android:$dsBridge"
|
||||
|
||||
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"
|
||||
|
||||
implementation("com.github.piasy:BigImageViewer:$bigImageViewer", {
|
||||
exclude group: 'com.squareup.okhttp3'
|
||||
})
|
||||
|
||||
debugImplementation "com.github.markzhai:blockcanary-android:$blockcanary"
|
||||
releaseImplementation "com.github.markzhai:blockcanary-no-op:$blockcanary"
|
||||
|
||||
implementation project(':libraries:LGLibrary')
|
||||
implementation project(':libraries:MTA')
|
||||
implementation project(':libraries:QQShare')
|
||||
implementation project(':libraries:TalkingData')
|
||||
implementation project(':libraries:UmengPush')
|
||||
// implementation project(':libraries:WechatShare')
|
||||
implementation project(':libraries:LogHub')
|
||||
implementation project(':libraries:im')
|
||||
implementation project(':libraries:Matisse')
|
||||
implementation project(path: ':libraries:gsyVideoPlayer-proxy_cache')
|
||||
}
|
||||
File propFile = file('sign.properties')
|
||||
if (propFile.exists()) {
|
||||
|
||||
Binary file not shown.
@ -30,6 +30,8 @@ public class Injection {
|
||||
// init stetho
|
||||
Stetho.initializeWithDefaults(application);
|
||||
|
||||
// 监控Bundle大小,预防溢出(需要调试的时候再开启吧!)
|
||||
// TooLargeTool.startLogging(application);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -28,6 +28,10 @@
|
||||
<!-- 修改系统设置的权限 -->
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.PACKAGE_USAGE_STATS"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
|
||||
<!-- bugly with tinker -->
|
||||
<uses-permission android:name="android.permission.READ_LOGS" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
@ -37,7 +41,10 @@
|
||||
com.shuyu.gsyvideoplayer.armv7a,
|
||||
com.shuyu.gsyvideoplayer.x86,
|
||||
com.shuyu.gsy.base,
|
||||
shuyu.com.androidvideocache" />
|
||||
com.google.android.exoplayer2,
|
||||
tv.danmaku.ijk.media.exo2,
|
||||
shuyu.com.androidvideocache,
|
||||
pl.droidsonroids.gif" />
|
||||
|
||||
<!-- 去掉 SDK 一些流氓权限 -->
|
||||
<uses-permission
|
||||
@ -78,6 +85,7 @@
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.MainActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppCompatTheme.APP"
|
||||
@ -107,6 +115,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" />
|
||||
@ -190,10 +202,6 @@
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SuggestSelectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SuggestionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -448,6 +456,19 @@
|
||||
android:name="com.gh.gamecenter.game.upload.GameSubmissionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.halo.assistant.fragment.user.UserPortraitCropImageActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.HelpAndFeedbackActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.help.HelpDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.comment.CommentActivity"
|
||||
android:screenOrientation="portrait"
|
||||
@ -456,8 +477,20 @@
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.detail.VideoDetailActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar" />
|
||||
<activity
|
||||
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
|
||||
|
||||
@ -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/click_guide.json
Normal file
1
app/src/main/assets/lottie/click_guide.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.5.9","fr":60,"ip":0,"op":90,"w":1080,"h":202,"nm":"click","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"椭圆形","sr":1,"ks":{"o":{"a":0,"k":20,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204,1455,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,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":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"椭圆形","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":63,"s":[10]},{"t":70,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204,1455,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":39,"s":[100,100,100]},{"t":49,"s":[110,110,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[36,36],"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":0,"op":120,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"圆环","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.531],"y":[0]},"t":28,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":38,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.526],"y":[0]},"t":48,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.446],"y":[0]},"t":63,"s":[50]},{"t":82,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[125.951,79.658,0],"ix":2},"a":{"a":0,"k":[205.951,1458.658,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.601,0.601,0.333],"y":[0,0,0]},"t":28,"s":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.528,0.528,0.333],"y":[0,0,0]},"t":38,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.526,0.526,0.333],"y":[0,0,0]},"t":48,"s":[120,120,100]},{"t":63,"s":[100,100,100]}],"ix":6}},"ao":0,"w":1080,"h":1920,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"点击手","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.596],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.515],"y":[0]},"t":63,"s":[100]},{"t":83,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.507],"y":[0]},"t":10,"s":[6]},{"t":30,"s":[2]}],"ix":10},"p":{"a":0,"k":[178.982,123.325,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.489,0.489,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"t":30,"s":[90,90,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":120,"st":0,"bm":0}],"markers":[]}
|
||||
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
1
app/src/main/assets/lottie/slide_guide.json
Normal file
1
app/src/main/assets/lottie/slide_guide.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.5.9","fr":60,"ip":0,"op":120,"w":1080,"h":586,"nm":"上滑","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"手","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.642],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.558],"y":[0]},"t":60,"s":[100]},{"t":71,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.479,"y":0},"t":3,"s":[611,475,0],"to":[0,-62.75,0],"ti":[0,62.75,0]},{"t":40,"s":[611,98.5,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[90,90,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-7.78,-12.06],[5.68,0.39],[-6.42,-2.45],[-6.32,-0.97],[-5.95,13.55],[4.87,7.91],[4.94,6.69],[1.26,-5.37],[5.25,-1.25],[1.5,-0.3],[3.4,-0.77],[1.4,1.68],[6.15,7.98],[-1.73,-6.64]],"o":[[1.62,2.49],[-5.68,-0.39],[9.37,3.63],[6.31,0.98],[2.39,-7.74],[-4.87,-7.92],[-2.45,-3.05],[-1.05,4.57],[-4.99,1.39],[-0.83,0.13],[-5.63,1.63],[-4.71,-5.72],[-2.75,-3.31],[3.52,6.76]],"v":[[-7.86,14.26],[-15.64,12.52],[-17.99,22.89],[8.47,31.78],[33.98,17.29],[29.55,-1.59],[16.85,-20.15],[7.86,-17.83],[1.56,-19.8],[-3.05,-14.02],[-8.33,-16.94],[-12.44,-11.045],[-26.761,-30.19],[-34.75,-25.78]],"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":"路径","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"矩形","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.715],"y":[0]},"t":57,"s":[100]},{"t":67,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[525,228.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.491,"y":0},"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[24.328,180.5],[-22,180.5],[-22,204.5],[24.328,204.5]],"c":true}]},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[24.328,-207.5],[-22,-207.5],[-22,204.5],[24.328,204.5]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"蒙版 1"}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[6,137],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,1,1,1,1,1,1,1,0,1,0.5,0.5,1,0],"ix":9}},"s":{"a":0,"k":[0,-68.5],"ix":5},"e":{"a":0,"k":[0,68.5],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-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},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":33,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":3,"op":123,"st":3,"bm":0}],"markers":[]}
|
||||
1
app/src/main/assets/lottie/tab_game.json
Normal file
1
app/src/main/assets/lottie/tab_game.json
Normal file
File diff suppressed because one or more lines are too long
1
app/src/main/assets/lottie/tab_home.json
Normal file
1
app/src/main/assets/lottie/tab_home.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.5.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"tab_index","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"椭圆形备份","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.596],"y":[0]},"t":0,"s":[0]},{"t":6,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,40.493,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.167,0.167,0.167],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.54,0.54,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.555,0.555,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.552,0.552,0.333],"y":[0,0,0]},"t":13,"s":[90,90,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[5,5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.635],"y":[0]},"t":0,"s":[0]},{"t":8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","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":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-0.5,"op":59.5,"st":-0.5,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"路径备份","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,32.993,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.508,0.508,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.488,0.488,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.502,0.502,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.534,0.534,0.333],"y":[0,0,0]},"t":13,"s":[95,95,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.24,-1.21],[-1.93,-1.89],[-0.24,-0.57],[0,-0.06],[0,-2.63],[1.76,0],[0,0],[0,1.72],[0,2.63],[-0.24,0.61],[-0.03,0.02],[-1.93,1.89]],"o":[[1.92,1.89],[0.02,0.02],[0.24,0.57],[0,2.63],[0,1.72],[0,0],[-1.76,0],[0,-2.62],[0,-0.07],[0.25,-0.61],[1.92,-1.89],[1.24,-1.21]],"v":[[2.26,-9.09],[8.03,-3.42],[8.76,-2.38],[9,-1.02],[9,6.88],[5.82,10],[-5.82,10],[-9,6.88],[-9,-0.99],[-8.71,-2.38],[-8.01,-3.43],[-2.23,-9.09]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.266,0.638,1,0.5,0.242,0.595,1,1,0.217,0.552,1],"ix":9}},"s":{"a":0,"k":[-4.902,-4.663],"ix":5},"e":{"a":0,"k":[8.159,8.646],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-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":0,"op":60,"st":0,"bm":0}],"markers":[]}
|
||||
1
app/src/main/assets/lottie/tab_video.json
Normal file
1
app/src/main/assets/lottie/tab_video.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.5.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"tab_video","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 1","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.771],"y":[0]},"t":0,"s":[0]},{"t":5,"s":[100]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-3.742,6.835,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[30.937,31.042,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sr","sy":2,"d":1,"pt":{"a":0,"k":3,"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":0,"k":0,"ix":5},"or":{"a":0,"k":29.286,"ix":7},"os":{"a":0,"k":75,"ix":9},"ix":1,"nm":"多边星形路径 1","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":13,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-20.75,-13.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[102.743,88.578],"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":"多边星形 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.657],"y":[0]},"t":0,"s":[0]},{"t":8,"s":[100]}],"ix":2},"o":{"a":0,"k":-115,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"路径 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33.004,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.508,0.508,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.488,0.488,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.502,0.502,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.534,0.534,0.333],"y":[0,0,0]},"t":13,"s":[95,95,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.16,0.38],[3.22,-0.55],[0.38,-2.16],[-0.55,-3.22],[-2.16,-0.38],[-1.63,0],[-1.61,0.27],[-0.38,2.16],[0.55,3.22]],"o":[[-0.38,-2.16],[-3.22,-0.55],[-2.16,0.38],[-0.55,3.22],[0.38,2.16],[1.61,0.27],[1.63,0],[2.16,-0.38],[0.55,-3.22],[0,0]],"v":[[9.09,-4.86],[4.86,-9.09],[-4.86,-9.09],[-9.09,-4.86],[-9.09,4.86],[-4.86,9.09],[0,9.5],[4.86,9.09],[9.09,4.86],[9.09,-4.86]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.266,0.638,1,0.5,0.242,0.595,1,1,0.217,0.552,1],"ix":9}},"s":{"a":0,"k":[-5.174,-4.43],"ix":5},"e":{"a":0,"k":[8.612,8.214],"ix":6},"t":1,"nm":"Gradient Fill 3","mn":"ADBE Vector Graphic - G-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":0,"op":60,"st":0,"bm":0}],"markers":[]}
|
||||
@ -63,6 +63,12 @@ RE.setHtml = function(contents) {
|
||||
RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
|
||||
}
|
||||
|
||||
// 后续初始化html代码,都用该方法
|
||||
RE.setHtmlByVideoStatus = function(contents) {
|
||||
RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
RE.getHtml = function() {
|
||||
return RE.editor.innerHTML;
|
||||
}
|
||||
@ -611,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);
|
||||
}
|
||||
BIN
app/src/main/assets/tab_community.gif
Normal file
BIN
app/src/main/assets/tab_community.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
BIN
app/src/main/assets/tab_mine.gif
Normal file
BIN
app/src/main/assets/tab_mine.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@ -1,6 +1,8 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@ -9,23 +11,17 @@ import android.text.TextUtils;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.common.util.StringUtils;
|
||||
import com.gh.common.util.TeaHelper;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.LoginActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.SuggestionActivity;
|
||||
import com.gh.gamecenter.eventbus.EBShowDialog;
|
||||
import com.gh.gamecenter.suggest.SuggestType;
|
||||
import com.lightgame.BaseAppCompatActivity;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -39,6 +35,8 @@ import org.json.JSONObject;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import butterknife.ButterKnife;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
|
||||
@ -47,14 +45,13 @@ import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
/**
|
||||
* 只提供基础的服务(EventBus/ButterKnife/Share/GlobalDialog/Permissions)
|
||||
* <p>
|
||||
* 需要通道工具栏的页面请继承{@link ToolBarActivity}
|
||||
* 需要工具栏的页面请继承{@link ToolBarActivity}
|
||||
*/
|
||||
|
||||
public abstract class BaseActivity extends BaseAppCompatActivity implements EasyPermissions.PermissionCallbacks {
|
||||
|
||||
// global dialog key
|
||||
public final static String DOWNLOAD_HIJACK = "hijack";
|
||||
public final static String DOWNLOAD_NOT_FOUND = "notfound";
|
||||
public final static String LOGIN_EXCEPTION = "loginException";
|
||||
public final static String PLUGGABLE = "plugin";
|
||||
|
||||
@ -98,8 +95,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;
|
||||
@ -112,7 +109,7 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
if (useEventBus()) EventBus.getDefault().unregister(this);
|
||||
mBaseHandler.removeCallbacksAndMessages(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
@ -138,9 +135,9 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
shareSummary,
|
||||
shareType);
|
||||
if (shareType == ShareUtils.ShareType.game || shareType == ShareUtils.ShareType.plugin) {
|
||||
DataUtils.onEvent(this, "内容分享", shareTitle + shareSummary);
|
||||
MtaHelper.onEvent("内容分享", "内容分享", shareTitle + shareSummary);
|
||||
} else {
|
||||
DataUtils.onEvent(this, "内容分享", shareTitle);
|
||||
MtaHelper.onEvent("内容分享", "内容分享", shareTitle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,7 +146,7 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
|
||||
&& this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
if (DOWNLOAD_HIJACK.equals(showDialog.getType())) {
|
||||
DialogUtils.showQqSessionDialog(this, "2586716223");// 建议用户联系客服
|
||||
DialogUtils.showQqSessionDialog(this);// 建议用户联系客服
|
||||
} else if (PLUGGABLE.equals(showDialog.getType())) {
|
||||
DialogUtils.showPluginDialog(this, () -> {
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
@ -176,28 +173,30 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (DOWNLOAD_NOT_FOUND.equals(showDialog.getType())) {
|
||||
DialogUtils.showAlertDialog(this, "下载失败", "下载链接已失效,建议提交反馈"
|
||||
, "立即反馈", "取消"
|
||||
, () -> SuggestionActivity.startSuggestionActivity(this,
|
||||
SuggestType.gameQuestion, null,
|
||||
(showDialog.getPath() + ",问题反馈:下载链接失效")), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
TeaHelper.onPause(this);
|
||||
super.onPause();
|
||||
if (isFinishing()) {
|
||||
onFinish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
TeaHelper.onResume(this);
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
/**
|
||||
* 此回调可用于确认当前 activity 已经执行了 finish() 方法并处于 isFinishing 状态
|
||||
*/
|
||||
protected void onFinish() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
@NonNull String[] permissions,
|
||||
@ -248,4 +247,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
|
||||
|
||||
@ -11,6 +11,7 @@ import android.view.View
|
||||
import android.webkit.JavascriptInterface
|
||||
import butterknife.OnClick
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.view.RichEditor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
@ -68,7 +69,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
val game = data?.getParcelableExtra<GameEntity>(GameEntity::class.java.simpleName)
|
||||
if (game != null) insertData = EditorInsertEntity.transform(game)
|
||||
}
|
||||
INSERT_VIDEO_CODE -> {
|
||||
VideoActivity.INSERT_VIDEO_CODE -> {
|
||||
val video = data?.getParcelableExtra<MyVideoEntity>(MyVideoEntity::class.java.simpleName)
|
||||
if (video != null) mRichEditor.insertCustomVideo(video)
|
||||
return
|
||||
@ -126,19 +127,30 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
R.id.editor_font_bold -> {
|
||||
mEditorFontBold.isChecked = !mEditorFontBold.isChecked
|
||||
mRichEditor.setBold()
|
||||
if (mEditorFontBold.isChecked) {
|
||||
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-加粗")
|
||||
}
|
||||
}
|
||||
R.id.editor_font_italic -> {
|
||||
mEditorFontItalic.isChecked = !mEditorFontItalic.isChecked
|
||||
mRichEditor.setItalic()
|
||||
if (mEditorFontItalic.isChecked) {
|
||||
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-斜体")
|
||||
}
|
||||
}
|
||||
R.id.editor_font_strikethrough -> {
|
||||
mEditorFontStrikeThrough.isChecked = !mEditorFontStrikeThrough.isChecked
|
||||
mRichEditor.setStrikeThrough()
|
||||
|
||||
if (mEditorFontStrikeThrough.isChecked) {
|
||||
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-删除线")
|
||||
}
|
||||
}
|
||||
R.id.editor_paragraph_h1 -> {
|
||||
if (mEditorParagraphH1.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-1级标题")
|
||||
mRichEditor.setHeading(1)
|
||||
}
|
||||
mEditorParagraphH1.isChecked = !mEditorParagraphH1.isChecked
|
||||
@ -147,6 +159,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
if (mEditorParagraphH2.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-2级标题")
|
||||
mRichEditor.setHeading(2)
|
||||
}
|
||||
mEditorParagraphH2.isChecked = !mEditorParagraphH2.isChecked
|
||||
@ -155,6 +168,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
if (mEditorParagraphH3.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-3级标题")
|
||||
mRichEditor.setHeading(3)
|
||||
}
|
||||
mEditorParagraphH3.isChecked = !mEditorParagraphH3.isChecked
|
||||
@ -163,6 +177,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
if (mEditorParagraphH4.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-4级标题")
|
||||
mRichEditor.setHeading(4)
|
||||
}
|
||||
mEditorParagraphH4.isChecked = !mEditorParagraphH4.isChecked
|
||||
@ -171,21 +186,26 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
if (mEditorParagraphQuote.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-引用")
|
||||
mRichEditor.setBlockquote()
|
||||
}
|
||||
mEditorParagraphQuote.isChecked = !mEditorParagraphQuote.isChecked
|
||||
}
|
||||
R.id.editor_link_answer -> {
|
||||
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-回答")
|
||||
startActivityForResult(InsertAnswerWrapperActivity.getIntent(this), INSERT_ANSWER_CODE)
|
||||
}
|
||||
R.id.editor_link_article -> {
|
||||
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-文章")
|
||||
startActivityForResult(InsertArticleWrapperActivity.getIntent(this), INSERT_ARTICLE_CODE)
|
||||
}
|
||||
R.id.editor_link_game -> {
|
||||
startActivityForResult(GameActivity.getIntent(this, "插入游戏"), INSERT_GAME_CODE)
|
||||
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-游戏")
|
||||
startActivityForResult(GameActivity.getIntent(this, GameActivity.INSERT_GAME_TITLE), INSERT_GAME_CODE)
|
||||
}
|
||||
R.id.editor_link_video -> {
|
||||
startActivityForResult(VideoActivity.getIntent(this), INSERT_VIDEO_CODE)
|
||||
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-视频")
|
||||
startActivityForResult(VideoActivity.getIntent(this), VideoActivity.INSERT_VIDEO_CODE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,6 +251,8 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun mtaEventName(): String
|
||||
|
||||
companion object {
|
||||
const val ELEMENT_NAME_BOLD = " b "
|
||||
const val ELEMENT_NAME_ITALIC = " i "
|
||||
@ -244,6 +266,5 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
const val INSERT_ANSWER_CODE = 411
|
||||
const val INSERT_ARTICLE_CODE = 412
|
||||
const val INSERT_GAME_CODE = 413
|
||||
const val INSERT_VIDEO_CODE = 414
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -140,8 +140,9 @@ class GHUmengNotificationService : UmengMessageService() {
|
||||
|
||||
notificationManager.notify(getNotificationTag(context), NOTIFICATION_ID, notification)
|
||||
} else {
|
||||
if (UserManager.getInstance().isLoggedIn
|
||||
&& HALO_MESSAGE_DIALOG == pushData.body?.custom) {
|
||||
if (UserManager.getInstance().isLoggedIn &&
|
||||
HALO_MESSAGE_DIALOG == pushData.body?.custom &&
|
||||
MessageUnreadRepository.unreadLiveData.value != null) {
|
||||
// 回答了问题或者关注了问题的消息
|
||||
val msg = gson.fromJson(message, PushMessageEntity::class.java)
|
||||
val data = msg?.extra?.data
|
||||
|
||||
@ -5,6 +5,7 @@ import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
@ -193,10 +194,20 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
|
||||
private void updateDownloadCountHint(List<GameUpdateEntity> updateList) {
|
||||
if (mDownloadCountHint == null) return;
|
||||
|
||||
int count = DownloadManager.getInstance(getApplicationContext()).getDownloadOrUpdateCount(updateList);
|
||||
if (count != 0) {
|
||||
String count = DownloadManager.getInstance(getApplicationContext()).getDownloadOrUpdateCount(updateList);
|
||||
if (count != null) {
|
||||
mDownloadCountHint.setVisibility(View.VISIBLE);
|
||||
mDownloadCountHint.setText(String.valueOf(count));
|
||||
mDownloadCountHint.setText(count);
|
||||
|
||||
ViewGroup.LayoutParams params = mDownloadCountHint.getLayoutParams();
|
||||
if (TextUtils.isEmpty(count)) {
|
||||
params.width = DisplayUtils.dip2px(6);
|
||||
params.height = DisplayUtils.dip2px(6);
|
||||
} else {
|
||||
params.width = DisplayUtils.dip2px(12);
|
||||
params.height = DisplayUtils.dip2px(12);
|
||||
}
|
||||
mDownloadCountHint.setLayoutParams(params);
|
||||
} else {
|
||||
mDownloadCountHint.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@ -15,11 +15,14 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
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;
|
||||
@ -31,12 +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 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;
|
||||
|
||||
@ -54,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);
|
||||
|
||||
@ -140,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
|
||||
@ -253,4 +304,16 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
return this;
|
||||
}
|
||||
|
||||
@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
|
||||
|
||||
@ -14,16 +14,16 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Checkable;
|
||||
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* ViewPager 配合ViewGroup Checkable实现双切换<br/>
|
||||
@ -78,7 +78,18 @@ public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_View
|
||||
public void onPageSelected(int index) {
|
||||
onPageChanged(index);
|
||||
try {
|
||||
// 补充Viewpager Fragment的生命周期
|
||||
// 补充Viewpager Fragment的生命周期, 先调用旧选中 fragment 的 onPause 再当前的 onResume
|
||||
if (mFragmentsList.size() > mLastPosition) {
|
||||
Fragment fragment = mFragmentsList.get(mLastPosition);
|
||||
fragment.onPause();
|
||||
|
||||
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
|
||||
List<Fragment> fragments = childFragmentManager.getFragments();
|
||||
for (Fragment childFragment : fragments) {
|
||||
childFragment.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
if (mFragmentsList.size() > index) {
|
||||
Fragment fragment = mFragmentsList.get(index);
|
||||
fragment.onResume();
|
||||
@ -89,17 +100,6 @@ public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_View
|
||||
childFragment.onResume();
|
||||
}
|
||||
}
|
||||
|
||||
if (mFragmentsList.size() > mLastPosition) {
|
||||
Fragment fragment = mFragmentsList.get(mLastPosition);
|
||||
fragment.onPause();
|
||||
|
||||
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
|
||||
List<Fragment> fragments = childFragmentManager.getFragments();
|
||||
for (Fragment childFragment : fragments) {
|
||||
childFragment.onPause();
|
||||
}
|
||||
}
|
||||
mLastPosition = index;
|
||||
} catch (Exception ignore) {
|
||||
|
||||
|
||||
164
app/src/main/java/com/gh/base/fragment/BaseLazyFragment.kt
Normal file
164
app/src/main/java/com/gh/base/fragment/BaseLazyFragment.kt
Normal file
@ -0,0 +1,164 @@
|
||||
package com.gh.base.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.normal.NormalFragment
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
/**
|
||||
* 懒加载(支持多层嵌套)
|
||||
*/
|
||||
abstract class BaseLazyFragment : NormalFragment() {
|
||||
|
||||
private var mIsFirstVisible = true
|
||||
|
||||
private var isViewCreated = false
|
||||
|
||||
protected var isSupportVisible = false
|
||||
|
||||
/**
|
||||
* 用于分发可见时间的时候获取 父fragment 是否隐藏
|
||||
*
|
||||
* @return true fragment 不可见, false 父 fragment 可见
|
||||
*/
|
||||
private val isParentInvisible: Boolean
|
||||
get() {
|
||||
val parentFragment = parentFragment
|
||||
return if (parentFragment is BaseLazyFragment) {
|
||||
val fragment = parentFragment as BaseLazyFragment?
|
||||
!fragment!!.isSupportVisible
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
||||
super.setUserVisibleHint(isVisibleToUser)
|
||||
// 对于默认 tab 和 间隔 checked tab 需要等到 isViewCreated = true 后才可以通过此通知用户可见
|
||||
// 这种情况下第一次可见不是在这里通知 因为 isViewCreated = false 成立,等从别的界面回到这里后会使用 onFragmentResume 通知可见
|
||||
// 对于非默认 tab mIsFirstVisible = true 会一直保持到选择则这个 tab 的时候,因为在 onActivityCreated 会返回 false
|
||||
if (isViewCreated) {
|
||||
if (isVisibleToUser && !isSupportVisible) {
|
||||
dispatchUserVisibleHint(true)
|
||||
} else if (!isVisibleToUser && isSupportVisible) {
|
||||
dispatchUserVisibleHint(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
isViewCreated = true
|
||||
// !isHidden() 默认为 true 在调用 hide show 的时候可以使用
|
||||
if (!isHidden && userVisibleHint) {
|
||||
dispatchUserVisibleHint(true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onHiddenChanged(hidden: Boolean) {
|
||||
super.onHiddenChanged(hidden)
|
||||
|
||||
if (hidden) {
|
||||
dispatchUserVisibleHint(false)
|
||||
} else {
|
||||
dispatchUserVisibleHint(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (!mIsFirstVisible) {
|
||||
if (!isHidden && !isSupportVisible && userVisibleHint) {
|
||||
dispatchUserVisibleHint(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
// 当前 Fragment 包含子 Fragment 的时候 dispatchUserVisibleHint 内部本身就会通知子 Fragment 不可见
|
||||
// 子 fragment 走到这里的时候自身又会调用一遍 ?
|
||||
if (isSupportVisible && userVisibleHint) {
|
||||
dispatchUserVisibleHint(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 统一处理 显示隐藏
|
||||
*
|
||||
* @param visible
|
||||
*/
|
||||
private fun dispatchUserVisibleHint(visible: Boolean) {
|
||||
//当前 Fragment 是 child 时候 作为缓存 Fragment 的子 fragment getUserVisibleHint = true
|
||||
//但当父 fragment 不可见所以 currentVisibleState = false 直接 return 掉
|
||||
// 这里限制则可以限制多层嵌套的时候子 Fragment 的分发
|
||||
if (visible && isParentInvisible) return
|
||||
|
||||
//此处是对子 Fragment 不可见的限制,因为 子 Fragment 先于父 Fragment回调本方法 currentVisibleState 置位 false
|
||||
// 当父 dispatchChildVisibleState 的时候第二次回调本方法 visible = false 所以此处 visible 将直接返回
|
||||
if (isSupportVisible == visible) {
|
||||
return
|
||||
}
|
||||
|
||||
isSupportVisible = visible
|
||||
|
||||
if (visible) {
|
||||
if (mIsFirstVisible && view != null) {
|
||||
mIsFirstVisible = false
|
||||
onFragmentFirstVisible()
|
||||
}
|
||||
onFragmentResume()
|
||||
dispatchChildVisibleState(true)
|
||||
} else {
|
||||
dispatchChildVisibleState(false)
|
||||
onFragmentPause()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前 Fragment 是 child 时候 作为缓存 Fragment 的子 fragment 的唯一或者嵌套 VP 的第一 fragment 时 getUserVisibleHint = true
|
||||
* 但是由于父 Fragment 还未进入可见状态所以自身也是不可见的, 这个方法可以存在是因为庆幸的是 父 fragment 的生命周期回调总是先于子 Fragment
|
||||
* 所以在父 fragment 设置完成当前不可见状态后,需要通知子 Fragment 我不可见,你也不可见,
|
||||
*
|
||||
*
|
||||
* 因为 dispatchUserVisibleHint 中判断了 isParentInvisible 所以当 子 fragment 走到了 onActivityCreated 的时候直接 return 掉了
|
||||
*
|
||||
*
|
||||
* 当真正的外部 Fragment 可见的时候,走 setVisibleHint (VP 中)或者 onActivityCreated (hide show) 的时候
|
||||
* 从对应的生命周期入口调用 dispatchChildVisibleState 通知子 Fragment 可见状态
|
||||
*
|
||||
* @param visible
|
||||
*/
|
||||
private fun dispatchChildVisibleState(visible: Boolean) {
|
||||
val childFragmentManager = childFragmentManager
|
||||
val fragments = childFragmentManager.fragments
|
||||
if (!fragments.isEmpty()) {
|
||||
for (child in fragments) {
|
||||
if (child is BaseLazyFragment && !child.isHidden() && child.getUserVisibleHint()) {
|
||||
child.dispatchUserVisibleHint(visible)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open fun onFragmentFirstVisible() {
|
||||
//ULog.e("对用户第一次可见")
|
||||
}
|
||||
|
||||
open fun onFragmentResume() {
|
||||
//ULog.e("对用户可见")
|
||||
}
|
||||
|
||||
open fun onFragmentPause() {
|
||||
//ULog.e("对用户不可见")
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
isViewCreated = false
|
||||
mIsFirstVisible = true
|
||||
}
|
||||
|
||||
}
|
||||
152
app/src/main/java/com/gh/base/fragment/BaseLazyTabFragment.kt
Normal file
152
app/src/main/java/com/gh/base/fragment/BaseLazyTabFragment.kt
Normal file
@ -0,0 +1,152 @@
|
||||
package com.gh.base.fragment
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.CheckedTextView
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
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.halo.assistant.HaloApp
|
||||
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)
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
super.onFragmentFirstVisible()
|
||||
|
||||
initFragmentList(mFragmentsList)
|
||||
initTabTitleList(mTabTitleList)
|
||||
|
||||
mViewPager.offscreenPageLimit = mFragmentsList.size
|
||||
mViewPager.addOnPageChangeListener(this)
|
||||
mViewPager.adapter = 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 = createDefaultTabCustomView(tabTitle)
|
||||
tab.customView = tabView
|
||||
}
|
||||
initTabStyle(mTabLayout, mCheckedIndex)
|
||||
}
|
||||
|
||||
open fun initTabStyle(tabLayout: TabLayout?, currentItem: Int) { // 默认选择addOnTabSelectedListener不会回调
|
||||
val tabCount = tabLayout!!.tabCount
|
||||
if (tabCount > 0) {
|
||||
val tab = tabLayout.getTabAt(currentItem)
|
||||
if (tab != null) updateTabStyle(tab, true)
|
||||
}
|
||||
tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, true)
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, false)
|
||||
}
|
||||
|
||||
override fun onTabReselected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
open fun updateTabStyle(tab: TabLayout.Tab, isChecked: Boolean) {
|
||||
val tabView = tab.customView
|
||||
if (tabView == null) {
|
||||
Utils.log("TabLayout->Tab样式不是通用样式,请检查")
|
||||
return
|
||||
}
|
||||
val tabTitle: TextView?
|
||||
tabTitle = if (tabView is TextView) {
|
||||
tabView
|
||||
} else {
|
||||
tabView.findViewById(R.id.tab_title)
|
||||
}
|
||||
if (tabTitle == null) {
|
||||
Utils.log("TabLayout->Tab样式不是通用样式,请检查")
|
||||
return
|
||||
}
|
||||
tabTitle.typeface = if (isChecked) Typeface.DEFAULT_BOLD else Typeface.DEFAULT
|
||||
}
|
||||
|
||||
// 如果不设置View的话,无法动态设置字体样式
|
||||
open fun createDefaultTabCustomView(title: String?): View {
|
||||
val view = LayoutInflater.from(HaloApp.getInstance().application.baseContext).inflate(R.layout.tab_item, null)
|
||||
val tabTitle = view.findViewById<View>(R.id.tab_title)
|
||||
if (tabTitle is CheckedTextView) {
|
||||
tabTitle.text = title
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
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,11 @@ import android.webkit.JavascriptInterface
|
||||
import androidx.annotation.Keep
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.util.*
|
||||
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
|
||||
@ -49,7 +51,7 @@ class DefaultJsApi(var context: Context) {
|
||||
|
||||
@JavascriptInterface
|
||||
fun getUserToken(msg: Any): String {
|
||||
return UserManager.getInstance().loginTokenEntity.accessToken.value
|
||||
return if (UserManager.getInstance().isLoggedIn) UserManager.getInstance().loginTokenEntity.accessToken.value else ""
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ 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
|
||||
@ -12,7 +13,9 @@ 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.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
object DefaultWebViewUrlHandler {
|
||||
@ -33,7 +36,7 @@ object DefaultWebViewUrlHandler {
|
||||
when (host) {
|
||||
"article" -> context.startActivity(NewsDetailActivity.getIntentById(context, id, entrance))
|
||||
|
||||
"game" -> GameDetailActivity.startGameDetailActivity(context, id, entrance)
|
||||
"game" -> GameDetailActivity.startGameDetailActivity(context, id, "libao" == uri.getQueryParameter("to"), entrance)
|
||||
|
||||
"column" -> SubjectActivity.startSubjectActivity(context, id, uri.getQueryParameter("name"), false, entrance)
|
||||
|
||||
@ -41,7 +44,7 @@ object DefaultWebViewUrlHandler {
|
||||
|
||||
"qq" -> try {
|
||||
DirectUtils.directToQqConversation(context, id)
|
||||
} catch (e: Exception) {
|
||||
} catch (e: Throwable) {
|
||||
Utils.toast(context, "请检查是否已经安装手机QQ")
|
||||
e.printStackTrace()
|
||||
}
|
||||
@ -76,10 +79,18 @@ object DefaultWebViewUrlHandler {
|
||||
"community" -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = id
|
||||
community.name = uri.getQueryParameter("name")
|
||||
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" -> {
|
||||
@ -107,10 +118,37 @@ object DefaultWebViewUrlHandler {
|
||||
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
|
||||
DirectUtils.directToVideoDetail(context, id, loaction, false, "", entrance, "", referer, type, act)
|
||||
}
|
||||
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
return true
|
||||
}
|
||||
if ("http" != uri.scheme && "https" != uri.scheme) return true
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -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,34 @@ 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)
|
||||
// 注册小米、华为和魅族通道
|
||||
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)
|
||||
pushAgent.onAppStart() // 开启App统计
|
||||
//友盟推送
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
|
||||
//注册推送服务,每次调用register方法都会回调该接口
|
||||
registerDevice()
|
||||
//注册推送服务,每次调用register方法都会回调该接口
|
||||
runOnIoThread { registerDevice() }
|
||||
|
||||
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?)
|
||||
}
|
||||
@ -9,20 +9,29 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.PackageHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.SuggestionActivity;
|
||||
import com.gh.gamecenter.entity.NewsEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 需要配置的请使用{@link PreferenceManager#getDefaultSharedPreferences(Context)}
|
||||
@ -169,6 +178,9 @@ public class Config {
|
||||
getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply();
|
||||
mSettingsEntity = settingsEntity;
|
||||
|
||||
// 更新 FIX_ARTICLE_KEY 状态
|
||||
mSettingsEntity.showArticleEntrance();
|
||||
|
||||
// 加载完设置后刷新下
|
||||
PackageHelper.initList();
|
||||
}
|
||||
@ -222,6 +234,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());
|
||||
@ -232,4 +248,29 @@ public class Config {
|
||||
editor.putBoolean(Config.FIX_PLUGIN_KEY, true);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static void getGhzsSettings() {
|
||||
String channel = HaloApp.getInstance().getChannel();
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
|
||||
.getApi().getSettings(PackageUtils.getVersionName(), channel)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<SettingsEntity>() {
|
||||
@Override
|
||||
public void onResponse(SettingsEntity response) {
|
||||
Config.setSettings(response);
|
||||
|
||||
// 意见反馈
|
||||
SharedPreferences.Editor edit = getPreferences().edit();
|
||||
edit.putString(SuggestionActivity.SUGGESTION_HINT_TYPE,
|
||||
GsonUtils.toJson(response.getSuggestion()));
|
||||
edit.apply();
|
||||
|
||||
if (!getPreferences().getBoolean(Config.FIX_DOWNLOAD_KEY, false) && Config.isShow()) {
|
||||
getPreferences().edit().putBoolean(Config.FIX_DOWNLOAD_KEY, true).apply();
|
||||
}
|
||||
EventBus.getDefault().post(new EBReuse("Refresh"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package com.gh.common.constant;
|
||||
|
||||
import com.gh.common.util.PackageUtils;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final int SEND_NEWS_FEEDBACK = 0x126;
|
||||
@ -24,16 +26,56 @@ public class Constants {
|
||||
public static final String GAME_DETAIL_COME_IN = "game_detail_come_in"; // 从游戏详情进入
|
||||
|
||||
public static final String XPOSED_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
|
||||
|
||||
|
||||
public static final String EB_QUIT_LOGIN = "quit_login";
|
||||
|
||||
public static final String GAME_ID_DIVIDER = ":"; // 用于避免历史下载掺和到普通下载状态的 ID 修饰符
|
||||
|
||||
// 最近显示的弹窗信息
|
||||
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_SHOWED_NOTIFICATION_HINT = "show_notification_hint";
|
||||
//标记安装的游戏为已玩过弹窗,最多取消2次
|
||||
public static final String SP_MARK_INSTALLED_GAME = "mark_installed_game";
|
||||
//引导设置 “通知管理” 引导弹窗
|
||||
public static final String SP_SHOWED_NOTIFICATION_LOGIN = "show_notification_login_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_QUESTION = "show_notification_question_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_ANSWER = "show_notification_answer_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_ARTICLE = "show_notification_article_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_VIDEO = "show_notification_video_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_RATING = "show_notification_rating_hint";
|
||||
// 新版本 也要触发一次“通知管理” 引导弹窗
|
||||
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";
|
||||
// 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 REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
|
||||
@ -66,10 +108,17 @@ public class Constants {
|
||||
public static final int SEARCH_CD = 5 * 60 * 1000;
|
||||
//评论 cd间隔
|
||||
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";
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ 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;
|
||||
@ -34,23 +35,27 @@ import com.gh.common.util.DownloadDialogHelper;
|
||||
import com.gh.common.util.GameUtils;
|
||||
import com.gh.common.util.GameViewUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.NewsUtils;
|
||||
import com.gh.common.util.NumberUtils;
|
||||
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;
|
||||
import com.gh.gamecenter.baselist.LoadStatus;
|
||||
import com.gh.gamecenter.databinding.KaifuAddItemBinding;
|
||||
import com.gh.gamecenter.databinding.KaifuDetailItemRowBinding;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.entity.ServerCalendarEntity;
|
||||
import com.gh.gamecenter.entity.TagStyleEntity;
|
||||
@ -194,6 +199,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) {
|
||||
@ -203,6 +219,32 @@ 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());
|
||||
}
|
||||
|
||||
@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) {
|
||||
@ -354,17 +396,25 @@ 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,
|
||||
entrance,
|
||||
location + ":" + gameEntity.getName());
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
case LAUNCH_OR_OPEN:
|
||||
@ -372,8 +422,11 @@ 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,
|
||||
entrance,
|
||||
location + ":" + gameEntity.getName());
|
||||
}
|
||||
break;
|
||||
case INSTALL_PLUGIN:
|
||||
@ -381,16 +434,17 @@ public class BindingAdapters {
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(progressBar.getContext()).getDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
|
||||
if (downloadEntity != null) {
|
||||
PackageUtils.launchSetup(v.getContext(), downloadEntity.getPath());
|
||||
PackageUtils.launchSetup(v.getContext(), downloadEntity);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RESERVABLE:
|
||||
CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> {
|
||||
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(progressBar.getContext(), () -> {
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
|
||||
gameEntity,
|
||||
() -> updateReservation(progressBar, gameEntity));
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(gameEntity, () -> {
|
||||
LogUtils.logReservation(gameEntity, traceEvent);
|
||||
updateReservation(progressBar, gameEntity);
|
||||
});
|
||||
dialogFragment.show(((AppCompatActivity) progressBar.getContext()).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
});
|
||||
@ -410,6 +464,12 @@ 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())));
|
||||
progressBar.getContext().startActivity(i);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@ -427,13 +487,24 @@ public class BindingAdapters {
|
||||
|
||||
// 显示下载按钮状态
|
||||
if (gameEntity.getApk().isEmpty() || gameEntity.getDownloadOffStatus() != null) {
|
||||
LinkEntity h5LinkEntity = gameEntity.getH5Link();
|
||||
String offStatus = gameEntity.getDownloadOffStatus();
|
||||
if (offStatus != null && "dialog".equals(offStatus)) {
|
||||
progressBar.setText("查看");
|
||||
if (h5LinkEntity != null) {
|
||||
if ("play".equals(h5LinkEntity.getType())) {
|
||||
progressBar.setText("开始玩");
|
||||
} else {
|
||||
progressBar.setText("查看");
|
||||
}
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.H5_GAME);
|
||||
} else {
|
||||
progressBar.setText("暂无");
|
||||
if (offStatus != null && "dialog".equals(offStatus)) {
|
||||
progressBar.setText("查看");
|
||||
} else {
|
||||
progressBar.setText("暂无");
|
||||
}
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
|
||||
} else {
|
||||
String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity, PluginLocation.only_game);
|
||||
switch (status) {
|
||||
@ -489,6 +560,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) {
|
||||
// 显示预约
|
||||
@ -525,7 +613,8 @@ public class BindingAdapters {
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(progressBar.getContext(), gameEntity.getName(), apkEntity.getPlatform(), entrance, "下载开始", method);
|
||||
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, ExposureUtils.DownloadType.DOWNLOAD);
|
||||
ExposureUtils.DownloadType downloadType = ExposureUtils.getDownloadType(apkEntity, method);
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, downloadType);
|
||||
|
||||
DownloadManager.createDownload(progressBar.getContext(),
|
||||
apkEntity,
|
||||
@ -544,27 +633,9 @@ 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));
|
||||
|
||||
if (gameEntity.getTest().getStart() == 0) {
|
||||
testTime.setVisibility(View.GONE);
|
||||
} else {
|
||||
testTime.setText(GameViewUtils.getGameTestDate(gameEntity.getTest().getStart()));
|
||||
}
|
||||
layout.addView(testView);
|
||||
} else {
|
||||
GameViewUtils.setLabelList(layout.getContext(), layout, gameEntity.getTag(), subjectTag, gameEntity.getTagStyle());
|
||||
}
|
||||
|
||||
@BindingAdapter("gameLabelList")
|
||||
public static void setGameLabelList(LinearLayout layout, List<TagStyleEntity> tagStyle) {
|
||||
GameViewUtils.setLabelList(layout.getContext(), layout, tagStyle);
|
||||
}
|
||||
|
||||
@BindingAdapter("isRefreshing")
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
234
app/src/main/java/com/gh/common/dialog/DeviceRemindDialog.kt
Normal file
234
app/src/main/java/com/gh/common/dialog/DeviceRemindDialog.kt
Normal file
@ -0,0 +1,234 @@
|
||||
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 com.lightgame.utils.Utils
|
||||
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_ad_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)
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,7 @@ 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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.gh.common.exposure.meta.Meta
|
||||
import com.gh.common.exposure.meta.MetaUtil
|
||||
import com.gh.common.exposure.time.TimeUtil
|
||||
@ -24,7 +24,8 @@ data class ExposureEvent(
|
||||
@PrimaryKey
|
||||
val id: String = UUID.randomUUID().toString()) : Parcelable {
|
||||
companion object {
|
||||
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>?, event: ExposureType): ExposureEvent {
|
||||
@JvmStatic
|
||||
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>? = null, event: ExposureType = ExposureType.EXPOSURE): ExposureEvent {
|
||||
return ExposureEvent(
|
||||
payload = ExposureEntity(gameId = gameEntity?.id,
|
||||
gameName = gameEntity?.name,
|
||||
@ -34,7 +35,7 @@ data class ExposureEvent(
|
||||
downloadCompleteType = gameEntity?.downloadCompleteType),
|
||||
source = source,
|
||||
eTrace = eTrace,
|
||||
event = event)
|
||||
event = event).apply { gameEntity?.exposureEvent = this }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,10 +31,10 @@ object ExposureManager {
|
||||
private val loghubHelper = LoghubHelper.getInstance()
|
||||
|
||||
// exposureCache 用来过滤掉具有相同 id 的曝光事件,避免重复发送事件
|
||||
private val exposureCache = FixedSizeLinkedHashSet<String>(100)
|
||||
private val exposureSet = hashSetOf<ExposureEvent>()
|
||||
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() }
|
||||
private val exposureExecutor = Executors.newSingleThreadExecutor()
|
||||
|
||||
@JvmStatic
|
||||
fun init() {
|
||||
@ -48,7 +48,7 @@ object ExposureManager {
|
||||
}
|
||||
|
||||
fixedRateTimer(name = "ExposureManager-Store-Checker", initialDelay = 500, period = STORE_FORCE_UPLOAD_PERIOD) {
|
||||
commitSavedExposureEvent(true)
|
||||
commitSavedExposureEvents(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,17 +57,19 @@ object ExposureManager {
|
||||
*/
|
||||
fun log(event: ExposureEvent) {
|
||||
exposureExecutor.execute {
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
|
||||
try {
|
||||
try {
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
|
||||
|
||||
exposureSet.add(event)
|
||||
exposureDao.insert(event)
|
||||
exposureCache.add(event.id)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
|
||||
} else {
|
||||
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 (${event.id} - ${event.payload.gameName})")
|
||||
}
|
||||
} else {
|
||||
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 (${event.id} - ${event.payload.gameName})")
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,24 +80,27 @@ object ExposureManager {
|
||||
fun log(eventList: List<ExposureEvent>) {
|
||||
exposureExecutor.execute {
|
||||
for (event in eventList) {
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
|
||||
try {
|
||||
try {
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
|
||||
exposureSet.add(event)
|
||||
exposureDao.insert(event)
|
||||
exposureCache.add(event.id)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} else {
|
||||
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 (${event.id} - ${event.payload.gameName})")
|
||||
}
|
||||
} else {
|
||||
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 (${event.id} - ${event.payload.gameName})")
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
commitSavedExposureEvent()
|
||||
commitSavedExposureEvents()
|
||||
}
|
||||
}
|
||||
|
||||
fun commitSavedExposureEvent(forced: Boolean = false) {
|
||||
/**
|
||||
* @param forced Ignore all restrictions.
|
||||
*/
|
||||
fun commitSavedExposureEvents(forced: Boolean = false) {
|
||||
exposureExecutor.execute {
|
||||
if (exposureSet.size < STORE_SIZE && !forced || exposureSet.size == 0) return@execute
|
||||
|
||||
|
||||
@ -6,4 +6,4 @@ import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@Keep
|
||||
@Parcelize
|
||||
data class ExposureSource(var k: String, var v: String): Parcelable
|
||||
data class ExposureSource(var k: String, var v: String = ""): Parcelable
|
||||
@ -1,7 +1,10 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.gamecenter.entity.ApkEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
import java.util.*
|
||||
|
||||
object ExposureUtils {
|
||||
@ -36,7 +39,31 @@ object ExposureUtils {
|
||||
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
|
||||
event = ExposureType.DOWNLOAD_COMPLETE)
|
||||
ExposureManager.log(exposureEvent)
|
||||
ExposureManager.commitSavedExposureEvent(forced = true)
|
||||
ExposureManager.commitSavedExposureEvents(forced = true)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getDownloadType(apkEntity: ApkEntity, method: String) : DownloadType {
|
||||
return if ("更新" == method) {
|
||||
if (PackageUtils.isSignature(HaloApp.getInstance().application, apkEntity.packageName)) {
|
||||
DownloadType.PLUGIN_UPDATE
|
||||
} 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 {
|
||||
|
||||
@ -17,6 +17,7 @@ data class Meta(
|
||||
val network: String? = "",
|
||||
val os: String? = "",
|
||||
val gid: String? = "",
|
||||
val oaid: String? = "",
|
||||
val channel: String? = "",
|
||||
val appVersion: String? = "",
|
||||
val userId: String? = "",
|
||||
|
||||
@ -35,6 +35,7 @@ object MetaUtil {
|
||||
network = getNetwork(),
|
||||
os = getOS(),
|
||||
gid = HaloApp.getInstance().gid,
|
||||
oaid = HaloApp.getInstance().oaid,
|
||||
channel = getChannel(),
|
||||
appVersion = BuildConfig.VERSION_NAME,
|
||||
userId = UserManager.getInstance().userId,
|
||||
|
||||
@ -7,17 +7,15 @@ import androidx.room.TypeConverters
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.gh.gamecenter.entity.HistoryGameEntity
|
||||
import com.gh.gamecenter.entity.MyVideoEntity
|
||||
import com.gh.gamecenter.entity.NewsEntity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.ArticleEntity
|
||||
import com.gh.gamecenter.room.converter.*
|
||||
import com.gh.gamecenter.room.dao.AnswerHistoryDao
|
||||
import com.gh.gamecenter.room.dao.ArticleHistoryDao
|
||||
import com.gh.gamecenter.room.dao.GameDao
|
||||
import com.gh.gamecenter.room.dao.NewsHistoryDao
|
||||
import com.gh.gamecenter.room.dao.*
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class], version = 4, exportSchema = false)
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 5, exportSchema = false)
|
||||
@TypeConverters(CountConverter::class,
|
||||
CommunityConverter::class,
|
||||
TimeConverter::class,
|
||||
@ -33,6 +31,7 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
abstract fun articleDao(): ArticleHistoryDao
|
||||
abstract fun newsDao(): NewsHistoryDao
|
||||
abstract fun gameDao(): GameDao
|
||||
abstract fun videoHistoryDao(): VideoHistoryDao
|
||||
|
||||
companion object {
|
||||
|
||||
@ -49,10 +48,17 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_4_5: Migration = object : Migration(4, 5) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE MyVideoEntity(id TEXT NOT NULL PRIMARY KEY,poster TEXT NOT NULL DEFAULT '',url TEXT NOT NULL DEFAULT '',vote INTEGER NOT NULL DEFAULT 0,length INTEGER NOT NULL DEFAULT 0,time INTEGER NOT NULL DEFAULT 0,videoStreamRecord INTEGER NOT NULL DEFAULT 0,status 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)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,16 +2,12 @@ package com.gh.common.im
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.core.view.ViewCompat
|
||||
import android.util.AttributeSet
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.KeyCharacterMap
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.ViewConfiguration
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.view.ViewCompat
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.gamecenter.R
|
||||
import kotlinx.android.synthetic.main.view_im_hint.view.*
|
||||
|
||||
@ -32,7 +28,7 @@ class ImHintView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
|
||||
val lp = ivContainer.layoutParams as RelativeLayout.LayoutParams
|
||||
|
||||
lp.setMargins(0, 0, dp2px(30f), dp2px(106f) + retrieveNavigationHeight())
|
||||
lp.setMargins(0, 0, dp2px(30f), dp2px(106f) + DisplayUtils.retrieveNavigationHeight(context))
|
||||
}
|
||||
|
||||
fun showDot(show: Boolean) {
|
||||
@ -46,39 +42,4 @@ class ImHintView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
private fun dp2px(dp: Float): Int {
|
||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.applicationContext.resources.displayMetrics).toInt()
|
||||
}
|
||||
|
||||
private fun hasSoftKeys(): Boolean {
|
||||
if (context !is Activity) return false
|
||||
|
||||
val hasSoftwareKeys: Boolean
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
val d = (context as Activity).windowManager.defaultDisplay
|
||||
|
||||
val realDisplayMetrics = DisplayMetrics()
|
||||
d.getRealMetrics(realDisplayMetrics)
|
||||
|
||||
val realHeight = realDisplayMetrics.heightPixels
|
||||
val realWidth = realDisplayMetrics.widthPixels
|
||||
|
||||
val displayMetrics = DisplayMetrics()
|
||||
d.getMetrics(displayMetrics)
|
||||
|
||||
val displayHeight = displayMetrics.heightPixels
|
||||
val displayWidth = displayMetrics.widthPixels
|
||||
|
||||
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0
|
||||
} else {
|
||||
val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
|
||||
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
|
||||
hasSoftwareKeys = !hasMenuKey && !hasBackKey
|
||||
}
|
||||
return hasSoftwareKeys
|
||||
}
|
||||
|
||||
private fun retrieveNavigationHeight(): Int {
|
||||
val resources = context.resources
|
||||
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
|
||||
return if (resourceId > 0 && hasSoftKeys()) resources.getDimensionPixelSize(resourceId) else 0
|
||||
}
|
||||
}
|
||||
@ -4,12 +4,13 @@ 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
|
||||
import com.gh.gamecenter.HelpAndFeedbackActivity
|
||||
import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.MessageActivity
|
||||
import com.gh.gamecenter.SuggestSelectActivity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.m7.imkfsdk.KfStartHelper
|
||||
@ -69,12 +70,12 @@ object ImManager {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun startChatActivity(activity: Activity) {
|
||||
fun startChatActivity(activity: Activity, inputContent: String? = "", requestCode: Int? = null) {
|
||||
if (!UserManager.getInstance().userId.isNullOrEmpty()) {
|
||||
try {
|
||||
SPUtils.setBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId, false)
|
||||
shouldShowFloatingWindowDot = false
|
||||
val chatHelper = KfStartHelper(activity, UserManager.getInstance().userInfoEntity.icon)
|
||||
val chatHelper = KfStartHelper(activity, UserManager.getInstance().userInfoEntity.icon, inputContent, requestCode)
|
||||
chatHelper.initSdkChat(
|
||||
ImReceiver.UNIQUE_BROADCAST_ACTION,
|
||||
IM_KEY,
|
||||
@ -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) {}
|
||||
@ -152,7 +153,7 @@ object ImManager {
|
||||
private fun isActivityValid(activity: Activity): Boolean {
|
||||
return when (activity) {
|
||||
is MainActivity -> true
|
||||
is SuggestSelectActivity -> true
|
||||
is HelpAndFeedbackActivity -> true
|
||||
is MessageActivity -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
21
app/src/main/java/com/gh/common/loghub/LoghubDatabase.kt
Normal file
21
app/src/main/java/com/gh/common/loghub/LoghubDatabase.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
|
||||
@Database(entities = [LoghubEvent::class], version = 1, exportSchema = false)
|
||||
abstract class LoghubDatabase : RoomDatabase() {
|
||||
companion object {
|
||||
private const val DATABASE = "gh_loghub_database"
|
||||
|
||||
fun buildDatabase(context: Context): LoghubDatabase {
|
||||
return Room.databaseBuilder(context, LoghubDatabase::class.java, DATABASE)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun logHubEventDao(): LoghubEventDao
|
||||
}
|
||||
17
app/src/main/java/com/gh/common/loghub/LoghubEvent.kt
Normal file
17
app/src/main/java/com/gh/common/loghub/LoghubEvent.kt
Normal file
@ -0,0 +1,17 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import java.util.*
|
||||
|
||||
@Keep
|
||||
@Parcelize
|
||||
@Entity(tableName = "loghubEvent")
|
||||
data class LoghubEvent(@PrimaryKey
|
||||
val id: String = UUID.randomUUID().toString(),
|
||||
var time: String,
|
||||
var content: String,
|
||||
var logStore: String) : Parcelable
|
||||
18
app/src/main/java/com/gh/common/loghub/LoghubEventDao.kt
Normal file
18
app/src/main/java/com/gh/common/loghub/LoghubEventDao.kt
Normal file
@ -0,0 +1,18 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import androidx.room.*
|
||||
|
||||
@Dao
|
||||
interface LoghubEventDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertMany(eventList: List<LoghubEvent>)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(event: LoghubEvent)
|
||||
|
||||
@Query("SELECT * FROM LoghubEvent")
|
||||
fun getAll(): List<LoghubEvent>
|
||||
|
||||
@Delete
|
||||
fun deleteMany(eventList: List<LoghubEvent>)
|
||||
}
|
||||
96
app/src/main/java/com/gh/common/loghub/LoghubUtils.kt
Normal file
96
app/src/main/java/com/gh/common/loghub/LoghubUtils.kt
Normal file
@ -0,0 +1,96 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import android.app.Application
|
||||
import com.aliyun.sls.android.sdk.model.Log
|
||||
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 by lazy { hashSetOf<LoghubEvent>() }
|
||||
private val loghubEventExecutor by lazy { Executors.newSingleThreadExecutor() }
|
||||
private val loghubEventDao by lazy { LoghubDatabase.buildDatabase(mApplication).logHubEventDao() }
|
||||
|
||||
@JvmStatic
|
||||
fun init(application: Application) {
|
||||
mApplication = application
|
||||
|
||||
loghubEventExecutor.execute {
|
||||
val eventList = loghubEventDao.getAll()
|
||||
loghubEventSet.addAll(eventList)
|
||||
}
|
||||
|
||||
fixedRateTimer(name = "Loghub-Event-Checker", initialDelay = 1000, period = STORE_FORCE_UPLOAD_INTERVAL) {
|
||||
commitSavedLoghubEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun log(logJson: JSONObject, logStore: String, forcedUpload: Boolean) {
|
||||
loghubEventExecutor.execute {
|
||||
try {
|
||||
val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = logJson.toString(), logStore = logStore)
|
||||
loghubEventSet.add(event)
|
||||
loghubEventDao.insert(event)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
if (forcedUpload || loghubEventSet.size >= STORE_SIZE) {
|
||||
commitSavedLoghubEvents()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun uploadLogGroup(logGroup: LogGroup, logStore: String) {
|
||||
LoghubHelper.getInstance().uploadLogGroup(logGroup, logStore)
|
||||
}
|
||||
|
||||
private fun commitSavedLoghubEvents() {
|
||||
loghubEventExecutor.execute {
|
||||
if (loghubEventSet.isEmpty()) return@execute
|
||||
|
||||
val exposureList = loghubEventSet.toList()
|
||||
|
||||
createLogGroupAndUpload()
|
||||
loghubEventSet.removeAll(exposureList)
|
||||
loghubEventDao.deleteMany(exposureList)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLogGroupAndUpload() {
|
||||
val logGroupHashMap = hashMapOf<String, LogGroup>()
|
||||
|
||||
for (event in loghubEventSet) {
|
||||
if (!logGroupHashMap.containsKey(event.logStore)) {
|
||||
logGroupHashMap[event.logStore] = LogGroup("sls android", "no ip")
|
||||
}
|
||||
|
||||
val log = Log()
|
||||
// 特殊处理,以下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)
|
||||
}
|
||||
|
||||
for ((logStore, logGroup) in logGroupHashMap) {
|
||||
uploadLogGroup(logGroup, logStore)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,18 +1,19 @@
|
||||
package com.gh.common.notifier
|
||||
|
||||
import android.animation.*
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.graphics.Path
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import android.util.AttributeSet
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.*
|
||||
import android.view.Gravity
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.ViewCompat
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.common.util.doOnEnd
|
||||
import com.gh.common.util.doOnStart
|
||||
@ -74,7 +75,7 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
|
||||
verticalAnimationOffset = dp2px(100F)
|
||||
|
||||
navigationHeight = retrieveNavigationHeight()
|
||||
navigationHeight = DisplayUtils.retrieveNavigationHeight(context)
|
||||
|
||||
rightToLeftPath = Path()
|
||||
leftToRightPath = Path()
|
||||
@ -290,41 +291,6 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.applicationContext.resources.displayMetrics).toInt()
|
||||
}
|
||||
|
||||
private fun hasSoftKeys(): Boolean {
|
||||
if (context !is Activity) return false
|
||||
|
||||
val hasSoftwareKeys: Boolean
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
val d = (context as Activity).windowManager.defaultDisplay
|
||||
|
||||
val realDisplayMetrics = DisplayMetrics()
|
||||
d.getRealMetrics(realDisplayMetrics)
|
||||
|
||||
val realHeight = realDisplayMetrics.heightPixels
|
||||
val realWidth = realDisplayMetrics.widthPixels
|
||||
|
||||
val displayMetrics = DisplayMetrics()
|
||||
d.getMetrics(displayMetrics)
|
||||
|
||||
val displayHeight = displayMetrics.heightPixels
|
||||
val displayWidth = displayMetrics.widthPixels
|
||||
|
||||
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0
|
||||
} else {
|
||||
val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
|
||||
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
|
||||
hasSoftwareKeys = !hasMenuKey && !hasBackKey
|
||||
}
|
||||
return hasSoftwareKeys
|
||||
}
|
||||
|
||||
private fun retrieveNavigationHeight(): Int {
|
||||
val resources = context.resources
|
||||
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
|
||||
return if (resourceId > 0 && hasSoftKeys()) resources.getDimensionPixelSize(resourceId) else 0
|
||||
}
|
||||
|
||||
interface OnShowNotificationListener {
|
||||
fun onShow()
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -2,12 +2,16 @@ 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.
|
||||
*/
|
||||
@ -19,8 +23,34 @@ public class CheckLoginUtils {
|
||||
if (listener != null) Utils.toast(context, "需要登录");
|
||||
LogUtils.login("dialog", null, entrance);
|
||||
LogUtils.login("activity", null, entrance);
|
||||
Intent intent = LoginActivity.getIntent(context, entrance);
|
||||
context.startActivity(intent);
|
||||
|
||||
// 有可能App未启动
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
bundle.putString(EntranceUtils.KEY_TO, LoginActivity.class.getName());
|
||||
EntranceUtils.jumpActivity(context, bundle);
|
||||
} else {
|
||||
if (listener != null) {
|
||||
listener.onLogin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
@ -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;
|
||||
@ -85,8 +83,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 +92,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 +117,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 +198,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)) {
|
||||
if (commentLikeCountTv.getCurrentTextColor() == ContextCompat.getColor(context, R.color.theme_font)) {
|
||||
Utils.toast(context, "已经点过赞啦!");
|
||||
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 +222,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);
|
||||
@ -284,13 +264,13 @@ public class CommentUtils {
|
||||
entrance = "社区文章详情-评论-点赞";
|
||||
}
|
||||
CheckLoginUtils.checkLogin(context, entrance, () -> {
|
||||
if (commentLikeCountTv.getCurrentTextColor() == ContextCompat.getColor(context, R.color.theme)) {
|
||||
if (commentLikeCountTv.getCurrentTextColor() == ContextCompat.getColor(context, R.color.theme_font)) {
|
||||
Utils.toast(context, "已经点过赞啦!");
|
||||
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 +287,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);
|
||||
@ -340,14 +320,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 +355,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 +368,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 {
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -9,8 +9,6 @@ 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;
|
||||
|
||||
@ -169,24 +167,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);
|
||||
}
|
||||
|
||||
// 网络错误
|
||||
|
||||
@ -238,18 +238,12 @@ public class DataUtils {
|
||||
}
|
||||
|
||||
public static void onError(Context context, Throwable throwable) {
|
||||
// MTA主动上传错误
|
||||
//bugly 作为默认处理异常的类库,已经上报了,此处不重复上报
|
||||
try {
|
||||
StatService.reportException(context, throwable);
|
||||
CrashReport.postCatchedException(throwable);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
// //bugly 作为默认处理异常的类库,已经上报了,此处不重复上报
|
||||
// try {
|
||||
// CrashReport.postCatchedException(throwable);
|
||||
// } catch (Exception e) {
|
||||
// }
|
||||
|
||||
//talkingdata
|
||||
try {
|
||||
TCAgent.onError(context, throwable);
|
||||
|
||||
@ -9,9 +9,11 @@ import com.gh.common.view.DownloadProgressBar;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.DetailViewHolder;
|
||||
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.
|
||||
@ -21,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())
|
||||
@ -33,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 {
|
||||
@ -47,35 +51,51 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
|
||||
if (viewHolder.gameEntity.getApk().isEmpty() || viewHolder.gameEntity.getDownloadOffStatus() != null) {
|
||||
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "查看详情" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE_WITH_HINT);
|
||||
LinkEntity h5LinkEntity = viewHolder.gameEntity.getH5Link();
|
||||
|
||||
if (h5LinkEntity != null) {
|
||||
if ("play".equals(h5LinkEntity.getType())) {
|
||||
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());
|
||||
}
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.H5_GAME);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "暂无下载" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
|
||||
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.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();
|
||||
@ -87,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;
|
||||
@ -115,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);
|
||||
@ -130,6 +154,4 @@ public class DetailDownloadUtils {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -5,7 +5,12 @@ import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.CountDownTimer;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
@ -17,25 +22,49 @@ import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
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;
|
||||
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.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class DialogUtils {
|
||||
|
||||
@ -144,29 +173,33 @@ public class DialogUtils {
|
||||
}
|
||||
|
||||
// 网络劫持时 打开QQ客户端,创建临时会话
|
||||
public static void showQqSessionDialog(final Context context, final String qq) {
|
||||
public static void showQqSessionDialog(final Context context) {
|
||||
String qq = "";
|
||||
if (Config.getSettings() != null && Config.getSettings().getSupport() != null) {
|
||||
qq = Config.getSettings().getSupport().getQq();
|
||||
}
|
||||
String finalQq = qq;
|
||||
showWarningDialog(context, "警告", "您当前网络环境异常,下载地址可能被运营商恶意替换(网络劫持)" +
|
||||
",如多次下载失败,请联系客服获取正确的下载地址(客服QQ:" + qq + ")"
|
||||
, "取消", "前往QQ", () -> DirectUtils.directToQqConversation(context, qq), null);
|
||||
, "取消", "前往QQ", () -> DirectUtils.directToQqConversation(context, finalQq), null);
|
||||
}
|
||||
|
||||
public static void checkDownload(Context context, String size, CheckDownloadCallBack callBack) {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
|
||||
if (!NetworkUtils.isNetworkConnected(context)) {
|
||||
showNoConnectionDownloadDialog(context, null,
|
||||
() -> callBack.onResponse(true));
|
||||
} else if (NetworkUtils.isWifiConnected(context) || filter4GorSize(context, size)) {
|
||||
} else if (NetworkUtils.isWifiConnected(context)
|
||||
|| filter4GorSize(context, size)) {
|
||||
callBack.onResponse(false);
|
||||
} else if (!preferences.getBoolean(SettingsFragment.getTrafficDownloadHintKey(), true)) {
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> Utils.toast(context, "当前使用移动网络下载,请注意流量消耗"), 500);
|
||||
callBack.onResponse(false);
|
||||
} else {
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "出现弹窗提示");
|
||||
showDownloadDialog(context,
|
||||
() -> {
|
||||
callBack.onResponse(false);
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "立即下载");
|
||||
},
|
||||
() -> {
|
||||
callBack.onResponse(true);
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "连上WiFi后自动下载");
|
||||
});
|
||||
() -> callBack.onResponse(false),
|
||||
() -> callBack.onResponse(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +211,8 @@ public class DialogUtils {
|
||||
String mb = size.toUpperCase().replaceAll("MB", "").trim();
|
||||
Float i = Float.valueOf(mb);
|
||||
if (NetworkUtils.isWifiOr4GConnected(context) && i <= 50) {
|
||||
Utils.toast(context, "当前使用移动流量下载");
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> Utils.toast(context, "当前使用移动网络下载,请注意流量消耗"), 500);
|
||||
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -206,14 +240,54 @@ public class DialogUtils {
|
||||
}
|
||||
|
||||
public static void showDownloadDialog(Context context, ConfirmListener listener, CancelListener cancelListener) {
|
||||
showWarningDialog(context, "下载提示", "当前正在使用移动网络,立即下载会消耗手机流量", "连上WiFi后自动下载", "立即下载", listener, cancelListener);
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_download_traffic, null);
|
||||
View allowOnce = contentView.findViewById(R.id.allow_once);
|
||||
View allowAlways = contentView.findViewById(R.id.allow_always);
|
||||
View wifiAuto = contentView.findViewById(R.id.wifi_auto);
|
||||
|
||||
Context finalContext = context;
|
||||
allowOnce.setOnClickListener(v -> {
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
Utils.toast(finalContext, "已使用移动网络下载,请注意流量消耗");
|
||||
}, 500);
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "本次允许");
|
||||
});
|
||||
wifiAuto.setOnClickListener(v -> {
|
||||
cancelListener.onCancel();
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "连上WiFi后自动下载");
|
||||
});
|
||||
allowAlways.setOnClickListener(v -> {
|
||||
PreferenceManager
|
||||
.getDefaultSharedPreferences(finalContext)
|
||||
.edit()
|
||||
.putBoolean(SettingsFragment.getTrafficDownloadHintKey(), false)
|
||||
.apply();
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
// 显示了弹窗以后,即便下面这个 toast 放在 listener.onConfirm 后调用也是显示 listener.onConfirm 里的 toast
|
||||
// 喷了,延时包治疑难杂症
|
||||
Utils.toast(finalContext, "已使用移动网络下载,请注意流量消耗");
|
||||
}, 500);
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "总是允许");
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showResumeDownloadDialog(Context context, ConfirmListener listener, CancelListener cancelListener) {
|
||||
showWarningDialog(context, "下载提示", "当前正在使用移动网络,继续下载会消耗手机流量", "连上WiFi后自动下载", "继续下载", listener, cancelListener);
|
||||
}
|
||||
|
||||
|
||||
public static void showDownloadDialog(Context context, ConfirmListener listener) {
|
||||
showWarningDialog(context, "下载提示", "您当前使用的网络为2G/3G/4G,开始下载将会消耗移动流量,确定下载?", listener);
|
||||
}
|
||||
@ -224,10 +298,30 @@ public class DialogUtils {
|
||||
}
|
||||
|
||||
public static void showPluginDialog(Context context, final ConfirmListener listener) {
|
||||
Spanned spanned = Html.fromHtml("您将进行插件化安装以实现插件功能,此过程将"
|
||||
+ "<font color=\"#ff0000\">卸载</font>" + "当前使用的版本并"
|
||||
+ "<font color=\"#ff0000\">安装插件版本</font>");
|
||||
showWarningDialog(context, "插件化安装", spanned, listener);
|
||||
context = checkDialogContext(context);
|
||||
|
||||
MtaHelper.onEvent("插件化", "插件化安装弹窗", "出现弹窗提示");
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_plugin, null);
|
||||
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
negativeTv.setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("插件化", "插件化安装弹窗", "取消");
|
||||
});
|
||||
positiveTv.setOnClickListener(view -> {
|
||||
if (listener != null) {
|
||||
listener.onConfirm();
|
||||
}
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("插件化", "插件化安装弹窗", "确认并开始");
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -563,9 +657,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);
|
||||
@ -786,38 +880,82 @@ public class DialogUtils {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static void showPrivacyPolicyDialog(Context context, String title, String content, EmptyCallback callback) {
|
||||
public static void showPrivacyPolicyDialog(Context context,
|
||||
@NonNull PrivacyPolicyEntity entity,
|
||||
EmptyCallback callback) {
|
||||
|
||||
final Context activityContext = checkDialogContext(context);
|
||||
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
AtomicBoolean isCanceledByClickOutsideOfDialog = new AtomicBoolean(true);
|
||||
|
||||
String privacyPolicyContent;
|
||||
String privacyPolicyTitle = (TextUtils.isEmpty(title)) ? "个人信息保护指引" : title;
|
||||
if (TextUtils.isEmpty(content)) {
|
||||
privacyPolicyContent = "光环助手致力于为每位用户提供更安全的互联网环境,我们将依据相关法律法规和技术规范来收集和使用你的个人信息。" +
|
||||
"<br/>1.为帮助你浏览内容、互动交流、注册认证等,我们需要获取一些必要的信息,以实现完整的功能;" +
|
||||
"<br/>2.日常使用中,我们可能需要开启 IMEI号码、IMSI号码、定位、相册 等信息的读取权限;" +
|
||||
"<br/>3.以上信息的读取权限均不会默认开启,只有在运行相关功能或服务时才会明确提示授权,光环助手不会在未经你同意的情况下收集相关信息。";
|
||||
} else {
|
||||
privacyPolicyContent = content;
|
||||
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.setBackgroundDrawableResource(android.R.color.transparent);
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.horizontalMargin = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
final Dialog dialog = new Dialog(activityContext, R.style.GhAlertDialog);
|
||||
|
||||
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
|
||||
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_privacy_policy, null);
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
TextView skipTv = contentView.findViewById(R.id.dialog_skip);
|
||||
TextView title = contentView.findViewById(R.id.title);
|
||||
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);
|
||||
|
||||
SpannableStringBuilder skipText = new SpannableStringBuilder("你可以查看完整版的 隐私政策");
|
||||
permissions.setLayoutManager(new FixLinearLayoutManager(context));
|
||||
permissions.setAdapter(new BaseRecyclerAdapter(context) {
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = mLayoutInflater.inflate(R.layout.privacy_item, parent, false);
|
||||
return new PrivacyPolicyItemViewHolder(PrivacyItemBinding.bind(view));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
if (holder instanceof PrivacyPolicyItemViewHolder) {
|
||||
PrivacyPolicyItemViewHolder viewHolder = (PrivacyPolicyItemViewHolder) holder;
|
||||
PrivacyItemBinding binding = viewHolder.getBinding();
|
||||
binding.setData(entity.getPermissions().get(position));
|
||||
GenericDraweeHierarchy hierarchy = binding.icon.getHierarchy();
|
||||
if (hierarchy != null) {
|
||||
if (position == 0) {
|
||||
hierarchy.setPlaceholderImage(R.drawable.permission_storage);
|
||||
} else {
|
||||
hierarchy.setPlaceholderImage(R.drawable.permission_phone_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return entity.getPermissions().size();
|
||||
}
|
||||
});
|
||||
|
||||
SpannableStringBuilder skipText = new SpannableStringBuilder("查看完整版的隐私政策和用户协议");
|
||||
skipText.setSpan(new ClickableSpan() {
|
||||
@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);
|
||||
}
|
||||
|
||||
@ -827,30 +965,47 @@ public class DialogUtils {
|
||||
Intent intent = WebActivity.getPrivacyPolicyIntent(activityContext);
|
||||
activityContext.startActivity(intent);
|
||||
}
|
||||
}, skipText.length() - 9, skipText.length() - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
skipText.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setColor(ContextCompat.getColor(activityContext, R.color.theme_font));
|
||||
ds.setUnderlineText(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(@NonNull View widget) {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击用户协议");
|
||||
activityContext.startActivity(WebActivity.getWebIntent(activityContext));
|
||||
}
|
||||
}, skipText.length() - 4, skipText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
title.setText(entity.getTitle());
|
||||
linkContent.setText(skipText);
|
||||
linkContent.setMovementMethod(new LinkMovementMethod());
|
||||
topContent.setText(entity.getTopContent());
|
||||
bottomContent.setText(entity.getBottomContent());
|
||||
|
||||
skipTv.setText(skipText);
|
||||
skipTv.setMovementMethod(new LinkMovementMethod());
|
||||
contentTv.setText(Html.fromHtml(privacyPolicyContent));
|
||||
titleTv.setText(privacyPolicyTitle);
|
||||
positiveTv.setText("我知道了");
|
||||
|
||||
positiveTv.setOnClickListener(view -> {
|
||||
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 -> {
|
||||
if (isCanceledByClickOutsideOfDialog.get()) {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击空白");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
dialog.setOnKeyListener((dialog1, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
||||
isCanceledByClickOutsideOfDialog.set(false);
|
||||
@ -861,7 +1016,37 @@ 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();
|
||||
@ -908,6 +1093,60 @@ public class DialogUtils {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static Dialog showTrackableDialog(Context context,
|
||||
String title,
|
||||
CharSequence message,
|
||||
String positive,
|
||||
String negative,
|
||||
final ConfirmListener cmListener,
|
||||
final CancelListener clListener,
|
||||
TrackableEntity trackableEntity) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final TrackableDialog dialog = new TrackableDialog(context,
|
||||
R.style.GhAlertDialog,
|
||||
trackableEntity.getEvent(),
|
||||
trackableEntity.getKey(),
|
||||
trackableEntity.getValue(),
|
||||
trackableEntity.getCancelValue(),
|
||||
trackableEntity.getKeyBackValue(),
|
||||
trackableEntity.getLogShowEvent());
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_alert, null);
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
if (message.toString().contains("红包奖励")) {//将红包奖励四个字标红
|
||||
String str = message.toString().substring(0, message.toString().indexOf("红包奖励")) + "<font color='#FF0000'>红包奖励</font>";
|
||||
contentTv.setText(Html.fromHtml(str));
|
||||
} else {
|
||||
contentTv.setText(message);
|
||||
}
|
||||
titleTv.setText(title);
|
||||
negativeTv.setText(negative);
|
||||
positiveTv.setText(positive);
|
||||
|
||||
negativeTv.setOnClickListener(view -> {
|
||||
if (clListener != null) {
|
||||
clListener.onCancel();
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
positiveTv.setOnClickListener(view -> {
|
||||
if (cmListener != null) {
|
||||
cmListener.onConfirm();
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static Dialog fixWebViewKeyboardNotWorking(Activity activity) {
|
||||
final Dialog dialog = new Dialog(activity, R.style.TransparentDialog);
|
||||
View view = new View(activity);
|
||||
@ -923,6 +1162,187 @@ public class DialogUtils {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static Dialog showUsageStatsDialog(Context context, final ConfirmListener cmListener, final CancelListener clListener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_usage_stats, null);
|
||||
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
negativeTv.setOnClickListener(view -> {
|
||||
if (clListener != null) {
|
||||
clListener.onCancel();
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
positiveTv.setOnClickListener(view -> {
|
||||
if (cmListener != null) {
|
||||
cmListener.onConfirm();
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.setOnDismissListener(dialog1 -> {
|
||||
if (clListener != null) {
|
||||
clListener.onCancel();
|
||||
}
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context may be is application context
|
||||
* @return activity context
|
||||
@ -936,6 +1356,7 @@ public class DialogUtils {
|
||||
return context;
|
||||
}
|
||||
|
||||
// currentActivity 是否存在 isDestroyed 的情况?
|
||||
return AppManager.getInstance().currentActivity();
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,8 @@ import android.text.TextUtils
|
||||
import com.gh.base.BaseActivity
|
||||
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.util.EntranceUtils.*
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.amway.AmwayActivity
|
||||
@ -19,6 +21,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.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.mygame.PlayedGameActivity
|
||||
import com.gh.gamecenter.personalhome.UserHomeActivity
|
||||
@ -34,6 +37,9 @@ import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.gh.gamecenter.suggest.SuggestType
|
||||
import com.gh.gamecenter.tag.TagsActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.gh.gamecenter.video.game.GameVideoActivity
|
||||
import com.gh.gamecenter.video.videomanager.VideoManagerActivity
|
||||
import com.lightgame.utils.Util_System_ClipboardManager
|
||||
import com.lightgame.utils.Utils
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
@ -49,27 +55,27 @@ object DirectUtils {
|
||||
@JvmStatic
|
||||
fun directToSpecificPage(context: Context, type: String, link: String, text: String? = "", entrance: String? = null, path: String? = null) {
|
||||
when (type) {
|
||||
EntranceUtils.HOST_ARTICLE -> directToArticle(context, id = link, entrance = entrance)
|
||||
HOST_ARTICLE -> directToArticle(context, id = link, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_GAME -> directToGameDetail(context, id = link, entrance = entrance)
|
||||
HOST_GAME -> directToGameDetail(context, id = link, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_GAME_DOWNLOAD -> directToGameDetail(context, id = link, entrance = entrance, autoDownload = true)
|
||||
HOST_GAME_DOWNLOAD -> directToGameDetail(context, id = link, entrance = entrance, autoDownload = true)
|
||||
|
||||
EntranceUtils.HOST_COLUMN -> directToSubject(context, id = link, subjectName = text, entrance = entrance)
|
||||
HOST_COLUMN -> directToSubject(context, id = link, subjectName = text, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_QUESTION -> directToQuestionDetail(context, id = link, entrance = entrance, path = path)
|
||||
HOST_QUESTION -> directToQuestionDetail(context, id = link, entrance = entrance, path = path)
|
||||
|
||||
EntranceUtils.HOST_ANSWER -> directToAnswerDetail(context, id = link, entrance = entrance, path = path)
|
||||
HOST_ANSWER -> directToAnswerDetail(context, id = link, entrance = entrance, path = path)
|
||||
|
||||
EntranceUtils.HOST_WEB -> directToWebView(context, url = link, entrance = entrance)
|
||||
HOST_WEB -> directToWebView(context, url = link, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_DOWNLOAD -> directToDownloadManagerAndStartDownload(context, gameId = link, packageName = text, entrance = entrance)
|
||||
HOST_DOWNLOAD -> directToDownloadManagerAndStartDownload(context, gameId = link, packageName = text, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_UPDATE -> directToDownloadManagerAndStartUpdate(context, gameId = link, packageName = text, entrance = entrance)
|
||||
HOST_UPDATE -> directToDownloadManagerAndStartUpdate(context, gameId = link, packageName = text, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_LIBAO -> directToGiftDetail(context, giftId = link, entrance = entrance)
|
||||
HOST_LIBAO -> directToGiftDetail(context, giftId = link, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_COMMUNITY -> directToCommunity(context, CommunityEntity(link, text!!))
|
||||
HOST_COMMUNITY -> directToCommunity(context, CommunityEntity(link, text!!))
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,37 +84,87 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String) {
|
||||
directToLinkPage(context, linkEntity, entrance, path, null)
|
||||
}
|
||||
|
||||
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String, exposureEvent: ExposureEvent? = null) {
|
||||
directToLinkPage(context, linkEntity, entrance, path, exposureEvent, null)
|
||||
}
|
||||
|
||||
// 用于判断是否已经对接相关类型
|
||||
var directLinkTypes = arrayOf(
|
||||
"article", "news",
|
||||
"game",
|
||||
"column",
|
||||
"question",
|
||||
"answer",
|
||||
"community",
|
||||
"community_article",
|
||||
"community_column",
|
||||
"community_special_column",
|
||||
"web", "inurl",
|
||||
"qq", "QQ",
|
||||
"qqqun",
|
||||
"tag",
|
||||
"all_community_article",
|
||||
"category",
|
||||
"block",
|
||||
"column_collection",
|
||||
"server",
|
||||
"top_game_comment",
|
||||
"wechat_bind",
|
||||
"video")
|
||||
|
||||
fun directToLinkPage(context: Context,
|
||||
linkEntity: LinkEntity,
|
||||
entrance: String,
|
||||
path: String,
|
||||
exposureEvent: ExposureEvent? = null,
|
||||
unknownCallback: (() -> Unit)?) {
|
||||
when (linkEntity.type) {
|
||||
"article", "news" -> {
|
||||
"article", "news", "文章" -> {
|
||||
NewsUtils.statNewsViews(context, linkEntity.link) // 统计阅读量
|
||||
context.startActivity(NewsDetailActivity.getIntentById(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path)))
|
||||
}
|
||||
|
||||
"game" -> GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
"game", "游戏" -> {
|
||||
if (exposureEvent != null) {
|
||||
GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path), exposureEvent)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
}
|
||||
}
|
||||
|
||||
"column" -> SubjectActivity.startSubjectActivity(context, linkEntity.link, linkEntity.text, false, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
"column", "游戏专题" -> SubjectActivity.startSubjectActivity(context, linkEntity.link, linkEntity.text, false, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
|
||||
"question" -> context.startActivity(QuestionsDetailActivity.getIntent(context, linkEntity.link, entrance, path))
|
||||
"question", "社区问题" -> context.startActivity(QuestionsDetailActivity.getIntent(context, linkEntity.link, entrance, path))
|
||||
|
||||
"answer" -> context.startActivity(AnswerDetailActivity.getIntent(context, linkEntity.link, entrance, path))
|
||||
"answer", "社区回答" -> context.startActivity(AnswerDetailActivity.getIntent(context, linkEntity.link, entrance, path))
|
||||
|
||||
"community" -> directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
|
||||
"community", "问答社区" -> directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
|
||||
|
||||
"community_article" -> context.startActivity(ArticleDetailActivity.getIntent(context, linkEntity.community!!, linkEntity.link!!, entrance, path))
|
||||
"community_article", "社区文章" -> context.startActivity(ArticleDetailActivity.getIntent(context, linkEntity.community!!, linkEntity.link!!, entrance, path))
|
||||
|
||||
"community_column" -> directToCommunityColumn(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))
|
||||
|
||||
"web", "inurl" -> 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" -> directToQqConversation(context, linkEntity.link)
|
||||
"qq", "QQ" -> directToQqConversation(context, linkEntity.link)
|
||||
|
||||
"outurl" -> directToExternalBrowser(context, linkEntity.link!!)
|
||||
|
||||
"qqqun" -> directToQqGroup(context, linkEntity.link!!)
|
||||
"qqqun", "QQ群" -> directToQqGroup(context, linkEntity.link!!)
|
||||
|
||||
"tag" -> context.startActivity(TagsActivity.getIntent(context, linkEntity.text!!, entrance, path))
|
||||
"tag" -> context.startActivity(TagsActivity.getIntent(context, linkEntity.text!!, linkEntity.title, entrance, path))
|
||||
|
||||
"all_community_article" -> {
|
||||
context.startActivity(SimpleArticleListActivity.getIntent(
|
||||
@ -118,11 +174,11 @@ object DirectUtils {
|
||||
path))
|
||||
}
|
||||
|
||||
"category" -> {
|
||||
"category", "分类" -> {
|
||||
context.startActivity(CategoryDirectoryActivity.getIntent(context, linkEntity.link!!, linkEntity.text!!))
|
||||
}
|
||||
|
||||
"block" -> {
|
||||
"block", "版块" -> {
|
||||
context.startActivity(BlockActivity.getIntent(context, SubjectRecommendEntity(
|
||||
link = linkEntity.link,
|
||||
text = linkEntity.text,
|
||||
@ -130,9 +186,9 @@ object DirectUtils {
|
||||
display = linkEntity.display ?: Display())))
|
||||
}
|
||||
|
||||
"column_collection" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
|
||||
"column_collection", "专题合集" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
|
||||
|
||||
"server" -> {
|
||||
"server", "game_server" -> {
|
||||
context.startActivity(GameServersActivity.getIntent(context, entrance, path))
|
||||
}
|
||||
|
||||
@ -140,15 +196,57 @@ object DirectUtils {
|
||||
|
||||
"wechat_bind" -> context.startActivity(WebActivity.getBindWechatIntent(context))
|
||||
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
"video", "video_stream" -> directToVideoDetail(context,
|
||||
videoId = linkEntity.link!!,
|
||||
fromLocation = VideoDetailContainerViewModel.Location.VIDEO_CHOICENESS.value,
|
||||
entrance = entrance,
|
||||
path = path)
|
||||
|
||||
"game_video" -> directToGameVideo(context, linkEntity.link ?: "", entrance, path)
|
||||
|
||||
"libao" -> directToGiftDetail(context, linkEntity.link ?: "", entrance)
|
||||
|
||||
"feedback" -> directToFeedback(context, linkEntity.name, linkEntity.text, entrance)
|
||||
|
||||
"qa" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "")
|
||||
|
||||
"qa_collection" -> directToQaCollection(context, linkEntity.text ?: "", linkEntity.link
|
||||
?: "")
|
||||
|
||||
"anliwall" -> directToAmway(context, fixedTopAmwayCommentId = null, entrance = entrance, path = path)
|
||||
|
||||
"" -> {
|
||||
// do nothing
|
||||
}
|
||||
else -> {
|
||||
if (unknownCallback != null) {
|
||||
unknownCallback.invoke()
|
||||
} else {
|
||||
DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至QA
|
||||
*/
|
||||
fun directToQa(context: Context, text: String, id: String) {
|
||||
context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaId = id))
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至QA合集
|
||||
*/
|
||||
fun directToQaCollection(context: Context, text: String, id: String) {
|
||||
context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaCollectionId = id))
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至专题合集
|
||||
*/
|
||||
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String) {
|
||||
context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance))
|
||||
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String, columnName: String = "") {
|
||||
context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance, columnName))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -171,6 +269,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)
|
||||
}
|
||||
|
||||
/**
|
||||
* 回到首页
|
||||
*/
|
||||
@ -183,15 +296,34 @@ 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) {
|
||||
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)
|
||||
}
|
||||
bundle.putBoolean(KEY_AUTO_DOWNLOAD, autoDownload ?: false)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转视频流-游戏介绍进入
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameDetailVideoStreaming(context: Context, id: String, entrance: String? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameVideoActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
bundle.putBoolean(KEY_OPEN_VIDEO_STREAMING, true)
|
||||
bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_DESC)
|
||||
// GameDetailActivity.startGameDetailToVideoStreaming(context, id, entrance)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
// 跳转至用户玩过的游戏
|
||||
fun directToPlayedGame(context: Context, userId: String, entrance: String = "", path: String = "") {
|
||||
context.startActivity(PlayedGameActivity.getIntent(context, userId, entrance, path))
|
||||
@ -211,12 +343,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)
|
||||
}
|
||||
|
||||
@ -309,16 +450,16 @@ object DirectUtils {
|
||||
context.startActivity(browserIntent)
|
||||
}
|
||||
|
||||
// 跳转 QQ
|
||||
// 跳转 QQ,qqNumber 为空选择默认客服 QQ
|
||||
@JvmStatic
|
||||
fun directToQqConversation(context: Context, qqNumber: String? = null) {
|
||||
var qq = qqNumber
|
||||
|
||||
if (TextUtils.isEmpty(qq)) {
|
||||
qq = "2586716223"
|
||||
qq = Config.getSettings()?.support?.qq ?: "3509629529"
|
||||
}
|
||||
if (ShareUtils.isQQClientAvailable(context)) {
|
||||
// 安装了 QQ 直接调用QQ,打开手机QQ进行会话 默认 QQ 号:2586716223
|
||||
// 安装了 QQ 直接调用QQ,打开手机QQ进行会话 默认 QQ 号:3509629529
|
||||
val chatType: String
|
||||
if (qq!!.startsWith("400") || qq.startsWith("800")) {
|
||||
chatType = "crm"
|
||||
@ -345,6 +486,7 @@ object DirectUtils {
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
// 未安装手Q或安装的版本不支持
|
||||
Utils.toast(context, "请安装QQ客户端")
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -380,6 +522,21 @@ object DirectUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToCommunity(context: Context) {
|
||||
if (MainActivity::class.java.name != RunningUtils.getTopActivity(context)) {
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
// 这里换个线程操作是为了做一点延时
|
||||
AppExecutor.ioExecutor.execute {
|
||||
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_ASK))
|
||||
EventBus.getDefault().post(EBReuse(CommunityFragment.EB_RETRY_PAGE))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToCommunityArticle(context: Context, articleId: String?, communityId: String?, entrance: String?, path: String?) {
|
||||
val bundle = Bundle()
|
||||
@ -409,21 +566,30 @@ object DirectUtils {
|
||||
* @param fromLocation 可见 [VideoDetailContainerViewModel.Location]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, entrance: String? = null, path: 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)
|
||||
bundle.putString(KEY_TO, VideoDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_ID, videoId)
|
||||
bundle.putString(KEY_GAMEID, gameId)
|
||||
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
|
||||
@ -445,4 +611,40 @@ object DirectUtils {
|
||||
fun directToBadgeWall(context: Context, userId: String?, name: String?, icon: String?) {
|
||||
context.startActivity(WebActivity.getBadgeCenterIntent(context, userId, name, icon))
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至上传视频
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToVideoManager(context: Context, linkEntity: VideoLinkEntity, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putParcelable(VideoLinkEntity::class.java.simpleName, linkEntity)
|
||||
bundle.putString(KEY_TO, VideoManagerActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转视频合集
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameVideo(context: Context, gameId: String, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_TO, GameVideoActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
bundle.putString(KEY_GAMEID, gameId)
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,19 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Display;
|
||||
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;
|
||||
|
||||
@ -17,7 +25,7 @@ import java.lang.reflect.Method;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class DisplayUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 根据手机的分辨率从 dip(像素) 的单位 转成为 px
|
||||
*/
|
||||
@ -25,7 +33,7 @@ public class DisplayUtils {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据手机的分辨率从 px(像素) 的单位 转成为 dip
|
||||
*/
|
||||
@ -33,19 +41,19 @@ public class DisplayUtils {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (pxValue / scale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据手机的分辨率从 dip(像素) 的单位 转成为 px
|
||||
*/
|
||||
public static int dip2px(float dpValue) {
|
||||
final float scale = HaloApp.getInstance()
|
||||
.getApplication()
|
||||
.getResources()
|
||||
.getDisplayMetrics().density;
|
||||
.getApplication()
|
||||
.getResources()
|
||||
.getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 将px值转换为sp值,保证文字大小不变
|
||||
*
|
||||
@ -57,7 +65,7 @@ public class DisplayUtils {
|
||||
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
|
||||
return (int) (pxValue / fontScale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将sp值转换为px值,保证文字大小不变
|
||||
*
|
||||
@ -69,7 +77,7 @@ public class DisplayUtils {
|
||||
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
|
||||
return (int) (spValue * fontScale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取状态栏的高度
|
||||
*
|
||||
@ -79,7 +87,7 @@ public class DisplayUtils {
|
||||
public static int getStatusBarHeight(Resources resources) {
|
||||
return getInternalDimensionSize(resources, "status_bar_height");
|
||||
}
|
||||
|
||||
|
||||
public static int getInternalDimensionSize(Resources res, String key) {
|
||||
int result = 0;
|
||||
int resourceId = res.getIdentifier(key, "dimen", "android");
|
||||
@ -88,7 +96,7 @@ public class DisplayUtils {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static void transparentStatusBar(Activity activity) {
|
||||
//make full transparent statusBar
|
||||
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
|
||||
@ -96,15 +104,15 @@ public class DisplayUtils {
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
setWindowFlag(activity, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false);
|
||||
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void transparentStatusAndNavigation(Activity activity) {
|
||||
//make full transparent statusBar
|
||||
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
|
||||
@ -112,8 +120,8 @@ public class DisplayUtils {
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
setWindowFlag(activity, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, false);
|
||||
@ -121,7 +129,7 @@ public class DisplayUtils {
|
||||
activity.getWindow().setNavigationBarColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void setWindowFlag(Activity activity, final int bits, boolean on) {
|
||||
Window win = activity.getWindow();
|
||||
WindowManager.LayoutParams winParams = win.getAttributes();
|
||||
@ -132,14 +140,12 @@ public class DisplayUtils {
|
||||
}
|
||||
win.setAttributes(winParams);
|
||||
}
|
||||
|
||||
public static void setLightStatusBar(Activity activity, boolean lightStatusBar) {
|
||||
boolean isMIUI = setMIUIStatusBarStyle(activity, lightStatusBar);
|
||||
|
||||
if (!isMIUI) {
|
||||
|
||||
public static void setLightStatusBar(Activity activity, boolean lightStatusBar, boolean isKeepLowVersionMiui) {
|
||||
if (!isMiuiOs()) {
|
||||
Window window = activity.getWindow();
|
||||
View decor = window.getDecorView();
|
||||
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (lightStatusBar) {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
@ -149,46 +155,128 @@ public class DisplayUtils {
|
||||
} else {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
} else {
|
||||
setMIUIStatusBarStyle(activity, lightStatusBar, isKeepLowVersionMiui);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean setMIUIStatusBarStyle(Activity activity, boolean lightStatusBar) {
|
||||
boolean result = false;
|
||||
Window window = activity.getWindow();
|
||||
if (window != null) {
|
||||
Class clazz = window.getClass();
|
||||
try {
|
||||
int darkModeFlag = 0;
|
||||
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
extraFlagField.invoke(window, lightStatusBar ? darkModeFlag : 0, darkModeFlag);//状态栏透明且黑色字体
|
||||
result = true;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && lightStatusBar) {
|
||||
//开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void setStatusBarColor(Activity activity, int color, boolean lightStatusBar) {
|
||||
public static void setLightStatusBar(Activity activity, boolean lightStatusBar) {
|
||||
setLightStatusBar(activity, lightStatusBar, true);
|
||||
}
|
||||
|
||||
private static void setMIUIStatusBarStyle(Activity activity, boolean lightStatusBar, boolean isKeepLowVersionMiui) {
|
||||
Window window = activity.getWindow();
|
||||
if (window != null) {
|
||||
|
||||
View decor = window.getDecorView();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (lightStatusBar) {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
} else {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
} else {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
|
||||
if (isKeepLowVersionMiui) {
|
||||
Class clazz = window.getClass();
|
||||
try {
|
||||
int darkModeFlag = 0;
|
||||
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
extraFlagField.invoke(window, lightStatusBar ? darkModeFlag : 0, darkModeFlag);//状态栏透明且黑色字体
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && lightStatusBar) {
|
||||
//开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void setStatusBarColor(Activity activity, int color, boolean lightStatusBar) {
|
||||
Window window = activity.getWindow();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.setStatusBarColor(ContextCompat.getColor(activity,color));
|
||||
window.setStatusBarColor(ContextCompat.getColor(activity, color));
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
|
||||
setLightStatusBar(activity,lightStatusBar);
|
||||
setLightStatusBar(activity, lightStatusBar);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static boolean isMiuiOs() {
|
||||
String property = getSystemProperty("ro.miui.ui.version.name", "");
|
||||
return !TextUtils.isEmpty(property);
|
||||
}
|
||||
|
||||
private static String getSystemProperty(String key, String defaultValue) {
|
||||
try {
|
||||
@SuppressLint("PrivateApi") Class<?> clz = Class.forName("android.os.SystemProperties");
|
||||
Method method = clz.getMethod("get", String.class, String.class);
|
||||
return (String) method.invoke(clz, key, defaultValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static int retrieveNavigationHeight(Context context) {
|
||||
Resources resources = context.getResources();
|
||||
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||
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 boolean hasSoftKeys(Context context) {
|
||||
if (!(context instanceof Activity)) return false;
|
||||
|
||||
boolean hasSoftwareKeys;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
Display d = ((Activity) context).getWindowManager().getDefaultDisplay();
|
||||
|
||||
DisplayMetrics realDisplayMetrics = new DisplayMetrics();
|
||||
d.getRealMetrics(realDisplayMetrics);
|
||||
|
||||
int realHeight = realDisplayMetrics.heightPixels;
|
||||
int realWidth = realDisplayMetrics.widthPixels;
|
||||
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
d.getMetrics(displayMetrics);
|
||||
|
||||
int displayHeight = displayMetrics.heightPixels;
|
||||
int displayWidth = displayMetrics.widthPixels;
|
||||
|
||||
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0;
|
||||
} else {
|
||||
boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
|
||||
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
|
||||
hasSoftwareKeys = !hasMenuKey && !hasBackKey;
|
||||
}
|
||||
return hasSoftwareKeys;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
@ -14,17 +15,21 @@ 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.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;
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadConfig;
|
||||
@ -35,6 +40,9 @@ import com.lightgame.utils.Utils;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* todo 下载判断不能以按钮文案为判断条件,否则按钮文案修改时又要修改判断逻辑
|
||||
*/
|
||||
public class DownloadItemUtils {
|
||||
|
||||
// 更新下载进度条
|
||||
@ -122,20 +130,20 @@ 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
|
||||
boolean isShowPlatform, PluginLocation pluginLocation, boolean hideDownloadBtnIfNoAvailableContent) {
|
||||
|
||||
// 控制是否显示下载按钮
|
||||
if (!Config.isShowDownload(gameEntity.getId()) || context.getString(R.string.app_name).equals(gameEntity.getName())) {
|
||||
@ -144,12 +152,6 @@ 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);
|
||||
@ -167,22 +169,37 @@ public class DownloadItemUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gameEntity.getApk().isEmpty() || gameEntity.getDownloadOffStatus() != null) {
|
||||
if (gameEntity.getApk().isEmpty()
|
||||
|| 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);
|
||||
|
||||
String offStatus = gameEntity.getDownloadOffStatus();
|
||||
if ("dialog".equals(offStatus)) {
|
||||
holder.gameDownloadBtn.setText("查看");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.white));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
|
||||
if (h5LinkEntity != null) {
|
||||
if ("play".equals(h5LinkEntity.getType())) {
|
||||
holder.gameDownloadBtn.setText("开始玩");
|
||||
} else {
|
||||
holder.gameDownloadBtn.setText("查看");
|
||||
}
|
||||
holder.gameDownloadBtn.setClickable(true);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setText("暂无");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.button_gray));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.news_detail_comment);
|
||||
if ("dialog".equals(offStatus)) {
|
||||
holder.gameDownloadBtn.setText("查看");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.white));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
updateNormalItem(context, holder, gameEntity, isShowPlatform, pluginLocation);
|
||||
} else {
|
||||
@ -319,10 +336,10 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -374,7 +391,10 @@ public class DownloadItemUtils {
|
||||
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(context, () -> {
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
|
||||
gameEntity,
|
||||
() -> adapter.notifyItemChanged(position)
|
||||
() -> {
|
||||
LogUtils.logReservation(gameEntity, traceEvent);
|
||||
adapter.notifyItemChanged(position);
|
||||
}
|
||||
);
|
||||
dialogFragment.show(((AppCompatActivity) context).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
@ -403,7 +423,13 @@ public class DownloadItemUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
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()));
|
||||
context.startActivity(i);
|
||||
});
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
EmptyCallback clickRunnable = () -> {
|
||||
if (clickCallback != null) {
|
||||
@ -425,7 +451,15 @@ 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,
|
||||
entrance,
|
||||
location);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -456,19 +490,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, 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))) {
|
||||
@ -512,8 +565,7 @@ public class DownloadItemUtils {
|
||||
downloadBtn.setText(R.string.downloading);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
|
||||
|
||||
// DownloadManager.getInstance(context).putStatus(gameEntity.getApk().get(0).getUrl(), "downloading");
|
||||
DeviceRemindDialog.Companion.showDeviceRemindDialog(context, gameEntity);
|
||||
} else {
|
||||
Utils.toast(context, msg);
|
||||
}
|
||||
@ -534,8 +586,6 @@ public class DownloadItemUtils {
|
||||
downloadBtn.setText(R.string.downloading);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
|
||||
|
||||
// DownloadManager.getInstance(context).putStatus(gameEntity.getApk().get(0).getUrl(), "downloading");
|
||||
} else {
|
||||
Utils.toast(context, msg);
|
||||
}
|
||||
@ -555,17 +605,23 @@ 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, path);
|
||||
PackageUtils.launchSetup(context, downloadEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//更新
|
||||
private static void update(Context context, GameEntity gameEntity, String entrance, String location,
|
||||
boolean isSubscribe, @Nullable ExposureEvent traceEvent) {
|
||||
DataUtils.onGameUpdateEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), "下载开始");
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, gameEntity.getApk().get(0).getPlatform(), traceEvent, ExposureUtils.DownloadType.UPDATE);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,161 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
|
||||
object DownloadNotificationHelper {
|
||||
|
||||
private const val DOWNLOAD_GROUP_KEY = "download_group_key"
|
||||
private const val DOWNLOAD_CHANNEL_ID = "download"
|
||||
private const val DOWNLOAD_NOTIFICATION_FOLD_ID = 889
|
||||
private const val DOWNLOAD_NOTIFICATION_ID = 888
|
||||
private const val PROGRESS_MAX = 100
|
||||
|
||||
const val ACTION_INSTALL = "com.gh.gamecenter.INSTALL"
|
||||
const val ACTION_DOWNLOAD = "com.gh.gamecenter.DOWNLOAD"
|
||||
|
||||
private val mNotifyMap: MutableMap<String, Long> = mutableMapOf()
|
||||
|
||||
private fun getNotificationManager(): NotificationManager {
|
||||
return HaloApp.getInstance().application.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Synchronized
|
||||
fun addOrUpdateDownloadNotification(entity: DownloadEntity) {
|
||||
var requireUpdateNotificationGroupDelay = false
|
||||
val notificationManager = getNotificationManager()
|
||||
val downloadNotificationId = (entity.gameId + entity.packageName).hashCode()
|
||||
|
||||
val intent = Intent()
|
||||
if (entity.status == DownloadStatus.done) {
|
||||
intent.putExtra(EntranceUtils.KEY_DATA, entity.toJson())
|
||||
intent.putExtra(EntranceUtils.KEY_PATH, entity.path)
|
||||
intent.action = ACTION_INSTALL
|
||||
} else {
|
||||
intent.action = ACTION_DOWNLOAD
|
||||
}
|
||||
val pendingIntent = PendingIntent.getBroadcast(HaloApp.getInstance().application,
|
||||
downloadNotificationId,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// importance == IMPORTANCE_DEFAULT 时每次更新都会触发震动
|
||||
val channel = NotificationChannel(DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
val whenTime = 1000 * 60 * (System.currentTimeMillis() / 1000 / 60)
|
||||
val builder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
|
||||
.setContentTitle(entity.name)
|
||||
.setSmallIcon(R.mipmap.logo)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setGroup(DOWNLOAD_GROUP_KEY)
|
||||
.setWhen(whenTime)
|
||||
.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
|
||||
|
||||
when (entity.status) {
|
||||
DownloadStatus.downloading -> builder.setContentText(String.format("%s(剩%s)",
|
||||
SpeedUtils.getSpeed(entity.speed),
|
||||
SpeedUtils.getRemainTime(entity.size, entity.progress, entity.speed * 1024)))
|
||||
DownloadStatus.done -> builder.setContentText("下载完成,点击立即安装")
|
||||
DownloadStatus.waiting -> builder.setContentText("等待中")
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.neterror -> builder.setContentText("已暂停,连接WiFi自动下载")
|
||||
else -> builder.setContentText("暂停中")
|
||||
}
|
||||
|
||||
when {
|
||||
entity.status == DownloadStatus.done -> {
|
||||
builder.setSortKey("A")
|
||||
builder.setOngoing(true) // 垃圾华为 sortKey 不起效 priority 也不起效,要将下载完成任务的通知置顶只能设置为 ongoing,喷了
|
||||
}
|
||||
entity.status == DownloadStatus.downloading -> builder.setSortKey("B")
|
||||
else -> builder.setSortKey("C")
|
||||
}
|
||||
|
||||
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)
|
||||
} 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 常驻
|
||||
AppExecutor.uiExecutor.executeWithDelay(Runnable { updateNotificationGroup() }, 100)
|
||||
} else {
|
||||
updateNotificationGroup()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateNotificationGroup() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val notificationManager = getNotificationManager()
|
||||
val activeNotifications = notificationManager.activeNotifications
|
||||
var downloadNotificationSize = 0
|
||||
var downloadGroupNotificationSize = 0
|
||||
for (activeNotification in activeNotifications) {
|
||||
if (activeNotification.id == DOWNLOAD_NOTIFICATION_ID) {
|
||||
downloadNotificationSize++
|
||||
}
|
||||
if (activeNotification.id == DOWNLOAD_NOTIFICATION_FOLD_ID) {
|
||||
downloadGroupNotificationSize++
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadNotificationSize == 0 && downloadGroupNotificationSize != 0) {
|
||||
// 删除组可能会把组内所有通知一并删除
|
||||
notificationManager.cancel(DOWNLOAD_NOTIFICATION_FOLD_ID)
|
||||
} else if (downloadNotificationSize != 0 && downloadGroupNotificationSize == 0) {
|
||||
val groupBuilder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
|
||||
.setSmallIcon(R.mipmap.logo)
|
||||
.setGroup(DOWNLOAD_GROUP_KEY)
|
||||
.setGroupSummary(true)
|
||||
.setStyle(NotificationCompat.BigTextStyle().bigText("下载任务"))
|
||||
val groupNotification = groupBuilder.build()
|
||||
groupNotification.flags = groupNotification.flags or Notification.FLAG_NO_CLEAR
|
||||
notificationManager.notify(DOWNLOAD_NOTIFICATION_FOLD_ID, groupNotification)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun initDownloadNotification(downloadTasks: MutableList<DownloadEntity>) {
|
||||
for (downloadTask in downloadTasks) {
|
||||
addOrUpdateDownloadNotification(downloadTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
239
app/src/main/java/com/gh/common/util/DownloadObserver.kt
Normal file
239
app/src/main/java/com/gh/common/util/DownloadObserver.kt
Normal file
@ -0,0 +1,239 @@
|
||||
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
|
||||
|
||||
@JvmStatic
|
||||
fun initObserver() {
|
||||
val dataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
val gameId = downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER)
|
||||
|
||||
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.getInstance(mApplication).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) {
|
||||
|
||||
Utils.toast(mApplication, "网络不稳定,下载任务已暂停")
|
||||
DataLogUtils.uploadNeterrorLog(mApplication, downloadEntity)
|
||||
|
||||
MtaHelper.onEventWithBasicDeviceInfo("下载自动暂停",
|
||||
"游戏", downloadEntity.name,
|
||||
"平台", downloadEntity.platform)
|
||||
}
|
||||
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.getInstance(mApplication).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)
|
||||
}
|
||||
}
|
||||
|
||||
// 添加观察者
|
||||
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(downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER), downloadEntity.name),
|
||||
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,12 +22,20 @@ 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 HOST_ARTICLE = "article";
|
||||
public static final String HOST_UPLOAD_VIDEO = "upload_video";//上传视频
|
||||
public static final String HOST_VIDEO_SINGLE = "video_single";//指定视频-不能划动
|
||||
public static final String HOST_VIDEO_MORE = "video_more";//指定视频-能划动
|
||||
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_COMMUNITY_ARTICLE = "community_article";
|
||||
public static final String HOST_COMMUNITY_COLUMN = "community_column";
|
||||
@ -32,6 +44,7 @@ public class EntranceUtils {
|
||||
public static final String HOST_COLUMN = "column";
|
||||
public static final String HOST_WEB = "web";
|
||||
public static final String HOST_QQ = "qq";
|
||||
public static final String HOST_QQ_GROUP = "qqgroup";
|
||||
public static final String HOST_DOWNLOAD = "download";
|
||||
public static final String HOST_UPDATE = "update";
|
||||
public static final String HOST_LIBAO = "libao";
|
||||
@ -48,6 +61,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_NAME = "name";
|
||||
public static final String KEY_POSITION = "position";
|
||||
public static final String KEY_ENTRANCE = "entrance";
|
||||
public static final String KEY_ENTRANCE_LINK = "entrance_link";
|
||||
public static final String KEY_TARGET = "target";
|
||||
public static final String ENTRANCE_BROWSER = "(浏览器)";
|
||||
public static final String ENTRANCE_WELCOME = "(启动弹窗)";
|
||||
@ -72,6 +86,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";
|
||||
@ -99,6 +114,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";
|
||||
@ -123,10 +139,24 @@ 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";
|
||||
public static final String KEY_OPEN_VIDEO_STREAMING = "openVideoStreaming";
|
||||
public static final String KEY_REFERER = "referer";
|
||||
public static final String KEY_UUID = "uuid";
|
||||
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 void jumpActivity(Context context, Bundle bundle) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
//TODO 把其他类似的跳转启动逻辑也处理掉
|
||||
if (RunningUtils.isRunning(context)
|
||||
@ -149,4 +179,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.ErrorEntity
|
||||
@ -22,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
|
||||
@ -32,11 +37,7 @@ object ErrorHelper {
|
||||
return
|
||||
}
|
||||
|
||||
if (customizedHandler(errorEntity.code ?: 0)) {
|
||||
return
|
||||
} else {
|
||||
handleError(context, showHighPriorityHint, errorEntity)
|
||||
}
|
||||
handleError(context, showHighPriorityHint, errorEntity)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,13 +111,15 @@ object ErrorHelper {
|
||||
403016 -> Utils.toast(context, "标签内容可能包含敏感信息,请修改后再提交")
|
||||
403018 -> Utils.toast(context, R.string.comment_failed_unable)
|
||||
403070 -> Utils.toast(context, "请勿重复提交~")
|
||||
403073 -> Utils.toast(context, "标题可能包含敏感词,请修改后再提交")
|
||||
403073 -> Utils.toast(context, "标题违规,请重新编辑")
|
||||
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 {
|
||||
@ -143,7 +146,7 @@ object ErrorHelper {
|
||||
val dialogContext = DialogUtils.checkDialogContext(context)
|
||||
DialogUtils.showAlertDialog(dialogContext,
|
||||
"提示",
|
||||
"你因违反《光环助手评论规则》,已被禁言,如有疑问$bannedType,请联系客服(QQ:3467475980)",
|
||||
"你因违反《光环助手评论规则》,已被禁言$bannedType,如有疑问,请联系客服(QQ:${Config.getSettings()?.support?.qq})",
|
||||
"去看看", "关闭", {
|
||||
dialogContext.startActivity(WebActivity.getCommentRulesIntent(dialogContext))
|
||||
}, null)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.animation.Animator
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.text.Editable
|
||||
@ -12,12 +13,14 @@ 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
|
||||
import androidx.lifecycle.*
|
||||
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.constant.Config
|
||||
import com.gh.common.constant.Constants
|
||||
@ -26,9 +29,13 @@ import com.gh.gamecenter.R
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import java.net.URI
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
@ -216,6 +223,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
|
||||
*/
|
||||
@ -223,6 +253,11 @@ fun String.fromHtml(): Spanned {
|
||||
return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||
}
|
||||
|
||||
// 将双引号换成单引号避免 JSON 解析异常 ( escape 后会有其它异常,暂时先替换成单引号了)
|
||||
fun String.eliminateDoubleQuote(): String {
|
||||
return this.replace("\"", "'")
|
||||
}
|
||||
|
||||
// 去掉文章/答案的插入内容
|
||||
fun String.removeInsertedContent(): String {
|
||||
val textRegex = "(?s)<div class=\"gh-internal-content content-right\".*?</div>"
|
||||
@ -262,6 +297,16 @@ fun Map<String, String>.createRequestBody(): RequestBody {
|
||||
return RequestBody.create(MediaType.parse("application/json"), json)
|
||||
}
|
||||
|
||||
fun Map<String, Any>.createRequestBodyAny(): RequestBody {
|
||||
val json = GsonUtils.toJson(this)
|
||||
return RequestBody.create(MediaType.parse("application/json"), json)
|
||||
}
|
||||
|
||||
fun Any.toRequestBody(): RequestBody {
|
||||
val json = GsonUtils.toJson(this)
|
||||
return RequestBody.create(MediaType.parse("application/json"), json)
|
||||
}
|
||||
|
||||
// 对在浏览器(WebView)显示的路径进行转码
|
||||
fun String.decodeURI(): String {
|
||||
return URI(null, null, this, null).rawPath
|
||||
@ -285,8 +330,9 @@ fun Float.px2dip(): Int {
|
||||
|
||||
/**
|
||||
* PopupWindow 自动适配方向
|
||||
* 弹出与锚点右对齐
|
||||
*/
|
||||
fun PopupWindow.showAutoOrientation(anchorView: View, distanceY: Int = 0) {
|
||||
fun PopupWindow.showAutoOrientation(anchorView: View, distanceY: Int = 0, distanceX: Int = 0) {
|
||||
val windowPos = IntArray(2)
|
||||
val anchorLoc = IntArray(2)
|
||||
// 获取锚点View在屏幕上的左上角坐标位置
|
||||
@ -294,21 +340,18 @@ fun PopupWindow.showAutoOrientation(anchorView: View, distanceY: Int = 0) {
|
||||
val anchorHeight = anchorView.height + distanceY
|
||||
// 获取屏幕的高宽
|
||||
val screenHeight = anchorView.context.resources.displayMetrics.heightPixels
|
||||
val screenWidth = anchorView.context.resources.displayMetrics.widthPixels
|
||||
// 测量contentView
|
||||
contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
|
||||
// 计算contentView的高宽
|
||||
val windowHeight = contentView.measuredHeight
|
||||
val windowWidth = contentView.measuredWidth
|
||||
|
||||
// 判断需要向上弹出还是向下弹出显示
|
||||
val isNeedShowUp = screenHeight - anchorLoc[1] - anchorHeight < windowHeight
|
||||
if (isNeedShowUp) {
|
||||
windowPos[0] = screenWidth - windowWidth
|
||||
windowPos[1] = anchorLoc[1] - windowHeight
|
||||
} else {
|
||||
windowPos[0] = screenWidth - windowWidth
|
||||
windowPos[1] = anchorLoc[1] + anchorHeight
|
||||
}
|
||||
windowPos[1] = if (isNeedShowUp) {
|
||||
anchorLoc[1] - windowHeight
|
||||
} else anchorLoc[1] + anchorHeight
|
||||
windowPos[0] = anchorLoc[0] - windowWidth + anchorView.width - distanceX
|
||||
|
||||
animationStyle = R.style.popwindow_option_anim_style
|
||||
showAtLocation(anchorView, Gravity.TOP or Gravity.START, windowPos[0], windowPos[1])
|
||||
@ -371,7 +414,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> {
|
||||
@ -400,7 +443,7 @@ fun TextView.setTextChangedListener(action: (s: CharSequence, start: Int, before
|
||||
}
|
||||
|
||||
fun Int.toColor(): Int {
|
||||
return HaloApp.getInstance().application.resources.getColor(this)
|
||||
return ContextCompat.getColor(HaloApp.getInstance().application, this)
|
||||
}
|
||||
|
||||
fun Int.toResString(): String {
|
||||
@ -431,4 +474,76 @@ inline fun testChannelOnly(f: () -> Unit) {
|
||||
if (HaloApp.getInstance().channel == Config.DEFAULT_CHANNEL) {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 倒计时,单位s
|
||||
*/
|
||||
inline fun countDownTimer(
|
||||
millisUntilFinish: Long,
|
||||
crossinline block: (finish: Boolean, millisUntilFinished: 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)
|
||||
} else {
|
||||
block.invoke(true, 0)
|
||||
if (subscribe != null && !subscribe!!.isDisposed) {
|
||||
subscribe?.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
return subscribe
|
||||
}
|
||||
|
||||
/**
|
||||
* 正计时
|
||||
* @start 起始时间
|
||||
*/
|
||||
inline fun countUpTimer(
|
||||
start: Long,
|
||||
period: Long = 1000,
|
||||
crossinline block: (millisUntilFinished: Long) -> Unit
|
||||
): Disposable {
|
||||
var startTime = start
|
||||
return Observable.interval(0, period, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
startTime += period
|
||||
block.invoke(startTime)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计时器(注意不需要的时候要取消订阅)
|
||||
*/
|
||||
inline fun rxTimer(interval: Long, crossinline block: (times: Long) -> Unit): Disposable {
|
||||
return Observable.interval(0, interval, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
block.invoke(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun LottieAnimationView.doOnAnimationEnd(action: () -> Unit) {
|
||||
this.addAnimatorListener(object : Animator.AnimatorListener {
|
||||
override fun onAnimationRepeat(animation: Animator?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
action.invoke()
|
||||
}
|
||||
|
||||
override fun onAnimationCancel(animation: Animator?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onAnimationStart(animation: Animator?) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -82,11 +82,70 @@ object GameRepositoryHelper {
|
||||
return null
|
||||
}
|
||||
|
||||
fun replaceInstalledApp(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 isThisPositionAdded = false
|
||||
// 检查是否已安装该游戏里同包名的 APK
|
||||
for (apk in game.getApk()) {
|
||||
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
|
||||
// 将该位置的游戏标记为需要替换
|
||||
positionOfTheGameToReplaceList.add(index)
|
||||
isThisPositionAdded = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 若此游戏所包含的 apk 没有已安装,那么再检查是否已安装有预设相关包名
|
||||
if (!isThisPositionAdded) {
|
||||
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 {
|
||||
// 若该补充游戏已经存在关联关系,判定为非唯一
|
||||
for (relatedId in game.relatedGameIds!!) {
|
||||
gameIdList.contains(relatedId)
|
||||
return false
|
||||
if (gameIdList.contains(relatedId)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for (apk in game.getApk()) {
|
||||
// 检查本地是否已安装该游戏,已过滤那部分框架服务的包名
|
||||
|
||||
@ -2,7 +2,6 @@ package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -10,6 +9,8 @@ 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;
|
||||
@ -18,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 {
|
||||
|
||||
@ -52,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,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; // 可更新数量
|
||||
@ -117,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();
|
||||
@ -148,7 +197,51 @@ public class GameUtils {
|
||||
gameUpdateEntity.setBrief(gameEntity.getBrief());
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@ package com.gh.common.util;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
@ -11,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;
|
||||
|
||||
@ -31,17 +33,34 @@ import java.util.TimeZone;
|
||||
*/
|
||||
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()) {
|
||||
if (tagStyle == null || tagStyle.isEmpty()) {
|
||||
TagStyleEntity tagEntity = new TagStyleEntity();
|
||||
tagEntity.setName("官方版");
|
||||
labelLayout.addView(getNewGameTagView(context, tagEntity, 0));
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setLabelList(Context context, LinearLayout labelLayout, String tagType, List<TagStyleEntity> tagStyle) {
|
||||
labelLayout.removeAllViews();
|
||||
if (tagStyle == null || tagStyle.isEmpty()) {
|
||||
labelLayout.addView(getGameTagView(context, "官方版", 0, tagType, null));
|
||||
} else {
|
||||
for (int i = 0, size = tag.size(); i < size; i++) {
|
||||
for (int i = 0; i < tagStyle.size() - 1; i++) {
|
||||
View view;
|
||||
if (i == size - 1) {
|
||||
view = getGameTagView(context, tag.get(i), 0, tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
|
||||
if (i == tagStyle.size() - 1) {
|
||||
view = getGameTagView(context, tagStyle.get(i).getName(), 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);
|
||||
view = getGameTagView(context, tagStyle.get(i).getName(), DisplayUtils.dip2px(context, 8), tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
|
||||
}
|
||||
if (view != null) {
|
||||
labelLayout.addView(view);
|
||||
@ -53,6 +72,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);
|
||||
|
||||
@ -15,7 +15,7 @@ class GhMatisseVideoFilter : Filter() {
|
||||
override fun filter(context: Context, item: Item): IncapableCause? {
|
||||
if (!needFiltering(context, item)) return null
|
||||
if (item.mimeType != MimeType.MP4.toString()) {
|
||||
return IncapableCause(IncapableCause.TOAST, "请把视频格式转换为Mp4后再上传")
|
||||
return IncapableCause(IncapableCause.TOAST, "请把视频格式转换为MP4后再上传")
|
||||
}
|
||||
|
||||
if (item.size > 500 * 1024 * 1024) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
app/src/main/java/com/gh/common/util/HomeBottomBarHelper.kt
Normal file
38
app/src/main/java/com/gh/common/util/HomeBottomBarHelper.kt
Normal file
@ -0,0 +1,38 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.gh.gamecenter.entity.Display
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
object HomeBottomBarHelper {
|
||||
private const val GAME_BAR_KEY = "game_bar_key"
|
||||
|
||||
@JvmStatic
|
||||
fun getDefaultGameBarData(): SubjectRecommendEntity {
|
||||
try {
|
||||
val json = SPUtils.getString(GAME_BAR_KEY)
|
||||
if (json.isNotEmpty()) {
|
||||
return GsonUtils.fromJson(json, SubjectRecommendEntity::class.java)
|
||||
}
|
||||
} catch (ignore: Exception) {
|
||||
|
||||
}
|
||||
val animationCode = HaloApp.getInstance().application.assets
|
||||
.open("lottie/tab_game.json")
|
||||
.bufferedReader().use { it.readText() }
|
||||
return SubjectRecommendEntity(link = "5de21b5d75e6fa054f784882",
|
||||
type = "block",
|
||||
text = "游戏库",
|
||||
name = "游戏库",
|
||||
iconSelect = "https://resource.ghzs.com/image/game/library/entrance/5e183202913fbd002c75f247.png",
|
||||
iconUnselect = "https://resource.ghzs.com/image/game/library/entrance/5e1831fd913fbd003024641e.png",
|
||||
animationCode = animationCode,
|
||||
default = false,
|
||||
display = Display())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun updateDefaultGameBarData(data: SubjectRecommendEntity) {
|
||||
SPUtils.setString(GAME_BAR_KEY, data.toJson())
|
||||
}
|
||||
}
|
||||
@ -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()
|
||||
@ -259,7 +261,8 @@ object ImageUtils {
|
||||
}
|
||||
|
||||
// Wifi/4G:x2 traffic:x1
|
||||
private fun getTransformLimitUrl(url: String?, width: Int?, context: Context?): String? {
|
||||
@JvmStatic
|
||||
fun getTransformLimitUrl(url: String?, width: Int?, context: Context?): String? {
|
||||
var transformUrl: String? = url
|
||||
if (width != null && width > 0) {
|
||||
val transformUrlX2 = addLimitWidth(url, width * 2)
|
||||
@ -322,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?)
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ public class InstallUtils {
|
||||
if (!TextUtils.isEmpty(installVersion) && downloadEntity != null &&
|
||||
installVersion.equals(downloadEntity.getVersionName())) {
|
||||
if (!downloadEntity.isPluggable() || PackageUtils.isSignature(context, packageName)) {
|
||||
EventBus.getDefault().post(new EBPackage("安装", 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();
|
||||
|
||||
@ -6,24 +6,102 @@ import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureSource;
|
||||
import com.gh.common.exposure.meta.Meta;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.common.loghub.LoghubUtils;
|
||||
import com.gh.download.DownloadDataHelper;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.CommunityEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.SpecialColumn;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.qa.entity.Questions;
|
||||
import com.gh.loghub.LogHubUtils;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Created by khy on 2/01/18.
|
||||
*/
|
||||
public class LogUtils {
|
||||
|
||||
|
||||
public static void logVideoStreamingUpload(String action, String entrance, String entranceDetail, String videoId) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
|
||||
try {
|
||||
object.put("event", "UPLOAD_VIDEO_STEAMING");
|
||||
object.put("action", action);
|
||||
payloadObject.put("entrance", entrance);
|
||||
payloadObject.put("entrance_detail", entranceDetail);
|
||||
payloadObject.put("video_id", videoId);
|
||||
object.put("payload", payloadObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploadVideoStreaming(object);
|
||||
}
|
||||
|
||||
public static void uploadDownloadEvent(DownloadEntity downloadEntity) {
|
||||
Context context = HaloApp.getInstance().getApplication();
|
||||
Meta meta = MetaUtil.INSTANCE.getMeta();
|
||||
JSONObject object = new JSONObject();
|
||||
|
||||
try {
|
||||
object.put("event", DownloadDataHelper.getDownloadStatusAlias(downloadEntity));
|
||||
object.put("msg", downloadEntity.getError());
|
||||
object.put("status", downloadEntity.getStatus().getStatus());
|
||||
|
||||
// payload
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
payloadObject.put("game_id", downloadEntity.getGameId());
|
||||
payloadObject.put("gameName", downloadEntity.getName());
|
||||
payloadObject.put("platform", downloadEntity.getPlatform());
|
||||
payloadObject.put("package", downloadEntity.getPackageName());
|
||||
payloadObject.put("filename", downloadEntity.getPath().substring(downloadEntity.getPath().lastIndexOf("/") + 1));
|
||||
payloadObject.put("total_size", (downloadEntity.getSize() / 1024 / 1024));
|
||||
payloadObject.put("completed_size", (downloadEntity.getProgress() / 1024 / 1024));
|
||||
|
||||
object.put("payload", payloadObject);
|
||||
|
||||
// meta
|
||||
JSONObject metaObject = new JSONObject();
|
||||
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", DeviceUtils.getNetwork(context));
|
||||
metaObject.put("os", meta.getOs());
|
||||
metaObject.put("userId", meta.getUserId());
|
||||
|
||||
object.put("meta", metaObject);
|
||||
object.put("timestamp", System.currentTimeMillis() / 1000);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->" + object.toString());
|
||||
}
|
||||
LoghubUtils.log(object, "download_debug", false);
|
||||
}
|
||||
|
||||
public static void uploadCommunityArticle(String tracers, String articleId, String articleTitle, int readTime, CommunityEntity community, SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -48,10 +126,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
|
||||
public static void uploadDevice(LunchType launchType) {
|
||||
JSONObject object = new JSONObject();
|
||||
Application application = HaloApp.getInstance().getApplication();
|
||||
@ -63,10 +141,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object, true);
|
||||
}
|
||||
|
||||
|
||||
public static void uploadAnswerReadTime(String tracers, int readTime, String answerId, Questions questions, String communityId, String CommunityName, SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -92,10 +170,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
|
||||
public static void uploadQuestionReadTime(String tracers, int readTime, Questions questions, String communityId, String communityName, SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -120,13 +198,13 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
|
||||
public static void uploadSearch(String searchKey) {
|
||||
if (TextUtils.isEmpty(searchKey)) return;
|
||||
|
||||
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("community_id", UserManager.getInstance().getCommunity().getId());
|
||||
@ -136,11 +214,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void communityRefresh(int dataCount, boolean manualRefresh) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -152,10 +229,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
|
||||
public static void login(String loginStep, String loginType, String entrance) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -166,10 +243,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object, true);
|
||||
}
|
||||
|
||||
|
||||
public static void qaAccess(String access, CommunityEntity communityEntity) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -180,15 +257,42 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
public static void logReservation(GameEntity gameEntity, @Nullable ExposureEvent event) {
|
||||
JSONObject object = new JSONObject();
|
||||
List<ExposureSource> exposureSourceList;
|
||||
|
||||
if (event == null) {
|
||||
exposureSourceList = new ArrayList<>();
|
||||
exposureSourceList.add(new ExposureSource("其它", ""));
|
||||
} else {
|
||||
exposureSourceList = event.getSource();
|
||||
}
|
||||
|
||||
try {
|
||||
object.put("source", GsonUtils.toJson(exposureSourceList));
|
||||
object.put("game_name", gameEntity.getName());
|
||||
object.put("game_id", gameEntity.getId());
|
||||
object.put("game_platform", gameEntity.getPlatform());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
uploadToReservation(object);
|
||||
}
|
||||
|
||||
private static void upload(JSONObject object) {
|
||||
private static void uploadToCommunity(JSONObject object) {
|
||||
uploadToCommunity(object, false);
|
||||
}
|
||||
|
||||
private static void uploadToCommunity(JSONObject object, boolean forcedUpload) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->" + object.toString());
|
||||
}
|
||||
|
||||
|
||||
Context context = HaloApp.getInstance().getApplication();
|
||||
try {
|
||||
object.put("version", PackageUtils.getVersionName());
|
||||
@ -200,13 +304,119 @@ public class LogUtils {
|
||||
object.put("device_system", android.os.Build.VERSION.RELEASE);
|
||||
object.put("device_model", android.os.Build.MODEL);
|
||||
object.put("imei", Util_System_Phone_State.getImei(HaloApp.getInstance()
|
||||
.getApplication()));
|
||||
.getApplication()));
|
||||
object.put("G_ID", UserManager.getInstance().getDeviceId());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
// 暂时除了曝光外的数据都是扔到 community 这个库的,要是不是这个这个库的话这里要改一下
|
||||
LogHubUtils.uploadLog(DeviceUtils.getIPAddress(context), object, "community");
|
||||
LoghubUtils.log(object, "community", forcedUpload);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传数据到“预约”的 logStore
|
||||
*/
|
||||
private static void uploadToReservation(JSONObject object) {
|
||||
Context context = HaloApp.getInstance().getApplication();
|
||||
try {
|
||||
object.put("version", PackageUtils.getVersionName());
|
||||
object.put("channel", HaloApp.getInstance().getChannel());
|
||||
object.put("android_id", Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID));
|
||||
object.put("time", Utils.getTime(context));
|
||||
object.put("network", DeviceUtils.getNetwork(context));
|
||||
object.put("user_id", UserManager.getInstance().getUserId());
|
||||
object.put("device_system", android.os.Build.VERSION.RELEASE);
|
||||
object.put("device_model", android.os.Build.MODEL);
|
||||
object.put("imei", Util_System_Phone_State.getImei(HaloApp.getInstance()
|
||||
.getApplication()));
|
||||
object.put("G_ID", UserManager.getInstance().getDeviceId());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
LoghubUtils.log(object, "appointment", false);
|
||||
}
|
||||
|
||||
private static void uploadVideoStreaming(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("meta", metaObject);
|
||||
object.put("timestamp", System.currentTimeMillis() / 1000);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->" + object.toString());
|
||||
}
|
||||
|
||||
LoghubUtils.log(object, "video_streaming", false);
|
||||
}
|
||||
|
||||
public static void uploadVideoStreamingEnter(String entrance, String entranceDetail, String videoId, String streamingId) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
|
||||
try {
|
||||
object.put("event", "ENTERING_VIDEO_STEAMING");
|
||||
payloadObject.put("entrance", entrance);
|
||||
if (!TextUtils.isEmpty(entranceDetail)) {
|
||||
payloadObject.put("entrance_detail", entranceDetail);
|
||||
}
|
||||
payloadObject.put("video_id", videoId);
|
||||
payloadObject.put("streaming_id", streamingId);
|
||||
object.put("payload", payloadObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploadVideoStreaming(object);
|
||||
}
|
||||
|
||||
public static void uploadVideoStreamingPlaying(String action, String msg, String entrance, String entranceDetail, String videoId, String streamingId, double videoSize, int videoTotalTime, int progress, String videoPlayStatus) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
|
||||
try {
|
||||
object.put("event", "VIDEO_PLAYING");
|
||||
object.put("action", action);
|
||||
if (!TextUtils.isEmpty(msg)) {
|
||||
object.put("msg", msg);
|
||||
}
|
||||
|
||||
payloadObject.put("entrance", entrance);
|
||||
if (!TextUtils.isEmpty(entranceDetail)) {
|
||||
payloadObject.put("entrance_detail", entranceDetail);
|
||||
}
|
||||
payloadObject.put("video_id", videoId);
|
||||
payloadObject.put("streaming_id", streamingId);
|
||||
if (videoSize > 0) {
|
||||
payloadObject.put("video_size", videoSize);
|
||||
}
|
||||
if (videoTotalTime > 0) {
|
||||
payloadObject.put("video_total_time", videoTotalTime);
|
||||
}
|
||||
payloadObject.put("progress", progress);
|
||||
payloadObject.put("video_play_status", videoPlayStatus);
|
||||
|
||||
object.put("payload", payloadObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploadVideoStreaming(object);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,6 +264,12 @@ public class LoginUtils {
|
||||
case 400212:
|
||||
Utils.toast(context, "请输入正确的手机号");
|
||||
break;
|
||||
case 400010:
|
||||
Utils.toast(context, "身份证无效,请重新输入");
|
||||
break;
|
||||
case 400011:
|
||||
Utils.toast(context, "请输入正确的身份信息");
|
||||
break;
|
||||
default:
|
||||
Utils.toast(context, code + "");
|
||||
break;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user