Compare commits
1013 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 113ebb36e9 | |||
| d0c9bd8038 | |||
| 104586fb7f | |||
| 1bc5bb3ef6 | |||
| 2719bff65f | |||
| b87972143d | |||
| 0cdec2a226 | |||
| 545c235b24 | |||
| 53d3cb320b | |||
| 38682f01a8 | |||
| 13a76e8de7 | |||
| 1e98fa98c3 | |||
| 20bc38add4 | |||
| efabaafa38 | |||
| 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 | |||
| 1facde123e | |||
| d02a527b36 | |||
| 8f9d6ed2ce | |||
| e43902be79 | |||
| 0f5f8861a7 | |||
| cb08886d27 | |||
| 322ec56787 | |||
| 75883e11d8 | |||
| 60b12a3bdf | |||
| 26a66e3a2b | |||
| e86e78a665 | |||
| 3ba68abbee | |||
| a46ba32f06 | |||
| 82348b519a | |||
| 8315a50d49 | |||
| dca07831db | |||
| d568dd0791 | |||
| 9dbfc68488 | |||
| 0b46e0ef8e | |||
| 472604bc15 | |||
| 58a2d38518 | |||
| c91186be8a | |||
| 03235438bc | |||
| d015285f1a | |||
| 45323a6817 | |||
| bcc8d35654 | |||
| 9137b65f4a | |||
| fbc9dac99e | |||
| c27a6e06ad | |||
| 07970fcbae | |||
| 0b3e250386 | |||
| 13b1ba613d | |||
| 5a1feb4500 | |||
| cc7accbc95 | |||
| 42a83ea0c5 | |||
| 39f84442cd | |||
| 047c25b0b7 | |||
| 045f21beac | |||
| 8a64460097 | |||
| 195d039904 | |||
| bcf77433b9 | |||
| 3a122a7137 | |||
| 354d286a98 | |||
| bfccc1c9b8 | |||
| 80767c17b2 | |||
| 0a9185462e | |||
| c058d3f8c1 | |||
| 70655da2e7 | |||
| 51f8c15af6 | |||
| 20d6984057 | |||
| f26813c137 | |||
| e2a265c3c7 | |||
| e840daa340 | |||
| c54df5336d | |||
| 4ec97409a8 | |||
| 31b5568dfa | |||
| 10cfc6521d | |||
| bfdbc7fc92 | |||
| ead332d863 | |||
| b8fd666e84 | |||
| fb6e3637de | |||
| 2db519f9e0 | |||
| f55aeaf3d4 | |||
| 2340d4957b | |||
| 7bed914a92 | |||
| 4b9f86a4bb | |||
| a1844e15e1 | |||
| 148589a6c5 | |||
| 2902a8b441 | |||
| b410016fae | |||
| 0d56448bfd | |||
| 326c292572 | |||
| afdaef1a64 | |||
| 9bcd4b8e95 | |||
| 4d455f13b6 | |||
| 94eea3aa90 | |||
| b00f47dd99 | |||
| 20a4427e08 | |||
| 3287f31e2c | |||
| fbb6b01585 | |||
| f07d1b7257 | |||
| 45d2d958a2 | |||
| 2ba2498f6b | |||
| d76dada9f8 | |||
| 28b63ee21b | |||
| 90ea78eb39 | |||
| 0cda0e93f0 | |||
| 2e0469f915 | |||
| fdfbd23963 | |||
| 5f8b11f8e0 | |||
| a1df2f6ca6 | |||
| 1d0d0e40de | |||
| b3e5144cea | |||
| aed74449b0 | |||
| 45dc231024 | |||
| c1a223f120 | |||
| 4a926997aa | |||
| ae764b95fb | |||
| 7bba3f8b4d | |||
| b2ad804d3c | |||
| c49fa5cd3d | |||
| 92b5e28675 | |||
| 4afa5f6bc6 | |||
| fbdc31aa97 | |||
| 4eedfadc22 | |||
| 3432a6c39f | |||
| 7e7c2180ce | |||
| 0386446a00 | |||
| 09853e4187 | |||
| 40020fa617 | |||
| cc68c15824 | |||
| 7aa874a0e3 | |||
| 8203e5b568 | |||
| 4f54bca286 | |||
| 087479325d | |||
| 357b2c2a60 | |||
| e1918b56e2 | |||
| 1f31d1e614 | |||
| f5468c5f11 | |||
| 672cf331ea | |||
| 348ad0faed | |||
| ae742547d8 | |||
| ff1c01c836 | |||
| a645a3c929 | |||
| 37c590400e | |||
| 785e2d8cf5 | |||
| 03d25cb102 | |||
| 869dd9ac11 | |||
| f647e172bd | |||
| 7069200c6e | |||
| c61cfcbed9 | |||
| 67eddc99ef | |||
| 03fd5aaf09 | |||
| 31a8f5e5c7 | |||
| b7c6460c0e | |||
| 538c096b8f | |||
| d05c738696 | |||
| 976035da22 | |||
| d47fd51c7c | |||
| a047c65efd | |||
| 5bbb6b1c89 | |||
| 95432cb591 | |||
| 04862e7f22 | |||
| abafd0bb24 | |||
| aa83617796 | |||
| a5b8806997 | |||
| 7a70c0158e | |||
| 74f5972874 | |||
| b01a29d2e9 | |||
| 88bd0dc9f5 | |||
| c7b6d44874 | |||
| 8b6e01929b | |||
| 2ecba00d2a | |||
| 851fcaab13 | |||
| e1b9504421 | |||
| 247e8ed6cc | |||
| 996d1be136 | |||
| a249d4d572 | |||
| c91d52d753 | |||
| 0c37db444a | |||
| eb93f1d915 | |||
| 74e6c9b145 | |||
| f15e630fd1 | |||
| 01ee84caa8 | |||
| 311a1916d1 | |||
| ae43ae1b97 | |||
| d9814bbb1f | |||
| dba8abacf2 | |||
| 3ee1474535 | |||
| 8481e923ee | |||
| 53cfb0f078 | |||
| 233277f6e8 | |||
| dbd75cb513 | |||
| bae14a54a1 | |||
| 9c48afca77 | |||
| 54ebc460fa | |||
| 901e9a39f9 | |||
| 2ebd12c6db | |||
| c762529b8b | |||
| 3c371038cf | |||
| 0350c19c81 | |||
| ebace67201 | |||
| cbe6e2e3bd | |||
| 4adefc885b | |||
| cade2882e4 | |||
| 8c0f2fd527 | |||
| 56809d8d66 | |||
| 14772494be | |||
| 4bbec7344f | |||
| 9907863ef5 | |||
| adfbe36fdf | |||
| 3cfb9ac1c3 | |||
| 2004b85a12 | |||
| 7dd3b5f122 | |||
| c849746a6f | |||
| a9582bc295 | |||
| fd49defe00 | |||
| 650a24775a | |||
| b62a864a7d | |||
| b76e10bdfc | |||
| 4311205e62 | |||
| 69bc1c971d | |||
| f13c720bcc | |||
| 63f66e9714 | |||
| 25d8ed079c | |||
| b923714b42 | |||
| 178295596a | |||
| 2e1dae86e0 | |||
| 4bb0206d2d | |||
| 23cda9c121 | |||
| a1d0b59e28 | |||
| 9de8e61b1b | |||
| be1188e8e4 | |||
| fdaefa52ab | |||
| d667e70b90 | |||
| 6184acc144 | |||
| 6f012dc459 | |||
| 94774c674a | |||
| 3bda3354f0 | |||
| 8a56459375 | |||
| aeb689648f | |||
| 761d4c3354 | |||
| 90899e7d1f | |||
| 9e9d8b7149 | |||
| f774df532c | |||
| d85c4533b7 | |||
| 79aeca832a | |||
| 50931b1fb6 | |||
| 63bd0cdebb | |||
| 8880d381db | |||
| 4eccd3b2ac | |||
| 716ba77d3e | |||
| 4053eec64c | |||
| b11463b0f7 | |||
| 109ada8e8b | |||
| ab32670b40 | |||
| 92f82099b5 | |||
| e41b7434c9 | |||
| 9c79df6d6e | |||
| fe1f491104 | |||
| 652bdf9f1d | |||
| 36b13d6d28 | |||
| 53b58b63a2 | |||
| 6b0f298a2d | |||
| 08bc8bc49e | |||
| c8b436de94 | |||
| 82b6323f72 | |||
| 6664bc9e62 | |||
| 544dc67d0d | |||
| d55c4d12bc | |||
| 707bc9bb1a | |||
| 41806eab54 | |||
| 443c3bf26a | |||
| 7ac6e82624 | |||
| 87106de6d6 | |||
| c52d94b003 | |||
| 5ac13f2107 | |||
| 9269548d64 |
@ -23,6 +23,10 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
// jumboMode = true
|
||||
javaMaxHeapSize "4g"
|
||||
@ -183,6 +187,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,13 +197,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}"
|
||||
|
||||
@ -206,6 +216,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}"
|
||||
|
||||
@ -239,13 +250,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}"
|
||||
@ -258,27 +269,40 @@ 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.shuyu:gsyVideoPlayer-armv7a:$gsyVideo"
|
||||
// implementation "com.shuyu:gsyVideoPlayer-x86:$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')
|
||||
@ -286,9 +310,9 @@ dependencies {
|
||||
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.
Binary file not shown.
@ -4,6 +4,7 @@ import android.app.Application;
|
||||
|
||||
import com.facebook.stetho.Stetho;
|
||||
import com.facebook.stetho.okhttp3.StethoInterceptor;
|
||||
import com.gu.toolargetool.TooLargeTool;
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
@ -29,7 +30,7 @@ public class Injection {
|
||||
|
||||
// init stetho
|
||||
Stetho.initializeWithDefaults(application);
|
||||
|
||||
TooLargeTool.startLogging(application);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -1,516 +1,580 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android = "http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools = "http://schemas.android.com/tools"
|
||||
package = "com.gh.gamecenter" >
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.gh.gamecenter">
|
||||
|
||||
<!-- 允许应用程序访问网络连接 -->
|
||||
<uses-permission android:name = "android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- 允许应用程序写入外部存储,如SD卡上写文件 -->
|
||||
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<!-- 允许应用程序读取扩展存储器 -->
|
||||
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<!-- 允许挂载和反挂载文件系统可移动存储 -->
|
||||
<uses-permission android:name = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
|
||||
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
|
||||
<!-- 允许应用程序访问Wi-Fi网络状态信息 -->
|
||||
<uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<!-- 允许应用程序获取网络信息状态 -->
|
||||
<uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<!-- 允许应用程序读取电话状态 -->
|
||||
<uses-permission android:name = "android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<!-- 允许应用程序获取当前或最近运行的应用 -->
|
||||
<uses-permission android:name = "android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<!-- 允许访问振动设备 -->
|
||||
<uses-permission android:name = "android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<!-- 允许应用程序改变Wi-Fi连接状态 -->
|
||||
<uses-permission android:name = "android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<!-- 允许应用程序打开系统窗口,显示其他应用程序 -->
|
||||
<uses-permission android:name = "android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<!-- 修改系统设置的权限 -->
|
||||
<uses-permission android:name = "android.permission.WRITE_SETTINGS" />
|
||||
<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" />
|
||||
<uses-permission android:name="android.permission.READ_LOGS" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
<uses-sdk
|
||||
tools:overrideLibrary="com.shuyu.gsyvideoplayer,
|
||||
<uses-sdk tools:overrideLibrary="com.shuyu.gsyvideoplayer,
|
||||
com.shuyu.gsyvideoplayer.lib,
|
||||
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 android:name = "android.permission.READ_CONTACTS" tools:node = "remove"/>
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_CONTACTS"
|
||||
tools:node="remove" />
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity = "true"
|
||||
android:largeScreens = "true"
|
||||
android:normalScreens = "true"
|
||||
android:resizeable = "true"
|
||||
android:smallScreens = "true" />
|
||||
android:anyDensity="true"
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:resizeable="true"
|
||||
android:smallScreens="true" />
|
||||
|
||||
<!--android:largeHeap = "true"-->
|
||||
<application
|
||||
android:name = "com.halo.assistant.TinkerApp"
|
||||
android:allowBackup = "true"
|
||||
android:icon = "@mipmap/logo"
|
||||
android:label = "@string/app_name"
|
||||
android:resizeableActivity = "true"
|
||||
android:theme = "@style/AppCompatTheme.APP"
|
||||
android:name="com.halo.assistant.TinkerApp"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/logo"
|
||||
android:label="@string/app_name"
|
||||
android:largeHeap="true"
|
||||
tools:targetApi = "n" >
|
||||
android:resizeableActivity="true"
|
||||
android:theme="@style/AppCompatTheme.APP"
|
||||
tools:targetApi="n">
|
||||
|
||||
<!--android:launchMode = "singleTask"-->
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SplashScreenActivity"
|
||||
android:configChanges = "keyboardHidden|orientation|screenSize"
|
||||
android:screenOrientation = "portrait"
|
||||
android:theme = "@style/AppGuideTheme" >
|
||||
<intent-filter >
|
||||
<action android:name = "android.intent.action.MAIN" />
|
||||
android:name="com.gh.gamecenter.SplashScreenActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.Launcher">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name = "android.intent.category.LAUNCHER" />
|
||||
</intent-filter >
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</activity >
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MainActivity"
|
||||
android:launchMode = "singleTask"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateAlwaysHidden|adjustResize" />
|
||||
android:name="com.gh.gamecenter.MainActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppCompatTheme.APP"
|
||||
android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.DownloadManagerActivity"
|
||||
android:launchMode = "singleTask"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.DownloadManagerActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!--android:theme = "@android:style/Theme.Black.NoTitleBar.Fullscreen" 退出时屏幕抖动 -->
|
||||
<activity android:name = "com.gh.gamecenter.ViewImageActivity" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SearchActivity"
|
||||
android:configChanges = "keyboardHidden"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.NewsDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SettingActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ConcernActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.subject.SubjectActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.NewsSearchActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.GameNewsActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.CropImageActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.WebActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ShareCardPicActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ShareCardActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MessageDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.LibaoActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.LibaoDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ShareGhActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.CleanApkActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SelectUserIconActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.AboutActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.CommentDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.mygame.MyGameActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.GameDetailActivity"
|
||||
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" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.VoteActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateAlwaysHidden|adjustResize" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ToolBoxActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
<activity android:name="com.gh.gamecenter.ViewImageActivity" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.WeiBoShareActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
android:name="com.gh.gamecenter.SearchActivity"
|
||||
android:configChanges="keyboardHidden"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppCompatTheme.APP" />
|
||||
|
||||
<activity
|
||||
android:name = ".category.CategoryDirectoryActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.amway.search.AmwaySearchActivity"
|
||||
android:configChanges="keyboardHidden"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppCompatTheme.APP" />
|
||||
|
||||
<activity
|
||||
android:name = ".category.CategoryListActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ShellActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.LoginActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
android:name="com.gh.gamecenter.NewsDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.UserInfoActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.SettingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.UserRegionActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ConcernActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.CollectionActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.subject.SubjectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MessageActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.NewsSearchActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.UserInfoEditActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
android:name="com.gh.gamecenter.GameNewsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.search.AskSearchActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.CropImageActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.WebActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ShareCardPicActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = ".qa.answer.fold.AnswerFoldActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ShareCardActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.answer.edit.AnswerEditActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.MessageDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ConcernInfoActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.LibaoActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.InfoActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.LibaoDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MessageKeFuActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ShareGhActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.select.CommunitiesSelectActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.CleanApkActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.subject.CommunitySubjectActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.SelectUserIconActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MessageInviteActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.AboutActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MessageVoteActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.CommentDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = ".qa.questions.invite.QuestionsInviteActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.mygame.MyGameActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.myqa.MyAskActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.GameDetailActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.column.order.AskTabOrderActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.SuggestionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.VoteActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.questions.edit.QuestionEditActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ToolBoxActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.servers.add.AddKaiFuActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
android:name="com.gh.gamecenter.WeiBoShareActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.servers.patch.PatchKaifuActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name=".category.CategoryDirectoryActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.BlockActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name=".category.CategoryListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.LoginActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.NetworkDiagnosisActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.UserInfoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.personalhome.fans.FansActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.UserRegionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.personalhome.followers.FollowersActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.CollectionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.personalhome.HomeActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.MessageActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.article.edit.ArticleEditActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.UserInfoEditActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.article.MyArticleActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.search.AskSearchActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.article.draft.ArticleDraftActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.article.detail.ArticleDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.draft.CommunityDraftWrapperActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name=".qa.answer.fold.AnswerFoldActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateVisible" />
|
||||
android:name="com.gh.gamecenter.qa.answer.edit.AnswerEditActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.questions.edit.manager.HistoryDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ConcernInfoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.questions.edit.manager.HistoryActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.InfoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.MessageKeFuActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.editor.GameActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.select.CommunitiesSelectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.subject.CommunitySubjectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.gamedetail.rating.RatingReplyActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.MessageInviteActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.history.HistoryActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.MessageVoteActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.personalhome.rating.RatingActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name=".qa.questions.invite.QuestionsInviteActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.gamedetail.rating.logs.CommentLogsActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.myqa.MyAskActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.tag.TagsActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.column.order.AskTabOrderActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.article.SimpleArticleListActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.questions.edit.QuestionEditActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.servers.add.AddKaiFuActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.servers.patch.PatchKaifuActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.BlockActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.amway.AmwayActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.NetworkDiagnosisActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.personalhome.fans.FansActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.personalhome.followers.FollowersActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.personalhome.UserHomeActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.edit.ArticleEditActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.MyArticleActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.draft.ArticleDraftActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.detail.ArticleDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.draft.CommunityDraftWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateVisible" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.questions.edit.manager.HistoryDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.questions.edit.manager.HistoryActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.editor.GameActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.rating.RatingReplyActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.history.HistoryActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.personalhome.rating.RatingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.rating.logs.CommentLogsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.tag.TagsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.SimpleArticleListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.videomanager.VideoManagerActivity"
|
||||
android:screenOrientation = "portrait"/>
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.upload.view.UploadVideoActivity"
|
||||
android:screenOrientation = "portrait"/>
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.game.GameVideoActivity"
|
||||
android:screenOrientation = "portrait"/>
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.editor.VideoActivity"
|
||||
android:screenOrientation = "portrait"/>
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.mygame.PlayedGameActivity"
|
||||
android:screenOrientation = "portrait"/>
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.servers.GameServersActivity"
|
||||
android:screenOrientation = "portrait"/>
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity"
|
||||
android:screenOrientation = "portrait"/>
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.game.upload.GameSubmissionActivity"
|
||||
android:screenOrientation = "portrait"/>
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.comment.CommentActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:theme = "@style/Theme.Transparent"
|
||||
android:windowSoftInputMode = "adjustNothing" />
|
||||
android:name="com.halo.assistant.fragment.user.UserPortraitCropImageActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity android:name="com.gh.gamecenter.video.detail.VideoDetailActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar"/>
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.HelpAndFeedbackActivity"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.help.HelpDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.comment.CommentActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.Transparent"
|
||||
android:windowSoftInputMode="adjustNothing" />
|
||||
|
||||
<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.PushProxyActivity"
|
||||
android:exported = "true"
|
||||
android:theme = "@android:style/Theme.Translucent" />
|
||||
android:name="com.gh.gamecenter.PushProxyActivity"
|
||||
android:exported="true"
|
||||
android:theme="@android:style/Theme.Translucent" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SkipActivity"
|
||||
android:theme = "@style/Theme.AppCompat.Light.Fullscreen.Transparent" >
|
||||
<intent-filter >
|
||||
<data android:scheme = "ghzhushou" />
|
||||
android:name="com.gh.gamecenter.SkipActivity"
|
||||
android:theme="@style/Theme.AppCompat.Light.Fullscreen.Transparent">
|
||||
<intent-filter>
|
||||
<data android:scheme="ghzhushou" />
|
||||
|
||||
<category android:name = "android.intent.category.DEFAULT" />
|
||||
<action android:name = "android.intent.action.VIEW" />
|
||||
<category android:name = "android.intent.category.BROWSABLE" />
|
||||
</intent-filter >
|
||||
</activity >
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name = "${applicationId}.wxapi.WXEntryActivity"
|
||||
android:exported = "true"
|
||||
android:label = "@string/app_name"
|
||||
android:launchMode = "singleTop"
|
||||
android:screenOrientation = "portrait"
|
||||
android:theme = "@android:style/Theme.Translucent.NoTitleBar" ></activity >
|
||||
android:name="${applicationId}.wxapi.WXEntryActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
|
||||
|
||||
<provider
|
||||
android:name = "androidx.core.content.FileProvider"
|
||||
android:authorities = "${applicationId}"
|
||||
android:exported = "false"
|
||||
android:grantUriPermissions = "true" >
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name = "android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource = "@xml/provider_paths" />
|
||||
</provider >
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
<receiver
|
||||
android:name = "com.gh.gamecenter.receiver.DownloadReceiver"
|
||||
android:exported = "false" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.DOWNLOAD" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
android:name="com.gh.gamecenter.receiver.DownloadReceiver"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.DOWNLOAD" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name = "com.gh.gamecenter.receiver.InstallReceiver"
|
||||
android:exported = "false" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.INSTALL" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
android:name="com.gh.gamecenter.receiver.InstallReceiver"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.INSTALL" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name = "com.gh.gamecenter.receiver.ActivitySkipReceiver"
|
||||
android:exported = "true" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.ACTIVITYSKIP" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
android:name="com.gh.gamecenter.receiver.ActivitySkipReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.ACTIVITYSKIP" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name = "com.gh.gamecenter.receiver.UmengMessageReceiver" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.UMENG" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
<receiver android:name="com.gh.gamecenter.receiver.UmengMessageReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.UMENG" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!--魅族push应用定义消息receiver声明 -->
|
||||
<receiver android:name = "com.gh.gamecenter.receiver.MeizuPushReceiver" >
|
||||
<intent-filter >
|
||||
<receiver android:name="com.gh.gamecenter.receiver.MeizuPushReceiver">
|
||||
<intent-filter>
|
||||
<!-- 接收push消息 -->
|
||||
<action android:name = "com.meizu.flyme.push.intent.MESSAGE" />
|
||||
<action android:name="com.meizu.flyme.push.intent.MESSAGE" />
|
||||
<!-- 接收register消息 -->
|
||||
<action android:name = "com.meizu.flyme.push.intent.REGISTER.FEEDBACK" />
|
||||
<action android:name="com.meizu.flyme.push.intent.REGISTER.FEEDBACK" />
|
||||
<!-- 接收unregister消息-->
|
||||
<action android:name = "com.meizu.flyme.push.intent.UNREGISTER.FEEDBACK" />
|
||||
<action android:name="com.meizu.flyme.push.intent.UNREGISTER.FEEDBACK" />
|
||||
<!-- 兼容低版本Flyme3推送服务配置 -->
|
||||
<action android:name = "com.meizu.c2dm.intent.REGISTRATION" />
|
||||
<action android:name = "com.meizu.c2dm.intent.RECEIVE" />
|
||||
<action android:name="com.meizu.c2dm.intent.REGISTRATION" />
|
||||
<action android:name="com.meizu.c2dm.intent.RECEIVE" />
|
||||
|
||||
<category android:name = "${applicationId}" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
<category android:name="${applicationId}" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name = "com.gh.common.im.ImReceiver"
|
||||
android:enabled = "true" >
|
||||
<intent-filter android:priority = "2147483647" >
|
||||
<action android:name = "com.gh.im" />
|
||||
<action android:name = "action_finish" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
android:name="com.gh.common.im.ImReceiver"
|
||||
android:enabled="true">
|
||||
<intent-filter android:priority="2147483647">
|
||||
<action android:name="com.gh.im" />
|
||||
<action android:name="action_finish" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name = "com.gh.base.GHUmengNotificationService" />
|
||||
<service android:name="com.gh.base.GHUmengNotificationService" />
|
||||
|
||||
<!--<service android:name = "com.gh.gamecenter.statistics.AppStaticService" />-->
|
||||
|
||||
</application >
|
||||
</application>
|
||||
|
||||
</manifest >
|
||||
</manifest>
|
||||
@ -2,16 +2,20 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<link rel="stylesheet" type="text/css" href="normalize.css">
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<link rel="stylesheet" type="text/css" href="video-js.min.css">
|
||||
<!-- <link rel="stylesheet" href="https://static-web.ghzs.com/website-static/lib/video-js.min.css">--> <!--在web页面播放视频-->
|
||||
<!--<link rel="stylesheet" type="text/css" href="https://resource.ghzs.com/css/halo_app.css">-->
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body style="overflow-x: hidden; word-break: break-all;">
|
||||
<div id="editor" contenteditable="false"></div>
|
||||
<script type="text/javascript" src="zepto.min.js"></script>
|
||||
<script type="text/javascript" src="rich_editor.js"></script>
|
||||
<script type="text/javascript" src="video.min.js"></script>
|
||||
<!--<script src="https://static-web.ghzs.com/website-static/lib/video.min.js"></script>--> <!--在web页面播放视频-->
|
||||
<!--<script type="text/javascript" src="content.js"></script>-->
|
||||
<!--<script type="text/javascript" src="https://resource.ghzs.com/js/halo_app.js"></script>-->
|
||||
</body>
|
||||
|
||||
1
app/src/main/assets/lottie/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/score_fireworks.json
Normal file
1
app/src/main/assets/lottie/score_fireworks.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,27 +1,26 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
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;
|
||||
import com.tencent.tauth.Tencent;
|
||||
@ -29,31 +28,40 @@ import com.tencent.tauth.Tencent;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import butterknife.ButterKnife;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
|
||||
public abstract class BaseActivity extends BaseToolBarActivity implements EasyPermissions.PermissionCallbacks {
|
||||
/**
|
||||
* 只提供基础的服务(EventBus/ButterKnife/Share/GlobalDialog/Permissions)
|
||||
* <p>
|
||||
* 需要工具栏的页面请继承{@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 LOGIN_EXCEPTION = "loginException";
|
||||
public final static String PLUGGABLE = "plugin";
|
||||
|
||||
@NonNull
|
||||
protected String mEntrance;
|
||||
|
||||
private boolean mIsPause;
|
||||
private boolean mIsExistLogoutDialog;
|
||||
|
||||
protected final Handler mBaseHandler = new BaseHandler(this);
|
||||
|
||||
protected static class BaseHandler extends Handler {
|
||||
|
||||
private final WeakReference<BaseActivity> mActivityWeakReference;
|
||||
|
||||
BaseHandler(BaseActivity activity) {
|
||||
@ -82,25 +90,9 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
}
|
||||
}
|
||||
|
||||
// 小米沉浸式黑色字体
|
||||
public void setStatusBarDarkMode(boolean darkmode, Activity activity) {
|
||||
Class<? extends Window> clazz = activity.getWindow().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(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setStatusBarDarkMode(true, this);
|
||||
EventBus.getDefault().register(this);
|
||||
ButterKnife.bind(this);
|
||||
mEntrance = getIntent().getStringExtra(KEY_ENTRANCE);
|
||||
@ -120,12 +112,6 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onNavigationIconClicked() {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
Utils.toast(this, msg);
|
||||
}
|
||||
@ -134,34 +120,40 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
toast(getString(msg));
|
||||
}
|
||||
|
||||
public void showShare(String url, String icon, String shareTitle, String shareSummary, ShareUtils.ShareType shareType) {
|
||||
|
||||
ShareUtils.getInstance(this).showShareWindows(this, getWindow().getDecorView(), url, icon, shareTitle, shareSummary, shareType);
|
||||
|
||||
public void showShare(String url,
|
||||
String icon,
|
||||
String shareTitle,
|
||||
String shareSummary,
|
||||
ShareUtils.ShareType shareType) {
|
||||
ShareUtils.getInstance(this).showShareWindows(this,
|
||||
getWindow().getDecorView(),
|
||||
url,
|
||||
icon,
|
||||
shareTitle,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(final EBShowDialog showDialog) {
|
||||
if (!mIsPause && this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
if ("hijack".equals(showDialog.getType())) {
|
||||
DialogUtils.showQqSessionDialog(this, "2586716223");// 建议用户联系客服
|
||||
} else if ("plugin".equals(showDialog.getType())) {
|
||||
DialogUtils.showPluginDialog(this, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
toast(R.string.install_failure_hint);
|
||||
} else {
|
||||
startActivity(PackageUtils.getUninstallIntent(BaseActivity.this, showDialog.getPath()));
|
||||
}
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
|
||||
&& this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
if (DOWNLOAD_HIJACK.equals(showDialog.getType())) {
|
||||
DialogUtils.showQqSessionDialog(this);// 建议用户联系客服
|
||||
} else if (PLUGGABLE.equals(showDialog.getType())) {
|
||||
DialogUtils.showPluginDialog(this, () -> {
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
toast(R.string.install_failure_hint);
|
||||
} else {
|
||||
startActivity(PackageUtils.getUninstallIntent(BaseActivity.this, showDialog.getPath()));
|
||||
}
|
||||
});
|
||||
} else if ("loginException".equals(showDialog.getType())) {
|
||||
} else if (LOGIN_EXCEPTION.equals(showDialog.getType())) {
|
||||
if (mIsExistLogoutDialog) return;
|
||||
mIsExistLogoutDialog = true;
|
||||
try {
|
||||
@ -176,51 +168,68 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
"你的账号已在另外一台设备登录多设备-重新登录"))
|
||||
);
|
||||
mBaseHandler.postDelayed(() -> mIsExistLogoutDialog = false, 5000);
|
||||
} catch (JSONException e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if ("notfound".equals(showDialog.getType())) {
|
||||
DialogUtils.showAlertDialog(this, "下载失败", "下载链接已失效,建议提交反馈"
|
||||
, "立即反馈", "取消"
|
||||
, () -> {
|
||||
SuggestionActivity.startSuggestionActivity(this, SuggestType.gameQuestion,
|
||||
null, showDialog.getPath() + ",问题反馈:下载链接失效");
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
TeaHelper.onPause(this);
|
||||
super.onPause();
|
||||
mIsPause = true;
|
||||
if (isFinishing()) {
|
||||
onFinish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
TeaHelper.onResume(this);
|
||||
super.onResume();
|
||||
mIsPause = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 可凭借此回调确定当前 activity 已经执行了 finish() 处于 isFinishing 状态
|
||||
* 可在后续进行
|
||||
*/
|
||||
protected void onFinish() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
@NonNull String[] permissions,
|
||||
@NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPermissionsDenied(int requestCode, List<String> perms) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPermissionsGranted(int requestCode, List<String> perms) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void setStatusBarColor(int color) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
window.setStatusBarColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供当前 activity 的中文名 (不重载的话为类名)
|
||||
*/
|
||||
public String getActivityNameInChinese() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entrance 上一个页面的链式入口名称
|
||||
* @param path 当前页面名称
|
||||
@ -237,8 +246,4 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
return StringUtils.buildString(entrance, "+(", path, ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean showDownloadMenu() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,15 +2,16 @@ package com.gh.base;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import android.view.View;
|
||||
|
||||
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.lightgame.view.NoScrollableViewPager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -22,7 +23,7 @@ import butterknife.BindView;
|
||||
* Created by khy on 15/03/18.
|
||||
*/
|
||||
|
||||
public abstract class BaseActivity_TabLayout extends BaseActivity implements ViewPager.OnPageChangeListener {
|
||||
public abstract class BaseActivity_TabLayout extends ToolBarActivity implements ViewPager.OnPageChangeListener {
|
||||
|
||||
public static final String PAGE_INDEX = "PAGE_INDEX";
|
||||
|
||||
|
||||
@ -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
|
||||
@ -27,7 +28,7 @@ import com.lightgame.utils.Utils
|
||||
import com.lightgame.view.CheckableImageView
|
||||
import kotterknife.bindView
|
||||
|
||||
abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
|
||||
val mRichEditor by bindView<RichEditor>(R.id.rich_editor)
|
||||
|
||||
@ -68,7 +69,7 @@ abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
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 : BaseActivity() {
|
||||
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 : BaseActivity() {
|
||||
if (mEditorParagraphH2.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-2级标题")
|
||||
mRichEditor.setHeading(2)
|
||||
}
|
||||
mEditorParagraphH2.isChecked = !mEditorParagraphH2.isChecked
|
||||
@ -155,6 +168,7 @@ abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
if (mEditorParagraphH3.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-3级标题")
|
||||
mRichEditor.setHeading(3)
|
||||
}
|
||||
mEditorParagraphH3.isChecked = !mEditorParagraphH3.isChecked
|
||||
@ -163,6 +177,7 @@ abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
if (mEditorParagraphH4.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-4级标题")
|
||||
mRichEditor.setHeading(4)
|
||||
}
|
||||
mEditorParagraphH4.isChecked = !mEditorParagraphH4.isChecked
|
||||
@ -171,21 +186,26 @@ abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
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 : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
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 : BaseActivity() {
|
||||
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
|
||||
|
||||
@ -9,15 +9,14 @@ import android.view.View;
|
||||
* Created by khy on 25/04/18.
|
||||
*/
|
||||
|
||||
public abstract class onDoubleTapListener implements View.OnTouchListener {
|
||||
public abstract class OnDoubleTapListener implements View.OnTouchListener {
|
||||
private GestureDetector mGestureDetector;
|
||||
|
||||
public onDoubleTapListener(Context context) {
|
||||
protected OnDoubleTapListener(Context context) {
|
||||
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap(MotionEvent e) {
|
||||
onDoubleTapListener.this.onDoubleTap();
|
||||
OnDoubleTapListener.this.onDoubleTap();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@ -26,7 +25,7 @@ public abstract class onDoubleTapListener implements View.OnTouchListener {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
mGestureDetector.onTouchEvent(event);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract void onDoubleTap();
|
||||
@ -2,6 +2,6 @@ package com.gh.base;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
public interface OnViewClickListener {
|
||||
void onClick(View v, Object data);
|
||||
public interface OnViewClickListener<T> {
|
||||
void onClick(View v, T data);
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
@ -22,12 +25,13 @@ import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.normal.ToolbarController;
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel;
|
||||
import com.lightgame.BaseAppCompatActivity;
|
||||
import com.lightgame.OnTitleClickListener;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
@ -38,10 +42,12 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
/**
|
||||
* Created by csheng on 15-10-12.
|
||||
* 需要用到工具栏的页面使用
|
||||
* <p>
|
||||
* 特殊页面请参考{@link BaseActivity}
|
||||
*/
|
||||
|
||||
public abstract class BaseToolBarActivity extends BaseAppCompatActivity implements ToolbarController, Toolbar.OnMenuItemClickListener {
|
||||
public abstract class ToolBarActivity extends BaseActivity implements ToolbarController, Toolbar.OnMenuItemClickListener {
|
||||
|
||||
@Nullable
|
||||
private PackageViewModel mPackageViewModel;
|
||||
@ -56,6 +62,8 @@ public abstract class BaseToolBarActivity extends BaseAppCompatActivity implemen
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setStatusBarDarkMode(true, this);
|
||||
initToolbar();
|
||||
|
||||
if (showDownloadMenu()) {
|
||||
@ -64,6 +72,21 @@ public abstract class BaseToolBarActivity extends BaseAppCompatActivity implemen
|
||||
}
|
||||
}
|
||||
|
||||
// 小米沉浸式黑色字体
|
||||
@SuppressLint("PrivateApi")
|
||||
public void setStatusBarDarkMode(boolean darkmode, Activity activity) {
|
||||
Class<? extends Window> clazz = activity.getWindow().getClass();
|
||||
try {
|
||||
Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
int darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void initToolbar() {
|
||||
mToolbar = findViewById(R.id.normal_toolbar);
|
||||
mTitleTv = findViewById(R.id.normal_title);
|
||||
@ -171,10 +194,20 @@ public abstract class BaseToolBarActivity extends BaseAppCompatActivity implemen
|
||||
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);
|
||||
}
|
||||
@ -206,44 +239,18 @@ public abstract class BaseToolBarActivity extends BaseAppCompatActivity implemen
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.menu_download) {
|
||||
// todo mEntrance set real value
|
||||
MtaHelper.onEvent("下载管理", "下载管理入口", getActivityNameInChinese());
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(this, "");
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(this, mEntrance);
|
||||
startActivity(intent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
return onNavigationIconClicked();
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供当前 activity 的中文名 (不重载的话为类名)
|
||||
*/
|
||||
public String getActivityNameInChinese() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
protected void setStatusBarColor(int color) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
window.setStatusBarColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean onNavigationIconClicked();
|
||||
|
||||
protected View.OnClickListener provideNavigationItemClickListener() {
|
||||
return view -> onBackPressed();
|
||||
}
|
||||
|
||||
protected abstract boolean showDownloadMenu();
|
||||
protected boolean showDownloadMenu() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,13 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.app.Dialog;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import android.view.KeyEvent;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
import com.gh.common.util.ClickUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -27,7 +28,7 @@ public class BaseDialogFragment extends DialogFragment {
|
||||
final Dialog dialog = new Dialog(getActivity(), R.style.DialogWindowTransparent);
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
dialog.setOnKeyListener((dialog1, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && ClickUtils.isFastDoubleClick()) { //会多次响应??
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && !ClickUtils.isFastDoubleClick()) {
|
||||
return onBack();
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -143,6 +148,49 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
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 +301,12 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected RecyclerView.Adapter provideSyncAdapter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean addSyncPageObserver() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,13 +10,20 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
* ViewPager 配合ViewGroup Checkable实现双切换<br/>
|
||||
@ -31,6 +38,8 @@ public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_View
|
||||
|
||||
protected ViewGroup mCheckableGroup;
|
||||
|
||||
private int mLastPosition = MainWrapperFragment.INDEX_HOME;
|
||||
|
||||
@IdRes
|
||||
protected abstract int getCheckableGroupId();
|
||||
|
||||
@ -68,6 +77,33 @@ public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_View
|
||||
@Override
|
||||
public void onPageSelected(int index) {
|
||||
onPageChanged(index);
|
||||
try {
|
||||
// 补充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();
|
||||
|
||||
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
|
||||
List<Fragment> fragments = childFragmentManager.getFragments();
|
||||
for (Fragment childFragment : fragments) {
|
||||
childFragment.onResume();
|
||||
}
|
||||
}
|
||||
mLastPosition = index;
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
163
app/src/main/java/com/gh/base/fragment/BaseLazyFragment.kt
Normal file
163
app/src/main/java/com/gh/base/fragment/BaseLazyFragment.kt
Normal file
@ -0,0 +1,163 @@
|
||||
package com.gh.base.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.normal.NormalFragment
|
||||
|
||||
/**
|
||||
* 懒加载(支持多层嵌套)
|
||||
*/
|
||||
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) {
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,14 +2,27 @@ package com.gh.common
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.Executors
|
||||
import com.gh.common.AppExecutor.ioExecutor
|
||||
import com.gh.common.AppExecutor.lightWeightIoExecutor
|
||||
import com.gh.common.AppExecutor.uiExecutor
|
||||
import java.util.concurrent.*
|
||||
|
||||
/**
|
||||
* APP 线程池管理类
|
||||
*
|
||||
* [ioExecutor] 是一个最大线程数固定的线程池,较为繁重的 IO 任务可以交给它
|
||||
* [uiExecutor] 是主线程的包裹,需要切换至主线程执行可以用它
|
||||
* [lightWeightIoExecutor] 是一个单线程的线程池,轻量级且需要保证同一线程的 IO 任务可以交给它
|
||||
*
|
||||
*/
|
||||
object AppExecutor {
|
||||
@JvmStatic
|
||||
var ioExecutor = Executors.newSingleThreadExecutor()
|
||||
|
||||
@JvmStatic
|
||||
var uiExecutor = MainThreadExecutor()
|
||||
@JvmStatic
|
||||
var lightWeightIoExecutor = Executors.newSingleThreadExecutor()
|
||||
@JvmStatic
|
||||
var ioExecutor = Executors.newCachedThreadPool()
|
||||
|
||||
class MainThreadExecutor : Executor {
|
||||
private val mainThreadHandler = Handler(Looper.getMainLooper())
|
||||
@ -24,8 +37,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) {
|
||||
|
||||
@ -1,15 +1,31 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.webkit.JavascriptInterface
|
||||
import androidx.annotation.Keep
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.util.toObject
|
||||
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
|
||||
import com.gh.gamecenter.room.AppDatabase
|
||||
import com.gh.gamecenter.user.LoginTag
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
import wendu.dsbridge.CompletionHandler
|
||||
|
||||
class DefaultJsApi {
|
||||
class DefaultJsApi(var context: Context) {
|
||||
|
||||
@JavascriptInterface
|
||||
fun isGhzs(msg: Any): String {
|
||||
@ -28,6 +44,94 @@ class DefaultJsApi {
|
||||
MtaHelper.onEvent(mtaEvent.name, mtaEvent.key, mtaEvent.value)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getUserInfo(msg: Any): String {
|
||||
return UserManager.getInstance().userInfoEntity.toJson()
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getUserToken(msg: Any): String {
|
||||
return if (UserManager.getInstance().isLoggedIn) UserManager.getInstance().loginTokenEntity.accessToken.value else ""
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun login(msg: Any) {
|
||||
val intent = LoginActivity.getIntent(context, "浏览器")
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun refreshUserInfoBadge(msg: Any) {
|
||||
val userInfoEntity = UserManager.getInstance().userInfoEntity
|
||||
if (msg.toString().isNotEmpty()) {
|
||||
val badge = msg.toString().toObject() ?: Badge()
|
||||
userInfoEntity.badge = badge
|
||||
} else {
|
||||
userInfoEntity.badge = null
|
||||
}
|
||||
UserManager.getInstance().userInfoEntity = userInfoEntity
|
||||
AppDatabase.getInstance(context).userInfoDao().updateUserInfo(userInfoEntity)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getChannel(msg: Any): String {
|
||||
return HaloApp.getInstance().channel
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getAppVersion(msg: Any): String {
|
||||
return BuildConfig.VERSION_NAME
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun bindWechat(msg: Any, handler: CompletionHandler<Any>) {
|
||||
context.ifLogin("浏览器") {
|
||||
LoginHelper.loginWithWechat(object : LoginHelper.LoginCallback {
|
||||
@SuppressLint("CheckResult")
|
||||
override fun onLoginSuccess(loginType: LoginTag, jsonContent: JSONObject) {
|
||||
|
||||
val wechatLoginInfoMap = hashMapOf<String, String>()
|
||||
wechatLoginInfoMap["openid"] = jsonContent.getString("openid")
|
||||
wechatLoginInfoMap["unionid"] = jsonContent.getString("unionid")
|
||||
wechatLoginInfoMap["access_token"] = jsonContent.getString("access_token")
|
||||
wechatLoginInfoMap["refresh_token"] = jsonContent.getString("refresh_token")
|
||||
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.api
|
||||
.postBindWechat(wechatLoginInfoMap.createRequestBody())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
handler.complete(true)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
handler.complete(false)
|
||||
if (exception is HttpException) {
|
||||
ErrorHelper.handleError(HaloApp.getInstance().application, exception.response().errorBody()?.string())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onLoginFailure(loginType: LoginTag, error: String) {
|
||||
handler.complete(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun copyText(msg: Any) {
|
||||
msg.toString().copyTextAndToast()
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun startApp(msg: Any) {
|
||||
val packageName = msg.toString()
|
||||
PackageUtils.launchApplicationByPackageName(HaloApp.getInstance().application, packageName)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun openImage(event: Any) {
|
||||
@ -47,9 +151,6 @@ class DefaultJsApi {
|
||||
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,16 +4,21 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.common.util.EntranceUtils.ENTRANCE_BROWSER
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.LibaoDetailActivity
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.lightgame.utils.Utils
|
||||
import com.moor.imkf.requesturl.RequestUrl.type
|
||||
|
||||
object DefaultWebViewUrlHandler {
|
||||
|
||||
@ -33,7 +38,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)
|
||||
|
||||
@ -106,12 +111,38 @@ object DefaultWebViewUrlHandler {
|
||||
context, typeId, communityId,
|
||||
entrance, "文章链接")
|
||||
}
|
||||
DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ import com.halo.assistant.HaloApp
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
/**
|
||||
* 统计用户在当前 Fragment 的停留时间,在 onViewDestroy 或 onDestroy 里获取 elapsedTime 即可,单位为秒
|
||||
* 统计用户在当前 Fragment/Activity 的停留时间,在 onViewDestroy 或 onDestroy 里获取 elapsedTime 即可,单位为秒
|
||||
*/
|
||||
class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) {
|
||||
|
||||
|
||||
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?)
|
||||
}
|
||||
@ -5,19 +5,28 @@ import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
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 androidx.annotation.Nullable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class Config {
|
||||
|
||||
public static final String API_HOST = BuildConfig.API_HOST;
|
||||
@ -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();
|
||||
}
|
||||
@ -232,4 +244,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;
|
||||
@ -16,20 +18,52 @@ public class Constants {
|
||||
public static final String USER_INFO_KEY = "userInfoKey";
|
||||
|
||||
public static final String DEVICE_KEY = "deviceKey";
|
||||
|
||||
|
||||
public static final String HAS_REQUESTED_NOTIFICATION_PERMISSIONS = "has_requested_notification_permissions";
|
||||
|
||||
public static final String SHOULD_SHOW_VIDEO_MOBILE_WARNING = "should_show_video_mobile_warning";
|
||||
|
||||
|
||||
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 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";
|
||||
|
||||
//引导设置 “通知管理” 引导弹窗
|
||||
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 REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
|
||||
@ -39,6 +73,14 @@ public class Constants {
|
||||
//输入规则
|
||||
public static final String INPUT_RULE = "0123456789abcdefghijklnmopqrstuvwxyzABCDEFGHIJKLNMOPQRSTUVWXYZ_";
|
||||
|
||||
// 微信绑定地址地址
|
||||
public static final String WECHAT_BIND_ADDRESS_DEV = "https://resource.ghzs.com/page/wechat_dev/index.html#/";
|
||||
public static final String WECHAT_BIND_ADDRESS = "https://resource.ghzs.com/page/wechat_pro/index.html#/";
|
||||
|
||||
// 徽章
|
||||
public static final String BADGE_ADDRESS_DEV = "http://resource.ghzs.com/page/badge_dev/index.html#/";
|
||||
public static final String BADGE_ADDRESS = "http://resource.ghzs.com/page/badge_pro/index.html#/";
|
||||
|
||||
//最少需要多少数据才能上传
|
||||
public static final int DATA_AMOUNT = 20;
|
||||
|
||||
@ -54,10 +96,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";
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ public class ItemViewType {
|
||||
public static final int GAME_SLIDE = 1; // 滚动图布局
|
||||
public static final int GAME_NORMAL = 2; // 正常游戏布局
|
||||
public static final int GAME_SUBJECT = 19;
|
||||
public static final int GAME_SUBJECT_SLIDE = 26;
|
||||
public static final int GAME_TEST = 3; // 测试游戏布局
|
||||
public static final int GAME_IMAGE = 4; // 游戏大图布局
|
||||
public static final int NEWS_HEADER = 5; // 新闻头部布局
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
package com.gh.common.databind;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
@ -12,8 +16,11 @@ import android.widget.TextView;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.OnViewClickListener;
|
||||
import com.gh.common.constant.Config;
|
||||
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.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
@ -21,24 +28,30 @@ 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.StringUtils;
|
||||
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.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;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.gh.gamecenter.qa.entity.CommunityVideoEntity;
|
||||
@ -52,6 +65,8 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.BindingAdapter;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
@ -308,8 +323,14 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
// 大图下的进度条
|
||||
@BindingAdapter({"downloadButton", "traceEvent"})
|
||||
public static void setDownloadButton(DownloadProgressBar progressBar, GameEntity gameEntity, ExposureEvent traceEvent) {
|
||||
@BindingAdapter({"downloadButton", "traceEvent", "clickCallBack", "entrance", "location"})
|
||||
public static void setDownloadButton(DownloadProgressBar progressBar,
|
||||
GameEntity gameEntity,
|
||||
ExposureEvent traceEvent,
|
||||
@Nullable View.OnClickListener clickCallBack,
|
||||
@Nullable String entrance,
|
||||
@Nullable String location) {
|
||||
|
||||
// 判断是否显示按钮
|
||||
if (gameEntity != null
|
||||
&& Config.isShowDownload(gameEntity.getId())
|
||||
@ -320,15 +341,121 @@ public class BindingAdapters {
|
||||
return;
|
||||
}
|
||||
|
||||
// 点击事件
|
||||
progressBar.setOnClickListener(v -> {
|
||||
if (clickCallBack != null) clickCallBack.onClick(v);
|
||||
switch (progressBar.getDownloadType()) {
|
||||
case DOWNLOADING_PLUGIN:
|
||||
case DOWNLOADING_NORMAL:
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(v.getContext(),
|
||||
gameEntity.getApk().get(0).getUrl(), entrance);
|
||||
v.getContext().startActivity(intent);
|
||||
break;
|
||||
case NONE:
|
||||
Utils.toast(v.getContext(), "该游戏已关闭下载");
|
||||
break;
|
||||
case NORMAL:
|
||||
case PLUGIN:
|
||||
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);
|
||||
}
|
||||
break;
|
||||
case LAUNCH_OR_OPEN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
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);
|
||||
}
|
||||
break;
|
||||
case INSTALL_PLUGIN:
|
||||
case INSTALL_NORMAL:
|
||||
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);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RESERVABLE:
|
||||
CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> {
|
||||
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(progressBar.getContext(), () -> {
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(gameEntity, () -> {
|
||||
LogUtils.logReservation(gameEntity, traceEvent);
|
||||
updateReservation(progressBar, gameEntity);
|
||||
});
|
||||
dialogFragment.show(((AppCompatActivity) progressBar.getContext()).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
});
|
||||
break;
|
||||
case RESERVED:
|
||||
if ("download".equals(gameEntity.getReserveStatus())) {
|
||||
ReservationHelper.showDeleteReservationDialog(progressBar.getContext(), () -> {
|
||||
ReservationHelper.deleteReservation(gameEntity, () -> {
|
||||
updateReservation(progressBar, gameEntity);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ReservationHelper.showCancelReservationDialog(progressBar.getContext(), () -> {
|
||||
ReservationHelper.cancelReservation(gameEntity, () -> {
|
||||
updateReservation(progressBar, gameEntity);
|
||||
});
|
||||
});
|
||||
}
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
// 显示预约
|
||||
if (gameEntity.isReservable()) {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
|
||||
progressBar.setText("预约");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.RESERVABLE);
|
||||
} else {
|
||||
progressBar.setText("已预约");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.RESERVED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示下载按钮状态
|
||||
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) {
|
||||
@ -382,61 +509,30 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 点击事件
|
||||
progressBar.setOnClickListener(v -> {
|
||||
switch (progressBar.getDownloadType()) {
|
||||
case DOWNLOADING_PLUGIN:
|
||||
case DOWNLOADING_NORMAL:
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(v.getContext(),
|
||||
gameEntity.getApk().get(0).getUrl(), "(我的光环:我的游戏)");
|
||||
v.getContext().startActivity(intent);
|
||||
break;
|
||||
case NONE:
|
||||
Utils.toast(v.getContext(), "该游戏已关闭下载");
|
||||
break;
|
||||
case NORMAL:
|
||||
case PLUGIN:
|
||||
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));
|
||||
});
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
"(我的光环:我的游戏)", "我的光环-我的游戏:" + gameEntity.getName(), traceEvent);
|
||||
}
|
||||
break;
|
||||
case LAUNCH_OR_OPEN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
DataUtils.onGameLaunchEvent(v.getContext(), gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), "我的光环-我的游戏");
|
||||
PackageUtils.launchApplicationByPackageName(v.getContext(), gameEntity.getApk().get(0).getPackageName());
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
"(我的光环:我的游戏)", "我的光环-我的游戏:" + gameEntity.getName(), traceEvent);
|
||||
}
|
||||
break;
|
||||
case INSTALL_PLUGIN:
|
||||
case INSTALL_NORMAL:
|
||||
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());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static void updateReservation(DownloadProgressBar progressBar, GameEntity gameEntity) {
|
||||
// 显示预约
|
||||
if (gameEntity.isReservable()) {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
|
||||
progressBar.setText("预约");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.RESERVABLE);
|
||||
} else {
|
||||
progressBar.setText("已预约");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.RESERVED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 开始下载
|
||||
private static void download(DownloadProgressBar progressBar, GameEntity
|
||||
gameEntity, ExposureEvent traceEvent, boolean isSubscribe) {
|
||||
private static void download(DownloadProgressBar progressBar,
|
||||
GameEntity gameEntity,
|
||||
ExposureEvent traceEvent,
|
||||
boolean isSubscribe,
|
||||
String entrance,
|
||||
String location) {
|
||||
String str = progressBar.getText();
|
||||
String method;
|
||||
if (str.contains("更新")) {
|
||||
@ -449,15 +545,17 @@ public class BindingAdapters {
|
||||
ApkEntity apkEntity = gameEntity.getApk().get(0);
|
||||
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity.getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(progressBar.getContext(), gameEntity.getName(), apkEntity.getPlatform(), "(我的光环:我的游戏)", "下载开始", method);
|
||||
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, ExposureUtils.DownloadType.DOWNLOAD);
|
||||
|
||||
DataUtils.onGameDownloadEvent(progressBar.getContext(), gameEntity.getName(), apkEntity.getPlatform(), entrance, "下载开始", method);
|
||||
|
||||
ExposureUtils.DownloadType downloadType = ExposureUtils.getDownloadType(apkEntity, method);
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, downloadType);
|
||||
|
||||
DownloadManager.createDownload(progressBar.getContext(),
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
method,
|
||||
StringUtils.buildString("(我的光环:我的游戏)"), "我的光环-我的游戏:" + gameEntity.getName(),
|
||||
entrance,
|
||||
location + gameEntity.getName(),
|
||||
isSubscribe,
|
||||
downloadExposureEvent);
|
||||
|
||||
@ -494,9 +592,7 @@ public class BindingAdapters {
|
||||
|
||||
@BindingAdapter("isRefreshing")
|
||||
public static void isRefreshing(SwipeRefreshLayout layout, LoadStatus status) {
|
||||
if (status == LoadStatus.INIT_LOADING) {
|
||||
layout.setRefreshing(true);
|
||||
} else {
|
||||
if (status != LoadStatus.INIT_LOADING && status != LoadStatus.LIST_LOADING) {
|
||||
layout.setRefreshing(false);
|
||||
}
|
||||
}
|
||||
@ -538,4 +634,33 @@ public class BindingAdapters {
|
||||
mVideoDuration.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"setGameTags", "setMaxGameTags"})
|
||||
public static void setGameTags(TextView view, List<TagStyleEntity> tags, int maxTags) {
|
||||
if (tags == null) {
|
||||
view.setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
int showCount = tags.size() > maxTags ? maxTags : tags.size(); // 最多显示3个
|
||||
|
||||
StringBuilder content = new StringBuilder();
|
||||
for (int i = 0; i < showCount; i++) {
|
||||
TagStyleEntity tag = tags.get(i);
|
||||
content.append(tag.getName());
|
||||
if (i != showCount - 1) content.append("/");
|
||||
}
|
||||
|
||||
Spannable span = new SpannableString(content);
|
||||
int index = 0;
|
||||
for (int i = 0; i < showCount; i++) {
|
||||
TagStyleEntity tag = tags.get(i);
|
||||
int start = index;
|
||||
int end = start + tag.getName().length() + ((i != showCount - 1) ? 1 : 0);
|
||||
index = end;
|
||||
span.setSpan(new ForegroundColorSpan(Color.parseColor("#" + tag.getColor())),
|
||||
start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
view.setText(span);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -25,6 +25,7 @@ import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
|
||||
// 预约弹窗
|
||||
class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
@ -83,14 +84,14 @@ class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
mViewModel.reservation.observeNonNull(this) {
|
||||
if (it.success) {
|
||||
showSuccessDialog(it.withMobile)
|
||||
showSuccessDialog(it.withMobile, it.boundWechat)
|
||||
mSuccessCallback?.onSuccess()
|
||||
}
|
||||
}
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
}
|
||||
|
||||
private fun showSuccessDialog(withMobile: Boolean) {
|
||||
private fun showSuccessDialog(withMobile: Boolean, boundWechat: Boolean) {
|
||||
reserveHintTv.text = "游戏预约成功"
|
||||
reserveContainer.visibility = View.GONE
|
||||
reserveCompletedContainer.visibility = View.VISIBLE
|
||||
@ -100,7 +101,7 @@ class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
reserveCompletedContentTv.text = dialogConfig?.htmlContent?.fromHtml()
|
||||
if (dialogConfig?.text.isNullOrEmpty()
|
||||
|| dialogConfig?.toLinkEntity()?.link.isNullOrEmpty()) {
|
||||
|| (dialogConfig?.type == "wechat_bind" && boundWechat)) {
|
||||
customizableBtn.visibility = View.GONE
|
||||
} else {
|
||||
customizableBtn.text = dialogConfig?.text
|
||||
@ -176,7 +177,12 @@ class ReserveViewModel(application: Application) : AndroidViewModel(application)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
reservation.postValue(Reservation(success = true, withMobile = mobile.isNotEmpty()))
|
||||
var boundWechat = false
|
||||
tryWithDefaultCatch {
|
||||
boundWechat = JSONObject(data.string() ?: "").getBoolean("wechat_bind")
|
||||
}
|
||||
|
||||
reservation.postValue(Reservation(success = true, withMobile = mobile.isNotEmpty(), boundWechat = boundWechat))
|
||||
ReservationRepository.addReservationToMemoryAndRefresh(gameId)
|
||||
|
||||
MtaHelper.onEvent("预约游戏", "预约", gameName)
|
||||
@ -188,6 +194,5 @@ class ReserveViewModel(application: Application) : AndroidViewModel(application)
|
||||
})
|
||||
}
|
||||
|
||||
class Reservation(var success: Boolean = false, var withMobile: Boolean = false)
|
||||
|
||||
class Reservation(var success: Boolean = false, var withMobile: Boolean = false, var boundWechat: Boolean = false)
|
||||
}
|
||||
@ -7,7 +7,7 @@ import android.view.KeyEvent
|
||||
import com.gh.common.util.MtaHelper
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
class TrackableDialog(context: Context,
|
||||
open class TrackableDialog(context: Context,
|
||||
themeResId: Int,
|
||||
private var mEvent: String,
|
||||
private var mKey: String,
|
||||
|
||||
@ -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 exposureDao by lazy { ExposureDatabase.buildDatabase(HaloApp.getInstance().application).logHubEventDao() }
|
||||
private val exposureExecutor = Executors.newSingleThreadExecutor()
|
||||
private val exposureCache = FixedSizeLinkedHashSet<String>(300)
|
||||
private val exposureDao by lazy { ExposureDatabase.buildDatabase(HaloApp.getInstance().application).logHubEventDao() }
|
||||
|
||||
@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>)
|
||||
}
|
||||
88
app/src/main/java/com/gh/common/loghub/LoghubUtils.kt
Normal file
88
app/src/main/java/com/gh/common/loghub/LoghubUtils.kt
Normal file
@ -0,0 +1,88 @@
|
||||
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 = 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()
|
||||
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,17 @@
|
||||
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"
|
||||
|
||||
}
|
||||
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)
|
||||
|
||||
"投诉" -> {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
@ -12,19 +13,23 @@ 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;
|
||||
import com.gh.gamecenter.entity.UserInfoEntity;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
@ -33,6 +38,9 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.HttpException;
|
||||
|
||||
/**
|
||||
@ -75,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);
|
||||
|
||||
@ -86,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("投诉");
|
||||
|
||||
@ -116,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;
|
||||
@ -208,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);
|
||||
|
||||
@ -232,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);
|
||||
@ -274,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);
|
||||
|
||||
@ -297,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);
|
||||
@ -330,27 +320,46 @@ 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()));
|
||||
}
|
||||
|
||||
if (entity.getUser().getBadge() != null) {
|
||||
holder.userBadgeSdv.setVisibility(View.VISIBLE);
|
||||
holder.badgeNameTv.setVisibility(View.VISIBLE);
|
||||
ImageUtils.display(holder.userBadgeSdv, entity.getUser().getBadge().getIcon());
|
||||
holder.badgeNameTv.setText(entity.getUser().getBadge().getName());
|
||||
} else {
|
||||
holder.userBadgeSdv.setVisibility(View.GONE);
|
||||
holder.badgeNameTv.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
//检查是否是自身评论
|
||||
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 {
|
||||
@ -359,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 {
|
||||
@ -376,6 +386,36 @@ public class CommentUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public static void isUserCommentedOnThisGame(String gameId, WeakReference<SimpleCallback<Boolean>> callback) {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
|
||||
.getApi()
|
||||
.isUserCommentedOnThisGame(UserManager.getInstance().getUserId(), gameId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<ResponseBody>() {
|
||||
@Override
|
||||
public void onSuccess(ResponseBody data) {
|
||||
SimpleCallback<Boolean> cb = callback.get();
|
||||
if (cb != null) {
|
||||
try {
|
||||
JSONObject object = new JSONObject(data.string());
|
||||
cb.onCallback(object.getBoolean("status"));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Exception exception) {
|
||||
Utils.toast(HaloApp.getInstance().getApplication(), "网络异常");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//复制文字
|
||||
public static void copyText(String copyContent, Context context) {
|
||||
ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
|
||||
@ -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,6 +9,7 @@ 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;
|
||||
@ -47,12 +48,24 @@ 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.downloadOffText) ? "查看详情" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE_WITH_HINT);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "暂无下载" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String status = GameUtils.getDownloadBtnText(viewHolder.context, viewHolder.gameEntity, PluginLocation.only_game);
|
||||
|
||||
@ -5,7 +5,11 @@ 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.CountDownTimer;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
@ -17,26 +21,41 @@ 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 androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchy;
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.TrackableDialog;
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.common.view.FixLinearLayoutManager;
|
||||
import com.gh.gamecenter.AboutActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.adapter.viewholder.PrivacyPolicyItemViewHolder;
|
||||
import com.gh.gamecenter.databinding.PrivacyItemBinding;
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
|
||||
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.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class DialogUtils {
|
||||
|
||||
public static Dialog showWaitDialog(Context context, String msg) {
|
||||
@ -144,29 +163,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 +201,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 +230,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 +288,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();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -420,7 +504,7 @@ public class DialogUtils {
|
||||
contentTv.setText(message);
|
||||
titleTv.setText(title);
|
||||
negativeTv.setText(negative);
|
||||
negativeTv.setTextColor(ContextCompat.getColor(context, R.color.hint));
|
||||
//negativeTv.setTextColor(ContextCompat.getColor(context, R.color.hint));
|
||||
positiveTv.setText(positive);
|
||||
|
||||
negativeTv.setOnClickListener(new View.OnClickListener() {
|
||||
@ -563,9 +647,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 +870,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 +955,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 +1006,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 +1083,59 @@ 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.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 +1151,79 @@ 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context may be is application context
|
||||
* @return activity context
|
||||
@ -936,6 +1237,7 @@ public class DialogUtils {
|
||||
return context;
|
||||
}
|
||||
|
||||
// currentActivity 是否存在 isDestroyed 的情况?
|
||||
return AppManager.getInstance().currentActivity();
|
||||
}
|
||||
|
||||
|
||||
@ -9,17 +9,22 @@ 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
|
||||
import com.gh.gamecenter.category.CategoryDirectoryActivity
|
||||
import com.gh.gamecenter.download.DownloadFragment.Companion.INDEX_UPDATE
|
||||
import com.gh.gamecenter.entity.*
|
||||
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.HomeActivity
|
||||
import com.gh.gamecenter.personalhome.UserHomeActivity
|
||||
import com.gh.gamecenter.qa.CommunityFragment
|
||||
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
|
||||
import com.gh.gamecenter.qa.article.SimpleArticleListActivity
|
||||
@ -27,10 +32,14 @@ import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity
|
||||
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
|
||||
import com.gh.gamecenter.qa.subject.CommunitySubjectActivity
|
||||
import com.gh.gamecenter.servers.GameServersActivity
|
||||
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
|
||||
@ -46,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!!))
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,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(
|
||||
@ -115,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,
|
||||
@ -127,14 +186,41 @@ object DirectUtils {
|
||||
display = linkEntity.display ?: Display())))
|
||||
}
|
||||
|
||||
"column_collection" -> {
|
||||
context.startActivity(ColumnCollectionDetailActivity.getIntent(context, linkEntity.link!!, entrance))
|
||||
"column_collection", "专题合集" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
|
||||
|
||||
"server" -> {
|
||||
context.startActivity(GameServersActivity.getIntent(context, entrance, path))
|
||||
}
|
||||
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
"top_game_comment" -> directToAmway(context, null, entrance, path)
|
||||
|
||||
"wechat_bind" -> context.startActivity(WebActivity.getBindWechatIntent(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)
|
||||
|
||||
else -> {
|
||||
if (unknownCallback != null) {
|
||||
unknownCallback.invoke()
|
||||
} else {
|
||||
DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至专题合集
|
||||
*/
|
||||
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String) {
|
||||
context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance))
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到新闻详情
|
||||
*/
|
||||
@ -147,24 +233,69 @@ object DirectUtils {
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至个人主页
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToHomeActivity(context: Context, userId: String?, entrance: String? = null, path: String? = null) {
|
||||
context.startActivity(HomeActivity.getIntent(context, userId ?: "", entrance, path))
|
||||
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)
|
||||
}
|
||||
|
||||
/**
|
||||
* 回到首页
|
||||
*/
|
||||
fun directToMainActivity(context: Context) {
|
||||
val intent = Intent(context, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_CLEAR_TOP }
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到游戏详情
|
||||
*/
|
||||
@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))
|
||||
@ -282,16 +413,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"
|
||||
@ -348,7 +479,22 @@ object DirectUtils {
|
||||
|
||||
// 这里换个线程操作是为了做一点延时
|
||||
AppExecutor.ioExecutor.execute {
|
||||
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_GAMEFRAGMENT, 1))
|
||||
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_ASK))
|
||||
EventBus.getDefault().post(EBReuse(CommunityFragment.EB_RETRY_PAGE))
|
||||
}
|
||||
}
|
||||
|
||||
@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))
|
||||
}
|
||||
}
|
||||
@ -382,18 +528,85 @@ 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
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToAmway(context: Context, fixedTopAmwayCommentId: String? = null, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, AmwayActivity::class.java.name)
|
||||
bundle.putString(KEY_ID, fixedTopAmwayCommentId)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至徽章墙
|
||||
*/
|
||||
@JvmStatic
|
||||
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;
|
||||
@ -16,9 +17,11 @@ import com.gh.common.view.DownloadDialog;
|
||||
import com.gh.download.DownloadManager;
|
||||
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;
|
||||
@ -167,21 +170,34 @@ 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));
|
||||
|
||||
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);
|
||||
}
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
}
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
updateNormalItem(context, holder, gameEntity, isShowPlatform, pluginLocation);
|
||||
} else {
|
||||
@ -367,20 +383,26 @@ public class DownloadItemUtils {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
CheckLoginUtils.checkLogin(context, entrance, () -> {
|
||||
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(context, () -> {
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
|
||||
gameEntity,
|
||||
() -> adapter.notifyItemChanged(position)
|
||||
);
|
||||
dialogFragment.show(((AppCompatActivity) context).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(context, () -> {
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
|
||||
gameEntity,
|
||||
() -> {
|
||||
LogUtils.logReservation(gameEntity, traceEvent);
|
||||
adapter.notifyItemChanged(position);
|
||||
}
|
||||
);
|
||||
dialogFragment.show(((AppCompatActivity) context).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
if ("download".equals(gameEntity.getReserveStatus())) {
|
||||
ReservationHelper.showDeleteReservationDialog(context, () -> {
|
||||
ReservationHelper.deleteReservation(gameEntity, () -> {
|
||||
@ -398,14 +420,20 @@ 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 = () -> {
|
||||
onNormalClick(context, downloadBtn, gameEntity, position, adapter, entrance, location, traceEvent);
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
onNormalClick(context, downloadBtn, gameEntity, position, adapter, entrance, location, traceEvent);
|
||||
};
|
||||
|
||||
// 启动不需要请求存储权限
|
||||
@ -417,11 +445,11 @@ public class DownloadItemUtils {
|
||||
});
|
||||
} else {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(context, () -> {
|
||||
DownloadDialog.getInstance(context).showPopupWindow(v, gameEntity, entrance, location, traceEvent);
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -508,8 +536,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);
|
||||
}
|
||||
@ -530,8 +556,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);
|
||||
}
|
||||
@ -552,16 +576,20 @@ public class DownloadItemUtils {
|
||||
}
|
||||
adapter.notifyItemChanged(position);
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
237
app/src/main/java/com/gh/common/util/DownloadObserver.kt
Normal file
237
app/src/main/java/com/gh/common/util/DownloadObserver.kt
Normal file
@ -0,0 +1,237 @@
|
||||
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) {
|
||||
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(downloadEntity.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(downloadEntity.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", "", "", "", "", ""))
|
||||
}
|
||||
|
||||
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.gameId, 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";
|
||||
@ -46,7 +59,9 @@ public class EntranceUtils {
|
||||
public static final String KEY_TYPE = "type";
|
||||
public static final String KEY_LINK = "link";
|
||||
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 = "(启动弹窗)";
|
||||
@ -65,6 +80,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_LOCATION = "location";
|
||||
public static final String KEY_CURRENTITEM = "currentItem";
|
||||
public static final String KEY_COMMENTID = "commentId";
|
||||
public static final String KEY_SHOW_KEYBOARD_IF_NEEDED = "show_key_board_if_needed";
|
||||
public static final String KEY_PATH = "path";
|
||||
public static final String KEY_OUTER_INFO = "outerInfo";
|
||||
public static final String KEY_OLDERUSER = "isOldUser";
|
||||
@ -97,6 +113,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";
|
||||
@ -120,10 +137,21 @@ public class EntranceUtils {
|
||||
public static final String KEY_VIDEO_ID = "videoId";
|
||||
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_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 void jumpActivity(Context context, Bundle bundle) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
//TODO 把其他类似的跳转启动逻辑也处理掉
|
||||
if (RunningUtils.isRunning(context)
|
||||
@ -146,4 +174,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,11 +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 {
|
||||
@ -141,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
|
||||
|
||||
/**
|
||||
@ -79,6 +86,21 @@ fun ViewPager.addOnPageChangeListener(onSelected: ((position: Int) -> Unit)? = n
|
||||
addOnPageChangeListener(listener)
|
||||
}
|
||||
|
||||
fun ViewPager.addOnScrollStateChanged(onStateChanged: ((state: Int) -> Unit)? = null) {
|
||||
val listener = object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
onStateChanged?.invoke(state)
|
||||
}
|
||||
}
|
||||
addOnPageChangeListener(listener)
|
||||
}
|
||||
|
||||
/**
|
||||
* RecyclerView Extensions
|
||||
*/
|
||||
@ -201,6 +223,20 @@ 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()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String related
|
||||
*/
|
||||
@ -208,6 +244,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>"
|
||||
@ -247,6 +288,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
|
||||
@ -270,8 +321,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在屏幕上的左上角坐标位置
|
||||
@ -279,21 +331,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])
|
||||
@ -353,10 +402,10 @@ fun FragmentActivity.checkStoragePermissionBeforeAction(action: (() -> Unit)) {
|
||||
/**
|
||||
* TextView related.
|
||||
*/
|
||||
fun TextView.setTextWithHighlightedTextWrappedInsideWrapper(text: String,
|
||||
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> {
|
||||
@ -385,7 +434,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 {
|
||||
@ -416,4 +465,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?) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -2,10 +2,11 @@ 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;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -56,7 +57,7 @@ public class GameUtils {
|
||||
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));
|
||||
downloadBtn.setTextColor(ContextCompat.getColor(context, R.color.theme_font));
|
||||
} else {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
}
|
||||
@ -148,6 +149,7 @@ public class GameUtils {
|
||||
gameUpdateEntity.setBrief(gameEntity.getBrief());
|
||||
gameUpdateEntity.setPlugin(apkEntity.getPlugin());
|
||||
gameUpdateEntity.setDownload(gameEntity.getDownload());
|
||||
gameUpdateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
return gameUpdateEntity;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
@ -22,6 +21,8 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
/**
|
||||
* @author 温冠超
|
||||
* @email 294299195@qq.com
|
||||
@ -53,6 +54,28 @@ public class GameViewUtils {
|
||||
}
|
||||
}
|
||||
|
||||
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; i < tagStyle.size() - 1; i++) {
|
||||
View view;
|
||||
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, tagStyle.get(i).getName(), DisplayUtils.dip2px(context, 8), tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
|
||||
}
|
||||
if (view != null) {
|
||||
labelLayout.addView(view);
|
||||
}
|
||||
if (labelLayout.getChildCount() == 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -8,6 +8,8 @@ import org.json.JSONObject
|
||||
|
||||
/**
|
||||
* 广点通辅助类 [https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/403]
|
||||
*
|
||||
* 更换帐号 [https://gitlab.ghzs.com/pm/yunying/issues/893]
|
||||
*/
|
||||
object GdtHelper {
|
||||
|
||||
@ -21,7 +23,7 @@ object GdtHelper {
|
||||
const val PLATFORM = "PLATFORM"
|
||||
|
||||
fun init(application: Application) {
|
||||
GDTAction.init(application, "1108222478", "0b2bb2b971c8221be45a8454f05a0b1f")
|
||||
GDTAction.init(application, "1110071928", "7fe03caa04ed382e9dce401312b1d0ae")
|
||||
}
|
||||
|
||||
fun logAction(type: String) {
|
||||
|
||||
@ -1,303 +0,0 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.user.LoginTag;
|
||||
import com.lightgame.utils.RuntimeUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.sina.weibo.sdk.WbSdk;
|
||||
import com.sina.weibo.sdk.auth.AuthInfo;
|
||||
import com.sina.weibo.sdk.auth.Oauth2AccessToken;
|
||||
import com.sina.weibo.sdk.auth.WbAuthListener;
|
||||
import com.sina.weibo.sdk.auth.WbConnectErrorMessage;
|
||||
import com.sina.weibo.sdk.auth.sso.SsoHandler;
|
||||
import com.tencent.mm.opensdk.modelmsg.SendAuth;
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI;
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
|
||||
import com.tencent.tauth.IUiListener;
|
||||
import com.tencent.tauth.Tencent;
|
||||
import com.tencent.tauth.UiError;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* Created by khy on 14/06/17.
|
||||
* <p>
|
||||
* 获取第三方登录数据
|
||||
*/
|
||||
|
||||
public class GetLoginDataUtils {
|
||||
|
||||
private static GetLoginDataUtils instance;
|
||||
|
||||
private Context mContext;
|
||||
private OnLoginDataListener mLoginListener; //登录成功回调
|
||||
|
||||
private Tencent mTencent;
|
||||
private IWXAPI mIWXAPI;
|
||||
private SsoHandler mSsoHandler;
|
||||
|
||||
private Oauth2AccessToken mAccessToken; // weibo
|
||||
public static final String SCOPE =
|
||||
"email,direct_messages_read,direct_messages_write,"
|
||||
+ "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"
|
||||
+ "follow_app_official_microblog," + "invitation_write"; // weiboCode
|
||||
|
||||
private GetLoginDataUtils(Context context) {
|
||||
mContext = context;
|
||||
mTencent = Tencent.createInstance(Config.TENCENT_APPID, mContext); //初始化QQ分享
|
||||
|
||||
mIWXAPI = WXAPIFactory.createWXAPI(mContext, Config.WECHAT_APPID, true); //初始化微信分享
|
||||
|
||||
WbSdk.install(context, new AuthInfo(mContext, Config.WEIBO_APPKEY, "http://www.sina.com", SCOPE));
|
||||
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "initLogin");
|
||||
}
|
||||
|
||||
public static GetLoginDataUtils getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
instance = new GetLoginDataUtils(context.getApplicationContext());
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
//QQ登录回调处理
|
||||
public IUiListener QqLoginListener = new IUiListener() {
|
||||
@Override
|
||||
public void onComplete(Object o) {
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQ 登录成功");
|
||||
if (o instanceof JSONObject) {
|
||||
JSONObject jsonObject = (JSONObject) o;
|
||||
String s = jsonObject.toString();
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQLoginComplete::" + s);
|
||||
try {
|
||||
mTencent.setOpenId(jsonObject.getString("openid"));
|
||||
mTencent.setAccessToken(jsonObject.getString("access_token"), jsonObject.getString("expires_in"));
|
||||
|
||||
JSONObject content = new JSONObject();
|
||||
content.put("openid", jsonObject.getString("openid"));
|
||||
content.put("access_token_expire", Utils.getTime(mContext) + jsonObject.getLong("expires_in"));
|
||||
content.put("access_token", jsonObject.getString("access_token"));
|
||||
if (mLoginListener != null) {
|
||||
mLoginListener.OnLoginData(content, LoginTag.qq);// QQ 登录回调
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQ登录数据回调异常::" + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// QQToken qqToken = mTencent.getQQToken();
|
||||
// UserInfo userInfo = new UserInfo(mContext, qqToken);
|
||||
// userInfo.getUserInfo(new IUiListener() { // 获取QQ用户信息
|
||||
// @Override
|
||||
// public void onComplete(Object o) {
|
||||
// Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQUserInfo::" + o.toString());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onError(UiError uiError) {
|
||||
// Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQUserInfoUiError::" + uiError.errorDetail + "==" + uiError.errorMessage + "==" + uiError.errorCode);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onCancel() {
|
||||
// Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQUserInfoonCancel");
|
||||
// }
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(UiError uiError) {
|
||||
Utils.toast(mContext, "登录失败");
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQ 登录失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
Utils.toast(mContext, "登录取消");
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQ 登录取消");
|
||||
}
|
||||
};
|
||||
|
||||
public void onQQCallback(int requestCode, int resultCode, Intent data) {
|
||||
Tencent.onActivityResultData(requestCode, resultCode, data, QqLoginListener);
|
||||
}
|
||||
|
||||
// QQ登录
|
||||
public void QQLogin(OnLoginDataListener listener, Activity activity) {
|
||||
mLoginListener = listener;
|
||||
if (mTencent != null && !mTencent.isSessionValid()) {
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQLogin");
|
||||
mTencent.login(activity, "all", QqLoginListener);
|
||||
}
|
||||
}
|
||||
|
||||
public void QQLogout() {
|
||||
if (mTencent != null && mTencent.isSessionValid()) {
|
||||
mTencent.logout(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 微信登录
|
||||
public void WCLogin(OnLoginDataListener listener) {
|
||||
mLoginListener = listener;
|
||||
if (mIWXAPI != null) {
|
||||
boolean register = mIWXAPI.registerApp(Config.WECHAT_APPID);
|
||||
|
||||
SendAuth.Req req = new SendAuth.Req();
|
||||
req.scope = "snsapi_userinfo";
|
||||
req.state = mContext.getString(R.string.app_name);
|
||||
boolean b = mIWXAPI.sendReq(req);
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "微信注册状态::" + register + "\n 发送状态::" + b);
|
||||
if (!register || !b) {
|
||||
Utils.toast(mContext, "请检查是否安装微信客户端");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WCLoginCallBack(JSONObject content) {
|
||||
if (mLoginListener != null) {
|
||||
mLoginListener.OnLoginData(content, LoginTag.wechat);
|
||||
}
|
||||
}
|
||||
|
||||
public void onWeiboCallback(int requestCode, int resultCode, Intent data) {
|
||||
if (mSsoHandler != null) {
|
||||
mSsoHandler.authorizeCallBack(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
// 微博登录
|
||||
public void WeiBoLogin(OnLoginDataListener listener, Activity context) {
|
||||
mSsoHandler = new SsoHandler(context);
|
||||
mLoginListener = listener;
|
||||
mSsoHandler.authorizeClientSso(new SelfWbAuthListener());
|
||||
// 第一次启动本应用,AccessToken 不可用
|
||||
mAccessToken = AccessTokenKeeper.readAccessToken(mContext);
|
||||
|
||||
// if (mAccessToken.isSessionValid()) {
|
||||
// updateTokenView(true);
|
||||
// }
|
||||
}
|
||||
|
||||
// 微博登录回调处理
|
||||
private class SelfWbAuthListener implements WbAuthListener {
|
||||
|
||||
@Override
|
||||
public void onSuccess(final Oauth2AccessToken token) {
|
||||
RuntimeUtils.getInstance().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mAccessToken = token;
|
||||
if (mAccessToken.isSessionValid()) {
|
||||
// 显示 Token
|
||||
// updateTokenView(false);
|
||||
// 保存 Token 到 SharedPreferences
|
||||
AccessTokenKeeper.writeAccessToken(mContext, mAccessToken);
|
||||
Toast.makeText(mContext, "授权成功", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JSONObject content = new JSONObject();
|
||||
try {
|
||||
content.put("uid", token.getUid());
|
||||
content.put("access_token", token.getToken());
|
||||
content.put("access_token_expire", Utils.getTime(mContext) + token.getExpiresTime());
|
||||
content.put("refresh_token", token.getRefreshToken());
|
||||
// content.put("refresh_token_expire", Utils.getTime(mContext) + 86400 * 30); // refresh_token 有效期30天
|
||||
if (mLoginListener != null) {
|
||||
mLoginListener.OnLoginData(content, LoginTag.weibo);// 微博 登录回调
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// AppController.MAIN_EXECUTOR.execute(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// getWeiBoUserInfo(token.getToken(), token.getUid());
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
Utils.toast(mContext, "取消授权");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(WbConnectErrorMessage errorMessage) {
|
||||
Utils.toast(mContext, "微博登录需要客户端支持,请先安装微博");
|
||||
}
|
||||
}
|
||||
|
||||
//微博 获取用户信息
|
||||
private void getWeiBoUserInfo(String accessToken, String uid) {
|
||||
String path = "https://api.weibo.com/2/users/show.json?access_token=" + accessToken + "&uid=" + uid;
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "getWeiBoUserInfo-url::" + path);
|
||||
|
||||
try {
|
||||
URL url = new URL(path);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setDoInput(true);
|
||||
int code = conn.getResponseCode();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "getWeiBoUserInfo-RequestCode::" + code);
|
||||
if (code == 200) {
|
||||
InputStream is = conn.getInputStream();
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, len);
|
||||
}
|
||||
String str = new String(baos.toByteArray());
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "getWeiBoUserInfo-Body::" + str);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 微博显示当前 Token 信息。
|
||||
*
|
||||
* @param hasExisted 配置文件中是否已存在 token 信息并且合法
|
||||
*/
|
||||
private void updateTokenView(boolean hasExisted) {
|
||||
String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(
|
||||
new java.util.Date(mAccessToken.getExpiresTime()));
|
||||
String format = "Token:%1$s \\n有效期:%2$s";
|
||||
String token = String.format(format, mAccessToken.getToken(), date);
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "::WB_TOKEN::" + token);
|
||||
String message = String.format(format, mAccessToken.getToken(), date);
|
||||
if (hasExisted) {
|
||||
message = "Token 仍在有效期内,无需再次登录。" + "\n" + message;
|
||||
}
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "::WB_MESSAGE::" + message);
|
||||
}
|
||||
|
||||
// 登录成功回调
|
||||
public interface OnLoginDataListener {
|
||||
void OnLoginData(JSONObject content, LoginTag loginTag);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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(); //返回文本字符串
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,7 +236,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 +259,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)
|
||||
|
||||
@ -166,12 +166,12 @@ public class LibaoUtils {
|
||||
case "coming":
|
||||
libaoBtn.setText(R.string.libao_coming);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme));
|
||||
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.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "finish":
|
||||
libaoBtn.setText(R.string.libao_finish);
|
||||
@ -181,12 +181,12 @@ public class LibaoUtils {
|
||||
case "linged":
|
||||
libaoBtn.setText(R.string.libao_linged);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme));
|
||||
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.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "copy":
|
||||
libaoBtn.setText(R.string.libao_copy);
|
||||
@ -195,7 +195,7 @@ public class LibaoUtils {
|
||||
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.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "repeatLinged":
|
||||
libaoBtn.setText(R.string.libao_repeat_ling);
|
||||
@ -204,7 +204,7 @@ public class LibaoUtils {
|
||||
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.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "repeatTaoed":
|
||||
libaoBtn.setText(R.string.libao_repeat_tao);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
196
app/src/main/java/com/gh/common/util/LoginHelper.kt
Normal file
196
app/src/main/java/com/gh/common/util/LoginHelper.kt
Normal file
@ -0,0 +1,196 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.widget.Toast
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.user.LoginTag
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.RuntimeUtils
|
||||
import com.lightgame.utils.Utils
|
||||
import com.sina.weibo.sdk.WbSdk
|
||||
import com.sina.weibo.sdk.auth.AuthInfo
|
||||
import com.sina.weibo.sdk.auth.Oauth2AccessToken
|
||||
import com.sina.weibo.sdk.auth.WbAuthListener
|
||||
import com.sina.weibo.sdk.auth.WbConnectErrorMessage
|
||||
import com.sina.weibo.sdk.auth.sso.SsoHandler
|
||||
import com.tencent.mm.opensdk.modelmsg.SendAuth
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory
|
||||
import com.tencent.tauth.IUiListener
|
||||
import com.tencent.tauth.Tencent
|
||||
import com.tencent.tauth.UiError
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
||||
|
||||
/**
|
||||
* 第三方登录辅助类
|
||||
*/
|
||||
object LoginHelper {
|
||||
|
||||
const val WEIBO_SCOPE = (
|
||||
"email,direct_messages_read,direct_messages_write,"
|
||||
+ "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"
|
||||
+ "follow_app_official_microblog," + "invitation_write") // weiboCode
|
||||
|
||||
private var mTencent: Tencent // QQ
|
||||
private var mIWXAPI: IWXAPI // 微信
|
||||
private var mSsoHandler: SsoHandler? = null // 微博 // TODO 完成回调时清掉这个 handler ?
|
||||
|
||||
private var mQqLoginListener: IUiListener
|
||||
|
||||
private var mAccessToken: Oauth2AccessToken? = null // weibo
|
||||
private var mLoginCallback: LoginCallback? = null
|
||||
|
||||
init {
|
||||
val context = HaloApp.getInstance().application.applicationContext
|
||||
mTencent = Tencent.createInstance(Config.TENCENT_APPID, context) //初始化QQ分享
|
||||
mIWXAPI = WXAPIFactory.createWXAPI(context, Config.WECHAT_APPID, true) //初始化微信分享
|
||||
|
||||
mQqLoginListener = object : IUiListener {
|
||||
override fun onComplete(o: Any?) {
|
||||
Utils.log("QQ 登录成功")
|
||||
if (o is JSONObject) {
|
||||
val s = o.toString()
|
||||
Utils.log("QQLoginComplete::$s")
|
||||
try {
|
||||
mTencent.openId = o.getString("openid")
|
||||
mTencent.setAccessToken(o.getString("access_token"), o.getString("expires_in"))
|
||||
|
||||
val content = JSONObject()
|
||||
content.put("openid", o.getString("openid"))
|
||||
content.put("access_token_expire", Utils.getTime(context) + o.getLong("expires_in"))
|
||||
content.put("access_token", o.getString("access_token"))
|
||||
|
||||
mLoginCallback?.onLoginSuccess(LoginTag.qq, content) // 回调QQ登录成功
|
||||
} catch (e: JSONException) {
|
||||
val errorString = "QQ登录数据回调异常::$e"
|
||||
|
||||
mLoginCallback?.onLoginFailure(LoginTag.qq, errorString) // 回调QQ登录失败
|
||||
|
||||
Utils.log(errorString)
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCancel() {
|
||||
mLoginCallback?.onLoginFailure(LoginTag.qq,"登录取消")
|
||||
Utils.log("QQ 登录取消")
|
||||
}
|
||||
|
||||
override fun onError(p0: UiError?) {
|
||||
mLoginCallback?.onLoginFailure(LoginTag.qq,"登录失败")
|
||||
Utils.log("QQ 登录失败")
|
||||
}
|
||||
}
|
||||
|
||||
WbSdk.install(context, AuthInfo(context, Config.WEIBO_APPKEY, "http://www.sina.com", WEIBO_SCOPE))
|
||||
|
||||
Utils.log("LoginHelper initialization")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onQQLoginCallback(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
Tencent.onActivityResultData(requestCode, resultCode, data, mQqLoginListener);
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onWechatLoginSuccess(content: JSONObject) {
|
||||
mLoginCallback?.onLoginSuccess(LoginTag.wechat, content)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onWechatLoginFailure(error: String) {
|
||||
mLoginCallback?.onLoginFailure(LoginTag.wechat, error)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onWeiboLoginCallback(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
mSsoHandler?.authorizeCallBack(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
// QQ登录
|
||||
@JvmStatic
|
||||
fun loginWithQQ(loginCallback: LoginCallback, activity: Activity) {
|
||||
mLoginCallback = loginCallback
|
||||
if (!mTencent.isSessionValid) {
|
||||
Utils.log("QQLogin")
|
||||
mTencent.login(activity, "all", mQqLoginListener)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logoutWithQQ() {
|
||||
if (mTencent.isSessionValid) {
|
||||
mTencent.logout(HaloApp.getInstance().application.applicationContext)
|
||||
}
|
||||
}
|
||||
|
||||
// 微信登录
|
||||
@JvmStatic
|
||||
fun loginWithWechat(loginCallback: LoginCallback) {
|
||||
mLoginCallback = loginCallback
|
||||
val register = mIWXAPI.registerApp(Config.WECHAT_APPID)
|
||||
|
||||
val req = SendAuth.Req()
|
||||
req.scope = "snsapi_userinfo"
|
||||
req.state = HaloApp.getInstance().application.getString(R.string.app_name)
|
||||
val b = mIWXAPI.sendReq(req)
|
||||
Utils.log("微信注册状态::$register\n 发送状态::$b")
|
||||
if (!register || !b) {
|
||||
loginCallback.onLoginFailure(LoginTag.wechat, "请检查是否安装微信客户端")
|
||||
Utils.toast(HaloApp.getInstance().application, "请检查是否安装微信客户端")
|
||||
}
|
||||
}
|
||||
|
||||
// 微博登录
|
||||
@JvmStatic
|
||||
fun loginWithWeibo(loginCallback: LoginCallback, context: Activity) {
|
||||
mLoginCallback = loginCallback
|
||||
mSsoHandler = SsoHandler(context)
|
||||
mSsoHandler?.authorizeClientSso(object : WbAuthListener {
|
||||
override fun onSuccess(token: Oauth2AccessToken?) {
|
||||
token?.let {
|
||||
RuntimeUtils.getInstance().runOnUiThread {
|
||||
mAccessToken = token
|
||||
if (mAccessToken?.isSessionValid == true) {
|
||||
// 保存 Token 到 SharedPreferences
|
||||
AccessTokenKeeper.writeAccessToken(context, mAccessToken)
|
||||
Toast.makeText(context, "授权成功", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
val content = JSONObject()
|
||||
tryWithDefaultCatch {
|
||||
content.put("uid", token.uid)
|
||||
content.put("access_token", token.token)
|
||||
content.put("access_token_expire", Utils.getTime(context) + token.expiresTime)
|
||||
content.put("refresh_token", token.refreshToken)
|
||||
// content.put("refresh_token_expire", Utils.getTime(mContext) + 86400 * 30); // refresh_token 有效期30天
|
||||
mLoginCallback?.onLoginSuccess(LoginTag.weibo, content)// 微博 登录回调
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(p0: WbConnectErrorMessage?) {
|
||||
mLoginCallback?.onLoginFailure(LoginTag.weibo, "微博登录需要客户端支持,请先安装微博")
|
||||
}
|
||||
|
||||
override fun cancel() {
|
||||
mLoginCallback?.onLoginFailure(LoginTag.weibo, "取消授权")
|
||||
}
|
||||
})
|
||||
// 第一次启动本应用,AccessToken 不可用
|
||||
mAccessToken = AccessTokenKeeper.readAccessToken(context)
|
||||
}
|
||||
|
||||
interface LoginCallback {
|
||||
fun onLoginSuccess(loginType: LoginTag, jsonContent: JSONObject)
|
||||
|
||||
fun onLoginFailure(loginType: LoginTag, error: String)
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -49,6 +49,10 @@ object MtaHelper {
|
||||
}
|
||||
}
|
||||
|
||||
if (prop.size == 0 && kv.size == 1) {
|
||||
prop.setProperty(kv[0], kv[0])
|
||||
}
|
||||
|
||||
if (prop.size == 0) return
|
||||
Utils.log("MTA","$eventId + [${kv.joinToString(" , ")}] + last $time seconds")
|
||||
StatService.trackCustomKVTimeIntervalEvent(HaloApp.getInstance().application, time, eventId, prop)
|
||||
|
||||
@ -1,22 +1,122 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.dialog.NotificationHintDialogFragment
|
||||
import com.gh.gamecenter.entity.NotificationHint
|
||||
import com.gh.gamecenter.entity.NotificationUgc
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.AppManager
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
object NotificationHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun showNotificationHintDialog(ugc: NotificationUgc) {
|
||||
val showedNewVersion = SPUtils.getInt(Constants.SP_SHOWED_NOTIFICATION_NEW_VERSION, 0)
|
||||
val currentVersion = PackageUtils.getVersionCode()
|
||||
// 版本升级后重置数据
|
||||
if (currentVersion > showedNewVersion) {
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, false)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, false)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, false)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, false)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, false)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, false)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, "")
|
||||
|
||||
SPUtils.setInt(Constants.SP_SHOWED_NOTIFICATION_NEW_VERSION, currentVersion)
|
||||
}
|
||||
|
||||
|
||||
val isShowedToday = SPUtils.getString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, "")
|
||||
// 每天最多只需提示一次
|
||||
if (isShowedToday == TimeUtils.getToday()) return
|
||||
|
||||
val isShowedLogin = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, false)
|
||||
val isShowedQuestion = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, false)
|
||||
val isShowedAnswer = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, false)
|
||||
val isShowedArticle = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, false)
|
||||
val isShowedVideo = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, false)
|
||||
val isShowedRating = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, false)
|
||||
|
||||
if (isShowedLogin && isShowedQuestion && isShowedAnswer && isShowedArticle && isShowedVideo && isShowedRating) return
|
||||
|
||||
when (ugc) {
|
||||
NotificationUgc.LOGIN -> {
|
||||
if (!isShowedLogin) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, true)
|
||||
// 设置今天的时间,表示今天已经触发过了
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
NotificationUgc.QUESTION -> {
|
||||
if (!isShowedQuestion) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, true)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
NotificationUgc.ANSWER -> {
|
||||
if (!isShowedAnswer) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, true)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
NotificationUgc.ARTICLE -> {
|
||||
if (!isShowedArticle) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, true)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
NotificationUgc.VIDEO -> {
|
||||
if (!isShowedVideo) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, true)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
NotificationUgc.RATING -> {
|
||||
if (!isShowedRating) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, true)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun show(activity: AppCompatActivity?) {
|
||||
if (activity == null) return
|
||||
RetrofitManager.getInstance(activity).api.bootPopup
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<NotificationHint>() {
|
||||
override fun onSuccess(data: NotificationHint) {
|
||||
try {
|
||||
showEnableNotificationDialogIfItsDisabled(activity, data)
|
||||
} catch (ignore: Exception) {
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showEnableNotificationDialogIfItsDisabled(activity: AppCompatActivity, notificationHint: NotificationHint) {
|
||||
if (notificationIsEnable()) {
|
||||
Utils.log("notification is enable")
|
||||
} else {
|
||||
NotificationHintDialogFragment.getInstance(notificationHint).show(activity.supportFragmentManager, "notification")
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_HINT, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,13 +7,22 @@ object NumberUtils {
|
||||
@JvmStatic
|
||||
fun transSimpleCount(count: Int): String {
|
||||
val s: String
|
||||
s = if (count > 100000) {
|
||||
s = if (count > 10000) {
|
||||
val number = count / 10000f
|
||||
val fmt = DecimalFormat("#")
|
||||
val fmt = DecimalFormat("#.0")
|
||||
fmt.format(number) + "万"
|
||||
} else {
|
||||
count.toString()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun transSimpleUsageTime(second: Long): String {
|
||||
val totalMinute = second / 60
|
||||
if (totalMinute < 60) return ((if (totalMinute == 0L) 1 else totalMinute).toString() + "分钟")
|
||||
val hour = Math.round((totalMinute / 60).toFloat())
|
||||
val minute = Math.round((totalMinute - hour * 60).toFloat())
|
||||
return hour.toString() + "小时" + if (minute == 0) "" else minute.toString() + "分钟"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user