Compare commits
677 Commits
v4.1.0
...
v4.5.2-252
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d9a4baf32 | |||
| 3a9132ff8c | |||
| 02a6ec9f7d | |||
| c779d775e3 | |||
| 3fbcd33f98 | |||
| dbcdd7f3cc | |||
| 69d9854b44 | |||
| 5246d6e743 | |||
| b20d598751 | |||
| 85e9799f20 | |||
| 6b533c8d09 | |||
| 2797135db4 | |||
| 7507a027da | |||
| 9873ae8946 | |||
| a5ef80ba33 | |||
| dfdd12bf18 | |||
| 9daf01d9a5 | |||
| ee7ed1fed2 | |||
| 08474a660e | |||
| d8dfe00057 | |||
| 6bd175f72b | |||
| 72b6b3042a | |||
| 3317b178ac | |||
| c86e7ba6ee | |||
| 14c5e4e963 | |||
| 6db8179f4d | |||
| 65c2571329 | |||
| 4810803988 | |||
| f3f030edb1 | |||
| 2ac2a3bf48 | |||
| cd104e4688 | |||
| e2de8cfb47 | |||
| c9f9451dee | |||
| 73c39edd3f | |||
| 7f739798ab | |||
| e41cf76d26 | |||
| 113d446e47 | |||
| 882ac7d67d | |||
| d94be8092b | |||
| b9138ae810 | |||
| 715cecd44b | |||
| dd756fce00 | |||
| 56a003704d | |||
| 50421e0b70 | |||
| 9f0d00f793 | |||
| a56fd8ff18 | |||
| f86fc7b0e1 | |||
| e6197776ca | |||
| 0415ae261b | |||
| d5313c7f98 | |||
| 360231e01f | |||
| 4d86d6f96b | |||
| dd03daae84 | |||
| 5d285fd60e | |||
| 7d4206bcd8 | |||
| a816636d9a | |||
| c6a5522b35 | |||
| 8b888f0ab4 | |||
| ef41a3aea5 | |||
| ba2206931f | |||
| ef4b7b28d8 | |||
| 4a5f12d341 | |||
| ced96f5f70 | |||
| 4180d87b36 | |||
| 2b7f802584 | |||
| 3e9a348019 | |||
| 9725402623 | |||
| 9827b04057 | |||
| b3052485f5 | |||
| d3dc09d377 | |||
| 58905c14a8 | |||
| aadbbbf2ea | |||
| 5256a9b267 | |||
| 0ded7b33f2 | |||
| cdc3158f30 | |||
| 06de179c9e | |||
| f32dc628ef | |||
| 62e371c928 | |||
| 84bcc481af | |||
| 085ddd4ea6 | |||
| b3e859678e | |||
| 7f586fbf13 | |||
| 9dab3dd263 | |||
| 3ee30f05f0 | |||
| 69c8c51000 | |||
| 28742f54bb | |||
| f62751423d | |||
| b0b699679e | |||
| 3c55284d86 | |||
| b6ae508cf0 | |||
| c13ee31ece | |||
| c87a1ba56e | |||
| 9f07cc7720 | |||
| 7bdfe7cef3 | |||
| 667126f92c | |||
| 0409d33d5e | |||
| 14e8285c0f | |||
| c7d63f9df1 | |||
| e2d9ad07d1 | |||
| 9287b6ac4c | |||
| 450da5e0db | |||
| 0397092414 | |||
| ddc515b490 | |||
| a6edde7853 | |||
| 80282f7bcc | |||
| 664df5cb44 | |||
| 8396a55ed2 | |||
| 5ee3f597bd | |||
| 9c8bd9f85e | |||
| 4321e0a33c | |||
| 6f75229209 | |||
| d6bd561e58 | |||
| c957d7585c | |||
| db0e92fd68 | |||
| 992446cf70 | |||
| dcfa52b05a | |||
| 2a06c41dca | |||
| 24214c5d6b | |||
| c839eff88d | |||
| 663505fdc9 | |||
| 641a820ea5 | |||
| bb3f888f88 | |||
| 75bdf6f251 | |||
| 0cacc15e7d | |||
| e4c2ac0aae | |||
| 7acf4c5941 | |||
| 8b22361213 | |||
| a1dee46436 | |||
| 49bf8c9e30 | |||
| 407686ca5b | |||
| 89b7b45ba0 | |||
| b00e7a2826 | |||
| 383d6e7700 | |||
| edce98e4c6 | |||
| a2c3873c8d | |||
| 7990353d08 | |||
| a7b138b2b2 | |||
| 951768e070 | |||
| 69f29fe83b | |||
| 88e28b2388 | |||
| 538bc6f97c | |||
| b1940125f4 | |||
| e1f8e293c2 | |||
| 0a49f27ed2 | |||
| 5dc7badc97 | |||
| d185d39985 | |||
| d9c98d39b5 | |||
| 6949f2b2ff | |||
| 2141440ec4 | |||
| 464c212638 | |||
| dbe74b2091 | |||
| ba55a5a61c | |||
| 452a94f4a2 | |||
| 310be97fe4 | |||
| 2fc45777e4 | |||
| da283fc1f6 | |||
| fee4e4635c | |||
| ebcd50cdee | |||
| cd922dd286 | |||
| 97598d7330 | |||
| 0db59a56d0 | |||
| bee3f5957e | |||
| 65d4b43c9c | |||
| 41f510d333 | |||
| 64d5af036c | |||
| b4c827bddf | |||
| caf3dfa9ee | |||
| c5c10ab208 | |||
| c2251e1ad6 | |||
| bd6d51dab3 | |||
| 1cf9bfcca3 | |||
| 992ec7bfe8 | |||
| cc39bfd06c | |||
| 15d0ad6f49 | |||
| a2e2379073 | |||
| d2431ed8ff | |||
| 80818dee55 | |||
| f2d0916a16 | |||
| 2fa84e0ce1 | |||
| 6fcd8397b6 | |||
| 3478aaba2f | |||
| 1f0b9a95e2 | |||
| 5cdc1635ca | |||
| c9f5cfd4aa | |||
| d6c1f692be | |||
| 12e6fb8330 | |||
| ad857d4500 | |||
| 43d8d24c1c | |||
| a34ee5a753 | |||
| ca39f723e1 | |||
| 3db784509b | |||
| e8f63ea99f | |||
| 97ac4b03a3 | |||
| 883a948b7b | |||
| ebb279c42f | |||
| 261e0cc45a | |||
| 0357a0a71e | |||
| d87de59427 | |||
| d5ee01a2e1 | |||
| 3563637919 | |||
| d881e08aee | |||
| f5ff838d2f | |||
| 52c1b08e59 | |||
| 652972f49d | |||
| 0d122cf8ba | |||
| 2b115c4058 | |||
| cfca7db4ef | |||
| 5f66c029fb | |||
| 8635652fe2 | |||
| a890ad532c | |||
| 65c9d2be2a | |||
| 9620e26f6a | |||
| e4ca1d8406 | |||
| 74ebaa592b | |||
| f9b689efdb | |||
| ed458f08ad | |||
| 9822646acc | |||
| 4259078420 | |||
| 3b9db4e964 | |||
| b7e6cd08fd | |||
| bba1e6f10c | |||
| 3fe2973968 | |||
| b16d33d9fa | |||
| e1a7ed9049 | |||
| 11354030e8 | |||
| ee109060fc | |||
| eebc0c1096 | |||
| 4ec45e2a27 | |||
| 12143f7f95 | |||
| 7025dc45bd | |||
| 772e7861e2 | |||
| ff71c9a3e8 | |||
| b7001cc996 | |||
| 83658e47f8 | |||
| 0699d3ccc4 | |||
| f80b998e98 | |||
| 91e84be708 | |||
| f589c286c6 | |||
| 379650a0f5 | |||
| 3796eb46bd | |||
| c240048c5e | |||
| 2f81c9240d | |||
| da0dc3df97 | |||
| d73c0f2044 | |||
| a6f9e12082 | |||
| 20f8ba0de5 | |||
| f7342a944e | |||
| 1086574b33 | |||
| 59e30d432d | |||
| 58631d540c | |||
| 08763aeb2d | |||
| 039d0ca06c | |||
| f39574c8b3 | |||
| 6067a52fb1 | |||
| a1298547d1 | |||
| 49d5514a25 | |||
| 09c414a02c | |||
| 6a6378f635 | |||
| 920050efc8 | |||
| 103ecc10d3 | |||
| f90e9a8085 | |||
| caa37ead4b | |||
| d18eeaf346 | |||
| b98d287843 | |||
| 66fb57f708 | |||
| 3911c10827 | |||
| c29972df50 | |||
| 8001ce2603 | |||
| b1079e84d8 | |||
| c6cf8aab1c | |||
| 4d7718e3af | |||
| 9cdbcd4935 | |||
| d396ebda44 | |||
| 6ab8bdc422 | |||
| 15352bb379 | |||
| b68536b561 | |||
| 762ee8d300 | |||
| 8dfda56586 | |||
| 93126517b6 | |||
| 04a8f5772c | |||
| 9687ddcd54 | |||
| 04c49cbad7 | |||
| 6addea7d73 | |||
| 229eaa0859 | |||
| 3876096f52 | |||
| bad3ab19c6 | |||
| b2100fe0e5 | |||
| 5998bb9d4a | |||
| fefe29a0b8 | |||
| a16554da21 | |||
| 6efc1e06bb | |||
| e51439d584 | |||
| 907bad48bc | |||
| 582df7da58 | |||
| 28f18a558c | |||
| 658fb8579c | |||
| 45632052e5 | |||
| 311211747a | |||
| 010995b16d | |||
| c82e981f4e | |||
| f9803fa244 | |||
| f21d86c8a7 | |||
| 8db525542e | |||
| 49cf093a44 | |||
| f2302ffc50 | |||
| f85685fd52 | |||
| a80419e4bd | |||
| 0e7b6bb097 | |||
| b795df2de8 | |||
| e99e8328ab | |||
| 500c77d6ed | |||
| 3c13431bd3 | |||
| d5e426a7f0 | |||
| 8a37e0bdf4 | |||
| 230eec78c1 | |||
| 8bb74461e6 | |||
| b0d0d3ca45 | |||
| 356c9432ec | |||
| 31e14fd47b | |||
| c0644dc705 | |||
| 1a43589bb1 | |||
| defd6d9a14 | |||
| 77b4e8f73d | |||
| 61ef40f9b5 | |||
| 13dd5c9892 | |||
| d20aef7107 | |||
| 8c9cd6e0ec | |||
| 487c2fd0a5 | |||
| 0ffdef080b | |||
| ba76dbbd15 | |||
| 7cfe82af47 | |||
| 567977089a | |||
| a258fe1d20 | |||
| 28cf1ab114 | |||
| 0e49c074ec | |||
| 85249f1d94 | |||
| 38bda5ec02 | |||
| 0cc24956e0 | |||
| c17bcd9765 | |||
| 9f1642f577 | |||
| 9c01f75e8b | |||
| a460722ae5 | |||
| 37330c2ab2 | |||
| 5db25f966e | |||
| 4749c743e9 | |||
| f5b614cc63 | |||
| 34b8b00cb2 | |||
| 6af86d871c | |||
| 0b7fade38b | |||
| 3237834f9a | |||
| 53e9554f08 | |||
| 70ee3001c2 | |||
| d7ae2b2aa4 | |||
| 9c9dbfb105 | |||
| c633c228db | |||
| ad82005881 | |||
| 815a0d0600 | |||
| e02f9db81d | |||
| c422b96da4 | |||
| 40a64996d7 | |||
| cbfca66d51 | |||
| f4a110c94d | |||
| f601fd2339 | |||
| e3217eaf22 | |||
| 540515ab41 | |||
| e1c02a6138 | |||
| a508576785 | |||
| 84e57d5c91 | |||
| 62b1005dbf | |||
| 04a5450a41 | |||
| 2ac4dd6c5a | |||
| 441a569f30 | |||
| f319201e74 | |||
| 47b2fa60d8 | |||
| 4d15c15b2d | |||
| 3702094d98 | |||
| 6185ca595d | |||
| 358b93029b | |||
| 38044b1d2b | |||
| 90877738b3 | |||
| 477613d21f | |||
| a77ee0fa70 | |||
| 036fa444c6 | |||
| d83e1e413f | |||
| 19986099ff | |||
| f23dd6a662 | |||
| 951d306765 | |||
| 8adfaa88a3 | |||
| fcb76e71e5 | |||
| 2da536f667 | |||
| 2034b1c587 | |||
| ea2e169199 | |||
| 2cf6c2747c | |||
| dd24b6243a | |||
| 81fc6aa6cb | |||
| 8e3bcf6b5b | |||
| 8e181c9846 | |||
| 7a737da328 | |||
| 5545c112b7 | |||
| a6f187d444 | |||
| 3ad72ee1f8 | |||
| 2cc100b887 | |||
| 761c5dc0bf | |||
| 80d3f140f4 | |||
| b72621ee2b | |||
| 7896f3ee46 | |||
| d33c15e47b | |||
| ddcd3f8169 | |||
| 42f66cd543 | |||
| c0efd4a8e4 | |||
| a4df780a8b | |||
| e8ac144454 | |||
| d543181b92 | |||
| 02cfb7515b | |||
| 4b71e44c51 | |||
| 68f7e1fa58 | |||
| 2f66588455 | |||
| f39cf38313 | |||
| 1141604d20 | |||
| 6b575f0169 | |||
| 6428179c54 | |||
| 44445e6e34 | |||
| fb48316069 | |||
| ea5312d606 | |||
| 5cb6f9e296 | |||
| fdb1d255ba | |||
| 153b19c966 | |||
| ba79d009e6 | |||
| 47f9c967b1 | |||
| 97ab6108cf | |||
| 8e9da6e1f5 | |||
| aca29abde6 | |||
| dac3f7e2d7 | |||
| 9f9254a835 | |||
| 58e3ef83e0 | |||
| 76bb5d1052 | |||
| afff3446c4 | |||
| 2fa6e9c549 | |||
| cb4bcedba7 | |||
| 5dbe10a8a8 | |||
| 13ca69c569 | |||
| 19e18226bd | |||
| 6b51a198c2 | |||
| 5ad38457af | |||
| ee3043875a | |||
| 92c8a698f3 | |||
| 41f78c365b | |||
| 4b8053beee | |||
| 8008266389 | |||
| 1ce04241f6 | |||
| a37701f148 | |||
| add1339f4a | |||
| f29b8da6d0 | |||
| de968a4820 | |||
| 859a2a5672 | |||
| ddddda10a5 | |||
| 30d6dabe4f | |||
| 7655cc25be | |||
| 52824e5baa | |||
| 014c80cd18 | |||
| a7a48ccf77 | |||
| 99eddec84a | |||
| 6b382ab080 | |||
| d492cfdace | |||
| 256f0af0e9 | |||
| 58d2290e12 | |||
| 547e6da027 | |||
| c3e34ba644 | |||
| e9583284d0 | |||
| b670a9c1c4 | |||
| 077e17c5aa | |||
| f264875b7d | |||
| 351b8a331c | |||
| 479f7c464b | |||
| e04a7fc4b9 | |||
| 595f7747f4 | |||
| 8c1343fdba | |||
| c3717869bd | |||
| 1e56dc533d | |||
| 1444531830 | |||
| 4e759e446b | |||
| 33d86a7995 | |||
| ef6c09d27b | |||
| efc241429c | |||
| 07be540ba1 | |||
| 50479d2e87 | |||
| 2934c9dc38 | |||
| 30a60797e6 | |||
| 53562297d5 | |||
| 144ee3ea8c | |||
| e0c8697e75 | |||
| 6aba2906f6 | |||
| 7bb468a1b1 | |||
| 871be728bf | |||
| bbac0c8d93 | |||
| 6b361ed077 | |||
| 1cfa54f8e8 | |||
| 80ce5052d9 | |||
| 5bd028cbe9 | |||
| b8f8711ba4 | |||
| ec805653bb | |||
| c1f899f0d5 | |||
| e4fd74da7d | |||
| bf9cc93daa | |||
| 3b974268a9 | |||
| 822853a4be | |||
| f699841427 | |||
| c700910b15 | |||
| 3c8d0cb3ec | |||
| 8492c762b5 | |||
| b2d70392bb | |||
| eb9cb08624 | |||
| a4ca2628dc | |||
| 727d78d0e5 | |||
| 693d8c4385 | |||
| d46e3fac2d | |||
| 7f0ec7f128 | |||
| 73eb2f6ecb | |||
| 6bd7ced28c | |||
| 086c31a7d4 | |||
| 3a839f6770 | |||
| b67c7e2803 | |||
| b7dbf30845 | |||
| ec86970cbe | |||
| 956755b985 | |||
| fe2779196d | |||
| 9eeeba93d0 | |||
| d7df019d6d | |||
| 68bfc26ddc | |||
| 94a1cfe4b2 | |||
| 936c3b00bb | |||
| b34229e4c4 | |||
| b51322b473 | |||
| e0657ccdcc | |||
| 4b67d8b5aa | |||
| 5b8cc49349 | |||
| 612f71e18c | |||
| 6239ccb8ab | |||
| 9680bea412 | |||
| a21d9096c8 | |||
| e6f3ad5cc2 | |||
| c41e996add | |||
| 58f230038c | |||
| bda41d8a26 | |||
| e3f41543a4 | |||
| 78c4d7acef | |||
| 8c884b6d23 | |||
| a5f9af2df2 | |||
| e2fd6dbf97 | |||
| e430b4e2de | |||
| caa3f46c5c | |||
| b2beba4d36 | |||
| 3a9c7fc71d | |||
| a5f8275f64 | |||
| 8fa3f3d832 | |||
| 97472b8259 | |||
| ee07889b30 | |||
| 8582860116 | |||
| b8903e7814 | |||
| b47bcfc2c3 | |||
| 35a987a835 | |||
| 6f413b27d4 | |||
| 92173b4794 | |||
| 89e79154aa | |||
| de9145cd70 | |||
| 8bf509ee2d | |||
| d7144265e1 | |||
| cc6c759658 | |||
| 8e5d482f9e | |||
| 5ed8f2499a | |||
| a8c9bcc1b0 | |||
| 21aabcc561 | |||
| a2b86a9e21 | |||
| 74882f56ee | |||
| 1eb9ec1dd3 | |||
| 9e95c0cc7e | |||
| 877238d2d5 | |||
| 9c6f69b16a | |||
| 64af456182 | |||
| 1a84477700 | |||
| a0b6285596 | |||
| 951c139062 | |||
| 99efcd6bbf | |||
| 3482f58b1b | |||
| 6b4f751a16 | |||
| 3be1308230 | |||
| b7710cffa3 | |||
| dc4fe89521 | |||
| c33eb6829a | |||
| e1793d57eb | |||
| cc4c48f718 | |||
| aa20ed9744 | |||
| b6d8688a40 | |||
| d1da2bb7fa | |||
| 7828bce732 | |||
| 026a8d7093 | |||
| 6a9a29c5ff | |||
| 16b4b6cc81 | |||
| 863e570b61 | |||
| c9e8408804 | |||
| 31984f1737 | |||
| ad2a0debdd | |||
| 4c45657092 | |||
| 5d7fc94d51 | |||
| 641b430fe5 | |||
| e1bb02f4e0 | |||
| 36fd8cf408 | |||
| e48b47b315 | |||
| 46935e4cad | |||
| b8a6b4baea | |||
| 8a8f0a95ed | |||
| cdbefd2d4f | |||
| 7e79b4e328 | |||
| 11dc9f9be0 | |||
| ec255099eb | |||
| 64738dceaf | |||
| 7d518696f0 | |||
| fcd97b66df | |||
| 47f5c3b7c1 | |||
| b64fee9d25 | |||
| 498efdf5ea | |||
| 59d6450ded | |||
| 7da206af7e | |||
| 8bd669e11a | |||
| 62570aed9e | |||
| bfe9c04384 | |||
| b27d007d47 | |||
| 7e50e6570d | |||
| 336d449889 | |||
| 3dfea1e6f9 | |||
| 3c1780d9b5 | |||
| 35ee7cf03d | |||
| 72e8c18f9c | |||
| f3f876d213 | |||
| 398907db90 | |||
| 5dd251eaa8 | |||
| 2c73e55f43 | |||
| f4406d7960 | |||
| 3e0a620ac5 | |||
| 9ea8c32608 | |||
| e2ea197f9e | |||
| f92038b5bf | |||
| fa9eee2c4a | |||
| 3e62fb61e1 | |||
| 5d71e0ccc1 | |||
| 4699923058 | |||
| 9206938938 | |||
| 46ac569f70 | |||
| b90d1b4f38 | |||
| 592b7bbc5e | |||
| 3ccb8b3772 | |||
| 422abe1b87 | |||
| a14f35a4f0 | |||
| 3bebc92106 | |||
| 21413cf250 | |||
| 04a34af370 | |||
| e1e6924b6e | |||
| fbd3a42e81 | |||
| 80a2cbb8cd | |||
| 96fc6cc183 | |||
| b5ff891db1 | |||
| d2171e7a3b | |||
| c3a06f57b1 | |||
| 18f41743bf | |||
| fcc647a1f8 | |||
| e80b198aa5 | |||
| 52efa96e2c | |||
| 816dd60298 | |||
| a181292f80 | |||
| 1b946c325c | |||
| befb323721 | |||
| e62c0aaaad | |||
| 4ecc0c073b | |||
| faa41248eb | |||
| 6dca13e80b | |||
| 553ebc137b | |||
| dd2338021e |
156
app/build.gradle
156
app/build.gradle
@ -6,7 +6,9 @@ apply plugin: 'kotlin-kapt'
|
||||
// apkChannelPackage
|
||||
apply plugin: 'channel'
|
||||
|
||||
apply from: 'tinker-support.gradle'
|
||||
import groovy.xml.XmlUtil
|
||||
|
||||
//apply from: 'tinker-support.gradle'
|
||||
|
||||
android {
|
||||
|
||||
@ -18,6 +20,10 @@ android {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
viewBinding {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
@ -45,6 +51,9 @@ android {
|
||||
abiFilters "armeabi-v7a"
|
||||
}
|
||||
|
||||
renderscriptTargetApi 18
|
||||
renderscriptSupportModeEnabled true
|
||||
|
||||
// 由于app只针对中文用户,所以仅保留zh资源,其他删掉
|
||||
resConfigs "zh"
|
||||
|
||||
@ -67,6 +76,8 @@ android {
|
||||
buildConfigField "String", "TD_APPID", "\"${TD_APPID}\""
|
||||
buildConfigField "String", "LETO_APPID", "\"${LETO_APPID}\""
|
||||
buildConfigField "String", "TTAD_APPID", "\"${TTAD_APPID}\""
|
||||
buildConfigField "String", "DOUYIN_CLIENTKEY", "\"${DOUYIN_CLIENTKEY}\""
|
||||
buildConfigField "String", "DOUYIN_CLIENTSECRET", "\"${DOUYIN_CLIENTSECRET}\""
|
||||
|
||||
buildConfigField "String", "MIPUSH_APPID", "\"${MIPUSH_APPID}\""
|
||||
buildConfigField "String", "MIPUSH_APPKEY", "\"${MIPUSH_APPKEY}\""
|
||||
@ -120,15 +131,27 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions "nonsense"
|
||||
flavorDimensions("env")
|
||||
|
||||
sourceSets {
|
||||
publish {
|
||||
java.srcDirs = ['src/main/java']
|
||||
}
|
||||
internal {
|
||||
java.srcDirs = ['src/main/java']
|
||||
}
|
||||
tea {
|
||||
java.srcDirs = ['src/main/java', 'src/tea/java']
|
||||
}
|
||||
gdt {
|
||||
java.srcDirs = ['src/main/java', 'src/gdt/java']
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 多渠道打包,渠道请参考"channel.txt"文件,所有渠道值均通过java code设置
|
||||
*/
|
||||
productFlavors {
|
||||
// publish release host
|
||||
publish {
|
||||
dimension "nonsense"
|
||||
dimension "env"
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
|
||||
buildConfigField "String", "SENSITIVE_API_HOST", "\"${SENSITIVE_API_HOST}\""
|
||||
@ -139,7 +162,7 @@ android {
|
||||
}
|
||||
// internal test dev host
|
||||
internal {
|
||||
dimension "nonsense"
|
||||
dimension "env"
|
||||
versionNameSuffix "-debug"
|
||||
|
||||
buildConfigField "String", "API_HOST", "\"${DEV_API_HOST}\""
|
||||
@ -150,6 +173,30 @@ android {
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${DEV_UMENG_MESSAGE_SECRET}\""
|
||||
buildConfigField "String", "BUGLY_APPID", "\"${DEV_BUGLY_APPID}\""
|
||||
}
|
||||
|
||||
tea {
|
||||
dimension "env"
|
||||
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
|
||||
buildConfigField "String", "SENSITIVE_API_HOST", "\"${SENSITIVE_API_HOST}\""
|
||||
|
||||
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
|
||||
buildConfigField "String", "BUGLY_APPID", "\"${BUGLY_APPID}\""
|
||||
}
|
||||
|
||||
gdt {
|
||||
dimension "env"
|
||||
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
|
||||
buildConfigField "String", "SENSITIVE_API_HOST", "\"${SENSITIVE_API_HOST}\""
|
||||
|
||||
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
|
||||
buildConfigField "String", "BUGLY_APPID", "\"${BUGLY_APPID}\""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,6 +226,7 @@ repositories {
|
||||
dependencies {
|
||||
|
||||
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
|
||||
gdtImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/gdt/libs')
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
|
||||
@ -187,6 +235,7 @@ dependencies {
|
||||
debugImplementation "com.facebook.stetho:stetho-okhttp3:${stetho}"
|
||||
debugImplementation "com.squareup.okhttp3:logging-interceptor:${okHttp}"
|
||||
debugImplementation "com.gu.android:toolargetool:${toolargetool}"
|
||||
debugImplementation "com.github.nichbar:WhatTheStack:$whatTheStack"
|
||||
|
||||
implementation "androidx.core:core:${core}"
|
||||
implementation "androidx.fragment:fragment:${fragment}"
|
||||
@ -243,7 +292,7 @@ dependencies {
|
||||
implementation "com.sina.weibo.sdk:core:${weiboSDK}"
|
||||
|
||||
// bugly with tinker support
|
||||
implementation "com.tencent.bugly:crashreport_upgrade:${buglyTinkerSupport}"
|
||||
// implementation "com.tencent.bugly:crashreport_upgrade:${buglyTinkerSupport}"
|
||||
|
||||
implementation "com.google.android:flexbox:${flexbox}"
|
||||
|
||||
@ -283,7 +332,9 @@ dependencies {
|
||||
|
||||
debugImplementation "com.github.nichbar.chucker:library:$chucker"
|
||||
releaseImplementation "com.github.nichbar.chucker:library-no-op:$chucker"
|
||||
implementation "com.bytedance.applog:RangersAppLog-Lite-cn:$bytedanceApplog"
|
||||
teaImplementation "com.bytedance.applog:RangersAppLog-Lite-cn:$bytedanceApplog"
|
||||
// implementation "com.bytedance.ies.ugc.aweme:opensdk-china-external:$bytedanceAweme"
|
||||
// implementation "com.bytedance.ies.ugc.aweme:opensdk-common:$bytedanceAweme"
|
||||
|
||||
implementation "com.aliyun.dpa:oss-android-sdk:${oss}"
|
||||
|
||||
@ -291,6 +342,8 @@ dependencies {
|
||||
|
||||
implementation "net.lingala.zip4j:zip4j:${zip4j}"
|
||||
|
||||
implementation "io.sentry:sentry-android:$sentry"
|
||||
|
||||
implementation("com.github.piasy:BigImageViewer:$bigImageViewer", {
|
||||
exclude group: 'com.squareup.okhttp3'
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
@ -299,12 +352,12 @@ dependencies {
|
||||
implementation "com.github.PhilJay:MPAndroidChart:${chart}"
|
||||
|
||||
implementation project(':libraries:LGLibrary')
|
||||
implementation project(':libraries:MTA')
|
||||
// implementation project(':libraries:MTA')
|
||||
implementation project(':libraries:QQShare')
|
||||
implementation project(':libraries:TalkingData')
|
||||
implementation project(':libraries:UmengPush')
|
||||
// implementation project(':libraries:TalkingData')
|
||||
// implementation project(':libraries:UmengPush')
|
||||
// implementation project(':libraries:WechatShare')
|
||||
implementation project(':libraries:im')
|
||||
// implementation project(':libraries:im')
|
||||
implementation project(':libraries:Matisse')
|
||||
}
|
||||
File propFile = file('sign.properties')
|
||||
@ -336,7 +389,7 @@ if (propFile.exists()) {
|
||||
android.buildTypes.release.signingConfig = null
|
||||
}
|
||||
|
||||
// 用于测试读取 META-INF 里的 JSON 的代码
|
||||
// 用于测试读取 META-INF 里的文件
|
||||
//task generateMetaJson {
|
||||
// def resDir = new File(buildDir, 'generated/FILES_FOR_META_INF/')
|
||||
// def destDir = new File(resDir, 'META-INF/')
|
||||
@ -363,3 +416,78 @@ if (propFile.exists()) {
|
||||
// task.name.startsWith('merge') && task.name.endsWith('Resources')
|
||||
// }.each { t -> t.dependsOn generateMetaJson }
|
||||
//}
|
||||
|
||||
|
||||
project.afterEvaluate {
|
||||
def variants = null
|
||||
try {
|
||||
variants = android.applicationVariants
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace()
|
||||
try {
|
||||
variants = android.libraryVariants
|
||||
} catch (Throwable tt) {
|
||||
tt.printStackTrace()
|
||||
}
|
||||
}
|
||||
if (variants != null) {
|
||||
variants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
def task = output.processManifestProvider.get()
|
||||
if (task == null) {
|
||||
return
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 Manifest 的 Activity 的 configChanges 添加自己手动处理 configurationChanges 配置 [https://developer.android.com/guide/topics/resources/runtime-changes]
|
||||
* AGP 4.1.0 从 ProcessManifest task 里拿 manifest 的 API 变更调整可以参考这里 [https://github.com/Tencent/tinker/pull/1476/commits/d71645729b13d545ca4ba6826f93fbf558751434]
|
||||
* (搞半天还是不会抽离方法,有空再把 gradle 改成用 kotlin 实现吧)
|
||||
*/
|
||||
task.doLast {
|
||||
def manifestFile = new File(multiApkManifestOutputDirectory.get().asFile, "AndroidManifest.xml")
|
||||
if (manifestFile == null || !manifestFile.exists()) {
|
||||
return
|
||||
}
|
||||
def parser = new XmlSlurper(false, true)
|
||||
def manifest = parser.parse(manifestFile)
|
||||
def app = manifest.'application'[0]
|
||||
app.'activity'.each { act ->
|
||||
String value = act.attributes()['android:configChanges']
|
||||
if (value == null || value.isEmpty()) {
|
||||
value = "keyboardHidden|orientation|screenSize|screenLayout|density|fontScale|locale"
|
||||
act.attributes()['androidconfigChanges'] = value
|
||||
} else {
|
||||
String[] valueSplit = value.split("\\|")
|
||||
if (!valueSplit.contains("keyboardHidden")) {
|
||||
value += "|keyboardHidden"
|
||||
}
|
||||
if (!valueSplit.contains("orientation")) {
|
||||
value += "|orientation"
|
||||
}
|
||||
if (!valueSplit.contains("screenSize")) {
|
||||
value += "|screenSize"
|
||||
}
|
||||
if (!valueSplit.contains("screenLayout")) {
|
||||
value += "|screenLayout"
|
||||
}
|
||||
if (!valueSplit.contains("density")) {
|
||||
value += "|density"
|
||||
}
|
||||
if (!valueSplit.contains("fontScale")) {
|
||||
value += "|fontScale"
|
||||
}
|
||||
if (!valueSplit.contains("locale")) {
|
||||
value += "|locale"
|
||||
}
|
||||
act.attributes()['android:configChanges'] = value
|
||||
}
|
||||
}
|
||||
|
||||
def tmpManifest = XmlUtil.serialize(manifest).replaceAll("androidconfigChanges", "android:configChanges")
|
||||
manifest = parser.parseText(tmpManifest)
|
||||
manifestFile.setText(XmlUtil.serialize(manifest), "utf-8")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
app/libs/gid-1.3.jar
Normal file
BIN
app/libs/gid-1.3.jar
Normal file
Binary file not shown.
@ -241,6 +241,13 @@
|
||||
-dontwarn com.shuyu.gsyvideoplayer.utils.**
|
||||
-keep class tv.danmaku.ijk.** { *; }
|
||||
-dontwarn tv.danmaku.ijk.**
|
||||
-keep public class * extends android.view.View{
|
||||
*** get*();
|
||||
void set*(***);
|
||||
public <init>(android.content.Context);
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
#穿山甲
|
||||
-keep class com.bytedance.sdk.openadsdk.** { *; }
|
||||
@ -254,4 +261,11 @@
|
||||
-keep class com.taobao.wireless.security.**{*;}
|
||||
-keep class com.ut.secbody.**{*;}
|
||||
-keep class com.taobao.dp.**{*;}
|
||||
-keep class com.alibaba.wireless.security.**{*;}
|
||||
-keep class com.alibaba.wireless.security.**{*;}
|
||||
|
||||
-keep class com.alibaba.sdk.android.**{*;}
|
||||
-keep class com.ut.**{*;}
|
||||
-keep class com.ta.**{*;}
|
||||
|
||||
-keep class com.gh.gamecenter.GdtHelper { *; }
|
||||
-keep class com.gh.gamecenter.TeaHelper { *; }
|
||||
@ -1,7 +1,9 @@
|
||||
package com.gh.common.util
|
||||
package com.gh.gamecenter
|
||||
|
||||
import android.app.Application
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import com.gh.common.util.ToastUtils
|
||||
import com.lightgame.utils.Utils
|
||||
import com.qq.gdt.action.GDTAction
|
||||
import org.json.JSONObject
|
||||
@ -22,15 +24,27 @@ object GdtHelper {
|
||||
const val SCORE = "SCORE"
|
||||
const val PLATFORM = "PLATFORM"
|
||||
|
||||
fun init(application: Application) {
|
||||
GDTAction.init(application, "1110071928", "7fe03caa04ed382e9dce401312b1d0ae")
|
||||
}
|
||||
|
||||
fun logAction(type: String) {
|
||||
GDTAction.logAction(type)
|
||||
Utils.log("GDT", type)
|
||||
@JvmStatic
|
||||
fun init(application: Application, channel: String) {
|
||||
if (shouldUseGdtHelper()) {
|
||||
if (channel == "GH_728") {
|
||||
GDTAction.init(application, "1111012969", "9d3d9da5b0948a317c03d08f14d445dc")
|
||||
} else if (channel == "GH_729") {
|
||||
GDTAction.init(application, "1111013063", "f53dabf458a356b101d99fc4069eb7f1")
|
||||
} else {
|
||||
GDTAction.init(application, "1110680399", "f5ddaafbf520d7d7385499232a408d0a")
|
||||
}
|
||||
}
|
||||
Utils.log("init GdtHelper")
|
||||
}
|
||||
|
||||
// fun logAction(type: String) {
|
||||
// if (shouldUseGdtHelper()) {
|
||||
// GDTAction.logAction(type)
|
||||
// Utils.log("GDT", type)
|
||||
// }
|
||||
// }
|
||||
@JvmStatic
|
||||
fun logAction(type: String, vararg kv: String?) {
|
||||
try {
|
||||
val actionParam = JSONObject()
|
||||
@ -50,4 +64,12 @@ object GdtHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 确认开启的渠道条件
|
||||
private fun shouldUseGdtHelper(): Boolean {
|
||||
return true
|
||||
//
|
||||
// val channel = HaloApp.getInstance().channel
|
||||
// return !(TextUtils.isEmpty(channel) || channel.contains("GDT".toLowerCase(Locale.CHINA)))
|
||||
}
|
||||
|
||||
}
|
||||
BIN
app/src/gdt/libs/GDTActionSDK.min.1.6.10.aar
Normal file
BIN
app/src/gdt/libs/GDTActionSDK.min.1.6.10.aar
Normal file
Binary file not shown.
@ -9,8 +9,6 @@
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<!-- 允许应用程序读取扩展存储器 -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<!-- 允许挂载和反挂载文件系统可移动存储 -->
|
||||
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
|
||||
<!-- 允许应用程序访问Wi-Fi网络状态信息 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<!-- 允许应用程序获取网络信息状态 -->
|
||||
@ -25,41 +23,33 @@
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<!-- 允许应用程序打开系统窗口,显示其他应用程序 -->
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<!-- 修改系统设置的权限 -->
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
<!-- 创建快捷方式的权限 -->
|
||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||
|
||||
<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.READ_LOGS" />-->
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<!--可选,穿山甲提供“获取地理位置权限”和“不给予地理位置权限,开发者传入地理位置参数”两种方式上报用户位置,两种方式均可不选,添加位置权限或参数将帮助投放定位广告-->
|
||||
<!--请注意:无论通过何种方式提供给穿山甲用户地理位置,均需向用户声明地理位置权限将应用于穿山甲广告投放,穿山甲不强制获取地理位置信息-->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />-->
|
||||
|
||||
<!-- 如果有视频相关的广告且使用textureView播放,请务必添加,否则黑屏 -->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<uses-sdk tools:overrideLibrary="com.shuyu.gsyvideoplayer,
|
||||
com.shuyu.gsyvideoplayer.lib,
|
||||
com.haroldadmin.whatthestack,
|
||||
com.shuyu.gsyvideoplayer.armv7a,
|
||||
com.shuyu.gsyvideoplayer.x86,
|
||||
com.shuyu.gsy.base,
|
||||
com.google.android.exoplayer2,
|
||||
tv.danmaku.ijk.media.exo2,
|
||||
shuyu.com.androidvideocache,
|
||||
pl.droidsonroids.gif,
|
||||
com.ledong.lib.minigame,
|
||||
com.ledong.lib.leto,
|
||||
com.leto.game.base.glide4,
|
||||
com.leto.game.ad.gdt,
|
||||
com.leto.game.fcm,
|
||||
com.leto.game.ad.toutiao" />
|
||||
pl.droidsonroids.gif" />
|
||||
|
||||
<!-- 去掉 SDK 一些流氓权限 -->
|
||||
<uses-permission
|
||||
@ -75,7 +65,7 @@
|
||||
|
||||
<!--android:largeHeap = "true"-->
|
||||
<application
|
||||
android:name="com.halo.assistant.TinkerApp"
|
||||
android:name="com.halo.assistant.HaloApp"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/logo"
|
||||
android:label="@string/app_name"
|
||||
@ -85,6 +75,10 @@
|
||||
tools:replace="android:allowBackup"
|
||||
tools:targetApi="n">
|
||||
|
||||
<meta-data
|
||||
android:name="io.sentry.auto-init"
|
||||
android:value="false" />
|
||||
|
||||
<!--android:launchMode = "singleTask"-->
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SplashScreenActivity"
|
||||
@ -170,6 +164,10 @@
|
||||
android:name="com.gh.gamecenter.WebActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.FullScreenWebActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.ShareCardPicActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -208,6 +206,14 @@
|
||||
android:name="com.gh.gamecenter.AboutActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.security.SecurityActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.security.BindPhoneActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.CommentDetailActivity"
|
||||
android:screenOrientation="portrait"
|
||||
@ -391,6 +397,10 @@
|
||||
android:name="com.gh.gamecenter.qa.article.detail.ArticleDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.detail.comment.ArticleDetailCommentActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.draft.CommunityDraftWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -451,7 +461,8 @@
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.upload.view.UploadVideoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.game.GameVideoActivity"
|
||||
@ -531,12 +542,73 @@
|
||||
android:name=".video.poster.PosterClipActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!-- 使用小米/华为推送弹窗功能提高推送成功率-->
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.PushProxyActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@android:style/Theme.Translucent" />
|
||||
android:name=".forum.select.ForumSelectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".forum.follow.ForumMyFollowActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".forum.detail.ForumDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".forum.moderator.ModeratorListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".video.label.VideoLabelActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".personalhome.border.AvatarBorderActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".personalhome.background.PersonalityBackgroundActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".personalhome.background.BackgroundPreviewActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".personalhome.background.BackgroundClipActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar" />
|
||||
|
||||
<activity
|
||||
android:name=".personalhome.excellentcomments.ExcellentCommentsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".simulatorgame.SimulatorGameActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".simulatorgame.SimulatorManagementActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".catalog.CatalogActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".catalog.NewCatalogListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".forum.search.ForumOrUserSearchActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!-- <!– 使用小米/华为推送弹窗功能提高推送成功率–>-->
|
||||
<!-- <activity-->
|
||||
<!-- android:name="com.gh.gamecenter.PushProxyActivity"-->
|
||||
<!-- android:exported="true"-->
|
||||
<!-- android:launchMode="singleTask"-->
|
||||
<!-- android:theme="@android:style/Theme.Translucent" />-->
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SkipActivity"
|
||||
@ -548,6 +620,14 @@
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<data android:scheme="market" />
|
||||
|
||||
<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
|
||||
@ -558,6 +638,12 @@
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
|
||||
|
||||
<!-- <activity-->
|
||||
<!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"-->
|
||||
<!-- android:launchMode="singleTask"-->
|
||||
<!-- android:taskAffinity="${applicationId}"-->
|
||||
<!-- android:exported="true" />-->
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}"
|
||||
@ -591,45 +677,45 @@
|
||||
</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.UmengMeizuPushReceiver">
|
||||
<intent-filter>
|
||||
<!-- 接收push消息 -->
|
||||
<action android:name="com.meizu.flyme.push.intent.MESSAGE" />
|
||||
<!-- 接收register消息 -->
|
||||
<action android:name="com.meizu.flyme.push.intent.REGISTER.FEEDBACK" />
|
||||
<!-- 接收unregister消息-->
|
||||
<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" />
|
||||
<!-- <!–魅族push应用定义消息receiver声明 –>-->
|
||||
<!-- <receiver android:name="com.gh.gamecenter.receiver.UmengMeizuPushReceiver">-->
|
||||
<!-- <intent-filter>-->
|
||||
<!-- <!– 接收push消息 –>-->
|
||||
<!-- <action android:name="com.meizu.flyme.push.intent.MESSAGE" />-->
|
||||
<!-- <!– 接收register消息 –>-->
|
||||
<!-- <action android:name="com.meizu.flyme.push.intent.REGISTER.FEEDBACK" />-->
|
||||
<!-- <!– 接收unregister消息–>-->
|
||||
<!-- <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" />-->
|
||||
|
||||
<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>
|
||||
<!-- <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>-->
|
||||
|
||||
<meta-data
|
||||
android:name="com.huawei.hms.client.appid"
|
||||
android:value="@string/huawei_push_appid" />
|
||||
<!-- <meta-data-->
|
||||
<!-- android:name="com.huawei.hms.client.appid"-->
|
||||
<!-- android:value="@string/huawei_push_appid" />-->
|
||||
|
||||
<service
|
||||
android:name="com.gh.base.GHUmengNotificationService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
<!-- <service-->
|
||||
<!-- android:name="com.gh.base.GHUmengNotificationService"-->
|
||||
<!-- android:permission="android.permission.BIND_JOB_SERVICE" />-->
|
||||
|
||||
<!--<service android:name = "com.gh.gamecenter.statistics.AppStaticService" />-->
|
||||
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
emoji_kf_1.png,:smile:
|
||||
emoji_kf_2.png,:smiley:
|
||||
emoji_kf_3.png,:laughing:
|
||||
emoji_kf_4.png,:blush:
|
||||
emoji_kf_5.png,:heart_eyes:
|
||||
emoji_kf_6.png,:smirk:
|
||||
emoji_kf_7.png,:flushed:
|
||||
emoji_kf_8.png,:kissing_heart:
|
||||
emoji_kf_9.png,:grin:
|
||||
emoji_kf_10.png,:wink:
|
||||
emoji_kf_11.png,:stuck_out_tongue_winking_eye:
|
||||
emoji_kf_12.png,:stuck_out_tongue_closed eyes:
|
||||
emoji_kf_13.png,:worried:
|
||||
emoji_kf_14.png,:sleeping:
|
||||
emoji_kf_15.png,:expressionless:
|
||||
emoji_kf_16.png,:sweat_smile:
|
||||
emoji_kf_17.png,:joy:
|
||||
emoji_kf_18.png,:cold_sweat:
|
||||
emoji_kf_19.png,:sob:
|
||||
emoji_kf_20.png,:angry:
|
||||
emoji_kf_21.png,:mask:
|
||||
emoji_kf_22.png,:scream:
|
||||
emoji_kf_23.png,:sunglasses:
|
||||
emoji_kf_24.png,:heart:
|
||||
emoji_kf_25.png,:broken_heart:
|
||||
emoji_kf_26.png,:star:
|
||||
emoji_kf_27.png,:anger:
|
||||
emoji_kf_28.png,:exclamation:
|
||||
emoji_kf_29.png,:question:
|
||||
emoji_kf_30.png,:zzz:
|
||||
emoji_kf_31.png,:thumbsup:
|
||||
emoji_kf_32.png,:thumbsdown:
|
||||
emoji_kf_33.png,:ok_hand:
|
||||
emoji_kf_34.png,:punch:
|
||||
emoji_kf_35.png,:yeah:
|
||||
emoji_kf_36.png,:clap:
|
||||
emoji_kf_37.png,:muscle:
|
||||
emoji_kf_38.png,:pray:
|
||||
emoji_kf_39.png,:skull:
|
||||
emoji_kf_40.png,:trollface:
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
File diff suppressed because one or more lines are too long
1
app/src/main/assets/lottie/tab_forum.json
Normal file
1
app/src/main/assets/lottie/tab_forum.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.6.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"bottom bar tab/论坛/选中/E","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"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,33,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.333,0.333,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.333,0.333,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.333,0.333,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"t":13,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":1,"y":0},"t":0,"s":[{"i":[[0,-0.66],[0,0],[1.38,0],[0,1.38],[0,0],[-0.66,0],[0,0]],"o":[[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.66],[0,0],[0.66,0]],"v":[[2.5,-1.3],[2.5,0],[0,2.5],[-2.5,0],[-2.5,-1.3],[-1.3,-2.5],[1.3,-2.5]],"c":true}]},{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":4,"s":[{"i":[[0,-0.66],[0,0],[1.38,0],[0,1.38],[0,0],[-0.66,0],[0,0]],"o":[[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.66],[0,0],[0.66,0]],"v":[[2.5,-0.102],[2.5,0],[0,2.109],[-2.5,0],[-2.5,-0.102],[-1.3,-1.302],[1.3,-1.302]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":1,"y":0},"t":9,"s":[{"i":[[0,-0.66],[0,0],[1.38,0],[0,1.38],[0,0],[-0.66,0],[0,0]],"o":[[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.66],[0,0],[0.66,0]],"v":[[2.498,-1.845],[2.5,0],[0,2.734],[-2.5,0],[-2.502,-1.845],[-1.302,-3.045],[1.298,-3.045]],"c":true}]},{"t":13,"s":[{"i":[[0,-0.66],[0,0],[1.38,0],[0,1.38],[0,0],[-0.66,0],[0,0]],"o":[[0,0],[0,1.38],[-1.38,0],[0,0],[0,-0.66],[0,0],[0.66,0]],"v":[[2.5,-1.3],[2.5,0],[0,2.5],[-2.5,0],[-2.5,-1.3],[-1.3,-2.5],[1.3,-2.5]],"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":150,"st":0,"bm":0},{"ddd":0,"ind":3,"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,33.76,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":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.8,0.42],[-3.44,-0.79],[-0.09,-1.71],[0,0],[0,0],[1.98,-0.1],[0,0],[0,0],[0,0],[0.62,0.57],[0,0],[0,0],[0,0],[0,0],[0,0],[0.2,1.89],[0,0],[0,0],[0,0]],"o":[[3.44,-0.79],[1.74,0.41],[0,0],[0,0],[0,2],[0,0],[0,0],[0,0],[-0.69,0.52],[0,0],[0,0],[0,0],[0,0],[0,0],[-1.94,0],[0,0],[0,0],[0,0],[0,-1.8]],"v":[[-6.39,-8.971],[6.39,-8.971],[9.49,-5.471],[9.5,-5.271],[9.5,3.249],[5.95,6.989],[5.75,6.999],[3.25,6.999],[0.3,9.209],[-1.95,9.089],[-2.06,8.969],[-2.17,8.849],[-2.21,8.779],[-3.4,6.999],[-5.75,6.999],[-9.48,3.639],[-9.49,3.449],[-9.5,3.249],[-9.5,-5.271]],"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":[-9.5,-9.561],"ix":5},"e":{"a":0,"k":[9.5,9.561],"ix":6},"t":1,"nm":"color","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":150,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"预合成 1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33,0],"ix":2},"a":{"a":0,"k":[33,33,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":0,"s":[100,100,100]},{"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":4,"s":[70,70,100]},{"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":9,"s":[110,110,100]},{"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":13,"s":[90,90,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"w":66,"h":66,"ip":0,"op":20,"st":0,"bm":0}],"markers":[]}
|
||||
@ -1,5 +0,0 @@
|
||||
# This is a simple Microlog configuration file
|
||||
microlog.level=DEBUG
|
||||
microlog.appender=LogCatAppender;FileAppender
|
||||
microlog.formatter=PatternFormatter
|
||||
microlog.formatter.PatternFormatter.pattern=%c [%P] %m %T
|
||||
132
app/src/main/assets/notification_style.json
Normal file
132
app/src/main/assets/notification_style.json
Normal file
@ -0,0 +1,132 @@
|
||||
[
|
||||
{
|
||||
"login": {
|
||||
"title": "开启消息通知",
|
||||
"content": "新游上线、互动回复,重要推送不错过",
|
||||
"image": "bg_notification_login_style_1",
|
||||
"styleNo": "样式A",
|
||||
"scenes": "场景1"
|
||||
},
|
||||
"question": {
|
||||
"title": "开启消息通知",
|
||||
"content": "及时查看大神回答",
|
||||
"image": "bg_notification_question_style_1",
|
||||
"styleNo": "样式A",
|
||||
"scenes": "场景2"
|
||||
},
|
||||
"answer": {
|
||||
"title": "开启消息通知",
|
||||
"content": "及时查看点赞与评论",
|
||||
"image": "bg_notification_answer_style_1",
|
||||
"styleNo": "样式A",
|
||||
"scenes": "场景3"
|
||||
},
|
||||
"article": {
|
||||
"title": "开启消息通知",
|
||||
"content": "及时查看点赞与评论",
|
||||
"image": "bg_notification_article_style_1",
|
||||
"styleNo": "样式A",
|
||||
"scenes": "场景4"
|
||||
},
|
||||
"video": {
|
||||
"title": "开启消息通知",
|
||||
"content": "实时获取审核与推荐进度",
|
||||
"image": "bg_notification_video_style_1",
|
||||
"styleNo": "样式A",
|
||||
"scenes": "场景5"
|
||||
},
|
||||
"rating": {
|
||||
"title": "开启消息通知",
|
||||
"content": "成功上墙立即知道",
|
||||
"image": "bg_notification_rating_style_1",
|
||||
"styleNo": "样式A",
|
||||
"scenes": "场景6"
|
||||
},
|
||||
"gift": {
|
||||
"title": "开启消息通知",
|
||||
"content": "新上礼包不再错过",
|
||||
"image": "bg_notification_gift_style_1",
|
||||
"styleNo": "样式A",
|
||||
"scenes": "场景7"
|
||||
},
|
||||
"reserveGame": {
|
||||
"title": "开启消息通知",
|
||||
"content": "新游上线即时体验",
|
||||
"image": "bg_notification_reserve_game_style_1",
|
||||
"styleNo": "样式A",
|
||||
"scenes": "场景8"
|
||||
},
|
||||
"feedback": {
|
||||
"title": "开启消息通知",
|
||||
"content": "及时查看客服回复",
|
||||
"image": "bg_notification_feedback_style_1",
|
||||
"styleNo": "样式A",
|
||||
"scenes": "场景9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"login": {
|
||||
"title": "咦!是新的小伙伴耶!",
|
||||
"content": "打开<font color=\"#1383EB\">通知开关</font>,游戏、礼包、抽奖活动不错过",
|
||||
"image": "bg_notification_login_style_2",
|
||||
"styleNo": "样式B",
|
||||
"scenes": "场景1"
|
||||
},
|
||||
"question": {
|
||||
"title": "发布成功!答案马上来!",
|
||||
"content": "为了第一时间通知您,需要打开<font color=\"#1383EB\">通知开关</font>",
|
||||
"image": "bg_notification_question_style_2",
|
||||
"styleNo": "样式B",
|
||||
"scenes": "场景2"
|
||||
},
|
||||
"answer": {
|
||||
"title": "精彩的回答!大佬牛啤!",
|
||||
"content": "打开<font color=\"#1383EB\">通知开关</font>,可以第一时间收获赞美和感谢哟!",
|
||||
"image": "bg_notification_answer_style_2",
|
||||
"styleNo": "样式B",
|
||||
"scenes": "场景3"
|
||||
},
|
||||
"article": {
|
||||
"title": "发布成功!不愧是你!",
|
||||
"content": "打开<font color=\"#1383EB\">通知开关</font>,可以第一时间收获赞美和互动哟!",
|
||||
"image": "bg_notification_article_style_2",
|
||||
"styleNo": "样式B",
|
||||
"scenes": "场景4"
|
||||
},
|
||||
"video": {
|
||||
"title": "“百万”播放预定!",
|
||||
"content": "<font color=\"#1383EB\">打开通知!</font>第一时间知道审核结果和互动信息哟!",
|
||||
"image": "bg_notification_video_style_2",
|
||||
"styleNo": "样式B",
|
||||
"scenes": "场景5"
|
||||
},
|
||||
"rating": {
|
||||
"title": "这游戏超好玩,我说的!",
|
||||
"content": "想知道有多少人吃下安利?<font color=\"#1383EB\">打开通知</font>,马上知道!",
|
||||
"image": "bg_notification_rating_style_2",
|
||||
"styleNo": "样式B",
|
||||
"scenes": "场景6"
|
||||
},
|
||||
"gift": {
|
||||
"title": "获得道具:神奇的游戏礼包!",
|
||||
"content": "<font color=\"#1383EB\">打开通知!</font>礼包上线,马上知道!",
|
||||
"image": "bg_notification_gift_style_2",
|
||||
"styleNo": "样式B",
|
||||
"scenes": "场景7"
|
||||
},
|
||||
"reserveGame": {
|
||||
"title": "玩最新的游戏,做游戏圈最靓的仔",
|
||||
"content": "<font color=\"#1383EB\">打开通知!</font>游戏上线,更快知道!",
|
||||
"image": "bg_notification_reserve_game_style_2",
|
||||
"styleNo": "样式B",
|
||||
"scenes": "场景8"
|
||||
},
|
||||
"feedback": {
|
||||
"title": "真是重要的反馈!",
|
||||
"content": "感恩有你,光环更精彩!<font color=\"#1383EB\">打开通知</font>,客服回复,马上知道!",
|
||||
"image": "bg_notification_feedback_style_2",
|
||||
"styleNo": "样式B",
|
||||
"scenes": "场景9"
|
||||
}
|
||||
}
|
||||
]
|
||||
758
app/src/main/assets/privacy_policies.html
Normal file
758
app/src/main/assets/privacy_policies.html
Normal file
@ -0,0 +1,758 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>隐私政策</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.page {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.date p {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: "SourceHanSansSC-regular" !important;
|
||||
color: #101010;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
margin-bottom: 6px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
b {
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.points {
|
||||
margin: 14px 0;
|
||||
}
|
||||
|
||||
.points p {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.introduce p {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.content p b {
|
||||
margin: 6px 0;
|
||||
display: block;
|
||||
}
|
||||
.link-text {
|
||||
color: rgb(19, 131, 235);
|
||||
cursor: pointer;
|
||||
}
|
||||
.link-text a {
|
||||
color: rgb(19, 131, 235);
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
.left-indent {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.page-title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin: 20px 0 10px 0;
|
||||
}
|
||||
.red-style {
|
||||
color: red;
|
||||
}
|
||||
.bold-font {
|
||||
font-weight: bold;
|
||||
}
|
||||
span.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.link-text {
|
||||
color: #005ad0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page">
|
||||
<div class="page-title">欢迎您使用光环助手!</div>
|
||||
|
||||
<div class="introduce">
|
||||
<p>
|
||||
为了向您提供游戏预约、论坛互动交流等相关服务,受制于手机系统限制,我们会申请您的设备信息权限;
|
||||
</p>
|
||||
<p>为了让您正常使用游戏下载和论坛功能,我们会申请您的储存权限;</p>
|
||||
<p>以下为完整《隐私权限政策》</p>
|
||||
<p>
|
||||
光环助手(简称“我们”)深知个人信息对您的重要性,我们将依据《中华人民共和国网络安全法》、《信息安全技术
|
||||
个人信息安全规范》(GB/T
|
||||
35273-2017)以及其他相关法律法规和技术规范收集和使用您的个人信息,以帮助我们向您提供更优质的产品和/或服务,
|
||||
保护您的个人信息及隐私安全。我们制定本“隐私指引”并特别提示:希望您在使用光环助手及相关服务前仔细阅读并理解本隐私政策,以便做出适当的选择。
|
||||
</p>
|
||||
<p>
|
||||
下文将帮您详细了解我们如何收集、使用、存储、传输、共享、转让(如适用)与保护个人信息;帮您了解查询、访问、删除、更正、撤回授权个人信息的方式。其中,
|
||||
<b>
|
||||
有关您个人信息权益的条款重要内容我们已用加粗形式提示,请特别关注。
|
||||
</b>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="points">
|
||||
<p><b>1.我们处理个人信息的法律依据</b></p>
|
||||
<p><b>2.我们如何共享、转让、公开披露个人信息</b></p>
|
||||
<p><b>3.我们如何收集和使用个人信息</b></p>
|
||||
<p><b>4.我们如何存储个人信息</b></p>
|
||||
<p><b>5.我们如何保护个人信息的安全</b></p>
|
||||
<p><b>6.管理您的个人信息</b></p>
|
||||
<p><b>7.未成年人使用条款</b></p>
|
||||
<p><b>8.隐私政策的修订和通知</b></p>
|
||||
<p><b>9.联系我们</b></p>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<p><b>1.我们处理个人信息的法律依据</b></p>
|
||||
<p>
|
||||
如果您是中华人民共和国大陆地区的用户,我们将依据《中华人民共和国网络安全法》、《信息安全技术
|
||||
个人信息安全规范》(GB/T
|
||||
35273-2017)以及其他相关法律法规收集和使用您的个人信息,为您提供产品或服务。
|
||||
</p>
|
||||
<p>
|
||||
我们通常只会在征得您同意的情况下收集您的个人信息。
|
||||
在某些情况下,我们可能还会基于法律义务或者履行合同之必需向您收集个人信息,或者可能需要个人信息来保护您的重要利益或其他人的利益。
|
||||
</p>
|
||||
|
||||
<p><b>2.我们如何共享、转让、公开披露个人信息</b></p>
|
||||
|
||||
<p class="title margintop"><b>2.1第三方SDK接入说明</b></p>
|
||||
<p>
|
||||
为保障光环助手App相关功能的实现与应用安全稳定的运行,我们会接入由第三方提供的软件开发包(SDK)实现相关功能。
|
||||
<br />
|
||||
我们会对合作方获取有关信息的软件工具开发包(SDK)进行严格的安全检测,并与授权合作伙伴约定严格的数据保护措施,令其按照我们的委托目的、服务说明、本隐私权政策以及其他任何相关的保密和安全措施来处理个人信息。
|
||||
<br />
|
||||
<span class="red-style">
|
||||
下方为整个光环助手
|
||||
<span class="bold">所有版本</span>
|
||||
内接入的所有信息收集类第三方SDK的权限说明,因隐私政策会因光环助手版本迭代而新接入SDK或停止合作部分SDK,方便照顾
|
||||
<span class="bold">所有版本</span>
|
||||
的用户查看自己SDK第三方权限说明。
|
||||
<br />
|
||||
我们对涉及用户信息使用的SDK相关情况进行了逐项列举,具体如下:
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class="margintop red-style bold-font"><b>(1)数据统计类</b></p>
|
||||
<p>1.头条推广</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">
|
||||
https://ad.oceanengine.com/openapi/index.html
|
||||
</span>
|
||||
</p>
|
||||
<p>SDK包名:com.bytedance</p>
|
||||
<p>企业主体:北京有竹居网络技术有限公司</p>
|
||||
<p>使用目的:用于广告流量统计相关服务</p>
|
||||
<p>
|
||||
收集信息类型:设备品牌、型号、软件系统相关信息、安卓(oaid、无线网SSID名称、WiFi路由器MAC地址、设备MAC地址、IMEI、地理位置)
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
https://ad.oceanengine.com/openapi/register/protocol.html?rid=vo25p8sfqde
|
||||
</span>
|
||||
</p>
|
||||
<p>2.talkingdata统计</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">http://www.talkingdata.com/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tendcloud</p>
|
||||
<p>企业主体:北京腾云天下科技有限公司</p>
|
||||
<p>使用目的:用于统计数据和效果分析,以便为用户提供更好的服务</p>
|
||||
<p>收集信息类型:设备信息、网络信息、位置信息、应用信息</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
http://www.talkingdata.com/privacy.jsp?languagetype=zh_cn
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>3.腾讯MTA</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://mta.qq.com/mta/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tencent</p>
|
||||
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
|
||||
<p>使用目的:用于统计数据和效果分析</p>
|
||||
<p>
|
||||
收集信息类型:Mac地址、唯一设备识别码(IMEI、android
|
||||
ID、IDFA、OPENUDID、GUID/SIM卡IMSI信息)、地理位置信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
https://mta.qq.com/mta/ctr_index/protocol_v2/
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>4.腾讯广点通</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://developers.e.qq.com/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tencent</p>
|
||||
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
|
||||
<p>使用目的:用于广告流量统计相关服务</p>
|
||||
<p>
|
||||
收集信息类型:
|
||||
个人常用设备信息(IMEI、AndroidID)、位置信息,IP地址、软件版本号
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">https://e.qq.com/optout.html</span>
|
||||
</p>
|
||||
|
||||
<p class="margintop red-style bold-font"><b>(2)社交登录类</b></p>
|
||||
<p>5.微信登录分享</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://open.weixin.qq.com/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tencent.mm.opensdk</p>
|
||||
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
|
||||
<p>使用目的:用于支持微信登录、分享</p>
|
||||
<p>
|
||||
收集信息类型:个人常用设备信息(MAC地址、IMEI、AndroidID)、硬件型号、操作系统类型、软件信息(软件版本号、浏览器类型)、IP地址、服务日志信息、通讯日志信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">https://privacy.tencent.com/</span>
|
||||
</p>
|
||||
|
||||
<p>6.QQ登录分享</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://connect.qq.com/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tentcent</p>
|
||||
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
|
||||
<p>使用目的:用于支持QQ登录、分享</p>
|
||||
<p>
|
||||
收集信息类型:个人常用设备信息(MAC地址、IMEI、AndroidID、IMSI、ICCID、序列号)、设备型号、操作系统版本、软件信息(软件版本号、浏览器类型)、网络信息、IP地址、服务日志信息、通讯日志信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
https://wiki.connect.qq.com/qq互联sdk隐私保护声明
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>7.微博登录分享</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">http://open.weibo.com/authentication</span>
|
||||
</p>
|
||||
<p>SDK包名:com.sina.weibo.sdk</p>
|
||||
<p>企业主体:北京微梦创科网络技术有限公司</p>
|
||||
<p>使用目的:用于支持微博登录、分享</p>
|
||||
<p>
|
||||
收集信息类型:个人常用设备信息(MAC地址、IMEI、AndroidID、IMSI、ICCID、序列号)、网络信息、应用列表,硬件型号、操作系统类型、软件信息(软件版本号、浏览器类型)、IP地址、服务日志信息、通讯日志信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">https://open.weibo.com/wiki/开发者协议</span>
|
||||
</p>
|
||||
|
||||
<p>8.头条抖音登录</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://open.douyin.com/platform</span>
|
||||
</p>
|
||||
<p>SDK包名:com.bytedance.sdk</p>
|
||||
<p>企业主体:北京字节跳动科技有限公司</p>
|
||||
<p>使用目的:用于支持抖音登录</p>
|
||||
<p>
|
||||
收集信息类型:个人常用设备信息(MAC地址、IMEI、AndroidID)、硬件型号、操作系统类型、软件信息(软件版本号、浏览器类型)、IP地址、服务日志信息、通讯日志信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
https://www.douyin.com/agreements/?id=6773901168964798477
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class="margintop red-style bold-font"><b>(3)推送通知类</b></p>
|
||||
<p>9.友盟推送</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://www.umeng.com/push</span>
|
||||
</p>
|
||||
<p>SDK包名:com.umeng</p>
|
||||
<p>企业主体:北京友盟网络科技有限公司</p>
|
||||
<p>使用目的:用于游戏相关信息的提醒通知</p>
|
||||
<p>
|
||||
收集信息类型:Mac地址、唯一设备识别码(IMEI、android
|
||||
ID、IDFA、OPENUDID、GUID/SIM卡IMSI信息)、地理位置信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
https://www.umeng.com/page/policy?spm=a213m0.14063960.0.0.7f626e72hx3nnv
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class="margintop red-style bold-font"><b>(4)其他功能类</b></p>
|
||||
<p>10.阿里云反爬虫</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://www.aliyun.com/product/antibot</span>
|
||||
</p>
|
||||
<p>SDK包名:com.alibaba.wireless</p>
|
||||
<p>企业主体:阿里巴巴网络技术有限公司</p>
|
||||
<p>使用目的:为APP提供网络应用安全防护</p>
|
||||
<p>
|
||||
收集信息类型:设备相关信息(例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息)、设备所在位置相关信息(例如IP地址、GPS位置以及能够提供相关信息的Wi-Fi接入点、蓝牙和基站等传感器信息)。
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
http://terms.aliyun.com/legal-agreement/terms/suit_bu1_ali_cloud/suit_bu1_ali_cloud201902141711_54837.html?spm=a2c4g.11186623.J_9220772140.81.b7574832gmk0vr
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>11.腾讯bugly</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://bugly.qq.com/v2/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tencent.bugly</p>
|
||||
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
|
||||
<p>使用目的:APP异常上报</p>
|
||||
<p>
|
||||
收集信息类型:设备及应用信息。如:设备名称、设备识别符、硬件型号、操作系统版本、应用程序版本
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">https://bugly.qq.com/v2/contract</span>
|
||||
</p>
|
||||
|
||||
<p>12.阿里云文件上传</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://www.alibabacloud.com/zh</span>
|
||||
</p>
|
||||
<p>SDK包名:com.alibaba.sdk.android</p>
|
||||
<p>SDK包名:com.alibaba.sdk.android</p>
|
||||
<p>企业主体:阿里巴巴网络技术有限公司</p>
|
||||
<p>使用目的:用于支持用户上传视频等相关内容</p>
|
||||
<p>
|
||||
收集信息类型:设备相关信息(例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息)、设备所在位置相关信息(例如IP地址、GPS位置以及能够提供相关信息的Wi-Fi接入点、蓝牙和基站等传感器信息)。
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
http://terms.aliyun.com/legal-agreement/terms/suit_bu1_ali_cloud/suit_bu1_ali_cloud201902141711_54837.html?spm=a2c4g.11186623.J_9220772140.81.b7574832gmk0vr
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>13.阿里云日志上传</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://www.alibabacloud.com/zh</span>
|
||||
</p>
|
||||
<p>SDK包名:com.aliyun.sls.android.sdk</p>
|
||||
<p>企业主体:阿里巴巴网络技术有限公司</p>
|
||||
<p>
|
||||
使用目的:通过网络日志分析这些信息以便更及时响应您的帮助请求,以及用于改进服务
|
||||
</p>
|
||||
<p>
|
||||
收集信息类型:设备相关信息(例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息)、设备所在位置相关信息(例如IP地址、GPS位置以及能够提供相关信息的Wi-Fi接入点、蓝牙和基站等传感器信息)。
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
http://terms.aliyun.com/legal-agreement/terms/suit_bu1_ali_cloud/suit_bu1_ali_cloud201902141711_54837.html?spm=a2c4g.11186623.J_9220772140.81.b7574832gmk0vr
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>14.容联七陌</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://www.7moor.com/developer</span>
|
||||
</p>
|
||||
<p>SDK包名:com.m7.imkfsdk</p>
|
||||
<p>企业主体:北京七陌科技有限公司</p>
|
||||
<p>使用目的:用于提供对应在线客服功能</p>
|
||||
<p>
|
||||
收集信息类型:设备相关信息(设备名称、设备型号、硬件序列号、操作系统和应用程序版本及类型、语言设置、分辨率、移动终端随机存储内存、摄像头/相册、通讯录权限等)
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
http://m.7moor.com/72/57/p5077783560e807/
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p><b>2.2 共享您的个人信息</b></p>
|
||||
<p>
|
||||
(1)我们不会与任何公司、组织和个人共享您的个人信息,但以下情况除外:
|
||||
</p>
|
||||
<p>
|
||||
(2)事先获得您的明确授权或同意:
|
||||
获得您的明确同意后,我们会与其他方共享您的个人信息;
|
||||
</p>
|
||||
<p>
|
||||
(3)在法定情形下的共享:
|
||||
根据适用的法律法规、法律程序、政府的强制命令或司法裁定而需共享您的个人信息;
|
||||
</p>
|
||||
<p>
|
||||
(4)在法律要求或允许的范围内,为了保护光环助手及其用户或社会公众的利益、财产或安全免遭损害而有必要提供您的个人信息给第三方;
|
||||
</p>
|
||||
<p>
|
||||
(5)与我们的关联公司共享:
|
||||
您的个人信息可能会在我们的关联公司之间共享。我们会对共享的个人信息进行匿名化处理,且这种共享受本指引所声明目的的约束。关联公司如要改变个人信息的处理目的,将再次征求您的授权同意。
|
||||
</p>
|
||||
<p><b>2.3转让</b></p>
|
||||
<p>
|
||||
(1)我们不会转让您的个人信息给任何其他第三方,除非征得您的明确同意。
|
||||
</p>
|
||||
<p>
|
||||
(2)随着我们业务的持续发展,我们将有可能进行合并、收购、资产转让,您的个人信息有可能因此而被转移。在发生前述变更时,我们将按照法律法规及不低于本隐私政策所载明的安全标准要求继受方保护您的个人信息,否则我们将要求继受方重新征得您的授权同意。
|
||||
</p>
|
||||
<p><b>2.4披露</b></p>
|
||||
<p>
|
||||
(1)我们不会公开披露您的信息,除非遵循国家法律法规规定或者获得您的同意。我们公开披露您的个人信息会采用符合行业内标准的安全保护措施。
|
||||
</p>
|
||||
<p>
|
||||
(2)基于法律、法律程序、诉讼或政府主管部门强制性要求的情况下,我们可能会向有权机关披露您的个人信息。但我们保证,在上述情况发生时,我们会要求披露请求方必须出具与之相应的有效法律文件,并对被披露的信息采取符合法律和业界标准的安全防护措施。
|
||||
</p>
|
||||
<p>
|
||||
(3)对违规账号、欺诈行为进行处罚公告时,我们会披露相关账号的信息。
|
||||
</p>
|
||||
|
||||
<p><b>2.5依法豁免征得同意共享、转让、公开披露的个人信息</b></p>
|
||||
<p>
|
||||
请您理解,在下列情形中,根据法律法规及国家标准,我们共享、转让、公开披露您的个人信息无需征得您的授权同意:
|
||||
</p>
|
||||
<p>(1)与国家安全、国防安全直接相关的;</p>
|
||||
<p>(2)与公共安全、公共卫生、重大公共利益直接相关的;</p>
|
||||
<p>(3)与犯罪侦查、起诉、审判和判决执行等直接相关的;</p>
|
||||
<p>
|
||||
(4)出于维护您或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;
|
||||
</p>
|
||||
<p>(5)您自行向社会公众公开的个人信息;</p>
|
||||
<p>
|
||||
(6)从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道。
|
||||
</p>
|
||||
|
||||
<p><b>3.我们如何收集和使用个人信息</b></p>
|
||||
<p>
|
||||
我们会遵循正当、合法、必要的原则,出于本指引所述的以下目的,收集和使用您在使用服务过程中主动提供或因使用产品或服务而产生的个人信息。
|
||||
</p>
|
||||
<p>
|
||||
我们收集和使用的您的个人信息类型包括两种:第一种:我们产品或服务的核心业务功能所必需的信息:此类信息为产品或服务正常运行的必备信息,您须授权我们收集。如您拒绝提供,您将无法正常使用我们的功能,以"仅浏览(游客身份)"
|
||||
的状态体验;第二种:我们产品或服务的附加业务功能可能需要收集的信息:此信息为非核心业务功能所需的信息,您可以选择是否授权我们收集。如您拒绝提供,将导致附加业务功能无法实现或无法达到我们拟达到的效果,但不影响您对核心业务功能的正常使用。
|
||||
</p>
|
||||
<p>
|
||||
如果我们要将您的个人信息用于本指引未载明的其它用途,或基于特定目的将收集而来的信息用于其他目的,我们将以合理的方式向您告知,并在使用前再次征得您的同意。
|
||||
</p>
|
||||
|
||||
<p><b>3.1实现产品或服务的基本功能</b></p>
|
||||
<p>
|
||||
(1)手机管理和内容资源下载功能。为实现手机管理及手机内容资源下载的基本功能,我们会通过手机系统的公用接口收集经过MD5算法加密的国际移动设备身份码(IMEI)和网络设备地址(MAC),以及手机型号、手机系统版本号、系统编号、系统ID号、屏幕分辨率、上网类型、手机中软件的名称、版本号、版本名、包名、软件使用时间和频率、软件崩溃信息、设备和软件相关的信息。这些信息是提供服务所必须收集的基础信息,如您拒绝提供上述权限将可能导致您无法使用我们的服务。
|
||||
</p>
|
||||
<p>
|
||||
(2)软件升级管理功能。为实现手机软件下载、安装、升级、卸载软件管理功能,在您使用产品时,我们会采集您手机中已安装软件的软件名称、版本号、版本名、软件包名信息并上传到我们的服务器进行软件版本比对。发现有更新的版本,我们会提示您升级相应的软件。上述软件信息为实现此功能所必需,不涉及您个人身份敏感信息。
|
||||
</p>
|
||||
<p>
|
||||
(3)过滤无法使用的软件功能。为了过滤您手机无法使用的软件,我们会收集您手机的手机型号、手机系统版本号、系统版本号、屏幕分辨率信息,并依据这些信息排除您手机无法使用的软件,以保证您在光环助手下载的软件都可安装使用。
|
||||
</p>
|
||||
|
||||
<p><b>3.2关于获取手机设备信息的说明</b></p>
|
||||
<p>
|
||||
(1)为方便区分每个用户的个人信息等,本软件需获取用户的手机设备信息,用于游戏主动预约、论坛互动交流后进行推送等用户相关的行为
|
||||
</p>
|
||||
<p>
|
||||
(2)为了保障软件与服务的安全运行,我们会收集您的硬件型号、操作系统版本号、国际移动设备识别码、唯一设备标识符、网络设备硬件地址、IP
|
||||
地址、WLAN接入点、蓝牙、基站、软件版本号、网络接入方式、类型、状态、网络质量数据、操作、使用、服务日志。
|
||||
</p>
|
||||
<p>
|
||||
(3)为了预防恶意程序及安全运营所必需,我们会收集安装的应用信息或正在运行的进程信息、应用程序的总体运行、使用情况与频率、应用崩溃情况、总体安装使用情况、性能数据、应用来源。
|
||||
</p>
|
||||
<p>
|
||||
(4)我们可能使用您的账户信息、设备信息、服务日志信息以及我们关联公司、合作方在获得您授权或依法可以共享的信息,用于判断账户安全、进行身份验证、检测及防范安全事件。
|
||||
</p>
|
||||
<p>(5)具体会发生获取手机设备信息场景如下说明:</p>
|
||||
|
||||
<p class="left-indent">
|
||||
1) 首次启动光环助手
|
||||
<b></b>
|
||||
2) 游戏列表/游戏详情/资讯文章详情/搜索结果页-预约功能
|
||||
<b></b>
|
||||
3) 礼包中心/礼包详情-领取功能
|
||||
<b></b>
|
||||
4) 评论详情-发送评论功能
|
||||
<b></b>
|
||||
5) 回答/问题详情-我来回答功能
|
||||
<b></b>
|
||||
6) 问答首页-提问功能
|
||||
<b></b>
|
||||
7) 个人主页-发文章功能
|
||||
<b></b>
|
||||
8) 帖子草稿/我的草稿-编辑功能
|
||||
<b></b>
|
||||
9) 游戏投稿功能
|
||||
<b></b>
|
||||
10)视频投稿-上传视频功能
|
||||
<b></b>
|
||||
11)游戏详情-关注游戏功能
|
||||
</p>
|
||||
|
||||
<p><b>3.3帮助您成为我们的在线用户</b></p>
|
||||
<p>(1)注册账号/登录账号</p>
|
||||
<p>
|
||||
a.当您注册、登录我们相关服务时,您可以通过手机号创建账号,并且您可以完善相关的网络身份识别信息(头像、昵称、密码),收集这些信息是为了帮助您完成注册。您还可以根据自身需求选择填写性别、生日、地区及个人介绍来完善您的信息。
|
||||
</p>
|
||||
<p>
|
||||
b.您也可以使用第三方账号登录并使用,您将授权我们获取您在第三方平台注册的公开信息(头像、昵称以及您授权的其他信息),用于与光环助手账号绑定,使您可以直接登录并使用本产品和相关服务。
|
||||
</p>
|
||||
<p>(2)认证用户</p>
|
||||
<p>
|
||||
a.在您使用身份认证的功能或服务时,根据相关法律法规,您可能需要提供您的真实身份信息(真实姓名、身份证号码、电话号码)以完成实名验证。
|
||||
</p>
|
||||
<p>
|
||||
b.这些信息属于个人敏感信息,您可以拒绝提供,但您将可能无法获得相关服务,但不影响其他功能与服务的正常使用。
|
||||
</p>
|
||||
|
||||
<p><b>3.4搜索</b></p>
|
||||
<p>
|
||||
(1)您使用“光环助手”的搜索服务时,我们会收集您的搜索关键字信息、日志记录。
|
||||
</p>
|
||||
<p>
|
||||
(2)为了提供高效的搜索服务,部分前述信息会暂时存储在您的本地存储设备之中,并可向您展示搜索结果内容、搜索历史记录。
|
||||
</p>
|
||||
|
||||
<p><b>3.5预约游戏</b></p>
|
||||
<p>
|
||||
当您使用游戏预约、游戏开测提醒功能时,您可以根据需要是否填写手机号。如您拒绝提供,仅会使您无法接收该预约游戏的短信快速提醒功能,但并不影响您正常使用产品与服务的其他。
|
||||
</p>
|
||||
|
||||
<p><b>3.6游戏时长统计</b></p>
|
||||
<p>
|
||||
您可以授权我们使用应用使用记录访问权限,我们会获取您使用某款游戏应用的使用时长,以便于提供游戏时长展示服务以及对应的大数据统计分析。
|
||||
</p>
|
||||
|
||||
<p><b>3.7信息发布功能</b></p>
|
||||
<p>
|
||||
(1)注册成为光环用户后,可在光环平台上发布提问、帖子、视频,并对别人的提问作出回答或邀请其他用户回答,您还可以对别人的回答、帖子和视频的评论作出回复、赞同、感谢。
|
||||
</p>
|
||||
<p>
|
||||
(2)上述功能基于相册(图片库/视频库)的图片/视频访问及上传的附加服务,我们会请求您授权相机、照片、麦克风权限,您可以使用该功能上传您的照片/图片/视频,以实现发布照片/图片/视频的功能、与其他用户进行照片/图片分享等功能。如您拒绝提供该权限和内容的,仅会使您无法使用该功能,但并不影响您正常使用产品与/或服务的其他功能。
|
||||
</p>
|
||||
<p>
|
||||
(3)您发布内容、评论、提问或回答时,我们将收集您发布的信息,并展示您的昵称、头像、发布内容。
|
||||
</p>
|
||||
<p>
|
||||
(4)用户因使用我们的产品或者服务而被我们收集的信息,例如其他用户发布的信息中可能含有您的部分信息(如:在评论、留言、发布图文、音视频中涉及到与您相关的信息)。
|
||||
</p>
|
||||
|
||||
<p><b>3.8浏览、关注与收藏功能</b></p>
|
||||
<p>(1)您可浏览的内容包括问答、评论、专栏、文章。</p>
|
||||
<p>
|
||||
(2)在浏览的过程中,您还可以关注您感兴趣的用户、专栏、问题、收藏,并收藏上述内容。
|
||||
</p>
|
||||
<p>
|
||||
(3)为此,
|
||||
我们可能会收集您使用时的设备信息,如设备型号、唯一设备标识符、操作系统、分辨率、电信运营商等软硬件信息。
|
||||
我们还可能收集您的浏览器类型,以此来为您提供信息展示的最优方案。
|
||||
</p>
|
||||
<p>
|
||||
(4)此外,在您使用浏览和收藏功能的过程中,我们会自动收集您使用的详细情况,并作为有关的
|
||||
网络日志保存,包括但不限于您输入的搜索关键词信息和点击的链接。
|
||||
</p>
|
||||
<p>
|
||||
(5)您浏览和发布的内容及评论信息,您上传的图片信息、您的交易信息、您使用的语言、访问的日期和时间、及您请求的网页记录、操作系统、软件版本号、登录
|
||||
IP 信息。
|
||||
</p>
|
||||
<p>
|
||||
(6)在此过程中,
|
||||
我们会收集您的浏览记录,浏览记录包括您浏览的问答、主页、文章、专栏,
|
||||
您可以自主删除浏览记录。
|
||||
</p>
|
||||
<p><b>3.9互动交流</b></p>
|
||||
<p>
|
||||
(1)您主动关注您感兴趣的账号、内容、视频并与之进行互动,进行浏览、评论、收藏、点赞或分享内容时,我们会收集您关注的账号,并向您展示您关注账号发布内容。
|
||||
</p>
|
||||
<p>
|
||||
(2)您使用推荐通讯录好友功能时,我们会请求通讯录权限,并将通讯录中的信息进行高强度加密算法处理后,用于向您推荐通信录中的好友。通讯录信息属于个人敏感信息,拒绝提供该信息仅会使您无法使用上述功能,但不影响您正常使用“光环助手”及相关服务的其他功能。
|
||||
</p>
|
||||
|
||||
<p><b>3.10收集、使用个人信息目的变更</b></p>
|
||||
<p>
|
||||
(1)请您了解,随着我们业务的发展,可能会对“光环助手”的功能和提供的服务有所调整变化。
|
||||
</p>
|
||||
<p>
|
||||
(2)原则上,当新功能或服务与我们当前提供的功能或服务相关时,收集与使用的个人信息将与原处理目的具有直接或合理关联。
|
||||
</p>
|
||||
<p>
|
||||
(3)在与原处理目的无直接或合理关联的场景下,我们收集、使用您的个人信息,会再次进行告知,并征得您的同意。
|
||||
</p>
|
||||
|
||||
<p><b>3.11依法豁免征得同意收集和使用的个人信息</b></p>
|
||||
<p>
|
||||
请您理解,在下列情形中,根据法律法规及相关国家标准,我们收集和使用您的个人信息无需征得您的授权同意:
|
||||
</p>
|
||||
<p>(1)与国家安全、国防安全直接相关的;</p>
|
||||
<p>(2)与公共安全、公共卫生、重大公共利益直接相关的;</p>
|
||||
<p>(3)与犯罪侦查、起诉、审判和判决执行等直接相关的;</p>
|
||||
<p>
|
||||
(4)出于维护个人信息主体或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;
|
||||
</p>
|
||||
<p>(5)所收集的您的个人信息是您自行向社会公众公开的;</p>
|
||||
<p>
|
||||
(6)从合法公开披露的信息中收集的您的个人信息的,如合法的新闻报道、政府信息公开等渠道;
|
||||
</p>
|
||||
<p>(7)根据您的要求签订或履行合同所必需的;</p>
|
||||
<p>
|
||||
(8)用于维护软件及相关服务的安全稳定运行所必需的,例如发现、处置软件及相关服务的故障;
|
||||
</p>
|
||||
<p>(9)为合法的新闻报道所必需的;</p>
|
||||
<p>
|
||||
(10)学术研究机构基于公共利益开展统计或学术研究所必要,且对外提供学术研究或描述的结果时,对结果中所包含的个人信息进行去标识化处理的。
|
||||
</p>
|
||||
<p>(11)法律法规规定的其他情形。</p>
|
||||
<p>
|
||||
特别提示您注意,如信息无法单独或结合其他信息识别到您的个人身份,其不属于法律意义上您的个人信息;当您的信息可以单独或结合其他信息识别到您的个人身份时或我们将无法与任何特定个人信息建立联系的数据与其他您的个人信息结合使用时,这些信息在结合使用期间,将作为您的个人信息按照本隐私政策处理与保护。
|
||||
</p>
|
||||
|
||||
<p><b>4.我们如何存储个人信息</b></p>
|
||||
<p><b>4.1 存储地点</b></p>
|
||||
<p>
|
||||
(1)我们依照法律法规的规定,将在境内运营过程中收集和产生的您的个人信息存储于中华人民共和国境内。
|
||||
</p>
|
||||
<p>
|
||||
(2)目前,我们不会将上述信息传输至境外,如果我们向境外传输,我们将会遵循相关国家规定或者征求您的同意。
|
||||
</p>
|
||||
<p><b>4.2存储期限</b></p>
|
||||
<p>
|
||||
(1)我们仅在为提供“光环助手”及服务之目的所必需的期间内保留您的个人信息:您发布的信息、评论、点赞及相关信息,在您未撤回、删除或未注销账号期间,我们会保留相关信息。
|
||||
</p>
|
||||
<p>
|
||||
(2)超出必要期限后,我们将对您的个人信息进行删除或匿名化处理,但法律法规另有规定的除外。
|
||||
</p>
|
||||
|
||||
<p><b>5.我们如何保护个人信息的安全</b></p>
|
||||
<p>
|
||||
(1)我们非常重视您个人信息的安全,将努力采取合理的安全措施(包括技术方面和管理方面)来保护您的个人信息,防止您提供的个人信息被不当使用或未经授权的情况下被访问、公开披露、使用、修改、损坏、丢失或泄漏。
|
||||
</p>
|
||||
<p>
|
||||
(2)我们会使用不低于行业同行的加密技术、匿名化处理及相关合理可行的手段保护您的个人信息,并使用安全保护机制防止您的个人信息遭到恶意攻击。
|
||||
</p>
|
||||
<p>
|
||||
(3)我们会建立专门的安全部门、安全管理制度、数据安全流程保障您的个人信息安全。我们采取严格的数据使用和访问制度,确保只有授权人员才可访问您的个人信息,并适时对数据和技术进行安全审计。
|
||||
</p>
|
||||
<p>
|
||||
(4)尽管已经采取了上述合理有效措施,并已经遵守了相关法律规定要求的标准,但请您理解,由于技术的限制以及可能存在的各种恶意手段,在互联网行业,即便竭尽所能加强安全措施,也不可能始终保证信息百分之百的安全,我们将尽力确保您提供给我们的个人信息的安全性。
|
||||
</p>
|
||||
<p>
|
||||
(5)您知悉并理解,您接入我们的服务所用的系统和通讯网络,有可能因我们可控范围外的因素而出现问题。因此,我们强烈建议您采取积极措施保护个人信息的安全,包括但不限于使用复杂密码、定期修改密码、不将自己的账号密码及相关个人信息透露给他人。
|
||||
</p>
|
||||
<p>
|
||||
(6)我们会制定应急处理预案,并在发生用户信息安全事件时立即启动应急预案,努力阻止这些安全事件的影响和后果扩大。一旦发生用户信息安全事件(泄露、丢失)后,我们将按照法律法规的要求,及时向您告知:安全事件的基本情况和可能的影响、我们已经采取或将要采取的处置措施、您可自主防范和降低风险的建议、对您的补救措施。我们将及时将事件相关情况以推送通知、邮件、信函、短信及相关形式告知您,难以逐一告知时,我们会采取合理、有效的方式发布公告。同时,我们还将按照相关监管部门要求,上报用户信息安全事件的处置情况。
|
||||
</p>
|
||||
<p>
|
||||
(7)您一旦离开“光环助手”及相关服务,浏览或使用其他网站、服务及内容资源,我们将没有能力和直接义务保护您在光环助手及相关服务之外的软件、网站提交的任何个人信息,无论您登录、浏览或使用上述软件、网站是否基于“光环助手”的链接或引导。
|
||||
</p>
|
||||
|
||||
<p><b>6.管理您的个人信息</b></p>
|
||||
<p>
|
||||
我们非常重视您对个人信息的管理,并尽全力保护您的隐私,对于您个人信息的查询、访问、修改、删除、撤回同意授权、注销账号、投诉举报以及设置隐私功能的相关权利,以使您有能力保障您的隐私和信息安全。
|
||||
</p>
|
||||
|
||||
<p><b>6.1 访问、删除、更正您的个人信息</b></p>
|
||||
<p>(1)访问个人账号信息</p>
|
||||
<p>a. 您可以查询、访问您的头像、用户名、简介、性别、生日、地区</p>
|
||||
<p>b.您可以在光环助手的“个人中心”中进行查询、访问。</p>
|
||||
<p>(2)查询访问、更正、取消您关注账号、查询访问粉丝、访客信息</p>
|
||||
<p>a.进入“关注”在关注列表中查询、访问、取消关注您关注的账号。</p>
|
||||
<p>
|
||||
(3)查询访问、更改、删除您的收藏、点赞、浏览记录、阅读历史记录、搜索历史历史记录
|
||||
</p>
|
||||
<p>
|
||||
a.点击“我的”—点击“我的收藏”、
|
||||
“我的点赞”、或“浏览历史”进入查询访问、删除;
|
||||
</p>
|
||||
<p>b.点击搜索栏—删除搜索“历史记录”</p>
|
||||
<p>c.您可以通过点击“系统设置”—点击“清理缓存”。</p>
|
||||
<p>(4)投诉举报</p>
|
||||
<p>a.您可按照我们公示的制度进行投诉或举报。</p>
|
||||
<p>
|
||||
b.如果您认为您的个人信息权利可能受到侵害,或者发现侵害个人信息权利的线索(例如:认为我们收集您的个人信息违反法律规定或者双方约定),“我的”—“基础功能”—“用户反馈”,进入用户反馈界面与我们联系。
|
||||
</p>
|
||||
<p>c.我们核查后会及时反馈您的投诉与举报。</p>
|
||||
<p>(5)访问隐私政策</p>
|
||||
<p>
|
||||
a.您可以在注册页面,或者在登录个人账号“设置”—“关于”查看本隐私政策的全部内容
|
||||
</p>
|
||||
<p>
|
||||
b.请您了解,本隐私政策中所述的“光环助手”及相关服务可能会根据您所使用的手机型号、系统版本、软件应用程序版本、移动客户端等因素而有所不同。最终的产品和服务以您所使用的“光环助手”软件及相关服务为准。
|
||||
</p>
|
||||
<p>(6)停止运营向您告知</p>
|
||||
<p>
|
||||
a.如我们停止运营,我们将及时停止收集您个人信息的活动,将停止运营的通知以逐一送达或公告的形式通知您,并对所持有的您的个人信息进行删除或匿名化处理。
|
||||
</p>
|
||||
|
||||
<p><b>6.2 注销您的个人账号</b></p>
|
||||
<p>
|
||||
如需要注销个人账户,可前往光环助手,我的光环> 设置 > 账号与安全 >
|
||||
账号安全中心 >
|
||||
注销账号,进行注销操作。请您注意,如果您选择注销光环助手账户,那么您的光环助手账号将不可被使用且相关账号信息将被删除,包括所发布的所有内容,包括:提问、回答、社区文章、评论、关注的人等均会被清空;您将无法再通过光环助手账号登录光环助手的服务(但不会影响您使用无需账号登录即可使用的服务和功能)
|
||||
</p>
|
||||
<p>
|
||||
当您注销账户后,除法律法规要求我们保存相关信息的情况外,我们将停止为您提供相应的产品(或服务),并在60个工作日内删除或匿名化您的个人信息。
|
||||
</p>
|
||||
|
||||
<p><b>7.未成年人条款</b></p>
|
||||
<p>
|
||||
a.若您是未满18周岁的未成年人,在使用“光环助手”及相关服务前,应在您的父母或其他监护人监护、指导下共同阅读并同意本隐私政策。
|
||||
</p>
|
||||
<p>
|
||||
b.我们根据国家相关法律法规的规定保护未成年人的个人信息,只会在法律允许、父母或其他监护人明确同意或保护未成年人所必要的情况下收集、使用、储存、共享、转让或披露未成年人的个人信息;如果我们发现在未事先获得可证实的父母同意的情况下收集了未成年人的个人信息,则会设法尽快删除相关信息。
|
||||
</p>
|
||||
<p>
|
||||
c.若您是未成年人的监护人,当您对您所监护的未成年人的个人信息有相关疑问时,请通过公司本隐私政策公示的联系方式与我们联系。
|
||||
</p>
|
||||
<p><b>8.隐私政策的修订和通知</b></p>
|
||||
<p>
|
||||
(1)为了给您提供更好的服务,光环助手及相关服务将不时更新与变化,我们会适时对本隐私政策进行修订,这些修订构成本隐私政策的一部分并具有等同于本隐私政策的效力,未经您明确同意,我们不会削减您依据当前生效的本隐私政策所应享受的权利。
|
||||
</p>
|
||||
<p>
|
||||
(2)本隐私政策更新后,我们会在光环助手发出更新版本,并在更新后的条款生效前通过公告或其他适当的方式提醒您更新的内容,以便您及时了解本隐私政策的最新版本。
|
||||
</p>
|
||||
<p><b>9.联系我们</b></p>
|
||||
<p>
|
||||
如果您对我们的隐私政策及对您个人信息的处理有任何疑问、意见、建议、或投诉,请通过以下方式与我们联系
|
||||
</p>
|
||||
<p>广州加兔网络科技有限公司</p>
|
||||
<p>注册地址:广州市番禺区市桥街丹山村青云一街2号229房</p>
|
||||
<p>在线客服QQ:350473523</p>
|
||||
<p>信息保护事务联系电话:020-85526920</p>
|
||||
<p>在一般情况下,我们会在15个工作日内对您的请求予以答复</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB |
493
app/src/main/assets/user_regulation.html
Normal file
493
app/src/main/assets/user_regulation.html
Normal file
@ -0,0 +1,493 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>光环助手软件许可及服务协议</title>
|
||||
</head>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.top {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
padding: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 14px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.margintop {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.left-indent {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.red-style {
|
||||
color: red;
|
||||
}
|
||||
.bold-font {
|
||||
font-weight: bold;
|
||||
}
|
||||
span.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.link-text {
|
||||
color: #005ad0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<h3 class="top">光环助手软件许可及服务协议</h3>
|
||||
<h5 class="title">首部及导言</h5>
|
||||
<p>欢迎使用光环助手软件许可及服务</p>
|
||||
<p>
|
||||
各位用户在使用光环助手前,请您务必审慎阅读、并充分理解本协议中的各项条款,
|
||||
<span class="bold">
|
||||
特别是免除或者限制责任的条款,以及开通或使用某项服务的单独协议,并选择接受或不接受。
|
||||
</span>
|
||||
除非您已阅读并接受本协议所有条款,否则您无权下载、安装或使用本软件及相关服务。您的下载、安装、使用、登录等行为即视为您已阅读并同意上述协议的约束。
|
||||
</p>
|
||||
<p>如果您未满18周岁,请在法定监护人的陪同下阅读本协议及其他上述协议。</p>
|
||||
<h5 class="title margintop">一、权利声明</h5>
|
||||
<p>
|
||||
“光环助手”的一切知识产权,以及与“光环助手”相关的所有信息内容,包括但不限于:文字表述及其组合、图标、图饰、图像、图表、色彩、界面设计、版面框架、有关数据、附加程序、印刷材料或电子文档等均为光环助手所有,受著作权法和国际著作权条约以及其他知识产权法律法规的保护。
|
||||
</p>
|
||||
<h5 class="title margintop">二、软件使用规范</h5>
|
||||
<p>
|
||||
2.1
|
||||
本软件是基于Android(安卓)系统手机、平板电脑(PAD)等设备开发的一款软件,提供注册登录、手机游戏管理、游戏推荐、文章阅读等功能
|
||||
</p>
|
||||
<p>2.2 软件的下载、安装和使用</p>
|
||||
<p>
|
||||
本软件为免费软件,用户可以非商业性、无限制数量地从光环授权的渠道下载、安装及使用本软件。
|
||||
</p>
|
||||
<p>
|
||||
<span class="bold">
|
||||
如果您从未经光环授权的第三方获取本软件或与本软件名称相同的安装程序,光环无法保证该软件能够正常使用,并对因此给您造成的损失不予负责。
|
||||
</span>
|
||||
</p>
|
||||
<p>2.3 软件的复制、分发和传播</p>
|
||||
<p>
|
||||
本产品以学习、研究交流为目的。用户可以非商业性、无限制数量地复制、分发和传播本软件产品。但必须保证每一份复制、分发和传播都是完整和真实的,
|
||||
包括所有有关本软件产品的软件、电子文档, 版权和商标,亦包括本协议。
|
||||
</p>
|
||||
<p>2.4 软件的更新</p>
|
||||
<p>
|
||||
为了改善用户体验、完善服务内容,光环将不断努力开发新的服务,并为您不时提供软件更新(这些更新可能会采取软件替换、修改、功能强化、版本升级等形式)。为了保证本软件及服务的安全性和功能的一致性,光环有权不经向您特别通知而对软件进行更新,或者对软件的部分功能效果进行改变或限制。本软件新版本发布后,旧版本的软件可能无法使用。光环不保证旧版本软件继续可用及相应的客户服务,请您随时核对并下载最新版本。
|
||||
</p>
|
||||
<h5 class="title margintop">三、用户使用须知</h5>
|
||||
<p>3.1 您理解并同意:</p>
|
||||
<p>
|
||||
为了向您提供有效的服务,本软件会利用您移动通讯终端的处理器和带宽等资源。本软件使用过程中可能产生数据流量的费用,用户需自行向运营商了解相关资费信息,并自行承担相关费用.
|
||||
</p>
|
||||
<p>3.2 您理解并同意:</p>
|
||||
<p>
|
||||
由本软件进行收录、推荐并提供下载、升级服务的第三方软件,由第三方享有一切合法权利,光环并不能识别用户利用本软件下载、安装的第三方软件是否有合法来源。
|
||||
<span class="bold">
|
||||
因第三方软件引发的任何纠纷,由该第三方负责解决,光环不承担任何责任。
|
||||
</span>
|
||||
同时光环不对第三方软件或技术提供客服支持,若用户需要获取支持,请与该软件或技术提供商联系,若您为有关软件的权利人,不愿本软件为您的软件提供用户下载、安装、使用的服务,也可按本协议约定的联系方式联系我们,我们将会积极配合进行处理。
|
||||
</p>
|
||||
<p>3.3 您理解并同意:</p>
|
||||
<p>
|
||||
<span class="bold">
|
||||
如果因您不正当使用本软件造成了不良影响,或因使用本软件造成的包括但不限于数据异常等问题,均由使用者自行承担,光环团队不对任意类型的使用结果承担责任;
|
||||
</span>
|
||||
</p>
|
||||
<p>3.4 您理解并同意:</p>
|
||||
<p>
|
||||
本软件不含任何破坏用户移动通讯设备数据和获取用户隐私信息的恶意代码,不会泄露用户的个人信息和隐私;
|
||||
</p>
|
||||
<p>3.5 您理解并同意:</p>
|
||||
<p>
|
||||
<span class="bold">
|
||||
对于包括但不限于互联网网络故障、计算机故障、手机故障或病毒、信息损坏或丢失、计算机系统问题,或其它任何基于不可抗力原因而产生的损失,光环团队不承担任何责任。
|
||||
</span>
|
||||
</p>
|
||||
<p>3.6 您理解并同意:</p>
|
||||
<p>光环发布、收录的文章均不代表光环立场。</p>
|
||||
<p>3.7 您理解并同意:</p>
|
||||
<p>
|
||||
为实现软件包括但不限于集中展示、下载、安装、卸载等游戏管理功能以及文章优先推荐功能,本软件会检测用户手机中已安装游戏的包名、版本号、版本名、游戏名称信息。除征得用户明确同意和法律明确规定外,光环不会向第三方泄露任何的用户信息
|
||||
</p>
|
||||
<p>3.8 您理解并同意:</p>
|
||||
<p>
|
||||
用户应在遵守法律及本协议的前提下使用本软件。用户无权实施包括但不限于下列行为:
|
||||
</p>
|
||||
3.8.1 不得删除或者改变本软件上的所有权利管理电子信息
|
||||
<br />
|
||||
3.8.2 不得故意避开或者破坏著作权人为保护本软件著作权而采取的技术措施;
|
||||
<br />
|
||||
3.8.3 用户不得利用本软件误导、欺骗他人;
|
||||
<br />
|
||||
3.8.4
|
||||
违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行;
|
||||
<br />
|
||||
3.8.5 未经允许,进入计算机信息网络或者使用计算机信息网络资源;
|
||||
<br />
|
||||
3.8.6 未经允许,对计算机信息网络功能进行删除、修改或者增加;
|
||||
<br />
|
||||
3.8.7
|
||||
未经允许,对计算机信息网络中存储、处理或者传输的数据和应用程序进行删除、修改或者增加;
|
||||
<br />
|
||||
3.8.8 破坏本软件系统或网站的正常运行,故意传播计算机病毒等破坏性程序;
|
||||
<br />
|
||||
3.8.9 其他任何危害计算机信息网络安全的行为。
|
||||
<br />
|
||||
<p>3.9 您理解并同意:</p>
|
||||
<p>
|
||||
本软件经过详细的测试,但不能保证与所有的软硬件系统完全兼容,不能保证本软件完全没有错误。如果出现不兼容及软件错误的情况,用户可通过各反馈途径将情况告知光环团队,获得技术支持。如果无法解决兼容性问题,用户可以删除本软件。
|
||||
</p>
|
||||
<h5 class="title margintop">四、争议解决处理</h5>
|
||||
<p>
|
||||
本《协议》的解释、效力及纠纷的解决,适用于中华人民共和国法律。若用户和光环助手之间发生任何纠纷或争议,首先应友好协商解决,协商不成的,用户在此完全同意将纠纷或争议提交光环助手所在地法院管辖
|
||||
</p>
|
||||
|
||||
<p class="title margintop"><b>五、第三方SDK接入说明</b></p>
|
||||
<p>
|
||||
为保障光环助手App相关功能的实现与应用安全稳定的运行,我们会接入由第三方提供的软件开发包(SDK)实现相关功能。
|
||||
<br />
|
||||
我们会对合作方获取有关信息的软件工具开发包(SDK)进行严格的安全检测,并与授权合作伙伴约定严格的数据保护措施,令其按照我们的委托目的、服务说明、本隐私权政策以及其他任何相关的保密和安全措施来处理个人信息。
|
||||
<br />
|
||||
<span class="red-style">
|
||||
下方为整个光环助手
|
||||
<span class="bold">所有版本</span>
|
||||
内接入的所有信息收集类第三方SDK的权限说明,因隐私政策会因光环助手版本迭代而新接入SDK或停止合作部分SDK,方便照顾
|
||||
<span class="bold">所有版本</span>
|
||||
的用户查看自己SDK第三方权限说明。
|
||||
<br />
|
||||
我们对涉及用户信息使用的SDK相关情况进行了逐项列举,具体如下:
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class="margintop red-style bold-font"><b>(1)数据统计类</b></p>
|
||||
<p>1.头条推广</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">
|
||||
https://ad.oceanengine.com/openapi/index.html
|
||||
</span>
|
||||
</p>
|
||||
<p>SDK包名:com.bytedance</p>
|
||||
<p>企业主体:北京有竹居网络技术有限公司</p>
|
||||
<p>使用目的:用于广告流量统计相关服务</p>
|
||||
<p>
|
||||
收集信息类型:设备品牌、型号、软件系统相关信息、安卓(oaid、无线网SSID名称、WiFi路由器MAC地址、设备MAC地址、IMEI、地理位置)
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
https://ad.oceanengine.com/openapi/register/protocol.html?rid=vo25p8sfqde
|
||||
</span>
|
||||
</p>
|
||||
<p>2.talkingdata统计</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">http://www.talkingdata.com/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tendcloud</p>
|
||||
<p>企业主体:北京腾云天下科技有限公司</p>
|
||||
<p>使用目的:用于统计数据和效果分析,以便为用户提供更好的服务</p>
|
||||
<p>收集信息类型:设备信息、网络信息、位置信息、应用信息</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
http://www.talkingdata.com/privacy.jsp?languagetype=zh_cn
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>3.腾讯MTA</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://mta.qq.com/mta/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tencent</p>
|
||||
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
|
||||
<p>使用目的:用于统计数据和效果分析</p>
|
||||
<p>
|
||||
收集信息类型:Mac地址、唯一设备识别码(IMEI、android
|
||||
ID、IDFA、OPENUDID、GUID/SIM卡IMSI信息)、地理位置信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
https://mta.qq.com/mta/ctr_index/protocol_v2/
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>4.腾讯广点通</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://developers.e.qq.com/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tencent</p>
|
||||
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
|
||||
<p>使用目的:用于广告流量统计相关服务</p>
|
||||
<p>
|
||||
收集信息类型:
|
||||
个人常用设备信息(IMEI、AndroidID)、位置信息,IP地址、软件版本号
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">https://e.qq.com/optout.html</span>
|
||||
</p>
|
||||
|
||||
<p class="margintop red-style bold-font"><b>(2)社交登录类</b></p>
|
||||
<p>5.微信登录分享</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://open.weixin.qq.com/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tencent.mm.opensdk</p>
|
||||
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
|
||||
<p>使用目的:用于支持微信登录、分享</p>
|
||||
<p>
|
||||
收集信息类型:个人常用设备信息(MAC地址、IMEI、AndroidID)、硬件型号、操作系统类型、软件信息(软件版本号、浏览器类型)、IP地址、服务日志信息、通讯日志信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">https://privacy.tencent.com/</span>
|
||||
</p>
|
||||
|
||||
<p>6.QQ登录分享</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://connect.qq.com/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tentcent</p>
|
||||
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
|
||||
<p>使用目的:用于支持QQ登录、分享</p>
|
||||
<p>
|
||||
收集信息类型:个人常用设备信息(MAC地址、IMEI、AndroidID、IMSI、ICCID、序列号)、设备型号、操作系统版本、软件信息(软件版本号、浏览器类型)、网络信息、IP地址、服务日志信息、通讯日志信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
https://wiki.connect.qq.com/qq互联sdk隐私保护声明
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>7.微博登录分享</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">http://open.weibo.com/authentication</span>
|
||||
</p>
|
||||
<p>SDK包名:com.sina.weibo.sdk</p>
|
||||
<p>企业主体:北京微梦创科网络技术有限公司</p>
|
||||
<p>使用目的:用于支持微博登录、分享</p>
|
||||
<p>
|
||||
收集信息类型:个人常用设备信息(MAC地址、IMEI、AndroidID、IMSI、ICCID、序列号)、网络信息、应用列表,硬件型号、操作系统类型、软件信息(软件版本号、浏览器类型)、IP地址、服务日志信息、通讯日志信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">https://open.weibo.com/wiki/开发者协议</span>
|
||||
</p>
|
||||
|
||||
<p>8.头条抖音登录</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://open.douyin.com/platform</span>
|
||||
</p>
|
||||
<p>SDK包名:com.bytedance.sdk</p>
|
||||
<p>企业主体:北京字节跳动科技有限公司</p>
|
||||
<p>使用目的:用于支持抖音登录</p>
|
||||
<p>
|
||||
收集信息类型:个人常用设备信息(MAC地址、IMEI、AndroidID)、硬件型号、操作系统类型、软件信息(软件版本号、浏览器类型)、IP地址、服务日志信息、通讯日志信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
https://www.douyin.com/agreements/?id=6773901168964798477
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class="margintop red-style bold-font"><b>(3)推送通知类</b></p>
|
||||
<p>9.友盟推送</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://www.umeng.com/push</span>
|
||||
</p>
|
||||
<p>SDK包名:com.umeng</p>
|
||||
<p>企业主体:北京友盟网络科技有限公司</p>
|
||||
<p>使用目的:用于游戏相关信息的提醒通知</p>
|
||||
<p>
|
||||
收集信息类型:Mac地址、唯一设备识别码(IMEI、android
|
||||
ID、IDFA、OPENUDID、GUID/SIM卡IMSI信息)、地理位置信息
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
https://www.umeng.com/page/policy?spm=a213m0.14063960.0.0.7f626e72hx3nnv
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class="margintop red-style bold-font"><b>(4)其他功能类</b></p>
|
||||
<p>10.阿里云反爬虫</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://www.aliyun.com/product/antibot</span>
|
||||
</p>
|
||||
<p>SDK包名:com.alibaba.wireless</p>
|
||||
<p>企业主体:阿里巴巴网络技术有限公司</p>
|
||||
<p>使用目的:为APP提供网络应用安全防护</p>
|
||||
<p>
|
||||
收集信息类型:设备相关信息(例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息)、设备所在位置相关信息(例如IP地址、GPS位置以及能够提供相关信息的Wi-Fi接入点、蓝牙和基站等传感器信息)。
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
http://terms.aliyun.com/legal-agreement/terms/suit_bu1_ali_cloud/suit_bu1_ali_cloud201902141711_54837.html?spm=a2c4g.11186623.J_9220772140.81.b7574832gmk0vr
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>11.腾讯bugly</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://bugly.qq.com/v2/</span>
|
||||
</p>
|
||||
<p>SDK包名:com.tencent.bugly</p>
|
||||
<p>企业主体:深圳市腾讯计算机系统有限公司</p>
|
||||
<p>使用目的:APP异常上报</p>
|
||||
<p>
|
||||
收集信息类型:设备及应用信息。如:设备名称、设备识别符、硬件型号、操作系统版本、应用程序版本
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">https://bugly.qq.com/v2/contract</span>
|
||||
</p>
|
||||
|
||||
<p>12.阿里云文件上传</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://www.alibabacloud.com/zh</span>
|
||||
</p>
|
||||
<p>SDK包名:com.alibaba.sdk.android</p>
|
||||
<p>SDK包名:com.alibaba.sdk.android</p>
|
||||
<p>企业主体:阿里巴巴网络技术有限公司</p>
|
||||
<p>使用目的:用于支持用户上传视频等相关内容</p>
|
||||
<p>
|
||||
收集信息类型:设备相关信息(例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息)、设备所在位置相关信息(例如IP地址、GPS位置以及能够提供相关信息的Wi-Fi接入点、蓝牙和基站等传感器信息)。
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
http://terms.aliyun.com/legal-agreement/terms/suit_bu1_ali_cloud/suit_bu1_ali_cloud201902141711_54837.html?spm=a2c4g.11186623.J_9220772140.81.b7574832gmk0vr
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>13.阿里云日志上传</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://www.alibabacloud.com/zh</span>
|
||||
</p>
|
||||
<p>SDK包名:com.aliyun.sls.android.sdk</p>
|
||||
<p>企业主体:阿里巴巴网络技术有限公司</p>
|
||||
<p>
|
||||
使用目的:通过网络日志分析这些信息以便更及时响应您的帮助请求,以及用于改进服务
|
||||
</p>
|
||||
<p>
|
||||
收集信息类型:设备相关信息(例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息)、设备所在位置相关信息(例如IP地址、GPS位置以及能够提供相关信息的Wi-Fi接入点、蓝牙和基站等传感器信息)。
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">
|
||||
http://terms.aliyun.com/legal-agreement/terms/suit_bu1_ali_cloud/suit_bu1_ali_cloud201902141711_54837.html?spm=a2c4g.11186623.J_9220772140.81.b7574832gmk0vr
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p>14.容联七陌</p>
|
||||
<p>
|
||||
SDK官网:
|
||||
<span class="link-text">https://www.7moor.com/developer</span>
|
||||
</p>
|
||||
<p>SDK包名:com.m7.imkfsdk</p>
|
||||
<p>企业主体:北京七陌科技有限公司</p>
|
||||
<p>使用目的:用于提供对应在线客服功能</p>
|
||||
<p>
|
||||
收集信息类型:设备相关信息(设备名称、设备型号、硬件序列号、操作系统和应用程序版本及类型、语言设置、分辨率、移动终端随机存储内存、摄像头/相册、通讯录权限等)
|
||||
</p>
|
||||
<p>
|
||||
隐私政策链接:
|
||||
<span class="link-text">http://m.7moor.com/72/57/p5077783560e807/</span>
|
||||
</p>
|
||||
|
||||
<h5 class="title margintop">六、关于获取手机设备信息的说明</h5>
|
||||
<div>
|
||||
(1)为方便区分每个用户的个人信息等,本软件需获取用户的手机设备信息,用于游戏主动预约、论坛互动交流后进行推送等用户相关的行为
|
||||
<br />
|
||||
(2)为了保障软件与服务的安全运行,我们会收集您的硬件型号、操作系统版本号、国际移动设备识别码、唯一设备标识符、网络设备硬件地址、IP
|
||||
地址、WLAN接入点、蓝牙、基站、软件版本号、网络接入方式、类型、状态、网络质量数据、操作、使用、服务日志。
|
||||
<br />
|
||||
(3)为了预防恶意程序及安全运营所必需,我们会收集安装的应用信息或正在运行的进程信息、应用程序的总体运行、使用情况与频率、应用崩溃情况、总体安装使用情况、性能数据、应用来源。
|
||||
<br />
|
||||
(4)我们可能使用您的账户信息、设备信息、服务日志信息以及我们关联公司、合作方在获得您授权或依法可以共享的信息,用于判断账户安全、进行身份验证、检测及防范安全事件。
|
||||
<br />
|
||||
(5)具体会发生获取手机设备信息场景如下说明:
|
||||
<br />
|
||||
<p class="left-indent">
|
||||
1) 首次启动光环助手
|
||||
<br />
|
||||
2) 游戏列表/游戏详情/资讯文章详情/搜索结果页-预约功能
|
||||
<br />
|
||||
3) 礼包中心/礼包详情-领取功能
|
||||
<br />
|
||||
4) 评论详情-发送评论功能
|
||||
<br />
|
||||
5) 回答/问题详情-我来回答功能
|
||||
<br />
|
||||
6) 问答首页-提问功能
|
||||
<br />
|
||||
7) 个人主页-发文章功能
|
||||
<br />
|
||||
8) 帖子草稿/我的草稿-编辑功能
|
||||
<br />
|
||||
9) 游戏投稿功能
|
||||
<br />
|
||||
10) 视频投稿-上传视频功能
|
||||
<br />
|
||||
11) 游戏详情-关注游戏功能
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h5 class="title margintop">七、其他</h5>
|
||||
<p>
|
||||
7.1
|
||||
本协议所有条款的标题仅为阅读方便,本身并无实际涵义,不能作为本协议涵义解释的依据。
|
||||
<br />
|
||||
7.2
|
||||
如果本协议中的任何条款无论因何种原因完全或部分无效或不具有执行力,或违反任何适用的法律,则该条款被视为删除,但本协议的其余条款仍应有效并且有约束力。
|
||||
<br />
|
||||
7.3
|
||||
光环有权随时根据有关法律、法规的变化以及公司经营状况和经营策略的调整等修改本协议。修改后的协议会在软件设置内发布。
|
||||
当发生有关争议时,以最新的协议文本为准。如果不同意改动的内容,用户可以自行删除本软件。如果用户继续使用本软件,则视为您接受本协议的变动。
|
||||
<br />
|
||||
<span class="bold">
|
||||
7.4 光环在法律允许的最大范围内对本协议拥有解释权与修改权。
|
||||
</span>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@ -26,6 +26,8 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import io.sentry.core.Sentry;
|
||||
|
||||
public class AppUncaughtHandler implements UncaughtExceptionHandler {
|
||||
|
||||
private Context mContext;
|
||||
@ -45,7 +47,9 @@ public class AppUncaughtHandler implements UncaughtExceptionHandler {
|
||||
Looper.loop();
|
||||
}
|
||||
});
|
||||
|
||||
saveLocalLog(mContext, ex);
|
||||
Sentry.captureException(ex);
|
||||
restart(mContext);
|
||||
}
|
||||
|
||||
|
||||
@ -27,16 +27,22 @@ import com.gh.base.fragment.BaseFragment;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.common.util.StringUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.LoginActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.SplashScreenActivity;
|
||||
import com.gh.gamecenter.eventbus.EBShowDialog;
|
||||
import com.lightgame.BaseAppCompatActivity;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.tencent.tauth.Tencent;
|
||||
@ -98,10 +104,13 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == com.tencent.connect.common.Constants.REQUEST_QQ_SHARE
|
||||
|| requestCode == com.tencent.connect.common.Constants.REQUEST_QZONE_SHARE) {
|
||||
Tencent.onActivityResultData(requestCode, resultCode, data, ShareUtils.getInstance(this).QqShareListener);
|
||||
}
|
||||
ExtensionsKt.tryCatchInRelease(() -> {
|
||||
if (requestCode == com.tencent.connect.common.Constants.REQUEST_QQ_SHARE
|
||||
|| requestCode == com.tencent.connect.common.Constants.REQUEST_QZONE_SHARE) {
|
||||
Tencent.onActivityResultData(requestCode, resultCode, data, ShareUtils.getInstance(this).QqShareListener);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -117,6 +126,23 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("ACTIVITY_ENTRANCE -> " + mEntrance);
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
String xapkUnzipActivity = SPUtils.getString(Constants.SP_XAPK_UNZIP_ACTIVITY);
|
||||
String xapkUrl = SPUtils.getString(Constants.SP_XAPK_URL);
|
||||
Utils.log("页面重建了--" + xapkUnzipActivity + "--" + xapkUrl);
|
||||
if (this.getClass().getName().equals(SplashScreenActivity.class.getName())) {
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "");
|
||||
SPUtils.setString(Constants.SP_XAPK_URL, "");
|
||||
return;
|
||||
}
|
||||
if (this.getClass().getName().equals(xapkUnzipActivity) && !TextUtils.isEmpty(xapkUrl)) {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(this).getDownloadEntityByUrl(xapkUrl);
|
||||
PackageInstaller.install(this, downloadEntity, false);
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "");
|
||||
SPUtils.setString(Constants.SP_XAPK_URL, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@ -169,14 +195,15 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
LinearLayout ll = new LinearLayout(this);
|
||||
TextView tv = new TextView(this);
|
||||
String envText = "正式环境";
|
||||
tv.setBackground(ContextCompat.getDrawable(this, R.color.theme));
|
||||
if (BuildConfig.FLAVOR.equals("internal")) {
|
||||
envText = "测试环境";
|
||||
tv.setBackground(ContextCompat.getDrawable(this, R.color.red));
|
||||
}
|
||||
tv.setText(envText);
|
||||
tv.setGravity(Gravity.CENTER);
|
||||
tv.setTextColor(Color.WHITE);
|
||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
|
||||
tv.setBackground(ContextCompat.getDrawable(this, R.color.red));
|
||||
tv.measure(0, 0);
|
||||
tv.setAlpha(0.15F);
|
||||
int height = tv.getMeasuredHeight();
|
||||
@ -187,6 +214,13 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
ll.addView(tv);
|
||||
ll.setPadding(0, (width - height) / 2, 0, (width - height) / 2);
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
tv.setOnLongClickListener(v -> {
|
||||
EntranceUtils.saveShortcut(this.getClass().getName(), getIntent().getExtras());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
screenRootView.addView(view);
|
||||
screenRootView.addView(ll);
|
||||
|
||||
|
||||
@ -4,10 +4,6 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.gh.base.adapter.FragmentAdapter;
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout;
|
||||
import com.gh.common.view.TabIndicatorView;
|
||||
@ -18,6 +14,9 @@ import com.lightgame.view.NoScrollableViewPager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
@ -73,10 +72,13 @@ public abstract class BaseActivity_TabLayout extends ToolBarActivity implements
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getIntent() != null) mCheckedIndex = getIntent().getIntExtra(PAGE_INDEX, 0);
|
||||
mFragmentsList = new ArrayList<>();
|
||||
initFragmentList(mFragmentsList);
|
||||
mTabTitleList = new ArrayList<>();
|
||||
initTabTitleList(mTabTitleList);
|
||||
mFragmentsList = new ArrayList<>(restoreFragments());
|
||||
if (mFragmentsList.isEmpty() || mFragmentsList.size() != mTabTitleList.size()) {
|
||||
mFragmentsList.clear();
|
||||
initFragmentList(mFragmentsList);
|
||||
}
|
||||
|
||||
mViewPager.setOffscreenPageLimit(mFragmentsList.size());
|
||||
mViewPager.addOnPageChangeListener(this);
|
||||
@ -100,6 +102,20 @@ public abstract class BaseActivity_TabLayout extends ToolBarActivity implements
|
||||
BaseFragment_TabLayout.initTabStyle(mTabLayout, mCheckedIndex);
|
||||
}
|
||||
|
||||
private ArrayList<Fragment> restoreFragments() {
|
||||
String tag = "android:switcher:" + mViewPager.getId() + ":";
|
||||
ArrayList<Fragment> fragments = new ArrayList<>();
|
||||
int childCount = mTabTitleList.size();
|
||||
for (int index = 0; index < childCount; index++) {
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag + index);
|
||||
if (fragment != null) {
|
||||
fragments.add(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
return fragments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
|
||||
mDraftBtn.text = if (this is AnswerEditActivity) {
|
||||
"回答草稿"
|
||||
} else "文章草稿"
|
||||
} else "帖子草稿"
|
||||
}
|
||||
|
||||
@OnClick(R.id.editor_image, R.id.editor_font, R.id.editor_link, R.id.editor_paragraph,
|
||||
|
||||
@ -4,10 +4,10 @@ import android.app.Activity;
|
||||
import android.app.Application.ActivityLifecycleCallbacks;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.gh.common.im.ImManager;
|
||||
import com.gh.common.notifier.Notifier;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.AppManager;
|
||||
|
||||
/**
|
||||
@ -34,23 +34,27 @@ public class GHActivityLifecycleCallbacksImpl implements ActivityLifecycleCallba
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
|
||||
DataUtils.onResume(activity);
|
||||
CurrentActivityHolder.getActivitySet().add(activity);
|
||||
ImManager.updateFloatingWindow();
|
||||
//FIXME 这里应该只是部分Activity需要
|
||||
try {
|
||||
// 初始化gameMap
|
||||
DownloadManager.getInstance(activity).initGameMap();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
if (HaloApp.isUserAcceptPrivacyPolicy(activity)) {
|
||||
DataUtils.onResume(activity);
|
||||
//FIXME 这里应该只是部分Activity需要
|
||||
try {
|
||||
// 初始化gameMap
|
||||
DownloadManager.getInstance(activity).initGameMap();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
DataUtils.onPause(activity);
|
||||
CurrentActivityHolder.getActivitySet().remove(activity);
|
||||
|
||||
if (HaloApp.isUserAcceptPrivacyPolicy(activity)) {
|
||||
DataUtils.onPause(activity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,229 +1,229 @@
|
||||
package com.gh.base
|
||||
|
||||
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 android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.text.htmlEncode
|
||||
import com.gh.common.notifier.Notifier
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.PushEntity
|
||||
import com.gh.gamecenter.entity.PushMessageEntity
|
||||
import com.gh.gamecenter.entity.PushMessageUnreadEntity
|
||||
import com.gh.gamecenter.entity.PushNotificationEntity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.message.MessageUnreadRepository
|
||||
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
|
||||
import com.gh.gamecenter.receiver.UmengMessageReceiver
|
||||
import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_CLICK
|
||||
import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_REMOVE
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.google.gson.Gson
|
||||
import com.umeng.message.UmengMessageService
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.android.agoo.common.AgooConstants
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
import java.util.*
|
||||
|
||||
class GHUmengNotificationService : UmengMessageService() {
|
||||
|
||||
companion object {
|
||||
const val ACTION_UMENG = "com.gh.gamecenter.UMENG"
|
||||
const val MESSAGE_FROM_SYSTEM = "message_from_system"
|
||||
const val HALO_MESSAGE_DIALOG = "HALO_MESSAGE_DIALOG"
|
||||
const val HALO_MESSAGE_CENTER = "HALO_MESSAGE_CENTER"
|
||||
const val ANSWER = "answer"
|
||||
const val FOLLOW_QUESTION = "follow_question"
|
||||
const val NOTIFICATION_ID = 2015
|
||||
const val DISPLAY_TYPE_NOTIFICATION = "notification"
|
||||
const val DISPLAY_TYPE_CUSTOM = "custom"
|
||||
const val MESSAGE_ID = "message_id"
|
||||
const val NOTIFICATION_MESSAGE_ID = "notification_message_id" // 通知中心消息 ID
|
||||
const val PUSH_ID = "push_id"
|
||||
}
|
||||
|
||||
val notificationTags = arrayOf("GH_UMENG_TAG_1", "GH_UMENG_TAG_2", "GH_UMENG_TAG_3")
|
||||
val gson = Gson()
|
||||
|
||||
override fun onMessage(context: Context, intent: Intent) {
|
||||
val message = intent.getStringExtra(AgooConstants.MESSAGE_BODY)
|
||||
val isMessageFromSystem = intent.getBooleanExtra(MESSAGE_FROM_SYSTEM, false)
|
||||
|
||||
try {
|
||||
val pushData = message.toObject<PushEntity>()
|
||||
pushData?.let { handlePushData(context, it, message, isMessageFromSystem) }
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlePushData(context: Context, pushData: PushEntity, message: String, isMessageFromSystem: Boolean) {
|
||||
val notificationManager = context.applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
if (pushData.displayType == DISPLAY_TYPE_NOTIFICATION) {
|
||||
// 其它类型的透传信息
|
||||
// 显示到通知栏
|
||||
val msg = message.toObject<PushNotificationEntity>()
|
||||
val data = msg?.extra?.data
|
||||
|
||||
// 系统推送(非自定义信息),直接处理跳转
|
||||
if (isMessageFromSystem) {
|
||||
val intent = Intent()
|
||||
intent.setClass(context, UmengMessageReceiver::class.java)
|
||||
intent.putExtra(EntranceUtils.KEY_DATA, data?.link)
|
||||
intent.putExtra(EntranceUtils.KEY_TYPE, UmengMessageReceiver.DIRECT_ONLY)
|
||||
intent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
intent.putExtra(NOTIFICATION_MESSAGE_ID, data?.messageId)
|
||||
context.sendBroadcast(intent)
|
||||
return
|
||||
}
|
||||
|
||||
// 用户未登录的情况下不生成消息中心通知,避免用户掉登录了还收到跳转至消息中心的通知
|
||||
if (data != null
|
||||
&& data.link?.link == "system"
|
||||
&& !UserManager.getInstance().isLoggedIn) {
|
||||
return
|
||||
}
|
||||
|
||||
val clickIntent = Intent()
|
||||
val removeIntent = Intent()
|
||||
|
||||
clickIntent.setClass(context, UmengMessageReceiver::class.java)
|
||||
clickIntent.putExtra(EntranceUtils.KEY_DATA, data?.link)
|
||||
clickIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
clickIntent.putExtra(MESSAGE_ID, msg?.msgId)
|
||||
clickIntent.putExtra(PUSH_ID, data?.pushId)
|
||||
clickIntent.putExtra(NOTIFICATION_MESSAGE_ID, data?.messageId)
|
||||
clickIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_CLICK)
|
||||
|
||||
removeIntent.setClass(context, UmengMessageReceiver::class.java)
|
||||
removeIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_REMOVE)
|
||||
removeIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
|
||||
val clickPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(),
|
||||
clickIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
val deletePendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt() + 1,
|
||||
removeIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel("Halo_Push", "Halo_Push", NotificationManager.IMPORTANCE_DEFAULT)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
val notification = NotificationCompat.Builder(context, "Halo_Push")
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setTicker(pushData.body?.ticker)
|
||||
.setContentTitle(pushData.body?.title)
|
||||
.setContentText(pushData.body?.text?.fromHtml())
|
||||
.setContentIntent(clickPendingIntent)
|
||||
.setDeleteIntent(deletePendingIntent)
|
||||
.build()
|
||||
notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL
|
||||
|
||||
notificationManager.notify(getNotificationTag(context), NOTIFICATION_ID, notification)
|
||||
} else {
|
||||
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
|
||||
|
||||
val type = if (ANSWER == data?.type) {
|
||||
"回答了你的问题"
|
||||
} else {
|
||||
"回答了你关注的问题"
|
||||
}
|
||||
|
||||
val userName = StringUtils.shrinkStringWithDot(data?.userEntity?.name, 8)
|
||||
val displayText = userName + type
|
||||
|
||||
if (Notifier.isActivityValid(CurrentActivityHolder.getCurrentActivity()) &&
|
||||
Notifier.shouldShowNotifier(data?.answer?.id + displayText)) {
|
||||
Notifier.create(CurrentActivityHolder.getCurrentActivity())
|
||||
.setText(displayText)
|
||||
.setDuration(5000)
|
||||
.setIcon(data?.userEntity?.icon)
|
||||
.setOnClickListener(View.OnClickListener {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceUtils.KEY_ANSWER_ID, data?.answer?.id)
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, EntranceUtils.ENTRANCE_UMENG)
|
||||
bundle.putString(EntranceUtils.KEY_TO, AnswerDetailActivity::class.java.name)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
|
||||
MtaHelper.onEvent("消息弹窗", type, "Does not contains any parameter.")
|
||||
|
||||
// 标记已读
|
||||
val jsonObject = JSONObject()
|
||||
jsonObject.put("type", type)
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
|
||||
RetrofitManager.getInstance(application).api.postMessageRead(UserManager.getInstance().userId, data?.id, body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
super.onResponse(response)
|
||||
MessageUnreadRepository.loadMessageUnreadData()
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
e?.printStackTrace()
|
||||
}
|
||||
})
|
||||
Notifier.hide()
|
||||
})
|
||||
.show(false)
|
||||
Notifier.tagNotifierAsShowed(data?.answer?.id + displayText)
|
||||
}
|
||||
} else if (HALO_MESSAGE_CENTER == pushData.body?.custom) {
|
||||
// 消息中心逻辑
|
||||
val msg = gson.fromJson(message, PushMessageUnreadEntity::class.java)
|
||||
val data = msg?.extra?.data
|
||||
data?.let { MessageUnreadRepository.loadMessageUnreadData() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则:最多三条消息,以旧换新
|
||||
*
|
||||
* @return NotificationTag
|
||||
*/
|
||||
private fun getNotificationTag(context: Context): String {
|
||||
val sp = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val edit = sp.edit()
|
||||
|
||||
val timeTagMap = HashMap<Long, String>()
|
||||
for (tag in notificationTags) {
|
||||
val time = sp.getLong(tag, 0)
|
||||
if (time == 0L) {
|
||||
edit.putLong(tag, System.currentTimeMillis()).apply()
|
||||
return tag
|
||||
} else {
|
||||
timeTagMap[time] = tag
|
||||
}
|
||||
}
|
||||
|
||||
val minTime = Collections.min(timeTagMap.keys)
|
||||
val tag = timeTagMap[minTime]
|
||||
edit.putLong(tag, System.currentTimeMillis()).apply()
|
||||
return if (TextUtils.isEmpty(tag)) notificationTags[0] else tag!!
|
||||
}
|
||||
}
|
||||
//package com.gh.base
|
||||
//
|
||||
//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 android.os.Bundle
|
||||
//import android.preference.PreferenceManager
|
||||
//import android.text.TextUtils
|
||||
//import android.view.View
|
||||
//import androidx.core.app.NotificationCompat
|
||||
//import androidx.core.text.htmlEncode
|
||||
//import com.gh.common.notifier.Notifier
|
||||
//import com.gh.common.util.*
|
||||
//import com.gh.gamecenter.R
|
||||
//import com.gh.gamecenter.entity.PushEntity
|
||||
//import com.gh.gamecenter.entity.PushMessageEntity
|
||||
//import com.gh.gamecenter.entity.PushMessageUnreadEntity
|
||||
//import com.gh.gamecenter.entity.PushNotificationEntity
|
||||
//import com.gh.gamecenter.manager.UserManager
|
||||
//import com.gh.gamecenter.message.MessageUnreadRepository
|
||||
//import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
|
||||
//import com.gh.gamecenter.receiver.UmengMessageReceiver
|
||||
//import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_CLICK
|
||||
//import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_REMOVE
|
||||
//import com.gh.gamecenter.retrofit.Response
|
||||
//import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
//import com.google.gson.Gson
|
||||
//import com.umeng.message.UmengMessageService
|
||||
//import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
//import io.reactivex.schedulers.Schedulers
|
||||
//import okhttp3.MediaType
|
||||
//import okhttp3.RequestBody
|
||||
//import okhttp3.ResponseBody
|
||||
//import org.android.agoo.common.AgooConstants
|
||||
//import org.json.JSONObject
|
||||
//import retrofit2.HttpException
|
||||
//import java.util.*
|
||||
//
|
||||
//class GHUmengNotificationService : UmengMessageService() {
|
||||
//
|
||||
// companion object {
|
||||
// const val ACTION_UMENG = "com.gh.gamecenter.UMENG"
|
||||
// const val MESSAGE_FROM_SYSTEM = "message_from_system"
|
||||
// const val HALO_MESSAGE_DIALOG = "HALO_MESSAGE_DIALOG"
|
||||
// const val HALO_MESSAGE_CENTER = "HALO_MESSAGE_CENTER"
|
||||
// const val ANSWER = "answer"
|
||||
// const val FOLLOW_QUESTION = "follow_question"
|
||||
// const val NOTIFICATION_ID = 2015
|
||||
// const val DISPLAY_TYPE_NOTIFICATION = "notification"
|
||||
// const val DISPLAY_TYPE_CUSTOM = "custom"
|
||||
// const val MESSAGE_ID = "message_id"
|
||||
// const val NOTIFICATION_MESSAGE_ID = "notification_message_id" // 通知中心消息 ID
|
||||
// const val PUSH_ID = "push_id"
|
||||
// }
|
||||
//
|
||||
// val notificationTags = arrayOf("GH_UMENG_TAG_1", "GH_UMENG_TAG_2", "GH_UMENG_TAG_3")
|
||||
// val gson = Gson()
|
||||
//
|
||||
// override fun onMessage(context: Context, intent: Intent) {
|
||||
// val message = intent.getStringExtra(AgooConstants.MESSAGE_BODY)
|
||||
// val isMessageFromSystem = intent.getBooleanExtra(MESSAGE_FROM_SYSTEM, false)
|
||||
//
|
||||
// try {
|
||||
// val pushData = message.toObject<PushEntity>()
|
||||
// pushData?.let { handlePushData(context, it, message, isMessageFromSystem) }
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun handlePushData(context: Context, pushData: PushEntity, message: String, isMessageFromSystem: Boolean) {
|
||||
// val notificationManager = context.applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
//
|
||||
// if (pushData.displayType == DISPLAY_TYPE_NOTIFICATION) {
|
||||
// // 其它类型的透传信息
|
||||
// // 显示到通知栏
|
||||
// val msg = message.toObject<PushNotificationEntity>()
|
||||
// val data = msg?.extra?.data
|
||||
//
|
||||
// // 系统推送(非自定义信息),直接处理跳转
|
||||
// if (isMessageFromSystem) {
|
||||
// val intent = Intent()
|
||||
// intent.setClass(context, UmengMessageReceiver::class.java)
|
||||
// intent.putExtra(EntranceUtils.KEY_DATA, data?.link)
|
||||
// intent.putExtra(EntranceUtils.KEY_TYPE, UmengMessageReceiver.DIRECT_ONLY)
|
||||
// intent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
// intent.putExtra(NOTIFICATION_MESSAGE_ID, data?.messageId)
|
||||
// context.sendBroadcast(intent)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 用户未登录的情况下不生成消息中心通知,避免用户掉登录了还收到跳转至消息中心的通知
|
||||
// if (data != null
|
||||
// && data.link?.link == "system"
|
||||
// && !UserManager.getInstance().isLoggedIn) {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// val clickIntent = Intent()
|
||||
// val removeIntent = Intent()
|
||||
//
|
||||
// clickIntent.setClass(context, UmengMessageReceiver::class.java)
|
||||
// clickIntent.putExtra(EntranceUtils.KEY_DATA, data?.link)
|
||||
// clickIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
// clickIntent.putExtra(MESSAGE_ID, msg?.msgId)
|
||||
// clickIntent.putExtra(PUSH_ID, data?.pushId)
|
||||
// clickIntent.putExtra(NOTIFICATION_MESSAGE_ID, data?.messageId)
|
||||
// clickIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_CLICK)
|
||||
//
|
||||
// removeIntent.setClass(context, UmengMessageReceiver::class.java)
|
||||
// removeIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_REMOVE)
|
||||
// removeIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
//
|
||||
// val clickPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(),
|
||||
// clickIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
//
|
||||
// val deletePendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt() + 1,
|
||||
// removeIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
//
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// val channel = NotificationChannel("Halo_Push", "Halo_Push", NotificationManager.IMPORTANCE_DEFAULT)
|
||||
// notificationManager.createNotificationChannel(channel)
|
||||
// }
|
||||
//
|
||||
// val notification = NotificationCompat.Builder(context, "Halo_Push")
|
||||
// .setSmallIcon(R.drawable.ic_notification)
|
||||
// .setTicker(pushData.body?.ticker)
|
||||
// .setContentTitle(pushData.body?.title)
|
||||
// .setContentText(pushData.body?.text?.fromHtml())
|
||||
// .setContentIntent(clickPendingIntent)
|
||||
// .setDeleteIntent(deletePendingIntent)
|
||||
// .build()
|
||||
// notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL
|
||||
//
|
||||
// notificationManager.notify(getNotificationTag(context), NOTIFICATION_ID, notification)
|
||||
// } else {
|
||||
// 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
|
||||
//
|
||||
// val type = if (ANSWER == data?.type) {
|
||||
// "回答了你的问题"
|
||||
// } else {
|
||||
// "回答了你关注的问题"
|
||||
// }
|
||||
//
|
||||
// val userName = StringUtils.shrinkStringWithDot(data?.userEntity?.name, 8)
|
||||
// val displayText = userName + type
|
||||
//
|
||||
// if (Notifier.isActivityValid(CurrentActivityHolder.getCurrentActivity()) &&
|
||||
// Notifier.shouldShowNotifier(data?.answer?.id + displayText)) {
|
||||
// Notifier.create(CurrentActivityHolder.getCurrentActivity())
|
||||
// .setText(displayText)
|
||||
// .setDuration(5000)
|
||||
// .setIcon(data?.userEntity?.icon)
|
||||
// .setOnClickListener(View.OnClickListener {
|
||||
// val bundle = Bundle()
|
||||
// bundle.putString(EntranceUtils.KEY_ANSWER_ID, data?.answer?.id)
|
||||
// bundle.putString(EntranceUtils.KEY_ENTRANCE, EntranceUtils.ENTRANCE_UMENG)
|
||||
// bundle.putString(EntranceUtils.KEY_TO, AnswerDetailActivity::class.java.name)
|
||||
// EntranceUtils.jumpActivity(context, bundle)
|
||||
//
|
||||
// MtaHelper.onEvent("消息弹窗", type, "Does not contains any parameter.")
|
||||
//
|
||||
// // 标记已读
|
||||
// val jsonObject = JSONObject()
|
||||
// jsonObject.put("type", type)
|
||||
// val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
//
|
||||
// RetrofitManager.getInstance(application).api.postMessageRead(UserManager.getInstance().userId, data?.id, body)
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .observeOn(AndroidSchedulers.mainThread())
|
||||
// .subscribe(object : Response<ResponseBody>() {
|
||||
// override fun onResponse(response: ResponseBody?) {
|
||||
// super.onResponse(response)
|
||||
// MessageUnreadRepository.loadMessageUnreadData()
|
||||
// }
|
||||
//
|
||||
// override fun onFailure(e: HttpException?) {
|
||||
// e?.printStackTrace()
|
||||
// }
|
||||
// })
|
||||
// Notifier.hide()
|
||||
// })
|
||||
// .show(false)
|
||||
// Notifier.tagNotifierAsShowed(data?.answer?.id + displayText)
|
||||
// }
|
||||
// } else if (HALO_MESSAGE_CENTER == pushData.body?.custom) {
|
||||
// // 消息中心逻辑
|
||||
// val msg = gson.fromJson(message, PushMessageUnreadEntity::class.java)
|
||||
// val data = msg?.extra?.data
|
||||
// data?.let { MessageUnreadRepository.loadMessageUnreadData() }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 规则:最多三条消息,以旧换新
|
||||
// *
|
||||
// * @return NotificationTag
|
||||
// */
|
||||
// private fun getNotificationTag(context: Context): String {
|
||||
// val sp = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
// val edit = sp.edit()
|
||||
//
|
||||
// val timeTagMap = HashMap<Long, String>()
|
||||
// for (tag in notificationTags) {
|
||||
// val time = sp.getLong(tag, 0)
|
||||
// if (time == 0L) {
|
||||
// edit.putLong(tag, System.currentTimeMillis()).apply()
|
||||
// return tag
|
||||
// } else {
|
||||
// timeTagMap[time] = tag
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val minTime = Collections.min(timeTagMap.keys)
|
||||
// val tag = timeTagMap[minTime]
|
||||
// edit.putLong(tag, System.currentTimeMillis()).apply()
|
||||
// return if (TextUtils.isEmpty(tag)) notificationTags[0] else tag!!
|
||||
// }
|
||||
//}
|
||||
@ -4,16 +4,20 @@ import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
import com.gh.common.util.ClickUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.lightgame.utils.RuntimeUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 17/05/2017
|
||||
@ -58,6 +62,18 @@ public class BaseDialogFragment extends DialogFragment {
|
||||
public boolean onBack() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(@NonNull FragmentManager manager, @Nullable String tag) {
|
||||
Fragment fragment = manager.findFragmentByTag(tag);
|
||||
if (fragment != null) {
|
||||
FragmentTransaction transaction = manager.beginTransaction();
|
||||
transaction.show(fragment);
|
||||
transaction.commit();
|
||||
} else {
|
||||
super.show(manager, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -3,15 +3,6 @@ package com.gh.base.fragment;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CheckedTextView;
|
||||
@ -21,6 +12,7 @@ import com.gh.base.adapter.FragmentAdapter;
|
||||
import com.gh.common.view.TabIndicatorView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.normal.NormalFragment;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.lightgame.view.NoScrollableViewPager;
|
||||
@ -28,6 +20,10 @@ import com.lightgame.view.NoScrollableViewPager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
@ -83,10 +79,27 @@ public abstract class BaseFragment_TabLayout extends NormalFragment implements V
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) mCheckedIndex = getArguments().getInt(PAGE_INDEX, 0);
|
||||
mFragmentsList = new ArrayList<>();
|
||||
initFragmentList(mFragmentsList);
|
||||
mTabTitleList = new ArrayList<>();
|
||||
initTabTitleList(mTabTitleList);
|
||||
mFragmentsList = new ArrayList<>(restoreFragments());
|
||||
if (mFragmentsList.isEmpty() || mFragmentsList.size() != mTabTitleList.size()) {
|
||||
mFragmentsList.clear();
|
||||
initFragmentList(mFragmentsList);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Fragment> restoreFragments() {
|
||||
String tag = "android:switcher:" + mViewPager.getId() + ":";
|
||||
ArrayList<Fragment> fragments = new ArrayList<>();
|
||||
int childCount = mTabTitleList.size();
|
||||
for (int index = 0; index < childCount; index++) {
|
||||
Fragment fragment = getChildFragmentManager().findFragmentByTag(tag + index);
|
||||
if (fragment != null) {
|
||||
fragments.add(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
return fragments;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
package com.gh.base.fragment
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager.widget.PagerAdapter
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
@ -13,9 +11,8 @@ import com.gh.base.adapter.FragmentAdapter
|
||||
import com.gh.common.view.TabIndicatorView
|
||||
import com.gh.gamecenter.R
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||
import com.lightgame.utils.Utils
|
||||
import com.lightgame.view.NoScrollableViewPager
|
||||
import java.util.*
|
||||
|
||||
abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeListener {
|
||||
|
||||
@ -72,9 +69,15 @@ abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeL
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
super.onFragmentFirstVisible()
|
||||
mTabTitleList.clear()
|
||||
mFragmentsList.clear()
|
||||
|
||||
initFragmentList(mFragmentsList)
|
||||
initTabTitleList(mTabTitleList)
|
||||
mFragmentsList.addAll(restoreFragments())
|
||||
if (mFragmentsList.isEmpty() || mFragmentsList.size != mTabTitleList.size) {
|
||||
mFragmentsList.clear()
|
||||
initFragmentList(mFragmentsList)
|
||||
}
|
||||
|
||||
mViewPager.offscreenPageLimit = mFragmentsList.size
|
||||
mViewPager.addOnPageChangeListener(this)
|
||||
@ -95,6 +98,19 @@ abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeL
|
||||
BaseFragment_TabLayout.initTabStyle(mTabLayout, mCheckedIndex)
|
||||
}
|
||||
|
||||
private fun restoreFragments(): ArrayList<Fragment> {
|
||||
val tag = "android:switcher:${mViewPager.id}:"
|
||||
val fragments = ArrayList<Fragment>()
|
||||
val childCount = mTabTitleList.size
|
||||
for (index in 0 until childCount) {
|
||||
val fragment = childFragmentManager.findFragmentByTag("$tag$index")
|
||||
if (fragment != null) {
|
||||
fragments.add(fragment)
|
||||
}
|
||||
}
|
||||
return fragments
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
|
||||
override fun onPageSelected(position: Int) {}
|
||||
|
||||
@ -81,8 +81,13 @@ public class WaitingDialogFragment extends BaseDialogFragment {
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
dismissAllowingStateLoss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismissAllowingStateLoss() {
|
||||
mBackListener = null;
|
||||
super.dismiss();
|
||||
super.dismissAllowingStateLoss();
|
||||
}
|
||||
|
||||
public static class WaitingDialogData {
|
||||
|
||||
@ -1,23 +1,28 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.webkit.JavascriptInterface
|
||||
import androidx.annotation.Keep
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.LoginActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.Badge
|
||||
import com.gh.gamecenter.entity.MtaEvent
|
||||
import com.gh.gamecenter.entity.NotificationUgc
|
||||
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.security.BindPhoneActivity
|
||||
import com.gh.gamecenter.user.LoginTag
|
||||
import com.gh.gamecenter.user.UserRepository
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
@ -25,6 +30,8 @@ import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class DefaultJsApi(var context: Context) {
|
||||
|
||||
@ -47,7 +54,7 @@ class DefaultJsApi(var context: Context) {
|
||||
|
||||
@JavascriptInterface
|
||||
fun getUserInfo(msg: Any): String {
|
||||
return UserManager.getInstance().userInfoEntity.toJson()
|
||||
return UserManager.getInstance().userInfoEntity?.toJson() ?: ""
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
@ -66,9 +73,9 @@ class DefaultJsApi(var context: Context) {
|
||||
val userInfoEntity = UserManager.getInstance().userInfoEntity
|
||||
if (msg.toString().isNotEmpty()) {
|
||||
val badge = msg.toString().toObject() ?: Badge()
|
||||
userInfoEntity.badge = badge
|
||||
userInfoEntity?.badge = badge
|
||||
} else {
|
||||
userInfoEntity.badge = null
|
||||
userInfoEntity?.badge = null
|
||||
}
|
||||
UserManager.getInstance().userInfoEntity = userInfoEntity
|
||||
}
|
||||
@ -83,6 +90,11 @@ class DefaultJsApi(var context: Context) {
|
||||
return BuildConfig.VERSION_NAME
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getAppVersionCode(msg: Any): Int {
|
||||
return PackageUtils.getVersionCode()
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun bindWechat(msg: Any, handler: CompletionHandler<Any>) {
|
||||
context.ifLogin("浏览器") {
|
||||
@ -166,11 +178,89 @@ class DefaultJsApi(var context: Context) {
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun openNotificationSetting(msg: Any){
|
||||
NotificationHelper.show(context as AppCompatActivity)
|
||||
fun openNotificationSetting(msg: Any) {
|
||||
NotificationHelper.show(context as AppCompatActivity, NotificationUgc.LOGIN)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun useDarkStatusBarText(msg: Any) {
|
||||
runOnUiThread {
|
||||
DisplayUtils.transparentStatusBar(context as AppCompatActivity)
|
||||
DisplayUtils.setLightStatusBar(context as AppCompatActivity, msg.toString() == "true")
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun exitWebView(msg: Any) {
|
||||
runOnUiThread { (context as Activity).finish() }
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun updateRegulationTestStatus(msg: Any) {
|
||||
if (msg.toString().toLowerCase(Locale.getDefault()) == "pass") {
|
||||
SPUtils.setString(Constants.SP_REGULATION_TEST_PASS_STATUS, "pass")
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getStatusBarHeight(msg: Any): String {
|
||||
val statusBarHeight = DisplayUtils.getStatusBarHeight(context.resources)
|
||||
return "$statusBarHeight"
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getGid(msg: Any): String {
|
||||
return HaloApp.getInstance().gid
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun showIncompatibleVersionDialog(msg: Any) {
|
||||
DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun shareBase64Image(event: Any) {
|
||||
val imageShareEvent = event.toString().toObject() ?: ImageShareEvent()
|
||||
val context = CurrentActivityHolder.getCurrentActivity()
|
||||
Base64ImageHolder.image = imageShareEvent.image.run {
|
||||
if (this.startsWith("data:image/png;base64")) this.split(",")[1] else this
|
||||
}
|
||||
MessageShareUtils.getInstance(context).shareFromWeb(context, imageShareEvent.type)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun bindPhone(msg: Any) {
|
||||
val intent = BindPhoneActivity.getNormalIntent(context, false)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun updateTitle(msg: Any) {
|
||||
if (context is WebActivity) {
|
||||
runOnUiThread { (context as WebActivity).setNavigationTitle(msg.toString()) }
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun logoutExitWebViewAndRedirectToLogin() {
|
||||
UserRepository.getInstance(context).logout()
|
||||
if (context is Activity) {
|
||||
AppExecutor.uiExecutor.executeWithDelay(Runnable {
|
||||
context.ifLogin("内部网页")
|
||||
(context as Activity).finish()
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun openInNewWebview(url: Any) {
|
||||
runOnUiThread { DirectUtils.directToWebView(context, url.toString(), "内部网页") }
|
||||
}
|
||||
|
||||
@Keep
|
||||
internal data class ImageEvent(var imageList: ArrayList<String> = arrayListOf(), var position: Int = 0)
|
||||
|
||||
@Keep
|
||||
internal data class ImageShareEvent(var image: String = "", var type: String = "")
|
||||
|
||||
}
|
||||
|
||||
@ -4,19 +4,25 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import android.util.Base64
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DirectUtils.directToFeedback
|
||||
import com.gh.common.util.DirectUtils.directToGameDetailVideoStreaming
|
||||
import com.gh.common.util.DirectUtils.directToGameServerCalendar
|
||||
import com.gh.common.util.DirectUtils.directToGameVideo
|
||||
import com.gh.common.util.DirectUtils.directToLinkPage
|
||||
import com.gh.common.util.DirectUtils.directToQa
|
||||
import com.gh.common.util.DirectUtils.directToVideoDetail
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity
|
||||
import com.gh.common.util.GsonUtils.gson
|
||||
import com.gh.gamecenter.LibaoDetailActivity
|
||||
import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.lightgame.utils.Utils
|
||||
import java.nio.charset.Charset
|
||||
|
||||
object DefaultUrlHandler {
|
||||
|
||||
@ -36,7 +42,7 @@ object DefaultUrlHandler {
|
||||
when (host) {
|
||||
"article" -> context.startActivity(NewsDetailActivity.getIntentById(context, id, entrance))
|
||||
|
||||
"game" -> GameDetailActivity.startGameDetailActivity(context, id, "libao" == uri.getQueryParameter("to"), entrance)
|
||||
"game" -> DirectUtils.directToGameDetail(context, id = id, tab = uri.getQueryParameter("to"), autoDownload = uri.getQueryParameter("auto_download") == "true", entrance = entrance)
|
||||
|
||||
"column" -> SubjectActivity.startSubjectActivity(context, id, uri.getQueryParameter("name"), false, entrance)
|
||||
|
||||
@ -123,9 +129,11 @@ object DefaultUrlHandler {
|
||||
val title = if (titleParameter.isNullOrEmpty()) "" else "#$titleParameter#"
|
||||
val categoryId = uri.getQueryParameter("category_id") ?: ""
|
||||
val link = uri.getQueryParameter("link") ?: ""
|
||||
val linkEntity = VideoLinkEntity(title, categoryId, link)
|
||||
val gameId = uri.getQueryParameter("gameId") ?: ""
|
||||
val gameName = uri.getQueryParameter("gameName") ?: ""
|
||||
val tagActivityId = uri.getQueryParameter("tagActivityId") ?: ""
|
||||
val tagActivityName = uri.getQueryParameter("tagActivityName") ?: ""
|
||||
val linkEntity = VideoLinkEntity(title, categoryId, link, tagActivityId, tagActivityName)
|
||||
val simpleGameEntity = SimpleGameEntity(gameId, gameName)
|
||||
CheckLoginUtils.checkLogin(context, null, true, EntranceUtils.ENTRANCE_BROWSER) {
|
||||
DirectUtils.directToVideoManager(context, linkEntity, simpleGameEntity, EntranceUtils.ENTRANCE_BROWSER, "")
|
||||
@ -142,6 +150,8 @@ object DefaultUrlHandler {
|
||||
val gameId = uri.getQueryParameter("gameId") ?: ""
|
||||
val fieldId = uri.getQueryParameter("fieldId") ?: ""
|
||||
val sectionName = uri.getQueryParameter("sectionName") ?: ""
|
||||
val paginationType = uri.getQueryParameter("paginationType")
|
||||
?: "page"//活动分页方式 page filter
|
||||
val location = if (!TextUtils.isEmpty(act)) {
|
||||
VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.value
|
||||
} else if (!TextUtils.isEmpty(fieldId)) {
|
||||
@ -149,7 +159,7 @@ object DefaultUrlHandler {
|
||||
} else {
|
||||
id
|
||||
}
|
||||
directToVideoDetail(context, id, location, false, gameId, entrance, "", referer, type, act, fieldId, sectionName)
|
||||
directToVideoDetail(context, id, location, false, gameId, entrance, "", referer, type, act, paginationType, fieldId, sectionName)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_SINGLE -> {
|
||||
val referer = uri.getQueryParameter("referer") ?: ""
|
||||
@ -230,6 +240,73 @@ object DefaultUrlHandler {
|
||||
DirectUtils.directGameZone(context, id, zoneUrl, entrance)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_LINK -> {
|
||||
try {
|
||||
val dataString = uri.getQueryParameter("data")
|
||||
if (!TextUtils.isEmpty(dataString)) {
|
||||
val linkData = Base64.decode(dataString, Base64.DEFAULT)
|
||||
val linkDataString = String(linkData, Charset.defaultCharset())
|
||||
val le = gson.fromJson(linkDataString, LinkEntity::class.java)
|
||||
directToLinkPage(context, le, entrance, "")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_NEWS -> {
|
||||
DirectUtils.directToGameNews(
|
||||
context,
|
||||
uri.getQueryParameter(EntranceUtils.KEY_GAME_ID),
|
||||
uri.getQueryParameter(EntranceUtils.KEY_GAME_NAME),
|
||||
entrance);
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_CALENDAR -> {
|
||||
directToGameServerCalendar(context, uri.getQueryParameter(EntranceUtils.KEY_GAME_ID))
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_HISTORY_APK -> {
|
||||
DirectUtils.directToHistoryApk(context, uri.getQueryParameter(EntranceUtils.KEY_GAME_ID))
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_FORUM_DETAIL -> {
|
||||
DirectUtils.directForumDetail(context, id, entrance)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_RATING_DETAIL -> {
|
||||
DirectUtils.directToGameRatingDetail(context, uri.getQueryParameter(EntranceUtils.KEY_GAME_ID), uri.getQueryParameter(EntranceUtils.KEY_COMMENT_ID), EntranceUtils.ENTRANCE_BROWSER)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_FORUM -> {
|
||||
DirectUtils.directToForum(context)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_SUGGESTION -> {
|
||||
val platform = uri.getQueryParameter(EntranceUtils.KEY_PLATFORM)
|
||||
val platformName = PlatformUtils.getInstance(context).getPlatformName(platform)
|
||||
val gameId = uri.getQueryParameter(EntranceUtils.KEY_GAMEID)
|
||||
val packageMd5 = uri.getQueryParameter(EntranceUtils.KEY_PACKAGE_MD5)
|
||||
val content = if (TextUtils.isEmpty(gameId) || TextUtils.isEmpty(packageMd5)) String.format("%s-%s-V%s,",
|
||||
uri.getQueryParameter(EntranceUtils.KEY_GAME_NAME),
|
||||
if (TextUtils.isEmpty(platformName)) platform else platformName,
|
||||
uri.getQueryParameter(EntranceUtils.KEY_VERSION)) else String.format("%s-%s-V%s\n游戏ID:%s\n游戏包MD5:%s\n",
|
||||
uri.getQueryParameter(EntranceUtils.KEY_GAME_NAME),
|
||||
if (TextUtils.isEmpty(platformName)) platform else platformName,
|
||||
uri.getQueryParameter(EntranceUtils.KEY_VERSION), gameId, packageMd5)
|
||||
val qaId = uri.getQueryParameter("qa_id") ?: ""
|
||||
val qaTitle = uri.getQueryParameter(EntranceUtils.KEY_QA_TITLE)
|
||||
if (!TextUtils.isEmpty(qaId)) {
|
||||
directToQa(context, qaTitle, qaId)
|
||||
} else {
|
||||
directToFeedback(context, content, EntranceUtils.ENTRANCE_BROWSER)
|
||||
}
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_HELP_AND_FEEDBACK -> {
|
||||
val position = uri.getQueryParameter("position") ?: ""
|
||||
DirectUtils.directToHelpAndFeedback(context, position.toInt())
|
||||
}
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
return true
|
||||
@ -274,13 +351,17 @@ object DefaultUrlHandler {
|
||||
@JvmStatic
|
||||
fun transformNormalScheme(context: Context, url: String, entrance: String): Boolean {
|
||||
val uri = Uri.parse(url)
|
||||
if (uri.host == "www.ghzs666.com" || uri.host == "www.ghzs.com" || uri.host == "ask.ghzs.com" || uri.host == "m.ghzs.com") {
|
||||
if (uri.host == "www.ghzs666.com"
|
||||
|| uri.host == "www.ghzs.com"
|
||||
|| uri.host == "ask.ghzs.com"
|
||||
|| uri.host == "m.ghzs.com"
|
||||
|| uri.host == "m.ghzs666.com") {
|
||||
Utils.log(uri.path)
|
||||
uri.path?.apply {
|
||||
when {
|
||||
contains("game") -> {
|
||||
val gameId = uri.getQueryParameter("gameId") ?: ""
|
||||
DirectUtils.directToGameDetail(context, gameId, entrance, autoDownload = false, scrollToLibao = false, traceEvent = null)
|
||||
DirectUtils.directToGameDetail(context, gameId, entrance, autoDownload = false, traceEvent = null)
|
||||
}
|
||||
contains("question") -> {
|
||||
val questionId = split("/")[2]
|
||||
|
||||
@ -4,7 +4,9 @@ import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.loghub.LoghubUtils
|
||||
import com.gh.common.util.doOnMainProcessOnly
|
||||
import com.gh.common.util.tryCatchInRelease
|
||||
import com.gh.common.videolog.VideoRecordUtils
|
||||
import com.gh.download.DownloadDataHelper
|
||||
import com.gh.gamecenter.entity.TimeEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -12,13 +14,16 @@ import com.halo.assistant.HaloApp
|
||||
import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
object FixedRateJobHelper {
|
||||
private const val CHECKER_PERIOD: Long = 60 * 1000L
|
||||
private const val CHECKER_PERIOD: Long = 15 * 1000L
|
||||
private const val TIME_PERIOD: Long = 600 * 1000L
|
||||
private const val LOGHUB_PERIOD: Long = 120 * 1000L
|
||||
private const val EXPOSURE_PERIOD: Long = 300 * 1000L
|
||||
private const val REGION_SETTING_PERIOD: Long = 300 * 1000L
|
||||
private const val VIDEO_RECORD_PERIOD: Long = 60 * 1000L
|
||||
|
||||
private const val DOWNLOAD_HEARTBEAT_PERIOD: Long = 60 * 1000L
|
||||
private const val DOWNLOAD_HEARTBEAT_SHEET_PERIOD: Long = 15 * 1000L
|
||||
|
||||
private var mExecuteCount: Int = 0
|
||||
|
||||
var timeDeltaBetweenServerAndClient: Long = 0
|
||||
@ -44,6 +49,14 @@ object FixedRateJobHelper {
|
||||
ExposureManager.commitSavedExposureEvents(true)
|
||||
}
|
||||
|
||||
// 分片检测下载进度
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_SHEET_PERIOD == 0L) {
|
||||
tryCatchInRelease {
|
||||
val upload = (mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_PERIOD == 0L
|
||||
DownloadDataHelper.uploadDownloadHeartbeat(upload)
|
||||
}
|
||||
}
|
||||
|
||||
// 提交普通 loghub 数据
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % LOGHUB_PERIOD == 0L) {
|
||||
LoghubUtils.commitSavedLoghubEvents()
|
||||
@ -51,7 +64,9 @@ object FixedRateJobHelper {
|
||||
|
||||
// 更新游戏屏蔽信息
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % REGION_SETTING_PERIOD == 0L) {
|
||||
RegionSettingHelper.getRegionSetting()
|
||||
if (HaloApp.getInstance().isRunningForeground) {
|
||||
RegionSettingHelper.getRegionSetting()
|
||||
}
|
||||
}
|
||||
|
||||
// 提交视频浏览记录数据
|
||||
|
||||
@ -1,39 +1,39 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.gh.common.im.ImManager
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.m7.imkfsdk.chat.ChatActivity
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
/**
|
||||
* 可使用 [LocalBroadcastManager] 来进行简单的模块间消息通知
|
||||
*/
|
||||
|
||||
class LocalBroadcastReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
intent?.let {
|
||||
when (intent.action) {
|
||||
ChatActivity.ACTION_DISMISS_FLOATING_WINDOW -> {
|
||||
ImManager.dismissFloatingWindow()
|
||||
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api.postImEnding(UserManager.getInstance().userId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
ChatActivity.ACTION_HIDE_UNREAD_DOT -> {
|
||||
ImManager.updateShouldShowFloatingWindowDot(false)
|
||||
}
|
||||
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//package com.gh.common
|
||||
//
|
||||
//import android.content.BroadcastReceiver
|
||||
//import android.content.Context
|
||||
//import android.content.Intent
|
||||
//import com.gh.common.im.ImManager
|
||||
//import com.gh.gamecenter.manager.UserManager
|
||||
//import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
//import com.halo.assistant.HaloApp
|
||||
//import com.m7.imkfsdk.chat.ChatActivity
|
||||
//import io.reactivex.schedulers.Schedulers
|
||||
//
|
||||
///**
|
||||
// * 可使用 [LocalBroadcastManager] 来进行简单的模块间消息通知
|
||||
// */
|
||||
//
|
||||
//class LocalBroadcastReceiver : BroadcastReceiver() {
|
||||
//
|
||||
// override fun onReceive(context: Context?, intent: Intent?) {
|
||||
// intent?.let {
|
||||
// when (intent.action) {
|
||||
// ChatActivity.ACTION_DISMISS_FLOATING_WINDOW -> {
|
||||
// ImManager.dismissFloatingWindow()
|
||||
//
|
||||
// RetrofitManager.getInstance(HaloApp.getInstance().application).api.postImEnding(UserManager.getInstance().userId)
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .subscribe()
|
||||
// }
|
||||
//
|
||||
// ChatActivity.ACTION_HIDE_UNREAD_DOT -> {
|
||||
// ImManager.updateShouldShowFloatingWindowDot(false)
|
||||
// }
|
||||
//
|
||||
// else -> return
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
@ -1,29 +1,8 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.preference.PreferenceManager
|
||||
import com.gh.base.GHUmengNotificationService
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.exposure.meta.MetaUtil
|
||||
import com.gh.common.util.edit
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.entity.AliasEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import com.umeng.commonsdk.UMConfigure
|
||||
import com.umeng.message.IUmengRegisterCallback
|
||||
import com.umeng.message.PushAgent
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import org.android.agoo.huawei.HuaWeiRegister
|
||||
import org.android.agoo.mezu.MeizuRegister
|
||||
import org.android.agoo.xiaomi.MiPushRegistar
|
||||
import org.json.JSONObject
|
||||
|
||||
object PushManager {
|
||||
|
||||
@ -36,102 +15,103 @@ object PushManager {
|
||||
|
||||
@JvmStatic
|
||||
fun init(channel: String) {
|
||||
tryWithDefaultCatch {
|
||||
//初始化友盟推送
|
||||
UMConfigure.init(mApplication, Config.UMENG_APPKEY, channel, UMConfigure.DEVICE_TYPE_PHONE, Config.UMENG_MESSAGE_SECRET)
|
||||
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
|
||||
runOnIoThread { registerDevice() }
|
||||
|
||||
// 注册小米、华为和魅族通道
|
||||
MiPushRegistar.register(mApplication, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
|
||||
HuaWeiRegister.register(mApplication)
|
||||
MeizuRegister.register(mApplication, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
|
||||
|
||||
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(mApplication).getString(SP_PUSH_ALIAS, "")
|
||||
mPreviousAlias = aliasInSp?.toObject()
|
||||
|
||||
if (mPreviousAlias == null) {
|
||||
getAndSetAlias()
|
||||
}
|
||||
|
||||
// 完全自定义处理(透传)
|
||||
pushAgent.setPushIntentServiceClass(GHUmengNotificationService::class.java)
|
||||
}
|
||||
// tryWithDefaultCatch {
|
||||
// //初始化友盟推送
|
||||
// UMConfigure.init(mApplication, Config.UMENG_APPKEY, channel, UMConfigure.DEVICE_TYPE_PHONE, Config.UMENG_MESSAGE_SECRET)
|
||||
//
|
||||
// val pushAgent = PushAgent.getInstance(mApplication)
|
||||
//
|
||||
// runOnIoThread { registerDevice() }
|
||||
//
|
||||
// // 注册小米、华为和魅族通道
|
||||
// MiPushRegistar.register(mApplication, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
|
||||
// HuaWeiRegister.register(mApplication)
|
||||
// MeizuRegister.register(mApplication, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
|
||||
//
|
||||
// val aliasInSp = PreferenceManager.getDefaultSharedPreferences(mApplication).getString(SP_PUSH_ALIAS, "")
|
||||
// mPreviousAlias = aliasInSp?.toObject()
|
||||
//
|
||||
// if (mPreviousAlias == null) {
|
||||
// getAndSetAlias()
|
||||
// }
|
||||
//
|
||||
// // 完全自定义处理(透传)
|
||||
// pushAgent.setPushIntentServiceClass(GHUmengNotificationService::class.java)
|
||||
// }
|
||||
}
|
||||
|
||||
private fun registerDevice() {
|
||||
PushAgent.getInstance(mApplication).register(object : IUmengRegisterCallback {
|
||||
override fun onSuccess(dToken: String) {
|
||||
//注册成功会返回device token
|
||||
deviceToken = dToken
|
||||
getAndSetAlias()
|
||||
Utils.log("deviceToken::$dToken")
|
||||
}
|
||||
|
||||
override fun onFailure(s: String, s1: String) {
|
||||
Utils.log("deviceToken::" + "注册失败")
|
||||
}
|
||||
})
|
||||
// PushAgent.getInstance(mApplication).register(object : IUmengRegisterCallback {
|
||||
// override fun onSuccess(dToken: String) {
|
||||
// //注册成功会返回device token
|
||||
// deviceToken = dToken
|
||||
// getAndSetAlias()
|
||||
// Utils.log("deviceToken::$dToken")
|
||||
// }
|
||||
//
|
||||
// override fun onFailure(s: String, s1: String) {
|
||||
// Utils.log("deviceToken::" + "注册失败")
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun getAndSetAlias() {
|
||||
if (deviceToken.isNullOrEmpty()) {
|
||||
registerDevice()
|
||||
return
|
||||
}
|
||||
|
||||
val meta = MetaUtil.getMeta()
|
||||
|
||||
val jsonObject = JSONObject()
|
||||
jsonObject.put("device_token", deviceToken)
|
||||
jsonObject.put("imei", meta.imei)
|
||||
jsonObject.put("android_id", meta.android_id)
|
||||
jsonObject.put("model", meta.model)
|
||||
jsonObject.put("manufacturer", meta.manufacturer)
|
||||
jsonObject.put("os", meta.os)
|
||||
jsonObject.put("os_version", meta.android_version)
|
||||
jsonObject.put("mac", meta.mac)
|
||||
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
|
||||
RetrofitManager.getInstance(mApplication).api.getAlias(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(
|
||||
{ setAlias(it) },
|
||||
{ it.printStackTrace() }
|
||||
)
|
||||
// if (deviceToken.isNullOrEmpty()) {
|
||||
// registerDevice()
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// val meta = MetaUtil.getMeta()
|
||||
//
|
||||
// val jsonObject = JSONObject()
|
||||
// jsonObject.put("device_token", deviceToken)
|
||||
// jsonObject.put("imei", meta.imei)
|
||||
// jsonObject.put("android_id", meta.android_id)
|
||||
// jsonObject.put("model", meta.model)
|
||||
// jsonObject.put("manufacturer", meta.manufacturer)
|
||||
// jsonObject.put("os", meta.os)
|
||||
// jsonObject.put("os_version", meta.android_version)
|
||||
// jsonObject.put("mac", meta.mac)
|
||||
// jsonObject.put("gid", meta.gid)
|
||||
//
|
||||
// val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
//
|
||||
// RetrofitManager.getInstance(mApplication).api.getAlias(body)
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .subscribe(
|
||||
// { setAlias(it) },
|
||||
// { it.printStackTrace() }
|
||||
// )
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setAlias(alias: AliasEntity) {
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
|
||||
mPreviousAlias = alias
|
||||
PreferenceManager.getDefaultSharedPreferences(mApplication).edit {
|
||||
putString(SP_PUSH_ALIAS, mPreviousAlias?.toJson())
|
||||
}
|
||||
|
||||
pushAgent.setAlias(alias.alias, alias.aliasType) { b, s ->
|
||||
Utils.log("注册别名 $b + $s")
|
||||
}
|
||||
// val pushAgent = PushAgent.getInstance(mApplication)
|
||||
//
|
||||
// mPreviousAlias = alias
|
||||
// PreferenceManager.getDefaultSharedPreferences(mApplication).edit {
|
||||
// putString(SP_PUSH_ALIAS, mPreviousAlias?.toJson())
|
||||
// }
|
||||
//
|
||||
// pushAgent.setAlias(alias.alias, alias.aliasType) { b, s ->
|
||||
// Utils.log("注册别名 $b + $s")
|
||||
// }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun deleteAlias() {
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
|
||||
mPreviousAlias?.let {
|
||||
pushAgent.deleteAlias(it.alias, it.aliasType) { b, s ->
|
||||
Utils.log("删除别名 $b + $s")
|
||||
}
|
||||
}
|
||||
PreferenceManager.getDefaultSharedPreferences(mApplication).edit {
|
||||
putString(SP_PUSH_ALIAS, "")
|
||||
}
|
||||
mPreviousAlias = null
|
||||
// val pushAgent = PushAgent.getInstance(mApplication)
|
||||
//
|
||||
// mPreviousAlias?.let {
|
||||
// pushAgent.deleteAlias(it.alias, it.aliasType) { b, s ->
|
||||
// Utils.log("删除别名 $b + $s")
|
||||
// }
|
||||
// }
|
||||
// PreferenceManager.getDefaultSharedPreferences(mApplication).edit {
|
||||
// putString(SP_PUSH_ALIAS, "")
|
||||
// }
|
||||
// mPreviousAlias = null
|
||||
}
|
||||
}
|
||||
3
app/src/main/java/com/gh/common/Typealias.kt
Normal file
3
app/src/main/java/com/gh/common/Typealias.kt
Normal file
@ -0,0 +1,3 @@
|
||||
package com.gh.common
|
||||
|
||||
typealias OnFastClickListener = (isSuccess: Boolean) -> Unit
|
||||
@ -5,8 +5,6 @@ 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;
|
||||
@ -25,6 +23,7 @@ import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
@ -51,6 +50,8 @@ public class Config {
|
||||
public static final String BUGLY_APPID = BuildConfig.BUGLY_APPID;
|
||||
public static final String LETO_APPID = BuildConfig.LETO_APPID;
|
||||
public static final String TTAD_APPID = BuildConfig.TTAD_APPID;
|
||||
public static final String DOUYIN_CLIENTKEY = BuildConfig.DOUYIN_CLIENTKEY;
|
||||
public static final String DOUYIN_CLIENTSECRET = BuildConfig.DOUYIN_CLIENTSECRET;
|
||||
// http://www.ghzs666.com/article/${articleId}.html
|
||||
public static final String URL_ARTICLE = "http://www.ghzs666.com/article/"; // ghzs/ghzs666 统一
|
||||
public static final String PATCHES = "patches";
|
||||
@ -239,6 +240,9 @@ public class Config {
|
||||
public static boolean isGameDomeSwitchOpen() {
|
||||
return getSettings() != null && getSettings().getGameDomeSwitch().equals("on");
|
||||
}
|
||||
public static boolean isPermissionPopupSwitchOpen() {
|
||||
return getSettings() != null && getSettings().getPermissionPopupSwitch().equals("on");
|
||||
}
|
||||
|
||||
public static void fixHideFunction() {
|
||||
SharedPreferences preferences = PreferenceManager.
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.constant;
|
||||
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.halo.assistant.HaloApp;
|
||||
|
||||
public class Constants {
|
||||
|
||||
@ -48,9 +49,19 @@ public class Constants {
|
||||
public static final String RAW_GAME_ICON = "raw_game_icon";
|
||||
public static final String GAME_ICON_SUBSCRIPT = "game_icon_subscript";
|
||||
|
||||
public static final String EXTRA_DOWNLOAD_TYPE = "extra_download_type";
|
||||
public static final String SILENT_UPDATE = "静默更新";
|
||||
public static final String SIMULATOR_DOWNLOAD = "下载模拟器";
|
||||
public static final String SIMULATOR_GAME = "simulator_game";
|
||||
public static final String SIMULATOR_DOWNLOAD_START_TIME = "simulator_download_start_time";
|
||||
public static final String LAST_GHZS_UPDATE_FILE_SIZE = "last_ghzs_update_file_size";
|
||||
|
||||
// 新用户首次启动光环的时间
|
||||
public static final String SP_INITIAL_USAGE_TIME = "initial_usage_time";
|
||||
|
||||
public static final String SP_IMEI = "imei";
|
||||
public static final String SP_ANDROID_ID = "android_id";
|
||||
|
||||
//引导设置 “通知管理” 引导弹窗
|
||||
public static final String SP_SHOWED_NOTIFICATION_LOGIN = "show_notification_login_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_QUESTION = "show_notification_question_hint";
|
||||
@ -58,6 +69,9 @@ public class Constants {
|
||||
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_GIFT = "show_notification_gift_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_RESERVE_GAME = "show_notification_reserve_game_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_FEEDBACK = "show_notification_feedback_hint";
|
||||
// 新版本 也要触发一次“通知管理” 引导弹窗
|
||||
public static final String SP_SHOWED_NOTIFICATION_NEW_VERSION = "show_notification_new_version";
|
||||
// 今天是否已经触发了 “通知管理” 引导弹窗
|
||||
@ -96,6 +110,30 @@ public class Constants {
|
||||
public static final String SP_TOP_VIDEO_SCHEDULE = "top_video_schedule";
|
||||
//我的光环小红点提示
|
||||
public static final String SP_GH_RED_POINT_REMIND = "gh_red_point_remind";
|
||||
//论坛首页引导
|
||||
public static final String SP_FORUM_GUIDE = "forum_guide";
|
||||
//礼仪考试开启状态
|
||||
public static final String SP_REGULATION_TEST_LAST_REMIND_TIME = "regulation_test_last_remind_time";
|
||||
public static final String SP_REGULATION_TEST_STATUS = "regulation_test_status";
|
||||
public static final String SP_REGULATION_TEST_PASS_STATUS = "regulation_test_pass_status";
|
||||
//相同设备号,每一种第三方登录方式登录后弹出绑定手机页面的次数
|
||||
public static final String SP_QQ_SHOW_BIND_PHONE_TIME = "qq_show_bind_phone_time" + HaloApp.getInstance().getGid();
|
||||
public static final String SP_WECHAT_SHOW_BIND_PHONE_TIME = "wechat_show_bind_phone_time" + HaloApp.getInstance().getGid();
|
||||
public static final String SP_WEIBO_SHOW_BIND_PHONE_TIME = "weibo_show_bind_phone_time" + HaloApp.getInstance().getGid();
|
||||
public static final String SP_DOUYIN_SHOW_BIND_PHONE_TIME = "douyin_show_bind_phone_time" + HaloApp.getInstance().getGid();
|
||||
//隐私政策是否有更新
|
||||
public static final String SP_PRIVACY_CURRENT_MD5 = "sp_privacy_current_md5";
|
||||
public static final String SP_PRIVACY_MINE_MD5 = "sp_privacy_mine_md5";
|
||||
public static final String SP_PRIVACY_SETTING_MD5 = "sp_privacy_setting_md5";
|
||||
public static final String SP_PRIVACY_MD5 = "sp_privacy_md5";
|
||||
|
||||
public static final String SP_IS_USER_ACCEPTED_PRIVACY_STATEMENT = "has_user_accepted_privacy_statement";
|
||||
public static final String SP_BRAND_NEW_USER = "brand_new_user";
|
||||
//包名检测是否点击不再提示
|
||||
public static final String SP_PACKAGE_CHECK = "package_check";
|
||||
|
||||
public static final String SP_XAPK_UNZIP_ACTIVITY = "xapk_unzip_activity";
|
||||
public static final String SP_XAPK_URL = "xapk_url";
|
||||
|
||||
//手机号码匹配规则
|
||||
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
|
||||
@ -105,16 +143,39 @@ 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 String REGULATION_TEST_ADDRESS_DEV = "https://static-web.ghzs.com/etiquette-dev/index.html#/";
|
||||
public static final String REGULATION_TEST_ADDRESS = "https://static-web.ghzs.com/etiquette/index.html#/";
|
||||
|
||||
// 徽章中心
|
||||
public static final String BADGE_ADDRESS_DEV = "https://static-web.ghzs.com/badge-dev/index.html#/";
|
||||
public static final String BADGE_ADDRESS = "https://static-web.ghzs.com/badge/index.html#/";
|
||||
|
||||
// 徽章详情
|
||||
public static final String BADGE_DETAIL_ADDRESS_DEV = "https://static-web.ghzs.com/badge-dev/index.html#/badgedetail";
|
||||
public static final String BADGE_DETAIL_ADDRESS = "https://static-web.ghzs.com/badge/index.html#/badgedetail";
|
||||
|
||||
// 分享个人主页地址
|
||||
public static final String SHARE_USER_HOME_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs-userhome-dev/index.html#/";
|
||||
public static final String SHARE_USER_HOME_ADDRESS = "https://static-web.ghzs.com/ghzs-userhome/index.html#/";
|
||||
|
||||
// 腾讯企点地址
|
||||
public static final String TENCENT_QIDIAN_ADDRESS = "https://url.cn/D80iyMVV?_type=wpa&qidian=true";
|
||||
public static final String TENCENT_QIDIAN_ADDRESS = "https://admin.qidian.qq.com/template/blue/mp/menu/qr-code-jump.html?linkType=0&env=ol&kfuin=2355094296&fid=457&key=c76dcb2e3d582b6ffbfb5bb22cde85ff&cate=1&source=&isLBS=&isCustomEntry=&type=16&ftype=1&_type=wpa&qidian=true";
|
||||
|
||||
//版规声明
|
||||
public static final String FORUM_REGULATIONS_NEWS_ID = "5f4db9cc34d44d01b92fd670";
|
||||
|
||||
//帮助内容详情
|
||||
public static final String HELP_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs_help_dev/help.html?content=";
|
||||
public static final String HELP_ADDRESS = "https://static-web.ghzs.com/ghzs_help/help.html?content=";
|
||||
|
||||
// 注销页面
|
||||
public static final String LOGOUT_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs_help_dev/help.html?content=5f6b1f02786564003944a693";
|
||||
public static final String LOGOUT_ADDRESS = "https://static-web.ghzs.com/ghzs_help/help.html?content=5f534111b1f72909fc225672";
|
||||
|
||||
//最少需要多少数据才能上传
|
||||
public static final int DATA_AMOUNT = 20;
|
||||
|
||||
@ -32,6 +32,9 @@ public class ItemViewType {
|
||||
public static final int IMAGE_SLIDE_ITEM = 23;
|
||||
public static final int VERTICAL_SLIDE_ITEM = 24;
|
||||
public static final int COLUMN_COLLECTION = 25;
|
||||
public static final int GALLERY_SLIDE = 27; // 首页自动滚动画廊专题
|
||||
public static final int GALLERY = 28; // 首页倾斜画廊专题
|
||||
public static final int BLANK_DIVIDER = 29; // 空白补充区域
|
||||
|
||||
/**
|
||||
* 普通列表
|
||||
|
||||
@ -24,10 +24,13 @@ import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.OnViewClickListener;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.CertificationDialog;
|
||||
import com.gh.common.dialog.PackageCheckDialogFragment;
|
||||
import com.gh.common.dialog.ReserveDialogFragment;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.common.simulator.SimulatorDownloadManager;
|
||||
import com.gh.common.simulator.SimulatorGameManager;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
@ -42,7 +45,6 @@ import com.gh.common.util.NewsUtils;
|
||||
import com.gh.common.util.NumberUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PermissionHelper;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.common.view.DownloadProgressBar;
|
||||
@ -72,6 +74,7 @@ import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -253,6 +256,14 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lazy 的 paddingTop
|
||||
*/
|
||||
@BindingAdapter("lazyPaddingLeft")
|
||||
public static void lazyPaddingLeft(View view, int paddingLeftInDp) {
|
||||
view.setPadding(DisplayUtils.dip2px(paddingLeftInDp), view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom());
|
||||
}
|
||||
|
||||
/**
|
||||
* lazy 的 paddingTop
|
||||
*/
|
||||
@ -318,7 +329,7 @@ public class BindingAdapters {
|
||||
@BindingAdapter("game")
|
||||
public static void setGame(View view, GameEntity gameEntity) {
|
||||
if (gameEntity != null && view instanceof GameIconView) {
|
||||
((GameIconView) view).setGameEntity(gameEntity);
|
||||
((GameIconView) view).displayGameIcon(gameEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,12 +447,23 @@ public class BindingAdapters {
|
||||
case PLUGIN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
ApkEntity apk = gameEntity.getApk().get(0);
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(v.getContext(), gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showOverseaDownloadDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apk.getUrl());
|
||||
if (gameEntity.getSimulator() != null) {
|
||||
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(v.getContext(), gameEntity.getSimulator().getApk().getPackageName());
|
||||
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(gameEntity) && !isInstalled) {
|
||||
SimulatorDownloadManager.getInstance().showDownloadDialog(v.getContext(), gameEntity.getSimulator(),
|
||||
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.getId(), gameEntity.getName(), null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
PackageCheckDialogFragment.show((AppCompatActivity) v.getContext(), gameEntity.getPackageDialog(), () -> {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(v.getContext(), gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showOverseaDownloadDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -461,6 +483,20 @@ public class BindingAdapters {
|
||||
break;
|
||||
case LAUNCH_OR_OPEN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
//启动模拟器游戏
|
||||
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
|
||||
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
|
||||
if (downloadEntity != null) {
|
||||
File file = new File(downloadEntity.getPath());
|
||||
if (!file.exists()) {
|
||||
download(progressBar, gameEntity, traceEvent, false, entrance, location);
|
||||
return;
|
||||
}
|
||||
|
||||
SimulatorGameManager.launchSimulatorGame(downloadEntity, gameEntity);
|
||||
}
|
||||
return;
|
||||
}
|
||||
DataUtils.onGameLaunchEvent(v.getContext(), gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), location);
|
||||
PackageUtils.launchApplicationByPackageName(v.getContext(), gameEntity.getApk().get(0).getPackageName());
|
||||
} else {
|
||||
@ -483,13 +519,11 @@ public class BindingAdapters {
|
||||
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");
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(gameEntity, () -> {
|
||||
LogUtils.logReservation(gameEntity, traceEvent);
|
||||
updateReservation(progressBar, gameEntity);
|
||||
});
|
||||
dialogFragment.show(((AppCompatActivity) progressBar.getContext()).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
break;
|
||||
case RESERVED:
|
||||
@ -516,9 +550,12 @@ public class BindingAdapters {
|
||||
HistoryHelper.insertGameEntity(gameEntity);
|
||||
}
|
||||
|
||||
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), isPlay,linkEntity.getCloseButton()));
|
||||
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), isPlay, linkEntity.getCloseButton()));
|
||||
progressBar.getContext().startActivity(i);
|
||||
break;
|
||||
case UPDATING:
|
||||
Utils.toast(progressBar.getContext(), "正在加急更新版本,敬请后续留意");
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@ -548,10 +585,14 @@ public class BindingAdapters {
|
||||
} else {
|
||||
if (offStatus != null && "dialog".equals(offStatus)) {
|
||||
progressBar.setText("查看");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
} else if ("updating".equals(offStatus)) {
|
||||
progressBar.setText("更新中");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.UPDATING);
|
||||
} else {
|
||||
progressBar.setText("暂无");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -26,21 +26,12 @@ import com.gh.gamecenter.UserInfoEditActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.AuthDialogEntity
|
||||
import com.gh.gamecenter.entity.AuthDialogLevel
|
||||
import com.gh.gamecenter.entity.DeviceDialogEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.user.UserViewModel
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.fragment.user.UserInfoEditFragment
|
||||
import com.lightgame.utils.AppManager
|
||||
import com.tencent.bugly.beta.tinker.TinkerManager.getApplication
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.HttpException
|
||||
|
||||
class CertificationDialog(context: Context, private val authDialogEntity: AuthDialogEntity, val gameId: String, val listener: DialogUtils.ConfirmListener) :
|
||||
Dialog(context, R.style.GhAlertDialog) {
|
||||
@ -127,7 +118,9 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi
|
||||
|
||||
//跳转登录页面
|
||||
private fun gotoLoginPage() {
|
||||
CheckLoginUtils.checkLogin(AppManager.getInstance().currentActivity() as AppCompatActivity,
|
||||
val currentActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
|
||||
CheckLoginUtils.checkLogin(currentActivity as AppCompatActivity,
|
||||
null, true, "实名认证弹窗") {
|
||||
if (UserManager.getInstance().isAuth) {
|
||||
listener.onConfirm()
|
||||
@ -138,7 +131,9 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi
|
||||
|
||||
//跳转实名认证页面
|
||||
private fun gotoAuthPage() {
|
||||
AvoidOnResultManager.getInstance(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
val currentActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
|
||||
AvoidOnResultManager.getInstance(currentActivity as AppCompatActivity)
|
||||
.startForResult(UserInfoEditActivity.getIntent(context, UserViewModel.TYPE_ID_CARD), object : Callback {
|
||||
override fun onActivityResult(resultCode: Int, data: Intent?) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
|
||||
@ -48,7 +48,7 @@ class GameOffServiceDialogFragment
|
||||
siteTv.setOnClickListener {
|
||||
// MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
|
||||
DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)")
|
||||
dismiss()
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
container.addView(siteTv)
|
||||
|
||||
@ -0,0 +1,135 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.app.Activity.RESULT_OK
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.PermissionHelper.INSTALL_PERMISSION_CODE
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.gamecenter.R
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import kotlin.random.Random
|
||||
|
||||
class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
lateinit var mView: View
|
||||
var isXapk = false
|
||||
var url: String = ""
|
||||
var mCallBack: (() -> Unit)? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
mView = inflater.inflate(R.layout.dialog_install_permission, null, false)
|
||||
return mView
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val closeTv = mView.findViewById<TextView>(R.id.closeTv)
|
||||
val closeIv = mView.findViewById<ImageView>(R.id.closeIv)
|
||||
val activateTv = mView.findViewById<TextView>(R.id.activateTv)
|
||||
val contentTv = mView.findViewById<TextView>(R.id.contentTv)
|
||||
val switchLottie = mView.findViewById<LottieAnimationView>(R.id.switchLottie)
|
||||
contentTv.text = if (isXapk) "未授权下解压XAPK可能导致解压失败" else "以保证游戏的安装和更新"
|
||||
|
||||
switchLottie.setAnimation("lottie/install_permission_switch.json")
|
||||
switchLottie.playAnimation()
|
||||
|
||||
val randomNumber = if (isXapk) 1 else Random.nextInt(2)
|
||||
closeTv.goneIf(randomNumber == 0)
|
||||
closeIv.goneIf(randomNumber != 0)
|
||||
if (isXapk) {
|
||||
closeTv.text = "暂不,尝试解压"
|
||||
closeIv.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
closeTv.setOnClickListener {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), "文案样式_点击以后再说")
|
||||
if (isXapk) {
|
||||
mCallBack?.invoke()
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
closeIv.setOnClickListener {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), "图标样式_点击关闭")
|
||||
dismiss()
|
||||
}
|
||||
activateTv.setOnClickListener {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), if (randomNumber == 0) "文案样式_点击立即开启" else "图标样式_点击立即开启")
|
||||
PermissionHelper.toInstallPermissionSetting(requireActivity())
|
||||
if (isXapk) {
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, requireActivity().javaClass.name)
|
||||
SPUtils.setString(Constants.SP_XAPK_URL, url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (resultCode == RESULT_OK && requestCode == INSTALL_PERMISSION_CODE) {
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "")
|
||||
SPUtils.setString(Constants.SP_XAPK_URL, "")
|
||||
mCallBack?.invoke()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEvent(): String = "安装引导弹窗"
|
||||
|
||||
override fun getKey(): String = "引导弹窗"
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun show(activity: AppCompatActivity, downloadEntity: DownloadEntity, callBack: (() -> Unit)?) {
|
||||
val isXapk = XapkInstaller.XAPK_EXTENSION_NAME == downloadEntity.path.getExtension()
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
callBack?.invoke()
|
||||
return
|
||||
}
|
||||
val haveInstallPermission = activity.packageManager.canRequestPackageInstalls()
|
||||
if (haveInstallPermission) {
|
||||
callBack?.invoke()
|
||||
return
|
||||
}
|
||||
if (isXapk) {
|
||||
val xapkUnzipVersions = Config.getSettings()?.permissionPopupAppliedVersions?.xapkUnzip
|
||||
if (xapkUnzipVersions?.contains(Build.VERSION.SDK_INT.toString()) == false) {
|
||||
callBack?.invoke()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
val installVersions = Config.getSettings()?.permissionPopupAppliedVersions?.install
|
||||
if (installVersions?.contains(Build.VERSION.SDK_INT.toString()) == false) {
|
||||
callBack?.invoke()
|
||||
return
|
||||
}
|
||||
}
|
||||
var installPermissionDialogFragment = activity.supportFragmentManager.findFragmentByTag(InstallPermissionDialogFragment::class.java.simpleName) as? InstallPermissionDialogFragment
|
||||
if (installPermissionDialogFragment != null) {
|
||||
installPermissionDialogFragment.mCallBack = callBack
|
||||
installPermissionDialogFragment.isXapk = isXapk
|
||||
installPermissionDialogFragment.url = downloadEntity.url
|
||||
val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction()
|
||||
transaction.show(installPermissionDialogFragment)
|
||||
transaction.commit()
|
||||
} else {
|
||||
installPermissionDialogFragment = InstallPermissionDialogFragment().apply {
|
||||
this.mCallBack = callBack
|
||||
this.isXapk = isXapk
|
||||
this.url = downloadEntity.url
|
||||
}
|
||||
installPermissionDialogFragment.show(activity.supportFragmentManager, InstallPermissionDialogFragment::class.java.simpleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,28 +2,33 @@ package com.gh.common.dialog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.GsonUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.util.PermissionHelper
|
||||
import com.gh.common.util.fromHtml
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.NotificationHint
|
||||
import com.gh.gamecenter.entity.NotificationStyleEntity
|
||||
import com.gh.gamecenter.entity.NotificationUgc
|
||||
import com.lightgame.utils.Utils
|
||||
import kotlinx.android.synthetic.main.dialog_notification_hint.*
|
||||
import org.json.JSONArray
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import kotlin.random.Random
|
||||
|
||||
// 通知权限弹窗
|
||||
class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
private var mNotificationHint: NotificationHint? = null
|
||||
private var mNotificationUgc: NotificationUgc? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.dialog_notification_hint, null)
|
||||
@ -34,23 +39,34 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
titleTv.text = mNotificationHint?.title
|
||||
|
||||
contentContainer.removeAllViews()
|
||||
for (item in mNotificationHint?.content ?: arrayListOf()) {
|
||||
val tv = TextView(context)
|
||||
|
||||
tv.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
topMargin = if (contentContainer.childCount == 0) 0 else DisplayUtils.dip2px(12f)
|
||||
}
|
||||
tv.text = item
|
||||
tv.setTextColor(Color.parseColor("#1383EB"))
|
||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
|
||||
contentContainer.addView(tv)
|
||||
val jsonString = getJsonFromAssets()
|
||||
if (jsonString.isNullOrEmpty()) {
|
||||
Utils.log("Failed to obtain configuration file")
|
||||
return
|
||||
}
|
||||
val index = Random.nextInt(2)
|
||||
val jsonArray = JSONArray(jsonString)
|
||||
val jsonObj = jsonArray.getJSONObject(index)
|
||||
if (!jsonObj.has(mNotificationUgc?.value)) {
|
||||
Utils.log("ugc type error")
|
||||
return
|
||||
}
|
||||
val styleEntityJson = jsonObj.getJSONObject(mNotificationUgc!!.value)
|
||||
val styleEntity = GsonUtils.fromJson(styleEntityJson.toString(), NotificationStyleEntity::class.java)
|
||||
val drawableId = resources.getIdentifier(styleEntity.image, "drawable", requireContext().packageName)
|
||||
notificationIv.setImageDrawable(ContextCompat.getDrawable(requireContext(), drawableId))
|
||||
notificationTitle.text = styleEntity.title
|
||||
notificationContent.text = styleEntity.content.fromHtml()
|
||||
if (index == 0) {
|
||||
closeIv.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_notification_close_1))
|
||||
} else {
|
||||
activateTv.background = ContextCompat.getDrawable(requireContext(), R.drawable.bg_notification_open_btn_style_1)
|
||||
activateTv.text = "优雅的开启"
|
||||
}
|
||||
|
||||
activateTv.setOnClickListener {
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击立即开启")
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击立即开启")
|
||||
dismiss()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
//这种方案适用于 API 26, 即8.0(含8.0)以上可以用
|
||||
@ -63,9 +79,10 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
laterTv.setOnClickListener {
|
||||
closeIv.setOnClickListener {
|
||||
dismiss()
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击以后再说")
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击关闭")
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击关闭")
|
||||
}
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
@ -81,10 +98,30 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
override fun trackWithBasicDeviceInfo() = true
|
||||
|
||||
private fun getJsonFromAssets(): String? {
|
||||
val stringBuilder = StringBuilder()
|
||||
var bufferedReader: BufferedReader? = null
|
||||
var inputStreamReader: InputStreamReader? = null
|
||||
try {
|
||||
inputStreamReader = InputStreamReader(requireContext().assets.open("notification_style.json"))
|
||||
bufferedReader = BufferedReader(inputStreamReader)
|
||||
var line: String?
|
||||
while (bufferedReader.readLine().also { line = it } != null) {
|
||||
stringBuilder.append(line)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
inputStreamReader?.close()
|
||||
bufferedReader?.close()
|
||||
}
|
||||
return stringBuilder.toString()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(hint: NotificationHint) = NotificationHintDialogFragment().apply {
|
||||
mNotificationHint = hint
|
||||
fun getInstance(ugc: NotificationUgc) = NotificationHintDialogFragment().apply {
|
||||
mNotificationUgc = ugc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,305 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.view.CustomLinkMovementMethod
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.FragmentPackageCheckBinding
|
||||
import com.gh.gamecenter.databinding.PackageCheckItemBinding
|
||||
import com.gh.gamecenter.entity.DetectionObjectEntity
|
||||
import com.gh.gamecenter.entity.PackageDialogEntity
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.lightgame.dialog.BaseDialogFragment
|
||||
import io.reactivex.disposables.Disposable
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
/**
|
||||
* 包名检测弹窗
|
||||
*/
|
||||
class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
|
||||
private lateinit var binding: FragmentPackageCheckBinding
|
||||
private var mTotalWidth = 0f
|
||||
private val mDuration = 3000
|
||||
private var mDisposable: Disposable? = null
|
||||
private var mAdapter: PackageCheckAdapter? = null
|
||||
var packageDialogEntity: PackageDialogEntity? = null
|
||||
var callBack: DialogUtils.ConfirmListener? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
EventBus.getDefault().register(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
binding = FragmentPackageCheckBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
packageDialogEntity?.let {
|
||||
changeParams(it.detectionObjects.size)
|
||||
|
||||
binding.packageRv.layoutManager = LinearLayoutManager(requireContext())
|
||||
mAdapter = PackageCheckAdapter(requireContext(), it.detectionObjects)
|
||||
binding.packageRv.adapter = mAdapter
|
||||
|
||||
binding.titleTv.text = it.title
|
||||
binding.contentTv.text = it.content
|
||||
|
||||
val spanBuilder = SpanBuilder(it.linkHintText).build()
|
||||
it.links.forEachIndexed { index, link ->
|
||||
val linkSpan = SpanBuilder(link.title ?: "").click(0, (link.title
|
||||
?: "").length, R.color.theme_font, true) {
|
||||
DirectUtils.directToLinkPage(requireContext(), link, "包名检测弹窗", "")
|
||||
}.build()
|
||||
spanBuilder.append(linkSpan)
|
||||
if (index != it.links.size - 1) {
|
||||
spanBuilder.append("、")
|
||||
}
|
||||
}
|
||||
binding.linkHintTv.text = spanBuilder
|
||||
binding.linkHintTv.movementMethod = CustomLinkMovementMethod.getInstance()
|
||||
|
||||
when (it.level) {
|
||||
"HINT_SKIP" -> {
|
||||
binding.cancelTv.text = "取消"
|
||||
binding.noRemindAgainCb.visibility = View.GONE
|
||||
}
|
||||
"ALWAYS_HINT" -> {
|
||||
binding.cancelTv.text = "我知道了"
|
||||
binding.noRemindAgainCb.visibility = View.GONE
|
||||
}
|
||||
else -> {
|
||||
binding.cancelTv.text = "我知道了"
|
||||
binding.noRemindAgainCb.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
initListener(it)
|
||||
}
|
||||
checkPackage()
|
||||
}
|
||||
|
||||
private fun changeParams(size: Int) {
|
||||
val params = binding.packageRv.layoutParams as LinearLayout.LayoutParams
|
||||
params.height = if (size > 3) (28f.dip2px() * 3.5).toInt() else 28f.dip2px() * size
|
||||
binding.packageRv.layoutParams = params
|
||||
}
|
||||
|
||||
private fun initListener(entity: PackageDialogEntity) {
|
||||
binding.downloadBtn.setOnClickListener {
|
||||
if (binding.noRemindAgainCb.isChecked) {
|
||||
SPUtils.setBoolean(Constants.SP_PACKAGE_CHECK, true)
|
||||
}
|
||||
val isAllPackageInstalled = isAllPackageInstalled(entity)
|
||||
if (isAllPackageInstalled) {
|
||||
callBack?.onConfirm()
|
||||
dismissAllowingStateLoss()
|
||||
} else {
|
||||
val packageLink = entity.links.find { it.buttonLink }
|
||||
if (packageLink != null) {
|
||||
DirectUtils.directToLinkPage(requireContext(), packageLink, "包名检测弹窗", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.cancelTv.setOnClickListener {
|
||||
if (entity.level != "HINT_SKIP") {
|
||||
callBack?.onConfirm()
|
||||
}
|
||||
if (binding.noRemindAgainCb.isChecked) {
|
||||
SPUtils.setBoolean(Constants.SP_PACKAGE_CHECK, true)
|
||||
}
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPackage() {
|
||||
var index = 0
|
||||
mTotalWidth = (DisplayUtils.getScreenWidth() - 108f.dip2px()).toFloat()
|
||||
mDisposable = rxTimer(1) {
|
||||
val width = (mTotalWidth / mDuration) * it
|
||||
val params = binding.progressView.layoutParams as RelativeLayout.LayoutParams
|
||||
params.width = width.toInt()
|
||||
binding.progressView.layoutParams = params
|
||||
|
||||
packageDialogEntity?.detectionObjects?.let { objects ->
|
||||
if (objects.isNotEmpty()) {
|
||||
val averageTime = if (objects.size == 1) {
|
||||
mDuration
|
||||
} else {
|
||||
mDuration / objects.size
|
||||
}
|
||||
if (it != 0L && it % averageTime == 0L && index < objects.size) {
|
||||
mAdapter?.notifyPackages()
|
||||
binding.packageRv.smoothScrollToPosition(index)
|
||||
index++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (it >= mDuration) {
|
||||
mDisposable?.dispose()
|
||||
binding.downloadBtn.isEnabled = true
|
||||
binding.progressText.text = "检测完成"
|
||||
binding.progressView.background = ContextCompat.getDrawable(requireContext(), R.drawable.package_check_complete_bg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = requireContext().resources.displayMetrics.widthPixels - 60F.dip2px()
|
||||
val height = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
dialog?.window?.setLayout(width, height)
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
packageDialogEntity?.let {
|
||||
if (isAllPackageInstalled(it)) {
|
||||
callBack?.onConfirm()
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
EventBus.getDefault().unregister(this)
|
||||
if (mDisposable?.isDisposed == false) {
|
||||
mDisposable?.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
//安装、卸载事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busFour: EBPackage) {
|
||||
if ("安装" == busFour.type || "卸载" == busFour.type) {
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
class PackageCheckAdapter(val context: Context, val entities: ArrayList<DetectionObjectEntity>) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
private var index = -1
|
||||
|
||||
fun notifyPackages() {
|
||||
index++
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return PackageCheckViewHolder(PackageCheckItemBinding.bind(LayoutInflater.from(context).inflate(R.layout.package_check_item, parent, false)))
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = entities.size
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is PackageCheckViewHolder) {
|
||||
val entity = entities[position]
|
||||
holder.binding.entity = entity
|
||||
if (position <= index) {
|
||||
var isAllInstalled = false
|
||||
entity.packages.forEach { packageName ->
|
||||
val isInstalled = PackageUtils.getInstalledPackages(context, 0).find { it.packageName == packageName } != null
|
||||
if (isInstalled) {
|
||||
isAllInstalled = true
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
if (isAllInstalled) {
|
||||
holder.binding.statusTv.text = "已安装"
|
||||
holder.binding.statusTv.setTextColor(ContextCompat.getColor(context, R.color.theme_font))
|
||||
} else {
|
||||
holder.binding.statusTv.text = "未安装"
|
||||
holder.binding.statusTv.setTextColor(ContextCompat.getColor(context, R.color.text_FF4147))
|
||||
}
|
||||
holder.binding.statusTv.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.binding.statusTv.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PackageCheckViewHolder(val binding: PackageCheckItemBinding) : BaseRecyclerViewHolder<DetectionObjectEntity>(binding.root)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun show(activity: AppCompatActivity, packageDialogEntity: PackageDialogEntity?, callBack: DialogUtils.ConfirmListener) {
|
||||
if (packageDialogEntity == null) {
|
||||
callBack.onConfirm()
|
||||
return
|
||||
}
|
||||
if (isAllPackageInstalled(packageDialogEntity)) {
|
||||
callBack.onConfirm()
|
||||
return
|
||||
}
|
||||
val isChoose = SPUtils.getBoolean(Constants.SP_PACKAGE_CHECK, false)
|
||||
if (packageDialogEntity.level == "OPTIONAL_HINT" && isChoose) {
|
||||
callBack.onConfirm()
|
||||
return
|
||||
}
|
||||
|
||||
var dialogFragment = activity.supportFragmentManager.findFragmentByTag(PackageCheckDialogFragment::class.java.simpleName) as? PackageCheckDialogFragment
|
||||
if (dialogFragment == null) {
|
||||
dialogFragment = PackageCheckDialogFragment()
|
||||
dialogFragment.packageDialogEntity = packageDialogEntity
|
||||
dialogFragment.callBack = callBack
|
||||
|
||||
dialogFragment.show(activity.supportFragmentManager, PackageCheckDialogFragment::class.java.simpleName)
|
||||
} else {
|
||||
dialogFragment.packageDialogEntity = packageDialogEntity
|
||||
dialogFragment.callBack = callBack
|
||||
|
||||
val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction()
|
||||
transaction.show(dialogFragment)
|
||||
transaction.commit()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun isAllPackageInstalled(packageDialogEntity: PackageDialogEntity): Boolean {
|
||||
var isAllInstalled = true
|
||||
|
||||
val isPackagesInstall: (ArrayList<String>) -> Boolean = { packages ->
|
||||
var isPackagesInstalled = false
|
||||
packages.forEach {packageName->
|
||||
val isInstalled = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0).find { it.packageName == packageName } != null
|
||||
if (isInstalled) {
|
||||
isPackagesInstalled = true
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
isPackagesInstalled
|
||||
}
|
||||
|
||||
packageDialogEntity.detectionObjects.forEach loop@{ obj ->
|
||||
if (!isPackagesInstall(obj.packages)) {
|
||||
isAllInstalled = false
|
||||
return isAllInstalled
|
||||
}
|
||||
}
|
||||
return isAllInstalled
|
||||
}
|
||||
}
|
||||
}
|
||||
155
app/src/main/java/com/gh/common/dialog/PrivacyDialogFragment.kt
Normal file
155
app/src/main/java/com/gh/common/dialog/PrivacyDialogFragment.kt
Normal file
@ -0,0 +1,155 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.TextPaint
|
||||
import android.text.method.ScrollingMovementMethod
|
||||
import android.text.style.ClickableSpan
|
||||
import android.view.*
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.util.DirectUtils.directToExternalBrowser
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.common.view.CustomLinkMovementMethod
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
class PrivacyDialogFragment : BaseDialogFragment() {
|
||||
|
||||
// private val mLocalPrivacyHtml = "file:///android_asset/privacy_policies.html"
|
||||
// private val mLocalRegulationHtml = "file:///android_asset/user_regulation.html"
|
||||
|
||||
var containerView: View? = null
|
||||
var mCallBack: ((isSuccess: Boolean) -> Unit)? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
containerView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_privacy_protocol, null, false)
|
||||
return containerView
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
// val mWebViewPrivacy = containerView?.findViewById<WebView>(R.id.webView)
|
||||
// val mWebViewRegulation = containerView?.findViewById<WebView>(R.id.webView2)
|
||||
//
|
||||
// mWebViewPrivacy?.isHorizontalScrollBarEnabled = false
|
||||
// mWebViewRegulation?.isHorizontalScrollBarEnabled = false
|
||||
|
||||
val contentTv = containerView?.findViewById<TextView>(R.id.contentTv)
|
||||
val descTv = containerView?.findViewById<TextView>(R.id.descTv)
|
||||
contentTv?.movementMethod = ScrollingMovementMethod()
|
||||
|
||||
val skipText = SpannableStringBuilder("查看完整版的隐私政策和用户协议")
|
||||
skipText.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
directToExternalBrowser(context!!, context!!.getString(R.string.privacy_policy_url))
|
||||
}
|
||||
}, skipText.length - 9, skipText.length - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
|
||||
skipText.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
directToExternalBrowser(requireContext(), requireContext().getString(R.string.disclaimer_url))
|
||||
}
|
||||
}, skipText.length - 4, skipText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
descTv?.movementMethod = CustomLinkMovementMethod()
|
||||
descTv?.text = skipText
|
||||
|
||||
// val mWebViewPrivacy = containerView?.findViewById<WebView>(R.id.webView)
|
||||
//
|
||||
// mWebViewPrivacy?.isHorizontalScrollBarEnabled = false
|
||||
//
|
||||
// val settingsArrayList = arrayListOf(mWebViewPrivacy?.settings, mWebViewRegulation?.settings)
|
||||
//
|
||||
// for (settings in settingsArrayList) {
|
||||
// settings?.javaScriptEnabled = true
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// settings?.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
|
||||
// }
|
||||
// // 避免提示网页有害信息不能访问
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// settings?.safeBrowsingEnabled = false
|
||||
// }
|
||||
//
|
||||
// // 适配大于屏幕宽度的页面
|
||||
// settings?.useWideViewPort = true
|
||||
// settings?.loadWithOverviewMode = true
|
||||
// settings?.domStorageEnabled = true
|
||||
//
|
||||
// // 自适应屏幕
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
// settings?.layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING
|
||||
// }
|
||||
// }
|
||||
|
||||
// mWebViewPrivacy?.webViewClient = client
|
||||
// mWebViewRegulation?.webViewClient = client
|
||||
|
||||
containerView?.findViewById<View>(R.id.refuseTv)?.setOnClickListener {
|
||||
mCallBack?.invoke(false)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
containerView?.findViewById<View>(R.id.agreeTv)?.setOnClickListener {
|
||||
mCallBack?.invoke(true)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val createDialog = super.onCreateDialog(savedInstanceState)
|
||||
createDialog.setCanceledOnTouchOutside(false)
|
||||
createDialog.setOnKeyListener(object : DialogInterface.OnKeyListener {
|
||||
override fun onKey(dialog: DialogInterface?, keyCode: Int, event: KeyEvent?): Boolean {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
val window = createDialog.window
|
||||
window?.setGravity(Gravity.CENTER)
|
||||
return createDialog
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = requireContext().resources.displayMetrics.widthPixels - 60F.dip2px()
|
||||
val height = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
dialog?.window?.setLayout(width, height)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun show(activity: AppCompatActivity, callBack: ((isSuccess: Boolean) -> Unit)?) {
|
||||
var privacyDialogFragment = activity.supportFragmentManager.findFragmentByTag(PrivacyDialogFragment::class.java.simpleName) as? PrivacyDialogFragment
|
||||
if (privacyDialogFragment != null) {
|
||||
privacyDialogFragment.mCallBack = callBack
|
||||
val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction()
|
||||
transaction.show(privacyDialogFragment)
|
||||
transaction.commit()
|
||||
} else {
|
||||
privacyDialogFragment = PrivacyDialogFragment().apply {
|
||||
mCallBack = callBack
|
||||
}
|
||||
privacyDialogFragment.show(activity.supportFragmentManager, PrivacyDialogFragment::class.java.simpleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,12 +15,14 @@ import butterknife.BindView
|
||||
import butterknife.ButterKnife
|
||||
import butterknife.OnClick
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.history.HistoryHelper
|
||||
import com.gh.common.repository.ReservationRepository
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.NotificationUgc
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -168,7 +170,7 @@ class ReserveDialogFragment
|
||||
}
|
||||
|
||||
private fun setMobileIndexHint(reserveMobile: String?) {
|
||||
var userMobile = UserManager.getInstance().userInfoEntity.mobile
|
||||
var userMobile = UserManager.getInstance().userInfoEntity?.mobile
|
||||
if (reserveMobile == userMobile) userMobile = null
|
||||
|
||||
if (!reserveMobile.isNullOrEmpty()) {
|
||||
@ -231,6 +233,9 @@ class ReserveDialogFragment
|
||||
R.id.close_btn -> {
|
||||
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击关闭")
|
||||
dismissAllowingStateLoss()
|
||||
AppExecutor.uiExecutor.executeWithDelay(Runnable {
|
||||
NotificationHelper.showNotificationHintDialog(NotificationUgc.RESERVE_GAME)
|
||||
}, 1000)
|
||||
}
|
||||
R.id.content_container -> {
|
||||
mobileIndexContainer.visibility = View.GONE
|
||||
|
||||
@ -17,6 +17,10 @@ data class ExposureEntity(
|
||||
val downloadType: String? = "",
|
||||
val downloadCompleteType: String? = "",
|
||||
|
||||
// 下载地址的 host 和 path
|
||||
var host: String? = "",
|
||||
var path: String? = "",
|
||||
|
||||
// 统计启动弹窗相关数据用的 (ugly)
|
||||
@SerializedName("dialog_id")
|
||||
var welcomeDialogId: String? = "",
|
||||
|
||||
@ -26,6 +26,8 @@ data class ExposureEvent(
|
||||
@PrimaryKey
|
||||
val id: String = UUID.randomUUID().toString()) : Parcelable {
|
||||
companion object {
|
||||
|
||||
// TODO 建一个 exposureEvent 池规避反复生成对象
|
||||
@JvmStatic
|
||||
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>? = null, event: ExposureType = ExposureType.EXPOSURE): ExposureEvent {
|
||||
if (gameEntity?.getApk()?.size == 1) {
|
||||
|
||||
@ -43,7 +43,7 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
|
||||
if (layoutManager == null) layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
||||
|
||||
layoutManager?.run {
|
||||
visibleState = ExposureThrottleBus.VisibleState(findFirstCompletelyVisibleItemPosition(), findLastCompletelyVisibleItemPosition())
|
||||
visibleState = ExposureThrottleBus.VisibleState(findFirstVisibleItemPosition(), findLastVisibleItemPosition())
|
||||
throttleBus?.postVisibleState(visibleState!!)
|
||||
}
|
||||
}
|
||||
@ -55,7 +55,7 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
|
||||
|
||||
val eventList = arrayListOf<ExposureEvent>()
|
||||
|
||||
for (pos in visibleState.firstCompletelyVisible..visibleState.lastCompletelyVisible) {
|
||||
for (pos in visibleState.firstVisiblePosition..visibleState.lastVisiblePosition) {
|
||||
try {
|
||||
exposable.getEventByPosition(pos)?.let { eventList.add(it) }
|
||||
exposable.getEventListByPosition(pos)?.let { eventList.addAll(it) }
|
||||
|
||||
@ -3,6 +3,7 @@ package com.gh.common.exposure
|
||||
import com.aliyun.sls.android.sdk.model.LogGroup
|
||||
import com.gh.common.exposure.time.TimeUtil
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.loghub.LgLOG
|
||||
import com.gh.loghub.LoghubHelper
|
||||
@ -94,15 +95,18 @@ object ExposureManager {
|
||||
*/
|
||||
fun commitSavedExposureEvents(forced: Boolean = false) {
|
||||
exposureExecutor.execute {
|
||||
if (exposureSet.size < STORE_SIZE && !forced || exposureSet.size == 0) return@execute
|
||||
tryWithDefaultCatch {
|
||||
// TODO 初始化 loghubHelper 去掉这个 tryCatch 块
|
||||
if (exposureSet.size < STORE_SIZE && !forced || exposureSet.size == 0) return@execute
|
||||
|
||||
val exposureList = exposureSet.toList()
|
||||
// uploadLogGroup 是一个异步方法,LoghubHelper 里面实现了重传功能,所以这里交给它就好了
|
||||
loghubHelper.uploadLogGroup(buildLogGroup(exposureList))
|
||||
val exposureList = exposureSet.toList()
|
||||
// uploadLogGroup 是一个异步方法,LoghubHelper 里面实现了重传功能,所以这里交给它就好了
|
||||
loghubHelper.uploadLogGroup(buildLogGroup(exposureList))
|
||||
|
||||
Utils.log("Exposure", "提交了${exposureList.size}条曝光记录")
|
||||
exposureSet.removeAll(exposureList)
|
||||
exposureDao.deleteMany(exposureList)
|
||||
Utils.log("Exposure", "提交了${exposureList.size}条曝光记录")
|
||||
exposureSet.removeAll(exposureList)
|
||||
exposureDao.deleteMany(exposureList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -38,21 +38,21 @@ class ExposureThrottleBus(var onSuccess: Consumer<VisibleState>, var onError: Co
|
||||
mPublishSubject.onNext(visibleState)
|
||||
}
|
||||
|
||||
class VisibleState(val firstCompletelyVisible: Int, val lastCompletelyVisible: Int) {
|
||||
class VisibleState(val firstVisiblePosition: Int, val lastVisiblePosition: Int) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || javaClass != other.javaClass) return false
|
||||
|
||||
val that = other as VisibleState
|
||||
|
||||
if (firstCompletelyVisible != that.firstCompletelyVisible) return false
|
||||
if (firstVisiblePosition != that.firstVisiblePosition) return false
|
||||
|
||||
return lastCompletelyVisible == that.lastCompletelyVisible
|
||||
return lastVisiblePosition == that.lastVisiblePosition
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = firstCompletelyVisible
|
||||
result = 31 * result + lastCompletelyVisible
|
||||
var result = firstVisiblePosition
|
||||
result = 31 * result + lastVisiblePosition
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,6 +38,8 @@ object ExposureUtils {
|
||||
fun logADownloadCompleteExposureEvent(entity: GameEntity,
|
||||
platform: String?,
|
||||
trace: String?,
|
||||
host: String? = "unknown",
|
||||
path: String? = "unknown",
|
||||
downloadType: DownloadType) {
|
||||
val gameEntity = entity.clone()
|
||||
gameEntity.platform = platform
|
||||
@ -47,6 +49,8 @@ object ExposureUtils {
|
||||
source = traceEvent?.source ?: ArrayList(),
|
||||
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
|
||||
event = ExposureType.DOWNLOAD_COMPLETE)
|
||||
exposureEvent.payload.host = host
|
||||
exposureEvent.payload.path = path
|
||||
ExposureManager.log(exposureEvent)
|
||||
ExposureManager.commitSavedExposureEvents(forced = true)
|
||||
}
|
||||
|
||||
@ -5,17 +5,17 @@ import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import android.telephony.TelephonyManager
|
||||
import android.text.TextUtils
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.leon.channel.helper.ChannelReaderUtil
|
||||
import com.walkud.rom.checker.RomIdentifier
|
||||
import java.io.File
|
||||
|
||||
object MetaUtil {
|
||||
|
||||
@ -23,9 +23,12 @@ object MetaUtil {
|
||||
private var channel = ""
|
||||
|
||||
private var m: Meta? = null
|
||||
private var imei: String? = null
|
||||
private var base64EncodedImei: String? = null
|
||||
private var androidId: String? = null
|
||||
|
||||
fun refreshMeta() {
|
||||
m = Meta(mac = getMac(),
|
||||
m = Meta(mac = "",
|
||||
imei = getIMEI(),
|
||||
model = getModel(),
|
||||
manufacturer = getManufacturer(),
|
||||
@ -57,60 +60,65 @@ object MetaUtil {
|
||||
return channel
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MAC address
|
||||
* TODO check > 6.0 results
|
||||
*/
|
||||
fun getMac(): String? {
|
||||
|
||||
var mac: String = ""
|
||||
|
||||
//Plan A
|
||||
try {
|
||||
mac = File("/sys/class/net/wlan0/address").inputStream().bufferedReader().use { it.readText() }
|
||||
if (!TextUtils.isEmpty(mac)) return mac.trim()
|
||||
} catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
}
|
||||
|
||||
// Plan B
|
||||
try {
|
||||
mac = File("/sys/class/net/eth0/address").inputStream().bufferedReader().use { it.readText() }
|
||||
if (!TextUtils.isEmpty(mac)) return mac.trim()
|
||||
} catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
}
|
||||
|
||||
// Plan C
|
||||
val wifiManager = application.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
try {
|
||||
mac = wifiManager.connectionInfo.macAddress
|
||||
} catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
}
|
||||
|
||||
return mac.trim()
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IMEI
|
||||
*/
|
||||
fun getIMEI(): String? {
|
||||
@JvmStatic
|
||||
fun getIMEI(): String {
|
||||
|
||||
if (application.checkCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED)
|
||||
if (!HaloApp.isUserAcceptPrivacyPolicy(HaloApp.getInstance().application)) {
|
||||
return ""
|
||||
}
|
||||
|
||||
if (imei != null) {
|
||||
return imei ?: ""
|
||||
}
|
||||
|
||||
imei = SPUtils.getString(Constants.SP_IMEI)
|
||||
|
||||
if (!TextUtils.isEmpty(imei)) {
|
||||
return imei ?: ""
|
||||
}
|
||||
|
||||
if (application.checkCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
|
||||
return ""
|
||||
}
|
||||
|
||||
val telephonyManager = application.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
return telephonyManager.imei
|
||||
if (Build.VERSION.SDK_INT >= 29) {
|
||||
return "".apply {
|
||||
imei = this
|
||||
SPUtils.setString(Constants.SP_IMEI, this)
|
||||
}
|
||||
} else if (Build.VERSION.SDK_INT >= 26) {
|
||||
return (telephonyManager.imei ?: "").apply {
|
||||
imei = this
|
||||
SPUtils.setString(Constants.SP_IMEI, this)
|
||||
}
|
||||
}
|
||||
|
||||
return telephonyManager.getDeviceId()
|
||||
return (telephonyManager.getDeviceId() ?: "").apply {
|
||||
imei = this
|
||||
SPUtils.setString(Constants.SP_IMEI, this)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getBase64EncodedIMEI(): String {
|
||||
if (TextUtils.isEmpty(base64EncodedImei) && imei != null) {
|
||||
try {
|
||||
base64EncodedImei = android.util.Base64.encodeToString(getIMEI().trim().toByteArray(), android.util.Base64.NO_WRAP)
|
||||
} catch (e: java.lang.Exception) {
|
||||
e.printStackTrace()
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
return base64EncodedImei ?: ""
|
||||
}
|
||||
|
||||
fun getModel(): String? {
|
||||
return Build.MODEL
|
||||
}
|
||||
@ -119,14 +127,35 @@ object MetaUtil {
|
||||
return Build.MANUFACTURER
|
||||
}
|
||||
|
||||
fun getAndroidId(): String? {
|
||||
var android_id: String = ""
|
||||
try {
|
||||
android_id = Settings.Secure.getString(application.contentResolver, Settings.Secure.ANDROID_ID)
|
||||
@JvmStatic
|
||||
fun getAndroidId(): String {
|
||||
|
||||
if (!HaloApp.isUserAcceptPrivacyPolicy(HaloApp.getInstance().application)) {
|
||||
return ""
|
||||
}
|
||||
|
||||
if (androidId != null) {
|
||||
return androidId ?: ""
|
||||
}
|
||||
|
||||
androidId = SPUtils.getString(Constants.SP_ANDROID_ID)
|
||||
|
||||
if (!TextUtils.isEmpty(androidId)) {
|
||||
return androidId ?: ""
|
||||
}
|
||||
|
||||
return try {
|
||||
Settings.Secure.getString(application.contentResolver, Settings.Secure.ANDROID_ID).apply {
|
||||
androidId = this
|
||||
SPUtils.setString(Constants.SP_ANDROID_ID, this)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
androidId = ""
|
||||
SPUtils.setString(Constants.SP_ANDROID_ID, "")
|
||||
""
|
||||
}
|
||||
return android_id
|
||||
|
||||
}
|
||||
|
||||
fun getAndroidSDK(): Int? {
|
||||
|
||||
@ -4,15 +4,16 @@ import android.annotation.SuppressLint
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.common.util.debounceActionWithInterval
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.functions.Function
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
object RegionSettingHelper {
|
||||
|
||||
@ -50,7 +51,7 @@ object RegionSettingHelper {
|
||||
list
|
||||
}
|
||||
|
||||
fun shouldGameOfThisCategoryUseMirrorInfo(category: String) : Boolean {
|
||||
fun shouldGameOfThisCategoryUseMirrorInfo(category: String): Boolean {
|
||||
return if (mChannelControl == null || mChannelControl?.effect == false || !isUserUsedLessThan24Hours()) {
|
||||
false
|
||||
} else {
|
||||
@ -61,24 +62,26 @@ object RegionSettingHelper {
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun getRegionSetting() {
|
||||
// 使用默认的 Schdulers.io() 可能会触发 OOM
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.sensitiveApi
|
||||
.getRegionSetting(HaloApp.getInstance().channel)
|
||||
.subscribeOn(AppExecutor.cachedScheduler)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<RegionSetting>() {
|
||||
override fun onSuccess(data: RegionSetting) {
|
||||
updateSettingsInMemory(data)
|
||||
SPUtils.setString(SP_SETTING, data.toJson())
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
SPUtils.getString(SP_SETTING).toObject<RegionSetting>()?.let {
|
||||
updateSettingsInMemory(it)
|
||||
debounceActionWithInterval(R.string.app_name, 3000) {
|
||||
// 使用默认的 Schdulers.io() 可能会触发 OOM
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.sensitiveApi
|
||||
.getRegionSetting(HaloApp.getInstance().channel)
|
||||
.subscribeOn(AppExecutor.cachedScheduler)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<RegionSetting>() {
|
||||
override fun onSuccess(data: RegionSetting) {
|
||||
updateSettingsInMemory(data)
|
||||
SPUtils.setString(SP_SETTING, data.toJson())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
SPUtils.getString(SP_SETTING).toObject<RegionSetting>()?.let {
|
||||
updateSettingsInMemory(it)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSettingsInMemory(data: RegionSetting) {
|
||||
|
||||
@ -4,6 +4,7 @@ import com.gh.common.runOnIoThread
|
||||
import com.gh.common.util.clearHtmlFormatCompletely
|
||||
import com.gh.common.util.removeInsertedContent
|
||||
import com.gh.common.util.removeVideoContent
|
||||
import com.gh.common.util.tryCatchInRelease
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.qa.entity.AnswerDetailEntity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
@ -14,27 +15,28 @@ object HistoryHelper {
|
||||
|
||||
fun insertAnswerEntity(answerDetailEntity: AnswerDetailEntity) {
|
||||
val answerEntity = convertAnswerDetailToAnswer(answerDetailEntity)
|
||||
runOnIoThread { HistoryDatabase.instance.answerDao().addAnswer(answerEntity) }
|
||||
// 偶尔有设备会出现磁盘满了写不进数据库的问题 database or disk is full 异常,毕竟只是插入个本地历史,这里直接捕抓
|
||||
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.answerDao().addAnswer(answerEntity) } }
|
||||
}
|
||||
|
||||
fun insertArticleEntity(articleDetailEntity: ArticleDetailEntity) {
|
||||
val articleEntity = convertArticleDetailToArticle(articleDetailEntity)
|
||||
runOnIoThread { HistoryDatabase.instance.articleDao().addArticle(articleEntity) }
|
||||
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.articleDao().addArticle(articleEntity) } }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun insertGameEntity(gameEntity: GameEntity) {
|
||||
val historyGameEntity = convertGameEntityToHistoryGameEntity(gameEntity)
|
||||
runOnIoThread { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) }
|
||||
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) } }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun insertGameEntity(updateEntity: GameUpdateEntity) {
|
||||
val historyGameEntity = convertGameUpdateEntityToHistoryGameEntity(updateEntity)
|
||||
runOnIoThread { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) }
|
||||
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) } }
|
||||
}
|
||||
|
||||
private fun convertGameUpdateEntityToHistoryGameEntity(updateEntity: GameUpdateEntity): HistoryGameEntity{
|
||||
private fun convertGameUpdateEntityToHistoryGameEntity(updateEntity: GameUpdateEntity): HistoryGameEntity {
|
||||
val historyGame = HistoryGameEntity()
|
||||
|
||||
historyGame.orderTag = System.currentTimeMillis()
|
||||
@ -110,6 +112,7 @@ object HistoryHelper {
|
||||
clearHtmlFormatCompletely().
|
||||
replace(" +".toRegex()," ")
|
||||
articleEntity.count = articleDetailEntity.count
|
||||
articleDetailEntity.community.id = articleDetailEntity.communityId
|
||||
articleEntity.community = articleDetailEntity.community
|
||||
articleEntity.time = articleDetailEntity.time
|
||||
articleEntity.title = articleDetailEntity.title
|
||||
|
||||
10
app/src/main/java/com/gh/common/iinterface/IOffsetable.kt
Normal file
10
app/src/main/java/com/gh/common/iinterface/IOffsetable.kt
Normal file
@ -0,0 +1,10 @@
|
||||
package com.gh.common.iinterface
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
interface IOffsetable {
|
||||
fun getOffset(position: Int): Int
|
||||
|
||||
fun updateOffset(position: Int, offset: Int)
|
||||
|
||||
fun resetOffset()
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.gh.common.iinterface
|
||||
|
||||
interface IScrollable {
|
||||
fun scrollToTop()
|
||||
}
|
||||
@ -1,67 +1,67 @@
|
||||
package com.gh.common.im
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.core.view.ViewCompat
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
object ImHintHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun show(activity: Activity?) {
|
||||
activity?.let {
|
||||
var hintView = retrieveHintViewFromActivity(it)
|
||||
if (hintView == null) {
|
||||
hintView = ImHintView(it)
|
||||
hintView.showDot(ImManager.shouldShowFloatingWindowDot)
|
||||
|
||||
val decorView = it.window.decorView as ViewGroup
|
||||
it.runOnUiThread {
|
||||
decorView.addView(hintView)
|
||||
}
|
||||
} else {
|
||||
hintView.showDot(ImManager.shouldShowFloatingWindowDot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun dismiss(activity: Activity?) {
|
||||
activity?.let {
|
||||
clearCurrent(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun retrieveHintViewFromActivity(activity: Activity?) : ImHintView? {
|
||||
(activity?.window?.decorView as? ViewGroup)?.let {
|
||||
for (i in 0..it.childCount) {
|
||||
val childView = if (it.getChildAt(i) is ImHintView) it.getChildAt(i) as ImHintView else null
|
||||
if (childView != null && childView.windowToken != null) {
|
||||
return childView
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun clearCurrent(activity: Activity?) {
|
||||
(activity?.window?.decorView as? ViewGroup)?.let {
|
||||
for (i in 0..it.childCount) {
|
||||
val childView = if (it.getChildAt(i) is ImHintView) it.getChildAt(i) as ImHintView else null
|
||||
if (childView != null && childView.windowToken != null) {
|
||||
ViewCompat.animate(childView).alpha(0f).withEndAction(getRemoveViewRunnable(childView))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRemoveViewRunnable(childView: View?): Runnable {
|
||||
return Runnable {
|
||||
childView?.let {
|
||||
(childView.parent as? ViewGroup)?.removeView(childView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//package com.gh.common.im
|
||||
//
|
||||
//import android.app.Activity
|
||||
//import androidx.core.view.ViewCompat
|
||||
//import android.view.View
|
||||
//import android.view.ViewGroup
|
||||
//
|
||||
//object ImHintHelper {
|
||||
//
|
||||
// @JvmStatic
|
||||
// fun show(activity: Activity?) {
|
||||
// activity?.let {
|
||||
// var hintView = retrieveHintViewFromActivity(it)
|
||||
// if (hintView == null) {
|
||||
// hintView = ImHintView(it)
|
||||
// hintView.showDot(ImManager.shouldShowFloatingWindowDot)
|
||||
//
|
||||
// val decorView = it.window.decorView as ViewGroup
|
||||
// it.runOnUiThread {
|
||||
// decorView.addView(hintView)
|
||||
// }
|
||||
// } else {
|
||||
// hintView.showDot(ImManager.shouldShowFloatingWindowDot)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @JvmStatic
|
||||
// fun dismiss(activity: Activity?) {
|
||||
// activity?.let {
|
||||
// clearCurrent(it)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun retrieveHintViewFromActivity(activity: Activity?) : ImHintView? {
|
||||
// (activity?.window?.decorView as? ViewGroup)?.let {
|
||||
// for (i in 0..it.childCount) {
|
||||
// val childView = if (it.getChildAt(i) is ImHintView) it.getChildAt(i) as ImHintView else null
|
||||
// if (childView != null && childView.windowToken != null) {
|
||||
// return childView
|
||||
// }
|
||||
// }
|
||||
// return null
|
||||
// }
|
||||
// return null
|
||||
// }
|
||||
//
|
||||
// private fun clearCurrent(activity: Activity?) {
|
||||
// (activity?.window?.decorView as? ViewGroup)?.let {
|
||||
// for (i in 0..it.childCount) {
|
||||
// val childView = if (it.getChildAt(i) is ImHintView) it.getChildAt(i) as ImHintView else null
|
||||
// if (childView != null && childView.windowToken != null) {
|
||||
// ViewCompat.animate(childView).alpha(0f).withEndAction(getRemoveViewRunnable(childView))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun getRemoveViewRunnable(childView: View?): Runnable {
|
||||
// return Runnable {
|
||||
// childView?.let {
|
||||
// (childView.parent as? ViewGroup)?.removeView(childView)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
@ -1,45 +1,45 @@
|
||||
package com.gh.common.im
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
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.*
|
||||
|
||||
class ImHintView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
|
||||
: RelativeLayout(context, attrs, defStyle) {
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.view_im_hint, this)
|
||||
|
||||
ViewCompat.setTranslationZ(this, Integer.MAX_VALUE.toFloat() - 1)
|
||||
|
||||
ivContainer.setOnClickListener {
|
||||
if (context is Activity) {
|
||||
ImManager.startChatActivity(context)
|
||||
ImManager.removeNotification()
|
||||
}
|
||||
}
|
||||
|
||||
val lp = ivContainer.layoutParams as RelativeLayout.LayoutParams
|
||||
|
||||
lp.setMargins(0, 0, dp2px(30f), dp2px(106f) + DisplayUtils.retrieveNavigationHeight(context))
|
||||
}
|
||||
|
||||
fun showDot(show: Boolean) {
|
||||
if (show) {
|
||||
unreadDot.visibility = View.VISIBLE
|
||||
} else {
|
||||
unreadDot.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun dp2px(dp: Float): Int {
|
||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.applicationContext.resources.displayMetrics).toInt()
|
||||
}
|
||||
}
|
||||
//package com.gh.common.im
|
||||
//
|
||||
//import android.app.Activity
|
||||
//import android.content.Context
|
||||
//import android.util.AttributeSet
|
||||
//import android.util.TypedValue
|
||||
//import android.view.View
|
||||
//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.*
|
||||
//
|
||||
//class ImHintView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
|
||||
// : RelativeLayout(context, attrs, defStyle) {
|
||||
//
|
||||
// init {
|
||||
// inflate(context, R.layout.view_im_hint, this)
|
||||
//
|
||||
// ViewCompat.setTranslationZ(this, Integer.MAX_VALUE.toFloat() - 1)
|
||||
//
|
||||
// ivContainer.setOnClickListener {
|
||||
// if (context is Activity) {
|
||||
// ImManager.startChatActivity(context)
|
||||
// ImManager.removeNotification()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val lp = ivContainer.layoutParams as RelativeLayout.LayoutParams
|
||||
//
|
||||
// lp.setMargins(0, 0, dp2px(30f), dp2px(106f) + DisplayUtils.retrieveNavigationHeight(context))
|
||||
// }
|
||||
//
|
||||
// fun showDot(show: Boolean) {
|
||||
// if (show) {
|
||||
// unreadDot.visibility = View.VISIBLE
|
||||
// } else {
|
||||
// unreadDot.visibility = View.GONE
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun dp2px(dp: Float): Int {
|
||||
// return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.applicationContext.resources.displayMetrics).toInt()
|
||||
// }
|
||||
//}
|
||||
@ -1,25 +1,9 @@
|
||||
package com.gh.common.im
|
||||
|
||||
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.manager.UserManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.m7.imkfsdk.KfStartHelper
|
||||
import com.m7.imkfsdk.utils.Utils
|
||||
import com.moor.imkf.ChatListener
|
||||
import com.moor.imkf.IMChat
|
||||
import com.moor.imkf.IMChatManager
|
||||
import com.moor.imkf.IMMessage
|
||||
import com.moor.imkf.utils.MoorUtils
|
||||
|
||||
object ImManager {
|
||||
|
||||
@ -35,57 +19,57 @@ object ImManager {
|
||||
|
||||
@JvmStatic
|
||||
fun attachIm() {
|
||||
try {
|
||||
if (UserManager.getInstance().userInfoEntity != null &&
|
||||
currentUserId != UserManager.getInstance().userId) {
|
||||
currentUserId = UserManager.getInstance().userId
|
||||
MoorUtils.init(HaloApp.getInstance().application)
|
||||
Utils.init(HaloApp.getInstance().application)
|
||||
IMChatManager.getInstance().init(
|
||||
HaloApp.getInstance().application,
|
||||
ImReceiver.UNIQUE_BROADCAST_ACTION,
|
||||
IM_KEY,
|
||||
UserManager.getInstance().userInfoEntity.name + "(" + UserManager.getInstance().userId + ")",
|
||||
UserManager.getInstance().userId)
|
||||
|
||||
shouldShowFloatingWindow = SPUtils.getBoolean(SP_FLOATING_WINDOW_KEY + UserManager.getInstance().userId)
|
||||
shouldShowFloatingWindowDot = SPUtils.getBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId)
|
||||
updateFloatingWindow()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
// try {
|
||||
// if (UserManager.getInstance().userInfoEntity != null &&
|
||||
// currentUserId != UserManager.getInstance().userId) {
|
||||
// currentUserId = UserManager.getInstance().userId
|
||||
// MoorUtils.init(HaloApp.getInstance().application)
|
||||
// Utils.init(HaloApp.getInstance().application)
|
||||
// IMChatManager.getInstance().init(
|
||||
// HaloApp.getInstance().application,
|
||||
// ImReceiver.UNIQUE_BROADCAST_ACTION,
|
||||
// IM_KEY,
|
||||
// UserManager.getInstance().userInfoEntity?.name + "(" + UserManager.getInstance().userId + ")",
|
||||
// UserManager.getInstance().userId)
|
||||
//
|
||||
// shouldShowFloatingWindow = SPUtils.getBoolean(SP_FLOATING_WINDOW_KEY + UserManager.getInstance().userId)
|
||||
// shouldShowFloatingWindowDot = SPUtils.getBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId)
|
||||
// updateFloatingWindow()
|
||||
// }
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun detachIm() {
|
||||
try {
|
||||
IMChatManager.getInstance().quitSDk()
|
||||
shouldShowFloatingWindow = false
|
||||
updateFloatingWindow()
|
||||
removeNotification()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
// try {
|
||||
// IMChatManager.getInstance().quitSDk()
|
||||
// shouldShowFloatingWindow = false
|
||||
// updateFloatingWindow()
|
||||
// removeNotification()
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
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, inputContent, requestCode)
|
||||
chatHelper.initSdkChat(
|
||||
ImReceiver.UNIQUE_BROADCAST_ACTION,
|
||||
IM_KEY,
|
||||
UserManager.getInstance().userInfoEntity.name + "(" + UserManager.getInstance().userId + ")"
|
||||
+ "[" + BuildConfig.VERSION_NAME + "]",
|
||||
UserManager.getInstance().userId)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
// 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, inputContent, requestCode)
|
||||
// chatHelper.initSdkChat(
|
||||
// ImReceiver.UNIQUE_BROADCAST_ACTION,
|
||||
// IM_KEY,
|
||||
// UserManager.getInstance().userInfoEntity?.name + "(" + UserManager.getInstance().userId + ")"
|
||||
// + "[" + BuildConfig.VERSION_NAME + "]",
|
||||
// UserManager.getInstance().userId)
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -104,50 +88,50 @@ object ImManager {
|
||||
|
||||
@JvmStatic
|
||||
fun removeNotification() {
|
||||
val notificationManager = HaloApp.getInstance().application?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.cancel(ImReceiver.NOTIFICATION_ID)
|
||||
// val notificationManager = HaloApp.getInstance().application?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
// notificationManager.cancel(ImReceiver.NOTIFICATION_ID)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun updateFloatingWindow() {
|
||||
try {
|
||||
CurrentActivityHolder.getCurrentActivity()?.let {
|
||||
if (isActivityValid(it)) {
|
||||
if (shouldShowFloatingWindow) {
|
||||
ImHintHelper.show(it)
|
||||
} else {
|
||||
ImHintHelper.dismiss(it)
|
||||
removeNotification()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
// try {
|
||||
// CurrentActivityHolder.getCurrentActivity()?.let {
|
||||
// if (isActivityValid(it)) {
|
||||
// if (shouldShowFloatingWindow) {
|
||||
// ImHintHelper.show(it)
|
||||
// } else {
|
||||
// ImHintHelper.dismiss(it)
|
||||
// removeNotification()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun sendFeedbackMessage(message: String) {
|
||||
val fromToMessage = IMMessage.createTxtMessage(message)
|
||||
runOnIoThread {
|
||||
tryWithDefaultCatch {
|
||||
IMChat.getInstance().sendMessage(fromToMessage, object : ChatListener {
|
||||
override fun onProgress(p0: Int) {}
|
||||
override fun onSuccess() {}
|
||||
override fun onFailed() {}
|
||||
})
|
||||
}
|
||||
}
|
||||
// val fromToMessage = IMMessage.createTxtMessage(message)
|
||||
// runOnIoThread {
|
||||
// tryWithDefaultCatch {
|
||||
// IMChat.getInstance().sendMessage(fromToMessage, object : ChatListener {
|
||||
// override fun onProgress(p0: Int) {}
|
||||
// override fun onSuccess() {}
|
||||
// override fun onFailed() {}
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
fun updateShouldShowFloatingWindow(show: Boolean) {
|
||||
SPUtils.setBoolean(SP_FLOATING_WINDOW_KEY + UserManager.getInstance().userId, show)
|
||||
shouldShowFloatingWindow = show
|
||||
// SPUtils.setBoolean(SP_FLOATING_WINDOW_KEY + UserManager.getInstance().userId, show)
|
||||
// shouldShowFloatingWindow = show
|
||||
}
|
||||
|
||||
fun updateShouldShowFloatingWindowDot(show: Boolean) {
|
||||
SPUtils.setBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId, show)
|
||||
shouldShowFloatingWindowDot = show
|
||||
// SPUtils.setBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId, show)
|
||||
// shouldShowFloatingWindowDot = show
|
||||
}
|
||||
|
||||
private fun isActivityValid(activity: Activity): Boolean {
|
||||
|
||||
@ -1,20 +1,9 @@
|
||||
package com.gh.common.im
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.util.doOnMainProcessOnly
|
||||
import com.gh.gamecenter.R
|
||||
import com.m7.imkfsdk.chat.ChatActivity
|
||||
import com.m7.imkfsdk.utils.Utils
|
||||
import com.moor.imkf.IMChatManager
|
||||
|
||||
class ImReceiver : BroadcastReceiver() {
|
||||
|
||||
@ -26,54 +15,54 @@ class ImReceiver : BroadcastReceiver() {
|
||||
var notificationManager: NotificationManager? = null
|
||||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
context?.doOnMainProcessOnly {
|
||||
intent?.let {
|
||||
if (intent.action == IMChatManager.NEW_MSG_ACTION) {
|
||||
notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
// 判断 ImActivity 是否在最顶端
|
||||
if (CurrentActivityHolder.getCurrentActivity() is ChatActivity) {
|
||||
ImManager.showFloatingWindow()
|
||||
ImManager.updateShouldShowFloatingWindowDot(false)
|
||||
} else {
|
||||
val contentIntent = Intent(Utils.getApp(), ChatActivity::class.java)
|
||||
|
||||
contentIntent.putExtra("PeerId", "")
|
||||
contentIntent.putExtra("type", "peedId")
|
||||
|
||||
contentIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
val resultPendingIntent = PendingIntent.getActivity(
|
||||
Utils.getApp(),
|
||||
0,
|
||||
contentIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
// 新的通知
|
||||
val builder = NotificationCompat.Builder(Utils.getApp(), "Halo_IM")
|
||||
val notification = builder.setTicker("您有新的消息")
|
||||
.setDefaults(Notification.DEFAULT_ALL)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setContentIntent(resultPendingIntent)
|
||||
.setContentTitle("光环助手客服回复")
|
||||
.setContentText("您有新的消息")
|
||||
.setAutoCancel(true)
|
||||
.build()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel("Halo_IM", "Halo_IM", NotificationManager.IMPORTANCE_DEFAULT)
|
||||
notificationManager?.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
if (notification != null) {
|
||||
notificationManager?.notify(NOTIFICATION_ID, notification)
|
||||
ImManager.showFloatingWindow()
|
||||
}
|
||||
}
|
||||
} else if (intent.action == IMChatManager.FINISH_ACTION) {
|
||||
ImManager.dismissFloatingWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
// context?.doOnMainProcessOnly {
|
||||
// intent?.let {
|
||||
// if (intent.action == IMChatManager.NEW_MSG_ACTION) {
|
||||
// notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
// // 判断 ImActivity 是否在最顶端
|
||||
// if (CurrentActivityHolder.getCurrentActivity() is ChatActivity) {
|
||||
// ImManager.showFloatingWindow()
|
||||
// ImManager.updateShouldShowFloatingWindowDot(false)
|
||||
// } else {
|
||||
// val contentIntent = Intent(Utils.getApp(), ChatActivity::class.java)
|
||||
//
|
||||
// contentIntent.putExtra("PeerId", "")
|
||||
// contentIntent.putExtra("type", "peedId")
|
||||
//
|
||||
// contentIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
// val resultPendingIntent = PendingIntent.getActivity(
|
||||
// Utils.getApp(),
|
||||
// 0,
|
||||
// contentIntent,
|
||||
// PendingIntent.FLAG_UPDATE_CURRENT
|
||||
// )
|
||||
//
|
||||
// // 新的通知
|
||||
// val builder = NotificationCompat.Builder(Utils.getApp(), "Halo_IM")
|
||||
// val notification = builder.setTicker("您有新的消息")
|
||||
// .setDefaults(Notification.DEFAULT_ALL)
|
||||
// .setSmallIcon(R.drawable.ic_notification)
|
||||
// .setWhen(System.currentTimeMillis())
|
||||
// .setContentIntent(resultPendingIntent)
|
||||
// .setContentTitle("光环助手客服回复")
|
||||
// .setContentText("您有新的消息")
|
||||
// .setAutoCancel(true)
|
||||
// .build()
|
||||
//
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// val channel = NotificationChannel("Halo_IM", "Halo_IM", NotificationManager.IMPORTANCE_DEFAULT)
|
||||
// notificationManager?.createNotificationChannel(channel)
|
||||
// }
|
||||
//
|
||||
// if (notification != null) {
|
||||
// notificationManager?.notify(NOTIFICATION_ID, notification)
|
||||
// ImManager.showFloatingWindow()
|
||||
// }
|
||||
// }
|
||||
// } else if (intent.action == IMChatManager.FINISH_ACTION) {
|
||||
// ImManager.dismissFloatingWindow()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@ import com.aliyun.sls.android.sdk.model.Log
|
||||
import com.aliyun.sls.android.sdk.model.LogGroup
|
||||
import com.gh.common.exposure.ExposureEntity
|
||||
import com.gh.common.exposure.meta.Meta
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.loghub.LoghubHelper
|
||||
import org.json.JSONObject
|
||||
import java.util.concurrent.Executors
|
||||
@ -69,13 +70,16 @@ object LoghubUtils {
|
||||
|
||||
fun commitSavedLoghubEvents() {
|
||||
loghubEventExecutor.execute {
|
||||
if (loghubEventSet.isEmpty()) return@execute
|
||||
// TODO 初始化 loghubHelper 去掉这个 tryCatch 块
|
||||
tryWithDefaultCatch {
|
||||
if (loghubEventSet.isEmpty()) return@execute
|
||||
|
||||
val exposureList = loghubEventSet.toList()
|
||||
val exposureList = loghubEventSet.toList()
|
||||
|
||||
createLogGroupAndUpload()
|
||||
loghubEventSet.removeAll(exposureList)
|
||||
loghubEventDao.deleteMany(exposureList)
|
||||
createLogGroupAndUpload()
|
||||
loghubEventSet.removeAll(exposureList)
|
||||
loghubEventDao.deleteMany(exposureList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.database.ContentObserver
|
||||
import android.media.AudioManager
|
||||
import android.os.Handler
|
||||
import com.gh.common.util.tryCatchInRelease
|
||||
|
||||
class VolumeObserver(var context: Context, handler: Handler, var callback: MuteCallback? = null)
|
||||
: ContentObserver(handler) {
|
||||
@ -11,7 +12,8 @@ class VolumeObserver(var context: Context, handler: Handler, var callback: MuteC
|
||||
|
||||
init {
|
||||
val audio = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
previousVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC)
|
||||
// 部分设备的 audioManager getStreamVolume 内部会触发空指针 :(
|
||||
tryCatchInRelease { previousVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC) }
|
||||
}
|
||||
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
|
||||
@ -5,7 +5,7 @@ import com.gh.common.util.ApkActiveUtils
|
||||
import com.gh.common.util.RandomUtils
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.tencent.bugly.beta.tinker.TinkerManager.getApplication
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.Observable
|
||||
|
||||
// 热门卡牌的仓库
|
||||
@ -16,7 +16,7 @@ object RemenkapaiRepository {
|
||||
@JvmStatic
|
||||
fun getRemenkapai(size: Int): Observable<List<GameEntity>> {
|
||||
return if (remenkapaiList.isEmpty()) {
|
||||
RetrofitManager.getInstance(getApplication()).sensitiveApi.remenkapai
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).sensitiveApi.remenkapai
|
||||
.map(RegionSettingHelper.filterGame)
|
||||
.map { gameList -> filterEntityWithoutApk(gameList) }
|
||||
.map { pickRandomSizeEntity(size) }
|
||||
|
||||
@ -0,0 +1,244 @@
|
||||
package com.gh.common.simulator
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.g00fy2.versioncompare.Version
|
||||
import com.gh.common.AppExecutor.uiExecutor
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.dialog.TrackableDialog
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.PackageInstaller.getDownloadPath
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.ApkEntity
|
||||
import com.gh.gamecenter.entity.SimulatorEntity
|
||||
import com.gh.gamecenter.entity.TrackableEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.*
|
||||
import com.lightgame.utils.Utils
|
||||
import java.text.DecimalFormat
|
||||
|
||||
class SimulatorDownloadManager private constructor() {
|
||||
|
||||
private var app_pb_progress: ProgressBar? = null
|
||||
private var appProgressSize: TextView? = null
|
||||
private var appProgressRemain: TextView? = null
|
||||
private var appProgressPercent: TextView? = null
|
||||
private var appProgressFilling: View? = null
|
||||
private var appProgressAnchor: View? = null
|
||||
private var downloadDialog: Dialog? = null
|
||||
|
||||
private var simulatorLocation: SimulatorLocation? = null
|
||||
private var simulator: SimulatorEntity? = null
|
||||
private var gameId: String = ""
|
||||
private var gameName: String = ""
|
||||
private var downloadType: String = ""
|
||||
|
||||
private val dataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity?) {
|
||||
if (downloadEntity?.isSimulatorDownload() == true) {
|
||||
val size = downloadEntity.progress.toFloat() / 1024 / 1024
|
||||
val df = DecimalFormat("0.00")
|
||||
appProgressSize!!.text = "${df.format(size.toDouble())}MB"
|
||||
appProgressRemain!!.text = String.format("剩余%s", SpeedUtils.getRemainSecondTime(downloadEntity.size,
|
||||
downloadEntity.progress, downloadEntity.speed * 1024))
|
||||
app_pb_progress!!.progress = (downloadEntity.percent * 10).toInt()
|
||||
|
||||
val width = app_pb_progress!!.width
|
||||
val marLeft = (downloadEntity.percent / 100 * width).toInt()
|
||||
val anchorLp = appProgressAnchor!!.layoutParams
|
||||
if (anchorLp is ConstraintLayout.LayoutParams) {
|
||||
anchorLp.leftMargin = marLeft
|
||||
appProgressAnchor!!.layoutParams = anchorLp
|
||||
}
|
||||
|
||||
val fillingLp = appProgressFilling!!.layoutParams
|
||||
fillingLp.width = marLeft + DisplayUtils.dip2px(5f)
|
||||
appProgressFilling!!.layoutParams = fillingLp
|
||||
|
||||
appProgressPercent?.text = if (downloadEntity.percent != 100.0) "${downloadEntity.percent}%" else "100%"
|
||||
when {
|
||||
DownloadStatus.done == downloadEntity.status -> {
|
||||
val locationStr = if (simulatorLocation == SimulatorLocation.LAUNCH) "${simulatorLocation?.value}《${gameName}》" else simulatorLocation?.value
|
||||
val fileName = downloadEntity.path.substring(downloadEntity.path.lastIndexOf('/') + 1).removeSuffix(".apk")
|
||||
val startTime = downloadEntity.getMetaExtra(Constants.SIMULATOR_DOWNLOAD_START_TIME)
|
||||
LogUtils.uploadSimulatorDownload("simulator_download_complete", fileName, simulator?.id, downloadEntity.name, gameId, locationStr, downloadType, startTime)
|
||||
DownloadManager.getInstance(HaloApp.getInstance().application).cancel(downloadEntity.url, false, true)
|
||||
downloadDialog?.dismiss()
|
||||
}
|
||||
DownloadStatus.neterror == downloadEntity.status -> {
|
||||
ToastUtils.showToast("网络不稳定,下载任务已暂停")
|
||||
}
|
||||
DownloadStatus.timeout == downloadEntity.status -> {
|
||||
ToastUtils.showToast("网络不稳定,下载任务已暂停")
|
||||
}
|
||||
DownloadStatus.notfound == downloadEntity.status -> {
|
||||
ToastUtils.showToast("下载链接异常,请稍后重试")
|
||||
}
|
||||
DownloadStatus.hijack == downloadEntity.status -> {
|
||||
ToastUtils.showToast("网络劫持,请稍后重试")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun showDownloadDialog(context: Context, simulator: SimulatorEntity?, location: SimulatorLocation) {
|
||||
showDownloadDialog(context, simulator, location, "", "", null)
|
||||
}
|
||||
|
||||
fun showDownloadDialog(context: Context, simulator: SimulatorEntity?, location: SimulatorLocation, gameId: String = "", gameName: String = "", cancelCallback: (() -> Unit)? = null) {
|
||||
this.simulatorLocation = location
|
||||
this.simulator = simulator
|
||||
this.gameId = gameId
|
||||
this.gameName = gameName
|
||||
//判断是否隐藏
|
||||
if (simulator?.active == false) {
|
||||
showNoneEmulatorDialog(context)
|
||||
return
|
||||
}
|
||||
val isInstalled = PackageUtils.isInstalledFromAllPackage(context, simulator?.apk?.packageName)
|
||||
val versionFromInstalledApp = PackageUtils.getVersionByPackage(simulator?.apk?.packageName)
|
||||
val shouldShowUpdate = Version(simulator?.apk?.version).isHigherThan(versionFromInstalledApp)
|
||||
val title = if (shouldShowUpdate && isInstalled) "更新模拟器" else "安装模拟器"
|
||||
val message = if (shouldShowUpdate && isInstalled) "检测到模拟器存在更高版本,是否前往更新" else "模拟器游戏需要先下载安装对应的模拟器,才可以运行"
|
||||
val positiveText = if (shouldShowUpdate && isInstalled) "更新(${simulator?.apk?.size})" else "下载(${simulator?.apk?.size})"
|
||||
val negativeText = if (shouldShowUpdate && isInstalled) "下次再说" else "取消"
|
||||
downloadType = if (shouldShowUpdate && isInstalled) "update" else "download"
|
||||
|
||||
val trackableEntity = TrackableEntity("模拟器下载",
|
||||
key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗",
|
||||
logShowEvent = true
|
||||
)
|
||||
DialogUtils.showNewAlertDialog(context, title, message, negativeText, positiveText, trackableEntity, Gravity.LEFT, {
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
cancelCallback?.invoke()
|
||||
MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说")
|
||||
}
|
||||
}, {
|
||||
showDownloadingDialog(context, simulator)
|
||||
MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, if (shouldShowUpdate && isInstalled) "点击更新" else "点击下载")
|
||||
})
|
||||
}
|
||||
|
||||
private fun showDownloadingDialog(context: Context, simulator: SimulatorEntity?) {
|
||||
val msg = FileUtils.isCanDownload(context, simulator?.apk?.size)
|
||||
if (!msg.isNullOrEmpty()) {
|
||||
Utils.toast(context, msg)
|
||||
return
|
||||
}
|
||||
if (NetworkUtils.isMobileConnected(context)) {
|
||||
Utils.toast(context, "当前使用移动数据进行下载")
|
||||
}
|
||||
|
||||
downloadDialog = TrackableDialog(context, R.style.GhAlertDialog, "模拟器下载", "下载中弹窗")
|
||||
downloadDialog?.window?.setBackgroundDrawableResource(R.color.transparent)
|
||||
|
||||
val view = View.inflate(context, R.layout.download_simulator_dialog, null)
|
||||
|
||||
app_pb_progress = view.findViewById(R.id.progress)
|
||||
appProgressSize = view.findViewById(R.id.size)
|
||||
appProgressRemain = view.findViewById(R.id.remain)
|
||||
appProgressAnchor = view.findViewById(R.id.progress_anchor)
|
||||
appProgressPercent = view.findViewById(R.id.percent)
|
||||
appProgressFilling = view.findViewById(R.id.progress_filling)
|
||||
|
||||
view.findViewById<View>(R.id.app_tv_cancel).setOnClickListener {
|
||||
DownloadManager.getInstance(context).pause(simulator?.apk?.url)
|
||||
MtaHelper.onEvent("模拟器下载", "下载中弹窗", "点击关闭")
|
||||
downloadDialog?.dismiss()
|
||||
}
|
||||
|
||||
downloadDialog?.setOnDismissListener {
|
||||
DownloadManager.getInstance(context).removeObserver(dataWatcher)
|
||||
}
|
||||
|
||||
downloadDialog?.setCanceledOnTouchOutside(false)
|
||||
downloadDialog?.setCancelable(false)
|
||||
downloadDialog?.closeOptionsMenu()
|
||||
downloadDialog?.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
downloadDialog?.setContentView(view)
|
||||
val params = downloadDialog?.window?.attributes
|
||||
params?.width = context.resources.displayMetrics.widthPixels - DisplayUtils.dip2px(60f)
|
||||
downloadDialog?.window?.attributes = params
|
||||
|
||||
download(context, simulator)
|
||||
}
|
||||
|
||||
private fun showNoneEmulatorDialog(context: Context) {
|
||||
val dialog = DialogUtils.showNewAlertDialog(context, "安装模拟器", "模拟器游戏需要先下载安装对应的模拟器,才可以运行", "取消", "暂无下载", null, {
|
||||
ToastUtils.showToast("该模拟器暂未提供下载")
|
||||
})
|
||||
dialog?.window?.findViewById<TextView>(R.id.confirm)?.setTextColor(ContextCompat.getColor(context, R.color.text_cccccc))
|
||||
}
|
||||
|
||||
private fun download(context: Context, simulator: SimulatorEntity?) {
|
||||
val apkEntity = simulator?.apk ?: return
|
||||
DownloadManager.getInstance(context).pauseAll()
|
||||
|
||||
val entity = DownloadManager.getInstance(context).getDownloadEntityByUrl(apkEntity.url)
|
||||
if (entity != null) {
|
||||
when (entity.status) {
|
||||
DownloadStatus.pause, DownloadStatus.subscribe,
|
||||
DownloadStatus.neterror, DownloadStatus.timeout -> {
|
||||
DownloadManager.getInstance(context).addObserver(dataWatcher)
|
||||
uiExecutor.executeWithDelay(Runnable { DownloadManager.getInstance(context).resume(entity, true) }, 200)
|
||||
downloadDialog?.show()
|
||||
}
|
||||
DownloadStatus.done -> DataChanger.notifyDataChanged(entity)
|
||||
|
||||
else -> createDownload(context, apkEntity, simulator)
|
||||
}
|
||||
} else {
|
||||
createDownload(context, apkEntity, simulator)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createDownload(context: Context, apkEntity: ApkEntity, simulator: SimulatorEntity) {
|
||||
DownloadManager.getInstance(context).addObserver(dataWatcher)
|
||||
val downloadEntity = DownloadEntity()
|
||||
downloadEntity.url = apkEntity.url
|
||||
downloadEntity.name = simulator.name
|
||||
downloadEntity.path = getDownloadPath(simulator.name, apkEntity.format)
|
||||
downloadEntity.platform = apkEntity.getPlatform()
|
||||
downloadEntity.packageName = apkEntity.packageName
|
||||
downloadEntity.versionName = apkEntity.version
|
||||
|
||||
downloadEntity.addMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE, Constants.SIMULATOR_DOWNLOAD)
|
||||
downloadEntity.addMetaExtra(Constants.SIMULATOR_DOWNLOAD_START_TIME, (System.currentTimeMillis() / 1000).toString())
|
||||
uiExecutor.executeWithDelay(Runnable { DownloadManager.getInstance(context).add(downloadEntity) }, 200)
|
||||
|
||||
val locationStr = if (simulatorLocation == SimulatorLocation.LAUNCH) "${simulatorLocation?.value}《${gameName}》" else simulatorLocation?.value
|
||||
val fileName = downloadEntity.path.substring(downloadEntity.path.lastIndexOf('/') + 1).removeSuffix(".apk")
|
||||
LogUtils.uploadSimulatorDownload("simulator_download", fileName, simulator.id, simulator.name, gameId, locationStr, downloadType, "")
|
||||
|
||||
downloadDialog?.show()
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var instance: SimulatorDownloadManager? = null
|
||||
|
||||
@JvmStatic
|
||||
fun getInstance(): SimulatorDownloadManager {
|
||||
return instance ?: synchronized(this) {
|
||||
instance ?: SimulatorDownloadManager().also { instance = it }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class SimulatorLocation(val value: String) {
|
||||
LAUNCH("启动"),
|
||||
SIMULATOR_GAME("模拟器游戏"),
|
||||
SIMULATOR_MANAGE("模拟器游戏-模拟器管理")
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,219 @@
|
||||
package com.gh.common.simulator
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import com.g00fy2.versioncompare.Version
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.EmptyResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadDao
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.FileUtils
|
||||
import com.lightgame.utils.AppManager
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import java.io.File
|
||||
|
||||
|
||||
object SimulatorGameManager {
|
||||
|
||||
private val gamePath = FileUtils.getDownloadPath(HaloApp.getInstance().application, "emulator_game")
|
||||
|
||||
@JvmStatic
|
||||
fun getPathByType(type: String) = "${gamePath}/${type}"
|
||||
|
||||
@JvmStatic
|
||||
fun deleteLocalGames(names: List<String>) {
|
||||
val downloadEntityList = DownloadDao.getInstance(HaloApp.getInstance().application).all
|
||||
names.forEach { name ->
|
||||
val downloadEntity = downloadEntityList.find { it.name == name }
|
||||
if (downloadEntity != null) {
|
||||
val file = File(downloadEntity.path)
|
||||
if (file.exists()) {
|
||||
file.delete()
|
||||
DownloadDao.getInstance(HaloApp.getInstance().application).delete(downloadEntity.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun deleteLocalGame(name: String) {
|
||||
val downloadEntityList = DownloadDao.getInstance(HaloApp.getInstance().application).all
|
||||
val downloadEntity = downloadEntityList.find { it.name == name }
|
||||
if (downloadEntity != null) {
|
||||
val file = File(downloadEntity.path)
|
||||
if (file.exists()) {
|
||||
file.delete()
|
||||
DownloadDao.getInstance(HaloApp.getInstance().application).delete(downloadEntity.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun findDownloadEntityByUrl(url: String?): DownloadEntity? {
|
||||
val downloadEntity = DownloadDao.getInstance(HaloApp.getInstance().application).get(url)
|
||||
if (downloadEntity != null) {
|
||||
val isFileCompleted = DownloadManager.getInstance(HaloApp.getInstance().application).isFileCompleted(url)
|
||||
if (downloadEntity.isSimulatorGame() && isFileCompleted) {
|
||||
return downloadEntity
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isSimulatorGame(gameEntity: GameEntity) = gameEntity.category == "simulator"
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun launchSimulatorGame(downloadEntity: DownloadEntity, gameEntity: GameEntity) {
|
||||
val versionFromInstalledApp = PackageUtils.getVersionByPackage(gameEntity.simulator?.apk?.packageName)
|
||||
val shouldShowUpdate = Version(gameEntity.simulator?.apk?.version).isHigherThan(versionFromInstalledApp)
|
||||
if (shouldShowUpdate) {
|
||||
SimulatorDownloadManager.getInstance().showDownloadDialog(AppManager.getInstance().recentActiveActivity, gameEntity.simulator,
|
||||
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name
|
||||
?: "") {
|
||||
jumpToSimulator(downloadEntity, gameEntity)
|
||||
}
|
||||
} else {
|
||||
jumpToSimulator(downloadEntity, gameEntity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun jumpToSimulator(downloadEntity: DownloadEntity, gameEntity: GameEntity) {
|
||||
val intent = Intent()
|
||||
intent.data = Uri.fromFile(File(downloadEntity.path))
|
||||
if (gameEntity.simulatorType == "FBA") {
|
||||
val apkEntity = gameEntity.getApk()[0]
|
||||
intent.putExtra("rom_name", apkEntity.packageName)
|
||||
}
|
||||
intent.putExtra("default_path", downloadEntity.path.substring(0, downloadEntity.path.lastIndexOf('/')))
|
||||
intent.putExtra("game_type", gameEntity.simulatorType)
|
||||
intent.putExtra("title", downloadEntity.name)
|
||||
intent.putExtra("icon", gameEntity.icon ?: "")
|
||||
intent.putExtra("meta", LogUtils.getMetaObject().toString())
|
||||
intent.putExtra("simulatorId", gameEntity.simulator?.id)
|
||||
intent.putExtra("simulatorName", gameEntity.simulator?.name)
|
||||
intent.putExtra("gameId", gameEntity.id)
|
||||
|
||||
val destActivity = "com.gh.emu.RequestPermissionActivity"
|
||||
intent.setClassName(gameEntity.simulator?.apk?.packageName ?: "", destActivity)
|
||||
try {
|
||||
AppManager.getInstance().recentActiveActivity.startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
ToastUtils.showToast("模拟器安装错误")
|
||||
}
|
||||
|
||||
recordPlaySimulatorGames(gameEntity.id)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 记录设备下载的模拟器游戏
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun recordDownloadSimulatorGames(gameId: String) {
|
||||
val requestMap = hashMapOf<String, Any>()
|
||||
requestMap["game_id"] = gameId
|
||||
requestMap["package"] = "-"
|
||||
val body = requestMap.createRequestBodyAny()
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
.downloadSimulatorGames(HaloApp.getInstance().gid, body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(EmptyResponse())
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记已玩过
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun postPlayedGame(gameId: String, packageName: String) {
|
||||
if (!TextUtils.isEmpty(gameId) && UserManager.getInstance().isLoggedIn) {
|
||||
val requestMap = hashMapOf<String, Any>()
|
||||
requestMap["game_id"] = gameId
|
||||
requestMap["package"] = packageName
|
||||
val body = requestMap.toRequestBody()
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
.postPlayedGame(UserManager.getInstance().userId, body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(EmptyResponse())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 记录启动设备上的模拟器游戏
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun recordPlaySimulatorGames(gameId: String) {
|
||||
val requestMap = hashMapOf<String, Any>()
|
||||
requestMap["game_id"] = gameId
|
||||
requestMap["package"] = "-"
|
||||
val body = requestMap.createRequestBodyAny()
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
.playedSimulatorGames(HaloApp.getInstance().gid, body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(EmptyResponse())
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除设备下载模拟器游戏的记录
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun deleteSimulatorGame(gameId: String, callback: () -> Unit) {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
.deleteSimulatorGame(HaloApp.getInstance().gid, gameId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
callback.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除设备下载模拟器游戏的记录
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun deleteSimulatorGames(gameIds: List<String>, callback: () -> Unit) {
|
||||
val requestMap = hashMapOf<String, Any>()
|
||||
requestMap["game_ids"] = gameIds
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
.deleteSimulatorGames(HaloApp.getInstance().gid, requestMap.toRequestBody())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
callback.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除设备下载模拟器游戏的记录
|
||||
*/
|
||||
@JvmStatic
|
||||
@SuppressLint("CheckResult")
|
||||
fun deleteAllSimulatorGame() {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
.deleteAllSimulatorGame(HaloApp.getInstance().gid)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(EmptyResponse())
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.gh.common.structure
|
||||
|
||||
class FixedSizeLinkedHashSet<T>(var maxSize: Int) : LinkedHashSet<T>() {
|
||||
override fun add(element: T): Boolean {
|
||||
if (size == maxSize) {
|
||||
pop()
|
||||
}
|
||||
return super.add(element);
|
||||
}
|
||||
|
||||
private fun pop() {
|
||||
if (size > 0) {
|
||||
remove(iterator().next())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,14 +5,17 @@ object SyncFieldConstants {
|
||||
// 是否点赞
|
||||
const val ANSWER_VOTE = "ANSWER_VOTE"
|
||||
const val ARTICLE_VOTE = "ARTICLE_VOTE"
|
||||
const val ARTICLE_COMMENT_VOTE = "ARTICLE_COMMENT_VOTE"
|
||||
|
||||
// 赞同数量
|
||||
const val ANSWER_VOTE_COUNT = "ANSWER_VOTE_COUNT"
|
||||
const val ARTICLE_VOTE_COUNT = "ARTICLE_VOTE_COUNT"
|
||||
const val ARTICLE_COMMENT_VOTE_COUNT = "ARTICLE_COMMENT_VOTE_COUNT"
|
||||
|
||||
// 评论数量
|
||||
const val ANSWER_COMMENT_COUNT = "ANSWER_COMMENT_COUNT"
|
||||
const val ARTICLE_COMMENT_COUNT = "ARTICLE_COMMENT_COUNT"
|
||||
const val ARTICLE_COMMENT_REPLY_COUNT = "ARTICLE_COMMENT_REPLY_COUNT"
|
||||
|
||||
// 回答数量
|
||||
const val ANSWER_COUNT = "ANSWER_COUNT"
|
||||
|
||||
@ -21,9 +21,7 @@ object ActivationHelper {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun sendActivationInfo() {
|
||||
// 能获取到 IMEI 并且之前没发送过激活信息才发
|
||||
if (!mHasSentActivatedInfo
|
||||
&& Util_System_Phone_State.canGetImei(HaloApp.getInstance().application)) {
|
||||
if (!mHasSentActivatedInfo) {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.api.postActivationInfo()
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@ -5,11 +5,12 @@ import com.gh.gamecenter.entity.SettingsEntity
|
||||
|
||||
object AdHelper {
|
||||
|
||||
// 搜索为空/求版本/意见反馈-功能收录/发现
|
||||
// 搜索为空/求版本/意见反馈-功能收录/发现/模拟器游戏
|
||||
const val LOCATION_SEARCH_EMPTY = "search_empty"
|
||||
const val LOCATION_GAME_REQUEST_VERSION = "game_request_version"
|
||||
const val LOCATION_SUGGESTION_FUNCTION = "suggestion_function"
|
||||
const val LOCATION_DISCOVER = "discover"
|
||||
const val LOCATION_SIMULATOR_GAME = "simulator_game"
|
||||
|
||||
fun getAd(location: String): SettingsEntity.AD? {
|
||||
val adList = Config.getSettings()?.adList ?: return null
|
||||
@ -34,4 +35,19 @@ object AdHelper {
|
||||
return discoverAdList
|
||||
}
|
||||
|
||||
fun getAdForLocation(location: String): SettingsEntity.AD? {
|
||||
val adList = Config.getSettings()?.adList ?: return null
|
||||
|
||||
var result: SettingsEntity.AD? = null
|
||||
run outside@ {
|
||||
for (ad in adList) {
|
||||
if (ad.location == location) {
|
||||
result = ad
|
||||
return@outside
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,10 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.alibaba.wireless.security.jaq.avmp.IJAQAVMPSignComponent
|
||||
import com.alibaba.wireless.security.open.SecurityGuardManager
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
object AntiBotHelper {
|
||||
@JvmStatic
|
||||
val manager by lazy {
|
||||
SecurityGuardManager.getInstance(HaloApp.getInstance().application).getInterface(IJAQAVMPSignComponent::class.java).apply {
|
||||
this.initialize()
|
||||
}
|
||||
}
|
||||
// @JvmStatic
|
||||
// val manager by lazy {
|
||||
// SecurityGuardManager.getInstance(HaloApp.getInstance().application).getInterface(IJAQAVMPSignComponent::class.java).apply {
|
||||
// this.initialize()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
@ -14,9 +15,17 @@ import com.halo.assistant.HaloApp;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.renderscript.Allocation;
|
||||
import androidx.renderscript.Element;
|
||||
import androidx.renderscript.RenderScript;
|
||||
import androidx.renderscript.ScriptIntrinsicBlur;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/10/21.
|
||||
*/
|
||||
@ -114,6 +123,14 @@ public class BitmapUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Bitmap getBitmapByFile(String filepath, int w, int h) {
|
||||
return getBitmapByFile(filepath, w, h, Bitmap.Config.RGB_565);
|
||||
}
|
||||
|
||||
public static Bitmap getBitmapByFile(String filepath, Bitmap.Config config) {
|
||||
return getBitmapByFile(filepath, 0, 0, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件路径返回bitmap
|
||||
*
|
||||
@ -122,12 +139,12 @@ public class BitmapUtils {
|
||||
* @param h 高
|
||||
* @return bitmap
|
||||
*/
|
||||
public static Bitmap getBitmapByFile(String filepath, int w, int h) {
|
||||
public static Bitmap getBitmapByFile(String filepath, int w, int h, Bitmap.Config config) {
|
||||
try {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
// 设置为ture只获取图片大小
|
||||
options.inJustDecodeBounds = true;
|
||||
options.inPreferredConfig = Bitmap.Config.RGB_565;
|
||||
options.inPreferredConfig = config;
|
||||
// 返回为空
|
||||
BitmapFactory.decodeFile(filepath, options);
|
||||
int width = options.outWidth;
|
||||
@ -135,8 +152,8 @@ public class BitmapUtils {
|
||||
float scaleWidth = 0.f, scaleHeight = 0.f;
|
||||
if (width > w || height > h) {
|
||||
// 缩放
|
||||
scaleWidth = ((float) width) / w;
|
||||
scaleHeight = ((float) height) / h;
|
||||
if (w > 0) scaleWidth = ((float) width) / w;
|
||||
if (h > 0) scaleHeight = ((float) height) / h;
|
||||
}
|
||||
options.inJustDecodeBounds = false;
|
||||
int scale = (int) Math.ceil(Math.max(scaleWidth, scaleHeight));
|
||||
@ -189,6 +206,7 @@ public class BitmapUtils {
|
||||
|
||||
/**
|
||||
* Drawable转Bitmap
|
||||
*
|
||||
* @param isSquare 是否是正方形
|
||||
*/
|
||||
public static Bitmap drawableToBitmap(Drawable drawable, boolean isSquare) {
|
||||
@ -196,7 +214,7 @@ public class BitmapUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
int w,h;
|
||||
int w, h;
|
||||
|
||||
// 取 drawable 的长宽
|
||||
w = drawable.getIntrinsicWidth();
|
||||
@ -227,4 +245,108 @@ public class BitmapUtils {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改bitmap透明度
|
||||
*
|
||||
* @param sourceImg
|
||||
* @param config
|
||||
* @param number
|
||||
* @return
|
||||
*/
|
||||
public static Bitmap getTransparentBitmap(Bitmap sourceImg, Bitmap.Config config, int number) {
|
||||
int[] argb = new int[sourceImg.getWidth() * sourceImg.getHeight()];
|
||||
sourceImg.getPixels(argb, 0, sourceImg.getWidth(), 0, 0, sourceImg
|
||||
.getWidth(), sourceImg.getHeight());// 获得图片的ARGB值
|
||||
number = number * 255 / 100;
|
||||
for (int i = 0; i < argb.length; i++) {
|
||||
argb[i] = (number << 24) | (argb[i] & 0x00FFFFFF);
|
||||
}
|
||||
sourceImg = Bitmap.createBitmap(argb, sourceImg.getWidth(), sourceImg
|
||||
.getHeight(), config);
|
||||
return sourceImg;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 高斯模糊
|
||||
*
|
||||
* @param context
|
||||
* @param image
|
||||
* @param radius
|
||||
* @return
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
public static Bitmap getBlurBitmap(Context context, Bitmap image, @IntRange(from = 1, to = 25) int radius) {
|
||||
// 计算图片缩小后的长宽
|
||||
int width = Math.round(image.getWidth() * 0.8f);
|
||||
int height = Math.round(image.getHeight() * 0.8f);
|
||||
|
||||
// 将缩小后的图片做为预渲染的图片。
|
||||
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
|
||||
// 创建一张渲染后的输出图片。
|
||||
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
|
||||
// 创建RenderScript内核对象
|
||||
RenderScript rs = RenderScript.create(context);
|
||||
// 创建一个模糊效果的RenderScript的工具对象
|
||||
ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
|
||||
|
||||
// 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间。
|
||||
// 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去。
|
||||
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
|
||||
Allocation tmpOut = Allocation.createTyped(rs, tmpIn.getType());
|
||||
// 设置渲染的模糊程度, 25f是最大模糊度
|
||||
blurScript.setRadius(radius);
|
||||
// 设置blurScript对象的输入内存
|
||||
blurScript.setInput(tmpIn);
|
||||
// 将输出数据保存到输出内存中
|
||||
blurScript.forEach(tmpOut);
|
||||
|
||||
// 将数据填充到Allocation中
|
||||
tmpOut.copyTo(outputBitmap);
|
||||
|
||||
return outputBitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存图片
|
||||
*
|
||||
* @param bitmap
|
||||
* @param path
|
||||
*/
|
||||
public static void saveBitmap(Bitmap bitmap, String path) {
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
FileOutputStream out;
|
||||
try {
|
||||
out = new FileOutputStream(file);
|
||||
if (bitmap.compress(Bitmap.CompressFormat.PNG, 80, out)) {
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Bitmap compressBitmap(Bitmap bitmap) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
Matrix matrix = new Matrix();
|
||||
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||
result.compress(Bitmap.CompressFormat.WEBP, 100, bos);
|
||||
|
||||
while (bos.toByteArray().length > 400 * 1024) {
|
||||
System.out.println(bos.toByteArray().length);
|
||||
matrix.setScale(0.9f, 0.9f);
|
||||
result = Bitmap.createBitmap(result, 0, 0, result.getWidth(), result.getHeight(), matrix, true);
|
||||
bos.reset();
|
||||
result.compress(Bitmap.CompressFormat.WEBP, 100, bos);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.gh.gamecenter.room.AppDatabase
|
||||
import com.gh.gamecenter.room.dao.CommentDraftDao
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
object CommentDraftContainer {
|
||||
val commentDraftDao: CommentDraftDao by lazy { AppDatabase.getInstance(HaloApp.getInstance().application).commentDraftDao() }
|
||||
}
|
||||
@ -16,8 +16,8 @@ import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.qa.comment.OnCommentOptionClickListener
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import com.tencent.bugly.beta.tinker.TinkerManager.getApplication
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
@ -33,12 +33,16 @@ object CommentHelper {
|
||||
showConversation: Boolean,
|
||||
articleId: String,
|
||||
communityId: String,
|
||||
isShowTop: Boolean = false,
|
||||
ignoreModerator: Boolean = false,
|
||||
listener: OnCommentOptionClickListener?) {
|
||||
showCommentOptions(view = view,
|
||||
commentEntity = commentEntity,
|
||||
showConversation = showConversation,
|
||||
articleId = articleId,
|
||||
communityId = communityId,
|
||||
isShowTop = isShowTop,
|
||||
ignoreModerator = ignoreModerator,
|
||||
listener = listener)
|
||||
}
|
||||
|
||||
@ -77,17 +81,30 @@ object CommentHelper {
|
||||
communityId: String? = null,
|
||||
answerId: String? = null,
|
||||
videoId: String? = null,
|
||||
isShowTop: Boolean = false,
|
||||
ignoreModerator: Boolean = false,
|
||||
isVideoAuthor: Boolean = false,
|
||||
listener: OnCommentOptionClickListener? = null) {
|
||||
val context = view.context
|
||||
val dialogOptions = ArrayList<String>()
|
||||
if (isShowTop && articleId != null && commentEntity.me?.isArticleOrAnswerAuthor == true) {
|
||||
dialogOptions.add(if (commentEntity.isTop) "取消置顶" else "置顶")
|
||||
}
|
||||
|
||||
dialogOptions.add("复制")
|
||||
if (commentEntity.user.id != UserManager.getInstance().userId) {
|
||||
dialogOptions.add("投诉")
|
||||
}
|
||||
if (isVideoAuthor || (videoId != null && commentEntity.user.id == UserManager.getInstance().userId)) {
|
||||
dialogOptions.add("删除评论")
|
||||
} else if (articleId != null && (commentEntity.user.id == UserManager.getInstance().userId ||
|
||||
commentEntity.me?.isModerator == true || commentEntity.me?.isArticleOrAnswerAuthor == true)) {
|
||||
dialogOptions.add("删除评论")
|
||||
}
|
||||
dialogOptions.add("复制")
|
||||
dialogOptions.add("投诉")
|
||||
|
||||
commentEntity.me?.let {
|
||||
if (ignoreModerator) return@let
|
||||
|
||||
if (it.isModerator || (it.moderatorPermissions.hideAnswerComment > Permissions.GUEST
|
||||
|| it.moderatorPermissions.topAnswerComment > Permissions.GUEST
|
||||
|| it.moderatorPermissions.hideCommunityArticleComment > Permissions.GUEST
|
||||
@ -123,7 +140,7 @@ object CommentHelper {
|
||||
|
||||
"投诉" -> {
|
||||
context.ifLogin("回答详情-评论-投诉") {
|
||||
showReportTypeDialog(context) { reportType ->
|
||||
showReportTypeDialog(context, !videoId.isNullOrEmpty()) { reportType ->
|
||||
|
||||
val commentListener = object : PostCommentUtils.PostCommentListener {
|
||||
override fun postSuccess(response: JSONObject?) {
|
||||
@ -184,7 +201,7 @@ object CommentHelper {
|
||||
var canHighlightCommentDirectly = false
|
||||
var canHideCommentDirectly = false
|
||||
|
||||
if (me.moderatorPermissions.topAnswerComment > Permissions.GUEST
|
||||
if (me.isModerator || me.moderatorPermissions.topAnswerComment > Permissions.GUEST
|
||||
|| me.moderatorPermissions.topCommunityArticleComment > Permissions.GUEST) {
|
||||
dialogOptions.add(highlight)
|
||||
if (me.moderatorPermissions.topAnswerComment > Permissions.REPORTER
|
||||
@ -193,7 +210,7 @@ object CommentHelper {
|
||||
}
|
||||
}
|
||||
|
||||
if (me.moderatorPermissions.hideAnswerComment > Permissions.GUEST
|
||||
if (me.isModerator || me.moderatorPermissions.hideAnswerComment > Permissions.GUEST
|
||||
|| me.moderatorPermissions.hideCommunityArticleComment > Permissions.GUEST) {
|
||||
dialogOptions.add(hide)
|
||||
if (me.moderatorPermissions.hideAnswerComment > Permissions.REPORTER
|
||||
@ -258,10 +275,10 @@ object CommentHelper {
|
||||
val errorJson = JSONObject(string)
|
||||
val errorCode = errorJson.getInt("code")
|
||||
if (errorCode == 403059) {
|
||||
Utils.toast(getApplication(), "权限错误,请刷新后重试")
|
||||
Utils.toast(HaloApp.getInstance().application, "权限错误,请刷新后重试")
|
||||
return
|
||||
} else {
|
||||
Utils.toast(getApplication(), e.message())
|
||||
Utils.toast(HaloApp.getInstance().application, e.message())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -307,10 +324,10 @@ object CommentHelper {
|
||||
val errorJson = JSONObject(string)
|
||||
val errorCode = errorJson.getInt("code")
|
||||
if (errorCode == 403059) {
|
||||
Utils.toast(getApplication(), "权限错误,请刷新后重试")
|
||||
Utils.toast(HaloApp.getInstance().application, "权限错误,请刷新后重试")
|
||||
return
|
||||
} else {
|
||||
Utils.toast(getApplication(), e.message())
|
||||
Utils.toast(HaloApp.getInstance().application, e.message())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -341,16 +358,22 @@ object CommentHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showReportTypeDialog(context: Context, reportCallback: (reportType: String) -> Unit) {
|
||||
private fun showReportTypeDialog(context: Context, isVideoComment: Boolean, reportCallback: (reportType: String) -> Unit) {
|
||||
val reportTypes = arrayListOf("垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息", "违法有害信息", "其它")
|
||||
|
||||
DialogUtils.showListDialog(context, reportTypes, null) { text ->
|
||||
val jsonObject = JSONObject()
|
||||
try {
|
||||
jsonObject.put("reason", text)
|
||||
reportCallback.invoke(jsonObject.toString())
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
if (!isVideoComment) {
|
||||
DialogUtils.showListDialog(context, reportTypes, null) { text ->
|
||||
val jsonObject = JSONObject()
|
||||
try {
|
||||
jsonObject.put("reason", text)
|
||||
reportCallback.invoke(jsonObject.toString())
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DialogUtils.showVideoComplaintDialog(context, reportTypes, null) { text ->
|
||||
reportCallback.invoke(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package com.gh.common.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.text.TextUtils;
|
||||
@ -12,6 +11,9 @@ import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.gamecenter.CommentDetailActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.CommentViewHolder;
|
||||
@ -20,6 +22,7 @@ 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.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -38,7 +41,6 @@ import java.util.Date;
|
||||
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;
|
||||
@ -50,9 +52,13 @@ import retrofit2.HttpException;
|
||||
public class CommentUtils {
|
||||
|
||||
public static void setCommentTime(TextView textView, long time) {
|
||||
textView.setText(getCommentTime(time));
|
||||
}
|
||||
|
||||
public static String getCommentTime(long timestamp) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
|
||||
try {
|
||||
long day = time * 1000;
|
||||
long day = timestamp * 1000;
|
||||
String year = String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
|
||||
format.applyPattern("yyyy");
|
||||
String currentYear = format.format(day);
|
||||
@ -63,35 +69,34 @@ public class CommentUtils {
|
||||
int hour = (int) (min / (60 * 60));
|
||||
if (hour == 0) {
|
||||
if (min < 60) {
|
||||
textView.setText("刚刚");
|
||||
return "刚刚";
|
||||
} else {
|
||||
textView.setText(String.format(Locale.getDefault(), "%d分钟前", (int) (min / 60)));
|
||||
return String.format(Locale.getDefault(), "%d分钟前", (int) (min / 60));
|
||||
}
|
||||
} else {
|
||||
textView.setText(String.format(Locale.getDefault(), "%d小时前", hour));
|
||||
return String.format(Locale.getDefault(), "%d小时前", hour);
|
||||
}
|
||||
} else if (day >= today - 86400 * 1000 && day < today) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText("昨天 ");
|
||||
return "昨天 ";
|
||||
} else if (day >= today - 86400 * 1000 * 7 && day < today - 86400 * 1000) {
|
||||
format.applyPattern("HH:mm");
|
||||
long days = (today - day) / 86400000 + 1;
|
||||
textView.setText(String.format(Locale.getDefault(), "%d天前 ", days));
|
||||
return String.format(Locale.getDefault(), "%d天前 ", days);
|
||||
} else if (day < today - 86400 * 1000 * 7 && year.equals(currentYear)) {
|
||||
format.applyPattern("MM-dd");
|
||||
textView.setText(format.format(day));
|
||||
return format.format(day);
|
||||
} else {
|
||||
format.applyPattern("yyyy-MM-dd");
|
||||
textView.setText(format.format(day));
|
||||
return format.format(day);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
format.applyPattern("yyyy-MM-dd");
|
||||
textView.setText(format.format(time * 1000));
|
||||
return format.format(timestamp * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void showReportDialog(final CommentEntity commentEntity,
|
||||
final Context context,
|
||||
final boolean showConversation,
|
||||
@ -275,6 +280,9 @@ public class CommentUtils {
|
||||
if (TextUtils.isEmpty(articleId)) {
|
||||
entrance = "社区文章详情-评论-点赞";
|
||||
}
|
||||
if (TextUtils.isEmpty(videoId)) {
|
||||
entrance = "视频流-评论-点赞";
|
||||
}
|
||||
CheckLoginUtils.checkLogin(context, entrance, () -> {
|
||||
if (commentLikeCountTv.getCurrentTextColor() == ContextCompat.getColor(context, R.color.theme_font)) {
|
||||
ToastUtils.INSTANCE.showToast("已经点过赞啦!");
|
||||
@ -326,6 +334,97 @@ public class CommentUtils {
|
||||
});
|
||||
});
|
||||
}
|
||||
public static void voteVideoComment(final Context context,
|
||||
String answerId,
|
||||
String articleId,
|
||||
String articleCommunityId,
|
||||
String videoId,
|
||||
final CommentEntity commentEntity,
|
||||
final TextView commentLikeCountTv,
|
||||
final ImageView commentLikeIv,
|
||||
final OnVoteListener listener) {
|
||||
|
||||
String entrance = "视频流-评论-点赞";
|
||||
CheckLoginUtils.checkLogin(context, entrance, () -> {
|
||||
|
||||
PostCommentUtils.likeComment(context, answerId, articleId, articleCommunityId, videoId, commentEntity.getId(),
|
||||
new PostCommentUtils.PostCommentListener() {
|
||||
@Override
|
||||
public void postSuccess(JSONObject response) {
|
||||
if (listener != null) {
|
||||
listener.onVote();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postFailed(Throwable e) {
|
||||
commentEntity.setVote(commentEntity.getVote() - 1);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.hint));
|
||||
commentLikeIv.setImageResource(R.drawable.comment_vote_unselect);
|
||||
commentLikeCountTv.setText(NumberUtils.transSimpleCount(commentEntity.getVote()));
|
||||
if (commentEntity.getVote() == 0) {
|
||||
commentLikeCountTv.setVisibility(View.GONE);
|
||||
} else {
|
||||
commentLikeCountTv.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (e instanceof HttpException) {
|
||||
HttpException exception = (HttpException) e;
|
||||
if (exception.code() == 403) {
|
||||
try {
|
||||
String detail = new JSONObject(exception.response().errorBody().string()).getString("detail");
|
||||
if ("voted".equals(detail)) {
|
||||
ToastUtils.INSTANCE.showToast("已经点过赞啦!");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Utils.toast(context, "网络异常,点赞失败");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static void unVoteVideoComment(final Context context,
|
||||
String videoId,
|
||||
final CommentEntity commentEntity,
|
||||
final TextView commentLikeCountTv,
|
||||
final ImageView commentLikeIv) {
|
||||
String entrance = "视频流-评论-取消点赞";
|
||||
CheckLoginUtils.checkLogin(context, entrance, () -> {
|
||||
RetrofitManager.getInstance(context).getApi()
|
||||
.unVoteVideoComment(videoId, commentEntity.getId())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(@Nullable ResponseBody response) {
|
||||
super.onResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@Nullable HttpException e) {
|
||||
super.onFailure(e);
|
||||
commentEntity.setVote(commentEntity.getVote() + 1);
|
||||
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);
|
||||
try {
|
||||
if (e != null && e.response().errorBody() != null) {
|
||||
ErrorHelper.handleError(context, e.response().errorBody().string(), false);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 设置评论item 用户相关的view(点赞/头像/用户名)
|
||||
@ -430,10 +529,7 @@ public class CommentUtils {
|
||||
|
||||
//复制文字
|
||||
public static void copyText(String copyContent, Context context) {
|
||||
ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cmb.setText(copyContent);
|
||||
|
||||
ToastUtils.INSTANCE.showToast("复制成功");
|
||||
ExtensionsKt.copyTextAndToast(copyContent, "复制成功");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2,10 +2,10 @@ package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.common.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.JSONObject;
|
||||
@ -53,10 +53,13 @@ public class DataLogUtils {
|
||||
String channel = HaloApp.getInstance().getChannel();
|
||||
map.put("version", version);
|
||||
map.put("user", user);
|
||||
map.put("device_id", Util_System_Phone_State.getDeviceId(context));
|
||||
map.put("device_id", MetaUtil.getIMEI());
|
||||
map.put("channel", channel);
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
if ("search-hot-tag".equals(topic) || "game".equals(topic) || "slide".equals(topic)) {
|
||||
params.put("meta", LogUtils.getMetaObject().toString());
|
||||
}
|
||||
params.put("topic", topic);
|
||||
params.put("source", "GH-ASSIST-Client");
|
||||
params.put("time", String.valueOf(Utils.getTime(context)));
|
||||
|
||||
@ -3,28 +3,25 @@ package com.gh.common.util;
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gid.GidCallback;
|
||||
import com.gh.gid.GidHelper;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.tencent.bugly.crashreport.CrashReport;
|
||||
import com.tencent.stat.MtaSDkException;
|
||||
import com.tencent.stat.StatConfig;
|
||||
import com.tencent.stat.StatCrashReporter;
|
||||
import com.tencent.stat.StatReportStrategy;
|
||||
import com.tencent.stat.StatService;
|
||||
import com.tendcloud.tenddata.TCAgent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import io.sentry.android.core.SentryAndroid;
|
||||
import io.sentry.core.Sentry;
|
||||
import io.sentry.core.protocol.User;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/6/15.
|
||||
@ -43,72 +40,101 @@ public class DataUtils {
|
||||
if (CommonDebug.IS_DEBUG) {
|
||||
return;
|
||||
}
|
||||
|
||||
SentryAndroid.init(context, options -> {
|
||||
options.setDebug(BuildConfig.DEBUG);
|
||||
options.setEnableSessionTracking(true);
|
||||
options.setEnvironment(BuildConfig.FLAVOR);
|
||||
options.setDsn("https://6b1caf0d17c1408e8680f3f73ff80bd0@sentry.ghzs.com/22");
|
||||
|
||||
options.setBeforeSend((event, hint) -> {
|
||||
if (BuildConfig.DEBUG) {
|
||||
return null;
|
||||
} else {
|
||||
return event;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Sentry.configureScope(scope -> {
|
||||
User user = new User();
|
||||
user.setId(HaloApp.getInstance().getGid());
|
||||
scope.setUser(user);
|
||||
|
||||
if (BuildConfig.BUILD_TIME != 0L) {
|
||||
scope.setTag("alias", "内测版" + BuildConfig.VERSION_NAME + "_" + BuildConfig.BUILD_TIME);
|
||||
} else {
|
||||
scope.setTag("alias", "正式版" + BuildConfig.VERSION_NAME);
|
||||
scope.setTag("channel", channel);
|
||||
}
|
||||
});
|
||||
|
||||
//TalkingData
|
||||
try {
|
||||
TCAgent.LOG_ON = false;
|
||||
TCAgent.init(context, Config.TALKINGDATA_APPID, channel);
|
||||
/**
|
||||
*
|
||||
* 不要启用!!!!不要启用,全部由{@link com.gh.base.AppUncaughtHandler}处理
|
||||
*/
|
||||
TCAgent.setReportUncaughtExceptions(false);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// try {
|
||||
// TCAgent.LOG_ON = false;
|
||||
// TCAgent.init(context, Config.TALKINGDATA_APPID, channel);
|
||||
// /**
|
||||
// *
|
||||
// * 不要启用!!!!不要启用,全部由{@link com.gh.base.AppUncaughtHandler}处理
|
||||
// */
|
||||
// TCAgent.setReportUncaughtExceptions(false);
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
|
||||
//MTA
|
||||
try {
|
||||
/**
|
||||
*
|
||||
* 不要启用!!!!全部由{@link com.gh.base.AppUncaughtHandler}处理
|
||||
*/
|
||||
StatConfig.setAutoExceptionCaught(false);
|
||||
|
||||
StatCrashReporter crashReporter = StatCrashReporter.getStatCrashReporter(context);
|
||||
crashReporter.setJavaCrashHandlerStatus(false);
|
||||
// crashReporter.setEnableInstantReporting(true);
|
||||
|
||||
StatConfig.setDebugEnable(false);
|
||||
|
||||
// 设置数据上报策略
|
||||
// 测试渠道的时候即时上传,方便查看日志
|
||||
if (Config.DEFAULT_CHANNEL.equals(HaloApp.getInstance().getChannel())) {
|
||||
StatConfig.setStatSendStrategy(StatReportStrategy.INSTANT);
|
||||
} else {
|
||||
StatConfig.setStatSendStrategy(StatReportStrategy.PERIOD);
|
||||
StatConfig.setSendPeriodMinutes(5);
|
||||
}
|
||||
|
||||
// 设置启用Tlink
|
||||
StatConfig.setTLinkStatus(true);
|
||||
|
||||
StatConfig.init(context);
|
||||
StatConfig.setInstallChannel(channel);
|
||||
StatConfig.setAntoActivityLifecycleStat(true);
|
||||
StatConfig.setAppVersion(PackageUtils.getVersionName());
|
||||
|
||||
// 开启收集服务
|
||||
StatService.startStatService(context, Config.MTA_APPKEY, com.tencent.stat.common.StatConstants.VERSION);
|
||||
StatService.registerActivityLifecycleCallbacks(context);
|
||||
} catch (MtaSDkException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// try {
|
||||
// /**
|
||||
// *
|
||||
// * 不要启用!!!!全部由{@link com.gh.base.AppUncaughtHandler}处理
|
||||
// */
|
||||
// StatConfig.setAutoExceptionCaught(false);
|
||||
//
|
||||
// StatCrashReporter crashReporter = StatCrashReporter.getStatCrashReporter(context);
|
||||
// crashReporter.setJavaCrashHandlerStatus(false);
|
||||
//// crashReporter.setEnableInstantReporting(true);
|
||||
//
|
||||
// StatConfig.setDebugEnable(false);
|
||||
//
|
||||
// // 设置数据上报策略
|
||||
// // 测试渠道的时候即时上传,方便查看日志
|
||||
// if (Config.DEFAULT_CHANNEL.equals(HaloApp.getInstance().getChannel())) {
|
||||
// StatConfig.setStatSendStrategy(StatReportStrategy.INSTANT);
|
||||
// } else {
|
||||
// StatConfig.setStatSendStrategy(StatReportStrategy.PERIOD);
|
||||
// StatConfig.setSendPeriodMinutes(5);
|
||||
// }
|
||||
//
|
||||
// // 设置启用Tlink
|
||||
// StatConfig.setTLinkStatus(true);
|
||||
//
|
||||
// StatConfig.init(context);
|
||||
// StatConfig.setInstallChannel(channel);
|
||||
// StatConfig.setAntoActivityLifecycleStat(true);
|
||||
// StatConfig.setAppVersion(PackageUtils.getVersionName());
|
||||
//
|
||||
// // 开启收集服务
|
||||
// StatService.startStatService(context, Config.MTA_APPKEY, com.tencent.stat.common.StatConstants.VERSION);
|
||||
// StatService.registerActivityLifecycleCallbacks(context);
|
||||
// } catch (MtaSDkException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
|
||||
// init bugly
|
||||
try {
|
||||
CrashReport.setIsDevelopmentDevice(context, Config.DEFAULT_CHANNEL.equals(channel));
|
||||
|
||||
CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(context);
|
||||
strategy.setEnableANRCrashMonitor(false);
|
||||
strategy.setEnableNativeCrashMonitor(false);
|
||||
strategy.setAppChannel(channel);
|
||||
strategy.setAppVersion(PackageUtils.getVersionName());
|
||||
|
||||
CrashReport.initCrashReport(context, Config.BUGLY_APPID, false, strategy);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// try {
|
||||
// CrashReport.setIsDevelopmentDevice(context, Config.DEFAULT_CHANNEL.equals(channel));
|
||||
//
|
||||
// CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(context);
|
||||
// strategy.setEnableANRCrashMonitor(false);
|
||||
// strategy.setEnableNativeCrashMonitor(false);
|
||||
// strategy.setAppChannel(channel);
|
||||
// strategy.setAppVersion(PackageUtils.getVersionName());
|
||||
//
|
||||
// CrashReport.initCrashReport(context, Config.BUGLY_APPID, false, strategy);
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@ -121,7 +147,7 @@ public class DataUtils {
|
||||
}
|
||||
|
||||
public static void getGid() {
|
||||
GidHelper.getInstance().registerDevice(new GidCallback() {
|
||||
GidHelper.getInstance().registerDevice(HaloApp.getInstance().getApplication(), new GidCallback() {
|
||||
@Override
|
||||
public void onSuccess(String gid) {
|
||||
Utils.log("Gid", gid);
|
||||
@ -141,26 +167,23 @@ public class DataUtils {
|
||||
|
||||
@Override
|
||||
public void onFailure(String s) {
|
||||
Utils.log(s);
|
||||
MtaHelper.onEventWithBasicDeviceInfo("开发辅助", "GID 获取异常", s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void onEvent(Context var0, String var1, String var2) {
|
||||
TCAgent.onEvent(var0, var1, var2);
|
||||
Properties prop = new Properties();
|
||||
prop.setProperty(var1, var2);
|
||||
StatService.trackCustomKVEvent(var0, var1, prop);
|
||||
// Properties prop = new Properties();
|
||||
// prop.setProperty(var1, var2);
|
||||
// StatService.trackCustomKVEvent(var0, var1, prop);
|
||||
}
|
||||
|
||||
public static void onPause(Activity var0) {
|
||||
TCAgent.onPageEnd(var0, var0.getClass().getSimpleName());
|
||||
StatService.onPause(var0);
|
||||
// StatService.onPause(var0);
|
||||
}
|
||||
|
||||
public static void onResume(Activity var0) {
|
||||
TCAgent.onPageStart(var0, var0.getClass().getSimpleName());
|
||||
StatService.onResume(var0);
|
||||
// StatService.onResume(var0);
|
||||
}
|
||||
|
||||
// 游戏启动
|
||||
@ -172,65 +195,64 @@ public class DataUtils {
|
||||
}
|
||||
|
||||
public static void onEvent(Context var0, String var1, String var2, Map<String, Object> var3) {
|
||||
TCAgent.onEvent(var0, var1, var2, var3);
|
||||
Properties prop = new Properties();
|
||||
prop.setProperty("label", var2);
|
||||
for (String key : var3.keySet()) {
|
||||
prop.setProperty(key, var3.get(key) + "");
|
||||
}
|
||||
StatService.trackCustomKVEvent(var0, var1, prop);
|
||||
// Properties prop = new Properties();
|
||||
// prop.setProperty("label", var2);
|
||||
// for (String key : var3.keySet()) {
|
||||
// prop.setProperty(key, var3.get(key) + "");
|
||||
// }
|
||||
// StatService.trackCustomKVEvent(var0, var1, prop);
|
||||
}
|
||||
|
||||
public static void trackTimeEvent(Context context, String eventId, int costTime, String... kv) {
|
||||
|
||||
Properties prop = new Properties();
|
||||
for (int i = 0; i < kv.length; i++) {
|
||||
if (i % 2 != 0 || i != 0) {
|
||||
String key = kv[i - 1];
|
||||
String value = kv[i];
|
||||
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
|
||||
prop.setProperty(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prop.size() == 0) return;
|
||||
|
||||
StatService.trackCustomKVTimeIntervalEvent(context, costTime, eventId, prop);
|
||||
//
|
||||
// Properties prop = new Properties();
|
||||
// for (int i = 0; i < kv.length; i++) {
|
||||
// if (i % 2 != 0 || i != 0) {
|
||||
// String key = kv[i - 1];
|
||||
// String value = kv[i];
|
||||
// if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
|
||||
// prop.setProperty(key, value);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (prop.size() == 0) return;
|
||||
//
|
||||
// StatService.trackCustomKVTimeIntervalEvent(context, costTime, eventId, prop);
|
||||
}
|
||||
|
||||
// 游戏下载
|
||||
public static void onGameDownloadEvent(Context context, String gameName, String platform, String entrance, String status, String method) {
|
||||
// Map<String, Object> kv = new HashMap<>();
|
||||
//
|
||||
// platform = PlatformUtils.getInstance(HaloApp.getInstance().getApplication()).getPlatformName(platform);
|
||||
//
|
||||
// kv.put("版本", platform);
|
||||
// kv.put("用户机型", Build.MODEL);
|
||||
// kv.put("设备IMEI", Util_System_Phone_State.getDeviceId(HaloApp.getInstance().getApplication()));
|
||||
// kv.put("网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
// kv.put("光环助手版本", BuildConfig.VERSION_NAME);
|
||||
// kv.put("位置", entrance);
|
||||
// kv.put("类型", method);
|
||||
// kv.put("厂商", Build.MANUFACTURER);
|
||||
// kv.put("Android版本", Build.VERSION.RELEASE);
|
||||
// onEvent(context, "游戏下载", gameName, kv);
|
||||
//
|
||||
// Map<String, Object> kv2 = new HashMap<>();
|
||||
// kv2.put("状态", status);
|
||||
// kv2.put("位置", entrance);
|
||||
//
|
||||
// if (status.equals("开始")) {
|
||||
// kv2.put("版本", entrance + "-开始");
|
||||
// kv2.put("游戏分平台", gameName + "-" + platform + "-开始");
|
||||
// kv2.put("光环助手版本", BuildConfig.VERSION_NAME + "-开始");
|
||||
// } else {
|
||||
// kv2.put("版本", platform);
|
||||
// kv2.put("游戏分平台", gameName + "-" + platform);
|
||||
// kv2.put("光环助手版本", BuildConfig.VERSION_NAME);
|
||||
// }
|
||||
//
|
||||
// onEvent(context, "游戏下载位置", gameName, kv2);
|
||||
Map<String, Object> kv = new HashMap<>();
|
||||
|
||||
platform = PlatformUtils.getInstance(HaloApp.getInstance().getApplication()).getPlatformName(platform);
|
||||
|
||||
kv.put("版本", platform);
|
||||
kv.put("用户机型", Build.MODEL);
|
||||
kv.put("设备IMEI", MetaUtil.getIMEI());
|
||||
kv.put("网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
kv.put("光环助手版本", BuildConfig.VERSION_NAME);
|
||||
kv.put("位置", entrance);
|
||||
kv.put("类型", method);
|
||||
kv.put("厂商", Build.MANUFACTURER);
|
||||
kv.put("Android版本", Build.VERSION.RELEASE);
|
||||
onEvent(context, "游戏下载", gameName, kv);
|
||||
|
||||
Map<String, Object> kv2 = new HashMap<>();
|
||||
kv2.put("状态", status);
|
||||
kv2.put("位置", entrance);
|
||||
|
||||
if (status.equals("开始")) {
|
||||
kv2.put("版本", entrance + "-开始");
|
||||
kv2.put("游戏分平台", gameName + "-" + platform + "-开始");
|
||||
kv2.put("光环助手版本", BuildConfig.VERSION_NAME + "-开始");
|
||||
} else {
|
||||
kv2.put("版本", platform);
|
||||
kv2.put("游戏分平台", gameName + "-" + platform);
|
||||
kv2.put("光环助手版本", BuildConfig.VERSION_NAME);
|
||||
}
|
||||
|
||||
onEvent(context, "游戏下载位置", gameName, kv2);
|
||||
}
|
||||
|
||||
// 游戏更新
|
||||
@ -244,13 +266,13 @@ public class DataUtils {
|
||||
public static void onError(Context context, Throwable throwable) {
|
||||
//bugly 作为默认处理异常的类库,已经上报了,此处不重复上报
|
||||
try {
|
||||
CrashReport.postCatchedException(throwable);
|
||||
// CrashReport.postCatchedException(throwable);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
//talkingdata
|
||||
try {
|
||||
TCAgent.onError(context, throwable);
|
||||
// TCAgent.onError(context, throwable);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import android.view.View;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.common.simulator.SimulatorGameManager;
|
||||
import com.gh.common.view.DownloadProgressBar;
|
||||
import com.gh.common.xapk.XapkInstaller;
|
||||
import com.gh.common.xapk.XapkUnzipStatus;
|
||||
@ -66,6 +67,9 @@ public class DetailDownloadUtils {
|
||||
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "查看详情" : viewHolder.gameEntity.getDownloadOffText());
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE_WITH_HINT);
|
||||
} else if ("updating".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "更新中" : viewHolder.gameEntity.getDownloadOffText());
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.UPDATING);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "暂无下载" : viewHolder.gameEntity.getDownloadOffText());
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
@ -148,13 +152,25 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
break;
|
||||
case done:
|
||||
viewHolder.mDownloadPb.setText(R.string.install);
|
||||
if (downloadEntity.isPluggable()
|
||||
&& PackagesManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_PLUGIN);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_NORMAL);
|
||||
if (SimulatorGameManager.isSimulatorGame(viewHolder.gameEntity)){
|
||||
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(viewHolder.context, viewHolder.gameEntity.getSimulator().getApk().getPackageName());
|
||||
if (isInstalled){
|
||||
viewHolder.mDownloadPb.setText(R.string.launch);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.LAUNCH_OR_OPEN);
|
||||
}else{
|
||||
viewHolder.mDownloadPb.setText(R.string.install);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_NORMAL);
|
||||
}
|
||||
}else{
|
||||
viewHolder.mDownloadPb.setText(R.string.install);
|
||||
if (downloadEntity.isPluggable()
|
||||
&& PackagesManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_PLUGIN);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case cancel:
|
||||
case hijack:
|
||||
|
||||
@ -3,12 +3,12 @@ package com.gh.common.util
|
||||
import android.content.Context
|
||||
import android.os.Environment
|
||||
import android.preference.PreferenceManager
|
||||
import com.gh.common.exposure.meta.MetaUtil
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.entity.TimeEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Util_System_Phone_State
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
@ -60,7 +60,7 @@ object DeviceTokenUtils {
|
||||
lunchType = LunchType.FIRST
|
||||
}
|
||||
// 保存deviceId
|
||||
var deviceId = Util_System_Phone_State.getDeviceId(HaloApp.getInstance().application)
|
||||
var deviceId = MetaUtil.getIMEI()
|
||||
if (deviceId.isNullOrEmpty()) {
|
||||
deviceId = Utils.getTime(HaloApp.getInstance().application).toString()
|
||||
}
|
||||
|
||||
@ -6,26 +6,21 @@ import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.tencent.stat.StatConfig;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.Reader;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
@ -46,14 +41,14 @@ public class DeviceUtils {
|
||||
context = context.getApplicationContext();
|
||||
JSONObject object = new JSONObject();
|
||||
object.put("os", "Android");
|
||||
object.put("imei", Util_System_Phone_State.getDeviceId(context));
|
||||
object.put("imei", MetaUtil.getIMEI());
|
||||
object.put("mac", getMac(context));
|
||||
object.put("model", MODEL);
|
||||
object.put("manufacturer", MANUFACTURER);
|
||||
object.put("android_id", Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID));
|
||||
object.put("android_id", MetaUtil.getAndroidId());
|
||||
object.put("android_sdk", Build.VERSION.SDK_INT);
|
||||
object.put("android_version", android.os.Build.VERSION.RELEASE);
|
||||
object.put("ip", getIPAddress(context));
|
||||
object.put("ip", "");
|
||||
object.put("network", getNetwork(context));
|
||||
return object;
|
||||
}
|
||||
@ -62,10 +57,10 @@ public class DeviceUtils {
|
||||
public static JSONObject getUserDevice(Context context) { // 判断新老用户device数据
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("IMEI", Util_System_Phone_State.getDeviceId(context));
|
||||
object.put("ANDROID_ID", Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID));
|
||||
object.put("IMEI", MetaUtil.getIMEI());
|
||||
object.put("ANDROID_ID", MetaUtil.getAndroidId());
|
||||
object.put("MAC", getMac(context));
|
||||
object.put("MTA_ID", StatConfig.getMid(context));
|
||||
// object.put("MTA_ID", StatConfig.getMid(context));
|
||||
object.put("MANUFACTURER", MANUFACTURER);
|
||||
object.put("MODEL", MODEL);
|
||||
object.put("ANDROID_SDK", Build.VERSION.SDK_INT);
|
||||
@ -78,39 +73,39 @@ public class DeviceUtils {
|
||||
}
|
||||
|
||||
public static String getMac(Context context) {
|
||||
String str = "";
|
||||
String macSerial = "";
|
||||
try {
|
||||
Process pp = Runtime.getRuntime().exec(
|
||||
"cat /sys/class/net/wlan0/address ");
|
||||
InputStreamReader ir = new InputStreamReader(pp.getInputStream());
|
||||
LineNumberReader input = new LineNumberReader(ir);
|
||||
|
||||
while (null != str) {
|
||||
str = input.readLine();
|
||||
if (str != null) {
|
||||
macSerial = str.trim();// 去空格
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
if ("".equals(macSerial)) {
|
||||
try {
|
||||
return loadFileAsString("/sys/class/net/eth0/address")
|
||||
.toUpperCase().substring(0, 17);
|
||||
} catch (FileNotFoundException e) {
|
||||
// do nothing
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
if (TextUtils.isEmpty(macSerial)) { // 备用方案
|
||||
macSerial = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)).getConnectionInfo().getMacAddress();
|
||||
}
|
||||
return macSerial;
|
||||
// String str = "";
|
||||
// String macSerial = "";
|
||||
// try {
|
||||
// Process pp = Runtime.getRuntime().exec(
|
||||
// "cat /sys/class/net/wlan0/address ");
|
||||
// InputStreamReader ir = new InputStreamReader(pp.getInputStream());
|
||||
// LineNumberReader input = new LineNumberReader(ir);
|
||||
//
|
||||
// while (null != str) {
|
||||
// str = input.readLine();
|
||||
// if (str != null) {
|
||||
// macSerial = str.trim();// 去空格
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// } catch (Exception ex) {
|
||||
// ex.printStackTrace();
|
||||
// }
|
||||
// if ("".equals(macSerial)) {
|
||||
// try {
|
||||
// return loadFileAsString("/sys/class/net/eth0/address")
|
||||
// .toUpperCase().substring(0, 17);
|
||||
// } catch (FileNotFoundException e) {
|
||||
// // do nothing
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// if (TextUtils.isEmpty(macSerial)) { // 备用方案
|
||||
// macSerial = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)).getConnectionInfo().getMacAddress();
|
||||
// }
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String loadFileAsString(String fileName) throws Exception {
|
||||
@ -242,8 +237,7 @@ public class DeviceUtils {
|
||||
|
||||
@Nullable
|
||||
public static String getTelephonySubscriberId(Context context) {
|
||||
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
return tm.getSubscriberId();
|
||||
return "";
|
||||
}
|
||||
|
||||
// ping domain
|
||||
@ -273,7 +267,6 @@ public class DeviceUtils {
|
||||
return memInfo.totalMem / (1024 * 1024);
|
||||
}
|
||||
|
||||
|
||||
// 只能获取WiFi的IpAddress
|
||||
public static String getCurrentIpAddress() {
|
||||
String ipAddress = "0.0.0.0";
|
||||
|
||||
@ -8,8 +8,11 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.CountDownTimer;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.Settings;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
@ -24,12 +27,23 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchy;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.TrackableDialog;
|
||||
@ -40,12 +54,13 @@ import com.gh.common.view.MaxHeightNestedScrollView;
|
||||
import com.gh.gamecenter.AboutActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.SuggestionActivity;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.adapter.viewholder.PrivacyPolicyItemViewHolder;
|
||||
import com.gh.gamecenter.databinding.DialogOverseaConfirmationBinding;
|
||||
import com.gh.gamecenter.databinding.ImprintContentItemBinding;
|
||||
import com.gh.gamecenter.databinding.PrivacyItemBinding;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.Badge;
|
||||
import com.gh.gamecenter.entity.BadgeEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
@ -56,18 +71,16 @@ import com.halo.assistant.fragment.SettingsFragment;
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.AppManager;
|
||||
import com.lightgame.utils.Util_System_Keyboard;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class DialogUtils {
|
||||
|
||||
public static Dialog showWaitDialog(Context context, String msg) {
|
||||
@ -84,7 +97,6 @@ public class DialogUtils {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
public static void showInstallHintDialog(Context context, final ConfirmListener cmListener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
@ -326,6 +338,84 @@ public class DialogUtils {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* ios 风格弹窗
|
||||
*
|
||||
* @param context
|
||||
* @param title 标题
|
||||
* @param message 内容
|
||||
* @param negative 取消按钮文本
|
||||
* @param positive 确认按钮文本
|
||||
* @param clListener 取消按钮监听
|
||||
* @param cmListener 确认按钮监听
|
||||
*/
|
||||
public static Dialog showNewAlertDialog(Context context, String title, CharSequence message
|
||||
, String negative, String positive, TrackableEntity trackableEntity, int gravity, final CancelListener clListener, final ConfirmListener cmListener) {
|
||||
context = checkDialogContext(context);
|
||||
final Dialog dialog;
|
||||
if (trackableEntity != null) {
|
||||
dialog = new TrackableDialog(context,
|
||||
R.style.GhAlertDialog,
|
||||
trackableEntity.getEvent(),
|
||||
trackableEntity.getKey(),
|
||||
trackableEntity.getValue(),
|
||||
trackableEntity.getCancelValue(),
|
||||
trackableEntity.getKeyBackValue(),
|
||||
trackableEntity.getLogShowEvent());
|
||||
} else {
|
||||
dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
}
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_new_alert, null);
|
||||
|
||||
TextView titleTv = contentView.findViewById(R.id.title);
|
||||
TextView contentTv = contentView.findViewById(R.id.content);
|
||||
TextView cancelBtn = contentView.findViewById(R.id.cancel);
|
||||
TextView confirmBtn = contentView.findViewById(R.id.confirm);
|
||||
View middleLine = contentView.findViewById(R.id.middle_line);
|
||||
titleTv.setGravity(gravity);
|
||||
contentTv.setGravity(gravity);
|
||||
|
||||
titleTv.setText(title);
|
||||
contentTv.setText(message);
|
||||
cancelBtn.setText(negative);
|
||||
confirmBtn.setText(positive);
|
||||
if (negative.isEmpty()) {
|
||||
cancelBtn.setVisibility(View.GONE);
|
||||
middleLine.setVisibility(View.GONE);
|
||||
confirmBtn.setTextColor(ContextCompat.getColor(context, R.color.text_333333));
|
||||
}
|
||||
if (positive.isEmpty()) {
|
||||
confirmBtn.setVisibility(View.GONE);
|
||||
middleLine.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
cancelBtn.setOnClickListener(v -> {
|
||||
if (clListener != null) clListener.onCancel();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
confirmBtn.setOnClickListener(v -> {
|
||||
if (cmListener != null) cmListener.onConfirm();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static Dialog showNewAlertDialog(Context context, String title, CharSequence message
|
||||
, String negative, String positive, final CancelListener clListener, final ConfirmListener cmListener) {
|
||||
return showNewAlertDialog(context, title, message, negative, positive, null, Gravity.LEFT, clListener, cmListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Material Design 风格弹窗
|
||||
*
|
||||
@ -543,8 +633,6 @@ public class DialogUtils {
|
||||
clListener.onCancel();
|
||||
});
|
||||
dialog.show();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -588,7 +676,6 @@ public class DialogUtils {
|
||||
dialog.setContentView(contentView);
|
||||
dialog.setCancelable(false);
|
||||
dialog.show();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -669,7 +756,6 @@ public class DialogUtils {
|
||||
TextPaint tp = mesage.getPaint();
|
||||
tp.setFakeBoldText(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void showSignDialog(Context context, String title, CharSequence message, CharSequence message2
|
||||
@ -902,13 +988,13 @@ public class DialogUtils {
|
||||
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;
|
||||
}
|
||||
// int height = context.getResources().getDisplayMetrics().heightPixels - DisplayUtils.dip2px(120);
|
||||
// int maxHeight = DisplayUtils.dip2px(446);
|
||||
// if (height > maxHeight) {
|
||||
// params.height = maxHeight;
|
||||
// } else {
|
||||
// params.height = height;
|
||||
// }
|
||||
window.setAttributes(params);
|
||||
}
|
||||
|
||||
@ -939,7 +1025,7 @@ public class DialogUtils {
|
||||
if (hierarchy != null) {
|
||||
if (position == 0) {
|
||||
hierarchy.setPlaceholderImage(R.drawable.permission_storage);
|
||||
} else {
|
||||
} else if (position == 1) {
|
||||
hierarchy.setPlaceholderImage(R.drawable.permission_phone_state);
|
||||
}
|
||||
}
|
||||
@ -963,9 +1049,8 @@ public class DialogUtils {
|
||||
|
||||
@Override
|
||||
public void onClick(@NonNull View widget) {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击隐私政策");
|
||||
Intent intent = WebActivity.getPrivacyPolicyIntent(activityContext);
|
||||
activityContext.startActivity(intent);
|
||||
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击隐私政策");
|
||||
DirectUtils.directToExternalBrowser(context, context.getString(R.string.privacy_policy_url));
|
||||
}
|
||||
}, skipText.length() - 9, skipText.length() - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
@ -979,11 +1064,26 @@ public class DialogUtils {
|
||||
|
||||
@Override
|
||||
public void onClick(@NonNull View widget) {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击用户协议");
|
||||
activityContext.startActivity(WebActivity.getWebIntent(activityContext));
|
||||
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击用户协议");
|
||||
DirectUtils.directToExternalBrowser(context, context.getString(R.string.disclaimer_url));
|
||||
}
|
||||
}, skipText.length() - 4, skipText.length(), 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("隐私政策弹窗", "隐私政策弹窗", "点击第三方SDK接入说明");
|
||||
activityContext.startActivity(WebActivity.getThirdPartySdkStatementIntent(activityContext));
|
||||
}
|
||||
}, skipText.length() - 10, skipText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);*/
|
||||
|
||||
title.setText(entity.getTitle());
|
||||
linkContent.setText(skipText);
|
||||
linkContent.setMovementMethod(new LinkMovementMethod());
|
||||
@ -993,30 +1093,30 @@ public class DialogUtils {
|
||||
allowButton.setOnClickListener(view -> {
|
||||
dialog.dismiss();
|
||||
callback.onCallback();
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击同意");
|
||||
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击同意");
|
||||
});
|
||||
|
||||
disallowButton.setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
showPrivacyPolicyDisallowDialog(activityContext, entity, callback);
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "不同意并退出App");
|
||||
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "不同意并退出App");
|
||||
});
|
||||
|
||||
dialog.setOnCancelListener(cd -> {
|
||||
if (isCanceledByClickOutsideOfDialog.get()) {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击空白");
|
||||
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击空白");
|
||||
}
|
||||
});
|
||||
|
||||
dialog.setOnKeyListener((dialog1, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
||||
isCanceledByClickOutsideOfDialog.set(false);
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击返回");
|
||||
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击返回");
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "出现弹窗");
|
||||
// 用户未同意隐私策略不应该触发 MTA 事件
|
||||
// MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "出现弹窗");
|
||||
|
||||
try {
|
||||
dialog.setCancelable(false);
|
||||
@ -1037,14 +1137,16 @@ public class DialogUtils {
|
||||
View reviewButton = contentView.findViewById(R.id.review_button);
|
||||
|
||||
backButton.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "退出提示弹窗", "退出应用");
|
||||
// 用户未同意隐私策略不应该触发 MTA 事件
|
||||
// MtaHelper.onEvent("隐私政策弹窗", "退出提示弹窗", "退出应用");
|
||||
dialog.dismiss();
|
||||
AppManager.getInstance().appExit(activityContext);
|
||||
});
|
||||
reviewButton.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "退出提示弹窗", "再次查看");
|
||||
// MtaHelper.onEvent("隐私政策弹窗", "退出提示弹窗", "再次查看");
|
||||
callback.onCallback();
|
||||
dialog.dismiss();
|
||||
showPrivacyPolicyDialog(activityContext, entity, callback);
|
||||
//showPrivacyPolicyDialog(activityContext, entity, callback);
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
@ -1471,6 +1573,56 @@ public class DialogUtils {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showRegulationTestDialog(Context context, @NonNull ConfirmListener confirmListener, @NonNull CancelListener cancelListener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new TrackableDialog(
|
||||
context,
|
||||
R.style.GhAlertDialog,
|
||||
"礼仪考试",
|
||||
"礼仪考试弹窗",
|
||||
null, null, null,
|
||||
true);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_regulation_test, null);
|
||||
|
||||
View cancelBtn = contentView.findViewById(R.id.cancel);
|
||||
View confirmBtn = contentView.findViewById(R.id.confirm);
|
||||
View linkTv = contentView.findViewById(R.id.link);
|
||||
|
||||
Context finalContext = context;
|
||||
linkTv.setOnClickListener(v -> {
|
||||
|
||||
MtaHelper.onEvent("礼仪考试", "礼仪考试弹窗", "了解更多");
|
||||
DirectUtils.directToArticle(finalContext, "5f4477be25e07e19be4e2a22", "(礼仪测试弹窗)");
|
||||
});
|
||||
|
||||
cancelBtn.setOnClickListener(v -> {
|
||||
cancelListener.onCancel();
|
||||
|
||||
MtaHelper.onEvent("礼仪考试", "礼仪考试弹窗", "跳过");
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
Context finalContext1 = context;
|
||||
confirmBtn.setOnClickListener(v -> {
|
||||
Util_System_Keyboard.hideSoftKeyboard((Activity) finalContext1);
|
||||
|
||||
MtaHelper.onEvent("礼仪考试", "礼仪考试弹窗", "确定");
|
||||
confirmListener.onConfirm();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showUnzipFailureDialog(Context context, DownloadEntity downloadEntity) {
|
||||
final Context activityContext = checkDialogContext(context);
|
||||
|
||||
@ -1501,6 +1653,255 @@ public class DialogUtils {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showNoticeDialog(Context context, String title, String content, @NonNull ConfirmListener listener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_notice, null);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
|
||||
if (title == null) {
|
||||
titleTv.setVisibility(View.GONE);
|
||||
} else {
|
||||
titleTv.setVisibility(View.VISIBLE);
|
||||
titleTv.setText(title);
|
||||
}
|
||||
contentTv.setText(content);
|
||||
|
||||
contentView.findViewById(R.id.dialog_ok).setOnClickListener(v -> {
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showVideoComplaintDialog(Context context,
|
||||
List<String> options,
|
||||
List<String> disabledOptions,
|
||||
OptionCallback callback) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
Dialog dialog = new Dialog(context);
|
||||
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.dialog_video_complaint, null, false);
|
||||
LinearLayout complaintContainer = view.findViewById(R.id.complaintContainer);
|
||||
ConstraintLayout otherComplaintContainer = view.findViewById(R.id.otherComplaintContainer);
|
||||
EditText complaintCommentEt = view.findViewById(R.id.complaintCommentEt);
|
||||
TextView backTv = view.findViewById(R.id.backTv);
|
||||
TextView commitTv = view.findViewById(R.id.commitTv);
|
||||
Context finalContext = context;
|
||||
//添加透明阴影,实现类似 clipPadding=false 效果
|
||||
complaintCommentEt.setShadowLayer(complaintCommentEt.getExtendedPaddingBottom(), 0f, 0f, Color.TRANSPARENT);
|
||||
|
||||
ExtensionsKt.setTextChangedListener(complaintCommentEt, (s, start, before, count) -> {
|
||||
commitTv.setTextColor(ContextCompat.getColor(finalContext, s.toString().trim().isEmpty() ? R.color.text_999999 : R.color.theme_font));
|
||||
return null;
|
||||
});
|
||||
|
||||
for (String option : options) {
|
||||
TextView reportTv = new TextView(context);
|
||||
reportTv.setText(option);
|
||||
reportTv.setTextSize(16f);
|
||||
if (disabledOptions != null && disabledOptions.contains(option)) {
|
||||
reportTv.setTextColor(ContextCompat.getColor(context, R.color.btn_gray));
|
||||
} else {
|
||||
reportTv.setTextColor(ContextCompat.getColor(context, R.color.title));
|
||||
reportTv.setBackgroundResource(R.drawable.textview_white_style);
|
||||
}
|
||||
reportTv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
reportTv.setPadding(DisplayUtils.dip2px(context, 20f), DisplayUtils.dip2px(context, 17f),
|
||||
DisplayUtils.dip2px(context, 20f), DisplayUtils.dip2px(context, 17f));
|
||||
if (option.equals("其它")) {
|
||||
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.ic_complaint_arrow_right);
|
||||
drawable.setBounds(0, 0, DisplayUtils.dip2px(6f), DisplayUtils.dip2px(10f));
|
||||
reportTv.setCompoundDrawables(null, null, drawable, null);
|
||||
}
|
||||
complaintContainer.addView(reportTv);
|
||||
|
||||
reportTv.setOnClickListener(v -> {
|
||||
if (option.equals("其它")) {
|
||||
complaintContainer.setVisibility(View.GONE);
|
||||
otherComplaintContainer.setVisibility(View.VISIBLE);
|
||||
complaintCommentEt.requestFocus();
|
||||
Util_System_Keyboard.showSoftKeyboard(finalContext, complaintCommentEt);
|
||||
} else {
|
||||
dialog.cancel();
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
try {
|
||||
jsonObject.put("reason", reportTv.getText().toString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
callback.onClicked(jsonObject.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
backTv.setOnClickListener(v -> {
|
||||
Util_System_Keyboard.hideSoftKeyboard(finalContext, complaintCommentEt);
|
||||
complaintContainer.setVisibility(View.VISIBLE);
|
||||
otherComplaintContainer.setVisibility(View.GONE);
|
||||
});
|
||||
commitTv.setOnClickListener(v -> {
|
||||
if (complaintCommentEt.getText().toString().isEmpty()) {
|
||||
ToastUtils.INSTANCE.showToast("请先输入说明~");
|
||||
return;
|
||||
}
|
||||
dialog.cancel();
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
try {
|
||||
jsonObject.put("reason", "其它");
|
||||
jsonObject.put("description", complaintCommentEt.getText().toString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
callback.onClicked(jsonObject.toString());
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(view);
|
||||
dialog.show();
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.width = context.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(40f);
|
||||
window.setAttributes(params);
|
||||
}
|
||||
}
|
||||
|
||||
public static void showViewBadgeDialog(Context context, Badge badge, ConfirmListener listener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_view_badge, null);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
SimpleDraweeView badgeView = contentView.findViewById(R.id.dialog_badge);
|
||||
ImageView badgeLightBg = contentView.findViewById(R.id.dialog_badge_light_bg);
|
||||
|
||||
ImageUtils.display(badgeView, badge.getIcon());
|
||||
titleTv.setText(badge.getName());
|
||||
|
||||
// 领取条件文本超过一行就不显示
|
||||
if (badge.getActions() == null || badge.getActions().isEmpty() || badge.getActions().size() > 1) {
|
||||
contentTv.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
contentTv.setText(badge.getActions().get(0).getText());
|
||||
contentTv.post(() -> {
|
||||
if (contentTv.getLineCount() > 1) contentTv.setVisibility(View.INVISIBLE);
|
||||
});
|
||||
}
|
||||
|
||||
Animation animation = AnimationUtils.loadAnimation(context, R.anim.anim_badge_light_bg);
|
||||
badgeLightBg.startAnimation(animation);
|
||||
|
||||
contentView.findViewById(R.id.dialog_ok).setOnClickListener(v -> {
|
||||
listener.onConfirm();
|
||||
badgeLightBg.clearAnimation();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showReceiveBadgeDialog(Context context, BadgeEntity badge, ConfirmListener listener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_receive_badge, null);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
SimpleDraweeView badgeView = contentView.findViewById(R.id.dialog_badge);
|
||||
ImageView badgeLightBg = contentView.findViewById(R.id.dialog_badge_light_bg);
|
||||
TextView receiveTv = contentView.findViewById(R.id.dialog_ok);
|
||||
|
||||
ImageUtils.display(badgeView, badge.getIcon());
|
||||
titleTv.setText(badge.getName());
|
||||
|
||||
// 领取条件文本超过一行就不显示
|
||||
if (badge.getActions() == null || badge.getActions().isEmpty() || badge.getActions().size() > 1) {
|
||||
contentTv.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
contentTv.setText(badge.getActions().get(0).getText());
|
||||
contentTv.post(() -> {
|
||||
if (contentTv.getLineCount() > 1) contentTv.setVisibility(View.INVISIBLE);
|
||||
});
|
||||
}
|
||||
|
||||
if ("self".equals(badge.getReceive().getType())) {
|
||||
receiveTv.setText(R.string.receive_badge);
|
||||
} else {
|
||||
receiveTv.setText(R.string.apply_badge);
|
||||
}
|
||||
|
||||
Animation animation = AnimationUtils.loadAnimation(context, R.anim.anim_badge_light_bg);
|
||||
badgeLightBg.startAnimation(animation);
|
||||
|
||||
contentView.findViewById(R.id.dialog_ok).setOnClickListener(v -> {
|
||||
listener.onConfirm();
|
||||
badgeLightBg.clearAnimation();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showPassRegulationDialog(Context context, String icon) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_pass_regulation, null);
|
||||
SimpleDraweeView userIcon = contentView.findViewById(R.id.dialog_icon);
|
||||
|
||||
ImageUtils.display(userIcon, icon);
|
||||
|
||||
contentView.findViewById(R.id.dialog_ok).setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showShortCutPermissionDialog(Context context) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_shortcut_permission, null);
|
||||
|
||||
Context finalContext = context;
|
||||
contentView.findViewById(R.id.dialog_positive).setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
intent.setData(Uri.parse("package:" + finalContext.getPackageName()));
|
||||
finalContext.startActivity(intent);
|
||||
});
|
||||
|
||||
contentView.findViewById(R.id.dialog_negative).setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context may be is application context
|
||||
* @return activity context
|
||||
|
||||
@ -8,10 +8,12 @@ import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.base.BaseActivity_TabLayout
|
||||
import com.gh.base.ToolBarActivity
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.exposure.ExposureEvent
|
||||
import com.gh.common.exposure.ExposureEvent.Companion.createEvent
|
||||
import com.gh.common.exposure.ExposureManager.log
|
||||
@ -20,17 +22,21 @@ import com.gh.common.exposure.ExposureType
|
||||
import com.gh.common.util.EntranceUtils.*
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.amway.AmwayActivity
|
||||
import com.gh.gamecenter.catalog.CatalogActivity
|
||||
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.forum.detail.ForumDetailActivity
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment
|
||||
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
|
||||
import com.gh.gamecenter.game.upload.GameSubmissionActivity
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity
|
||||
import com.gh.gamecenter.gamedetail.history.HistoryApkListActivity
|
||||
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.mvvm.Resource
|
||||
import com.gh.gamecenter.mygame.PlayedGameActivity
|
||||
import com.gh.gamecenter.personalhome.UserHomeActivity
|
||||
import com.gh.gamecenter.qa.CommunityFragment
|
||||
@ -52,12 +58,14 @@ import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.gh.gamecenter.video.game.GameVideoActivity
|
||||
import com.gh.gamecenter.video.videomanager.VideoManagerActivity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Util_System_ClipboardManager
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import retrofit2.HttpException
|
||||
import java.net.URLEncoder
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* 跳转用的方法
|
||||
@ -94,9 +102,6 @@ object DirectUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到特定页面,只支持App内部跳转
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String) {
|
||||
directToLinkPage(context, linkEntity, entrance, path, null)
|
||||
@ -128,7 +133,9 @@ object DirectUtils {
|
||||
"server",
|
||||
"top_game_comment",
|
||||
"wechat_bind",
|
||||
"video")
|
||||
"video",
|
||||
"catalog"
|
||||
)
|
||||
|
||||
fun directToLinkPage(context: Context,
|
||||
linkEntity: LinkEntity,
|
||||
@ -195,6 +202,8 @@ object DirectUtils {
|
||||
|
||||
"category", "分类" -> directCategoryDirectory(context, linkEntity.link!!, linkEntity.text!!)
|
||||
|
||||
"catalog" -> directCatalog(context, linkEntity.link!!, linkEntity.text!!, entrance, path)
|
||||
|
||||
"block", "版块" -> {
|
||||
if (linkEntity.link.isNullOrEmpty()) return
|
||||
directToBlock(context,
|
||||
@ -238,6 +247,8 @@ object DirectUtils {
|
||||
|
||||
"game_upload", "游戏投稿" -> directGameUpload(context, entrance, path)
|
||||
|
||||
"bbs_detail" -> directForumDetail(context, linkEntity.link ?: "", entrance)
|
||||
|
||||
//"h5_game_center" -> directLetoGameCenter(context)
|
||||
|
||||
"" -> {
|
||||
@ -257,7 +268,7 @@ object DirectUtils {
|
||||
* 跳转至QA
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToQa(context: Context, text: String, id: String) {
|
||||
fun directToQa(context: Context, text: String? = "", id: String) {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, QaActivity::class.java.simpleName)
|
||||
@ -294,6 +305,45 @@ object DirectUtils {
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至资讯文章列表
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameNews(context: Context, gameId: String?, gameName: String?, entrance: String?) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameNewsActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_GAMEID, gameId)
|
||||
bundle.putString(KEY_GAMENAME, gameName)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至游戏日历表
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameServerCalendar(context: Context, gameId: String?) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, ServersCalendarActivity::class.java.name)
|
||||
bundle.putParcelable(GameEntity::class.java.simpleName, GameEntity().apply {
|
||||
id = gameId ?: ""
|
||||
})
|
||||
bundle.putParcelable(GameDetailServer::class.java.simpleName, GameDetailServer())
|
||||
bundle.putParcelable(MeEntity::class.java.simpleName, MeEntity())
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至游戏历史版本页面
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToHistoryApk(context: Context, gameId: String?) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, HistoryApkListActivity::class.java.name)
|
||||
bundle.putString(KEY_GAMEID, gameId)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到新闻详情
|
||||
*/
|
||||
@ -342,15 +392,19 @@ object DirectUtils {
|
||||
* 跳转到游戏详情
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameDetail(context: Context, id: String, entrance: String? = null, autoDownload: Boolean? = null, scrollToLibao: Boolean = false, traceEvent: ExposureEvent? = null) {
|
||||
fun directToGameDetail(context: Context, id: String, entrance: String? = null, autoDownload: Boolean? = null, tab: String? = "", traceEvent: ExposureEvent? = null) {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, GameDetailActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
if (scrollToLibao) {
|
||||
bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_TRENDES)
|
||||
bundle.putBoolean(KEY_SCROLL_TO_LIBAO, scrollToLibao)
|
||||
if (!TextUtils.isEmpty(tab)) {
|
||||
when (tab) {
|
||||
"comment" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_RATING)
|
||||
"desc" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_DESC)
|
||||
"forum" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_BBS)
|
||||
"zone" -> bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_TRENDES)
|
||||
}
|
||||
}
|
||||
if (traceEvent != null) {
|
||||
val clickEvent = createEvent(GameEntity(id), traceEvent.source, appendTrace(traceEvent), ExposureType.CLICK)
|
||||
@ -361,6 +415,19 @@ object DirectUtils {
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到游戏评分详情
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameRatingDetail(context: Context, gameId: String? = "", commentId: String? = "", entrance: String? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_GAMEID, gameId)
|
||||
bundle.putString(KEY_COMMENTID, commentId)
|
||||
bundle.putString(KEY_TO, RatingReplyActivity::class.java.name)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转视频流-游戏介绍进入
|
||||
*/
|
||||
@ -512,7 +579,7 @@ object DirectUtils {
|
||||
@JvmStatic
|
||||
fun directToExternalBrowser(context: Context, url: String) {
|
||||
if (url.isEmpty()) return
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(Uri.decode(url)))
|
||||
if (context !is AppCompatActivity) {
|
||||
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
@ -543,8 +610,7 @@ object DirectUtils {
|
||||
context.startActivity(intent)
|
||||
} else {
|
||||
// 没有安装QQ 复制账号
|
||||
Util_System_ClipboardManager.setText(context, qq)
|
||||
Utils.toast(context, "已复制 QQ $qq")
|
||||
qq?.copyTextAndToast("已复制 QQ $qq")
|
||||
}
|
||||
}
|
||||
|
||||
@ -582,6 +648,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, LibaoDetailActivity::class.java.simpleName)
|
||||
bundle.putString(EntranceUtils.KEY_ID, giftId)
|
||||
HaloApp.put(LibaoEntity.TAG, null)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -662,7 +729,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null,
|
||||
path: String? = "", referer: String = "", type: String = "", act: String = "", fieldId: String = "", sectionName: String = "") {
|
||||
path: String? = "", referer: String = "", type: String = "", act: String = "", paginationType: String = "", fieldId: String = "", sectionName: String = "") {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
@ -675,6 +742,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_REFERER, referer)
|
||||
bundle.putString(KEY_TYPE, type)
|
||||
bundle.putString(KEY_ACTIVITY_NAME, act)
|
||||
bundle.putString(KEY_PAGINATION_TYPE, paginationType)
|
||||
bundle.putString(KEY_FIELD_ID, fieldId)
|
||||
bundle.putString(KEY_SECTION_NAME, sectionName)
|
||||
jumpActivity(context, bundle)
|
||||
@ -707,7 +775,29 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToBadgeWall(context: Context, userId: String?, name: String?, icon: String?) {
|
||||
context.startActivity(WebActivity.getBadgeCenterIntent(context, userId, name, icon))
|
||||
var url: String = if ("internal" == BuildConfig.FLAVOR) {
|
||||
Constants.BADGE_ADDRESS_DEV
|
||||
} else {
|
||||
Constants.BADGE_ADDRESS
|
||||
}
|
||||
|
||||
url = String.format(Locale.CHINA, "%s?user_id=%s&name=%s&icon=%s×tamp=%d", url, userId, name, URLEncoder.encode(icon), (Date().time / 1000 / 1000.toFloat()).roundToInt())
|
||||
directToFullScreenWebPage(context, url, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至徽章详情
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToBadgeDetail(context: Context, userId: String?, badgeId: String?) {
|
||||
var url: String = if ("internal" == BuildConfig.FLAVOR) {
|
||||
Constants.BADGE_DETAIL_ADDRESS_DEV
|
||||
} else {
|
||||
Constants.BADGE_DETAIL_ADDRESS
|
||||
}
|
||||
|
||||
url = String.format(Locale.CHINA, "%s?user_id=%s&badge_id=%s×tamp=%d", url, userId, badgeId, (Date().time / 1000 / 1000.toFloat()).roundToInt())
|
||||
directToFullScreenWebPage(context, url, true)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -724,6 +814,21 @@ object DirectUtils {
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToFullScreenWebPage(context: Context, url: String, webViewHandleBackPressed: Boolean = false) {
|
||||
context.startActivity(FullScreenWebActivity.getIntent(context, url, webViewHandleBackPressed))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToRegulationTestPage(context: Context) {
|
||||
val url = if ("internal" == BuildConfig.FLAVOR) {
|
||||
Constants.REGULATION_TEST_ADDRESS_DEV
|
||||
} else {
|
||||
Constants.REGULATION_TEST_ADDRESS
|
||||
}
|
||||
directToFullScreenWebPage(context, url, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转视频合集
|
||||
*/
|
||||
@ -787,6 +892,20 @@ object DirectUtils {
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转新分类
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directCatalog(context: Context, catalogId: String, catalogTitle: String, entrance: String? = null, path: String? = "") {
|
||||
if (catalogId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, CatalogActivity::class.java.name)
|
||||
bundle.putString(KEY_CATALOG_ID, catalogId)
|
||||
bundle.putString(KEY_CATALOG_TITLE, catalogTitle)
|
||||
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到问题标签详情
|
||||
*/
|
||||
@ -900,4 +1019,45 @@ object DirectUtils {
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directForumDetail(context: Context, bbsId: String? = "", entrance: String? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, ForumDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_BBS_ID, bbsId)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 到首页论坛 tab
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToForum(context: Context) {
|
||||
if (RunningUtils.isRunning(context)
|
||||
&& MainActivity::class.java.name == RunningUtils.getBaseActivity(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))
|
||||
}
|
||||
} else {
|
||||
jumpActivity(context, Bundle().apply { putInt(KEY_POSITION, MainWrapperFragment.INDEX_ASK) })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至使用帮助与反馈
|
||||
* @param position 使用帮助:[HelpAndFeedbackActivity.HELP_ITEM],意见反馈:[HelpAndFeedbackActivity.SUGGESTION_ITEM]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToHelpAndFeedback(context: Context, position: Int = HelpAndFeedbackActivity.HELP_ITEM) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, HelpAndFeedbackActivity::class.java.name)
|
||||
bundle.putInt(BaseActivity_TabLayout.PAGE_INDEX, position)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,7 @@ import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Display;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
@ -272,13 +273,23 @@ public class DisplayUtils {
|
||||
}
|
||||
|
||||
public static int getToastOffset() {
|
||||
int i = Resources.getSystem().getIdentifier("toast_y_offset", "dimen", "android");
|
||||
return HaloApp.getInstance().getApplication().getResources().getDimensionPixelSize(i);
|
||||
try {
|
||||
int i = Resources.getSystem().getIdentifier("toast_y_offset", "dimen", "android");
|
||||
return HaloApp.getInstance().getApplication().getResources().getDimensionPixelSize(i);
|
||||
} catch (Resources.NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return dip2px(24);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getToastDefaultGravity() {
|
||||
int i = Resources.getSystem().getIdentifier("config_toastDefaultGravity", "integer", "android");
|
||||
return HaloApp.getInstance().getApplication().getResources().getInteger(i);
|
||||
try {
|
||||
int i = Resources.getSystem().getIdentifier("config_toastDefaultGravity", "integer", "android");
|
||||
return HaloApp.getInstance().getApplication().getResources().getInteger(i);
|
||||
} catch (Resources.NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasSoftKeys(Context context) {
|
||||
|
||||
@ -8,13 +8,22 @@ import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.CertificationDialog;
|
||||
import com.gh.common.dialog.DeviceRemindDialog;
|
||||
import com.gh.common.dialog.PackageCheckDialogFragment;
|
||||
import com.gh.common.dialog.ReserveDialogFragment;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.common.simulator.SimulatorDownloadManager;
|
||||
import com.gh.common.simulator.SimulatorGameManager;
|
||||
import com.gh.common.xapk.XapkInstaller;
|
||||
import com.gh.common.xapk.XapkUnzipStatus;
|
||||
import com.gh.download.DownloadManager;
|
||||
@ -34,14 +43,9 @@ import com.lightgame.download.DownloadStatus;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* todo 下载判断不能以按钮文案为判断条件,否则按钮文案修改时又要修改判断逻辑
|
||||
*/
|
||||
@ -195,6 +199,10 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadBtn.setText("查看");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.white));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
} else if ("updating".equals(offStatus)) {
|
||||
holder.gameDownloadBtn.setText("更新中");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.white));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.download_button_updating_style);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setText("暂无");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.button_gray));
|
||||
@ -223,9 +231,18 @@ public class DownloadItemUtils {
|
||||
if (entryMap != null && !entryMap.isEmpty()) {
|
||||
DownloadEntity downloadEntity = entryMap.get(apkEntity.getPlatform());
|
||||
if (downloadEntity != null) {
|
||||
// 更改进度条和提示文本的状态
|
||||
changeStatus(context, holder, downloadEntity, isShowPlatform, true);
|
||||
return;
|
||||
if (ExtensionsKt.isSimulatorGame(downloadEntity)) {
|
||||
if (downloadEntity.getStatus() != DownloadStatus.done) {
|
||||
// 更改进度条和提示文本的状态
|
||||
changeStatus(context, holder, downloadEntity, isShowPlatform, true);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// 更改进度条和提示文本的状态
|
||||
changeStatus(context, holder, downloadEntity, isShowPlatform, true);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,7 +420,7 @@ public class DownloadItemUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clickCallback 供那些需要知道点击回调的地方使用
|
||||
* @param clickCallback 供那些需要知道点击回调的地方使用,触发具体响应才会回调
|
||||
*/
|
||||
public static void setOnClickListener(final Context context,
|
||||
final TextView downloadBtn,
|
||||
@ -415,27 +432,50 @@ public class DownloadItemUtils {
|
||||
final ExposureEvent traceEvent,
|
||||
@Nullable final EmptyCallback clickCallback) {
|
||||
|
||||
setOnClickListener(context, downloadBtn, gameEntity, position, adapter, entrance, location, traceEvent, clickCallback, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param allStateClickCallback 供那些需要知道点击回调的地方使用,只要触发点击动作就会回调
|
||||
*/
|
||||
public static void setOnClickListener(final Context context,
|
||||
final TextView downloadBtn,
|
||||
final GameEntity gameEntity,
|
||||
final int position,
|
||||
final RecyclerView.Adapter<? extends RecyclerView.ViewHolder> adapter,
|
||||
final String entrance,
|
||||
final String location,
|
||||
final ExposureEvent traceEvent,
|
||||
@Nullable final EmptyCallback clickCallback,
|
||||
@Nullable final EmptyCallback allStateClickCallback) {
|
||||
|
||||
if (gameEntity.isReservable()) {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
if (allStateClickCallback != null) {
|
||||
allStateClickCallback.onCallback();
|
||||
}
|
||||
|
||||
CheckLoginUtils.checkLogin(context, entrance, () -> {
|
||||
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");
|
||||
});
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
|
||||
gameEntity,
|
||||
() -> {
|
||||
LogUtils.logReservation(gameEntity, traceEvent);
|
||||
adapter.notifyItemChanged(position);
|
||||
}
|
||||
);
|
||||
dialogFragment.show(((AppCompatActivity) context).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
});
|
||||
} else {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
if (allStateClickCallback != null) {
|
||||
allStateClickCallback.onCallback();
|
||||
}
|
||||
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
@ -459,6 +499,10 @@ public class DownloadItemUtils {
|
||||
|
||||
if (gameEntity.getApk().size() == 0 && gameEntity.getH5Link() != null) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
if (allStateClickCallback != null) {
|
||||
allStateClickCallback.onCallback();
|
||||
}
|
||||
|
||||
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
|
||||
|
||||
LinkEntity linkEntity = gameEntity.getH5Link();
|
||||
@ -468,12 +512,16 @@ public class DownloadItemUtils {
|
||||
HistoryHelper.insertGameEntity(gameEntity);
|
||||
}
|
||||
|
||||
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), isPlay,linkEntity.getCloseButton());
|
||||
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), isPlay, linkEntity.getCloseButton());
|
||||
context.startActivity(i);
|
||||
});
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
EmptyCallback clickRunnable = () -> {
|
||||
if (allStateClickCallback != null) {
|
||||
allStateClickCallback.onCallback();
|
||||
}
|
||||
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
@ -489,6 +537,10 @@ public class DownloadItemUtils {
|
||||
});
|
||||
} else {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
if (allStateClickCallback != null) {
|
||||
allStateClickCallback.onCallback();
|
||||
}
|
||||
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
@ -506,7 +558,6 @@ public class DownloadItemUtils {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void onNormalClick(final Context context,
|
||||
@ -532,23 +583,27 @@ public class DownloadItemUtils {
|
||||
|
||||
if (str.equals(context.getString(R.string.download))) {
|
||||
// 先弹下载弹窗(如果需要的话)
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
PackageCheckDialogFragment.show((AppCompatActivity) context, gameEntity.getPackageDialog(), () -> {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
DataLogUtils.uploadGameLog(context, gameEntity.getId(), gameEntity.getName(), entrance);
|
||||
} else if (str.equals(context.getString(R.string.attempt))) {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
PackageCheckDialogFragment.show((AppCompatActivity) context, gameEntity.getPackageDialog(), () -> {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -570,8 +625,30 @@ public class DownloadItemUtils {
|
||||
});
|
||||
}
|
||||
} else if (str.equals(context.getString(R.string.install))) {
|
||||
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apk.getUrl());
|
||||
if (gameEntity.getSimulator() != null) {
|
||||
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(context, gameEntity.getSimulator().getApk().getPackageName());
|
||||
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(gameEntity) && !isInstalled) {
|
||||
SimulatorDownloadManager.getInstance().showDownloadDialog(context, gameEntity.getSimulator(),
|
||||
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.getId(), gameEntity.getName(), null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
install(context, gameEntity, position, adapter);
|
||||
} else if (str.equals(context.getString(R.string.launch))) {
|
||||
//启动模拟器游戏
|
||||
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
|
||||
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
|
||||
if (downloadEntity != null) {
|
||||
File file = new File(downloadEntity.getPath());
|
||||
if (!file.exists()) {
|
||||
download(context, gameEntity, downloadBtn, entrance, location, false, traceEvent);
|
||||
return;
|
||||
}
|
||||
SimulatorGameManager.launchSimulatorGame(downloadEntity, gameEntity);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (entrance.contains("我的游戏")) {
|
||||
MtaHelper.onEvent("我的游戏_启动", "启动", gameEntity.getName());
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import com.walkud.rom.checker.RomIdentifier
|
||||
|
||||
object DownloadNotificationHelper {
|
||||
|
||||
@ -29,6 +30,7 @@ object DownloadNotificationHelper {
|
||||
const val ACTION_DOWNLOAD = "com.gh.gamecenter.DOWNLOAD"
|
||||
|
||||
private val mNotifyMap: MutableMap<String, Long> = mutableMapOf()
|
||||
private val mShouldUseAlternativeNotificationIcon by lazy { RomIdentifier.getRom().versionName == null }
|
||||
|
||||
private fun getNotificationManager(): NotificationManager {
|
||||
return HaloApp.getInstance().application.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
@ -42,6 +44,9 @@ object DownloadNotificationHelper {
|
||||
val downloadNotificationId = (entity.gameId + entity.packageName).hashCode()
|
||||
val xapkStatus = entity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
|
||||
|
||||
if (entity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.SILENT_UPDATE) return
|
||||
if (entity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.SIMULATOR_DOWNLOAD) return
|
||||
|
||||
val intent = Intent()
|
||||
if (entity.status == DownloadStatus.done && xapkStatus != XapkUnzipStatus.FAILURE.name) {
|
||||
intent.putExtra(EntranceUtils.KEY_DATA, entity.toJson())
|
||||
@ -56,7 +61,6 @@ object DownloadNotificationHelper {
|
||||
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)
|
||||
}
|
||||
@ -64,12 +68,11 @@ object DownloadNotificationHelper {
|
||||
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)
|
||||
.setSmallIcon(getNotificationIcon())
|
||||
.setContentIntent(pendingIntent)
|
||||
.setGroup(DOWNLOAD_GROUP_KEY)
|
||||
.setWhen(whenTime)
|
||||
|
||||
|
||||
if (xapkStatus == XapkUnzipStatus.FAILURE.name) {
|
||||
builder.setContentText("《" + entity.name + "》解压失败,点击查看详情~")
|
||||
} else {
|
||||
@ -112,7 +115,8 @@ object DownloadNotificationHelper {
|
||||
|| entity.status == DownloadStatus.overflow
|
||||
|| (entity.status == DownloadStatus.done // 触发安装事件以后也 cancel 掉通知
|
||||
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty()
|
||||
&& xapkStatus != XapkUnzipStatus.FAILURE.name)) {
|
||||
&& xapkStatus != XapkUnzipStatus.FAILURE.name)
|
||||
||entity.status == DownloadStatus.done && entity.isSimulatorGame()) {//模拟器游戏下载完需要cancel掉通知
|
||||
requireUpdateNotificationGroupDelay = true
|
||||
notificationManager.cancel(entity.path, DOWNLOAD_NOTIFICATION_ID)
|
||||
} else {
|
||||
@ -139,32 +143,35 @@ object DownloadNotificationHelper {
|
||||
}
|
||||
|
||||
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++
|
||||
// 部分华为设备调用 getActiveNotifications() 方法时会触发方法内的空指针,这里整体包裹处理了
|
||||
tryCatchInRelease {
|
||||
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 (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)
|
||||
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(getNotificationIcon())
|
||||
.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -175,4 +182,8 @@ object DownloadNotificationHelper {
|
||||
addOrUpdateDownloadNotification(downloadTask)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNotificationIcon(): Int {
|
||||
return if (mShouldUseAlternativeNotificationIcon) R.drawable.ic_notification else R.mipmap.logo
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,13 @@
|
||||
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.common.exposure.meta.MetaUtil
|
||||
import com.gh.common.simulator.SimulatorDownloadManager
|
||||
import com.gh.common.simulator.SimulatorGameManager
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.download.DownloadDataHelper
|
||||
import com.gh.download.DownloadManager
|
||||
@ -26,7 +28,6 @@ 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
|
||||
@ -59,8 +60,8 @@ object DownloadObserver {
|
||||
if (DownloadStatus.hijack == downloadEntity.status) {
|
||||
// 链接被劫持
|
||||
processHijack(downloadEntity)
|
||||
val nameAndPlatform = (downloadEntity.name + ":"
|
||||
+ PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
|
||||
// val nameAndPlatform = (downloadEntity.name + ":"
|
||||
// + PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
|
||||
// MtaHelper.onEvent("下载劫持",
|
||||
// "游戏名字", nameAndPlatform,
|
||||
// "网络状态", DeviceUtils.getNetwork(mApplication))
|
||||
@ -75,9 +76,10 @@ object DownloadObserver {
|
||||
// MtaHelper.onEventWithBasicDeviceInfo("下载失败弹窗",
|
||||
// "游戏", downloadEntity.name,
|
||||
// "平台", downloadEntity.platform)
|
||||
val currentActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
|
||||
DialogUtils.showAlertDialog(AppManager.getInstance().currentActivity(), "下载失败", "下载链接已失效,建议提交反馈", "立即反馈", "取消", {
|
||||
SuggestionActivity.startSuggestionActivity(AppManager.getInstance().currentActivity(),
|
||||
DialogUtils.showAlertDialog(currentActivity, "下载失败", "下载链接已失效,建议提交反馈", "立即反馈", "取消", {
|
||||
SuggestionActivity.startSuggestionActivity(currentActivity,
|
||||
SuggestType.gameQuestion, "notfound",
|
||||
StringUtils.buildString(downloadEntity.name, ",问题反馈:下载链接失效"),
|
||||
SimpleGameEntity(gameId, downloadEntity.name, ""))
|
||||
@ -103,15 +105,22 @@ object DownloadObserver {
|
||||
Utils.log("DownloadObserver", "下载自动暂停->" + downloadEntity.toJson())
|
||||
}
|
||||
}
|
||||
} else if (DownloadStatus.redirected == downloadEntity.status) {
|
||||
debugOnly { Utils.log("重定向完毕") }
|
||||
DownloadDataHelper.uploadRedirectEvent(downloadEntity)
|
||||
}
|
||||
if (DownloadStatus.done == downloadEntity.status) {
|
||||
if (downloadEntity.name.contains(mApplication.getString(R.string.app_name))) {
|
||||
MtaHelper.onEvent("软件更新", "下载完成")
|
||||
// 会有 ActivityNotFoundException 异常,catch 掉不管了
|
||||
tryWithDefaultCatch {
|
||||
// 会有 ActivityNotFoundException 异常,catch 掉不管了
|
||||
PackageInstaller.install(mApplication, downloadEntity)
|
||||
if (Constants.SILENT_UPDATE != downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)) {
|
||||
// TODO 在 Android 11 上没有授权安装未知应用的权限前第一次调用这个方法系统会杀掉我们的进程...
|
||||
// 没能找到类似的解释,最接近的是这个 https://issuetracker.google.com/issues/154157387,但也只是点授权杀进程而已
|
||||
PackageInstaller.install(mApplication, downloadEntity);
|
||||
DataLogUtils.uploadUpgradeLog(mApplication, "install") //上传更新安装数据
|
||||
}
|
||||
}
|
||||
DataLogUtils.uploadUpgradeLog(mApplication, "install") //上传更新安装数据
|
||||
} else {
|
||||
statDoneEvent(downloadEntity)
|
||||
|
||||
@ -128,20 +137,38 @@ object DownloadObserver {
|
||||
Utils.toast(mApplication, downloadEntity.name + " - 下载完成")
|
||||
}
|
||||
if (!downloadEntity.isPluggable) {
|
||||
// 是否是自动安装
|
||||
if (PreferenceManager.getDefaultSharedPreferences(mApplication).getBoolean(SettingsFragment.AUTO_INSTALL_SP_KEY, true)) {
|
||||
if (FileUtils.isEmptyFile(downloadEntity.path)) {
|
||||
Utils.toast(mApplication, R.string.install_failure_hint)
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
} else {
|
||||
if (PackageUtils.isCanLaunchSetup(mApplication, downloadEntity.path)) {
|
||||
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
|
||||
tryWithDefaultCatch {
|
||||
PackageInstaller.install(mApplication, downloadEntity, false)
|
||||
}
|
||||
if (downloadEntity.isSimulatorGame()) {
|
||||
val gameEntity = HaloApp.get(GameEntity::class.java.simpleName, true) as? GameEntity
|
||||
if (gameEntity?.simulator != null) {
|
||||
val isInstalled = PackageUtils.isInstalledFromAllPackage(HaloApp.getInstance().application, gameEntity.simulator!!.apk!!.packageName)
|
||||
if (!isInstalled) {
|
||||
val currentActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
|
||||
SimulatorDownloadManager.getInstance().showDownloadDialog(currentActivity, gameEntity.simulator,
|
||||
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name
|
||||
?: "", null)
|
||||
}
|
||||
SimulatorGameManager.recordDownloadSimulatorGames(gameEntity.id)
|
||||
SimulatorGameManager.postPlayedGame(gameEntity.id, downloadEntity.packageName)
|
||||
}
|
||||
} else {
|
||||
val downloadType = downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)
|
||||
// 是否是自动安装
|
||||
val isAutoInstall = PreferenceManager.getDefaultSharedPreferences(mApplication).getBoolean(SettingsFragment.AUTO_INSTALL_SP_KEY, true)
|
||||
if (downloadType == Constants.SIMULATOR_DOWNLOAD || isAutoInstall) {
|
||||
if (FileUtils.isEmptyFile(downloadEntity.path)) {
|
||||
Utils.toast(mApplication, R.string.install_failure_hint)
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
} else {
|
||||
// 弹出卸载提示框
|
||||
EventBus.getDefault().post(EBShowDialog(BaseActivity.PLUGGABLE, downloadEntity.path))
|
||||
if (PackageUtils.isCanLaunchSetup(mApplication, downloadEntity.path)) {
|
||||
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
|
||||
tryWithDefaultCatch {
|
||||
PackageInstaller.install(mApplication, downloadEntity, false)
|
||||
}
|
||||
} else {
|
||||
// 弹出卸载提示框
|
||||
EventBus.getDefault().post(EBShowDialog(BaseActivity.PLUGGABLE, downloadEntity.path))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,15 +179,15 @@ object DownloadObserver {
|
||||
}
|
||||
|
||||
// 下载过程分析统计
|
||||
val pm = mApplication.packageManager
|
||||
val packageInfo = pm.getPackageArchiveInfo(downloadEntity.path, PackageManager.GET_ACTIVITIES)
|
||||
if (packageInfo == null) {
|
||||
// val pm = mApplication.packageManager
|
||||
// val packageInfo = pm.getPackageArchiveInfo(downloadEntity.path, 0)
|
||||
// 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) {
|
||||
@ -192,7 +219,7 @@ object DownloadObserver {
|
||||
kv1["版本"] = platform
|
||||
kv1["状态"] = "下载完成"
|
||||
kv1["用户机型"] = Build.MODEL
|
||||
kv1["设备IMEI"] = Util_System_Phone_State.getDeviceId(HaloApp.getInstance().application)
|
||||
kv1["设备IMEI"] = MetaUtil.getIMEI()
|
||||
kv1["网络状态"] = DeviceUtils.getNetwork(HaloApp.getInstance().application)
|
||||
kv1["光环助手版本"] = BuildConfig.VERSION_NAME
|
||||
if (downloadEntity.isUpdate) {
|
||||
@ -235,6 +262,8 @@ object DownloadObserver {
|
||||
gameVersion = downloadEntity.versionName ?: ""),
|
||||
downloadEntity.platform,
|
||||
downloadEntity.exposureTrace,
|
||||
downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown",
|
||||
downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] ?: "unknown",
|
||||
type)
|
||||
|
||||
DataCollectionUtils.uploadDownload(mApplication, downloadEntity, "完成")
|
||||
|
||||
@ -1,17 +1,31 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.gh.common.avoidcallback.AvoidOnResultManager;
|
||||
import com.gh.common.avoidcallback.Callback;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.MainActivity;
|
||||
import com.gh.gamecenter.NormalActivity;
|
||||
import com.gh.gamecenter.SplashScreenActivity;
|
||||
import com.gh.gamecenter.normal.NormalFragment;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
@ -25,8 +39,10 @@ public class EntranceUtils {
|
||||
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_GAME_ID = "game_id";
|
||||
public static final String KEY_ID = "id";
|
||||
public static final String KEY_URL = "url";
|
||||
public static final String KEY_BUNDLE = "bundle";
|
||||
public static final String KEY_GAMENAME = "gameName";
|
||||
public static final String KEY_PACKAGE_MD5 = "package_md5";
|
||||
public static final String HOST_ARTICLE = "article";
|
||||
@ -38,6 +54,7 @@ public class EntranceUtils {
|
||||
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_FORUM = "forum";
|
||||
public static final String HOST_CATEGORY = "category";//分类
|
||||
public static final String HOST_COLUMN_COLLECTION = "column_collection";//专题合集
|
||||
public static final String HOST_COMMUNITY_QUESTION_LABEL_DETAIL = "community_question_label_detail";//问题标签详情
|
||||
@ -45,6 +62,8 @@ public class EntranceUtils {
|
||||
public static final String HOST_BLOCK = "block";//板块
|
||||
public static final String HOST_SERVER_BLOCK = "server";//开服表板块
|
||||
public static final String HOST_AMWAY_BLOCK = "amway";//安利墙板块
|
||||
public static final String HOST_GAME_CALENDAR = "game_calendar";// 指定游戏的开服表页面
|
||||
public static final String HOST_HISTORY_APK = "history_apk"; // 历史版本页面
|
||||
public static final String HOST_HELP = "help";//Q&A
|
||||
public static final String HOST_HELP_COLLECTION = "help_collection";//Q&A合集
|
||||
public static final String HOST_GAME_UPLOAD = "game_upload";//游戏上传
|
||||
@ -53,6 +72,7 @@ public class EntranceUtils {
|
||||
public static final String HOST_COMMUNITY_COLUMN = "community_column";
|
||||
public static final String HOST_GAME = "game";
|
||||
public static final String HOST_GAME_DOWNLOAD = "game_download";
|
||||
public static final String HOST_GAME_NEWS = "game_news";
|
||||
public static final String HOST_COLUMN = "column";
|
||||
public static final String HOST_WEB = "web";
|
||||
public static final String HOST_QQ = "qq";
|
||||
@ -60,12 +80,17 @@ public class EntranceUtils {
|
||||
public static final String HOST_QQ_QUN = "qqqun";
|
||||
public static final String HOST_DOWNLOAD = "download";
|
||||
public static final String HOST_UPDATE = "update";
|
||||
public static final String HOST_LINK = "link";
|
||||
public static final String HOST_LIBAO = "libao";
|
||||
public static final String HOST_COMMUNITY = "community";
|
||||
public static final String HOST_SUGGESTION = "suggestion";
|
||||
public static final String HOST_ANSWER = "answer";
|
||||
public static final String HOST_QUESTION = "question";
|
||||
public static final String HOST_TOOLBOX = "toolbox";
|
||||
public static final String HOST_FORUM_DETAIL = "forum_detail";
|
||||
public static final String HOST_GAME_RATING_DETAIL = "game_rating_detail";
|
||||
public static final String HOST_HELP_AND_FEEDBACK = "help_and_feedback";
|
||||
public static final String HOST_LAUNCH_SIMULATOR_GAME = "launch_simulator_game";
|
||||
public static final String KEY_DATA = "data";
|
||||
public static final String KEY_MESSAGE = "message";
|
||||
public static final String KEY_MESSAGE_ID = "message_id";
|
||||
@ -94,8 +119,10 @@ 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_COMMENT_ID = "comment_id";
|
||||
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_LOCAL_PATH = "local_path";
|
||||
public static final String KEY_OUTER_INFO = "outerInfo";
|
||||
public static final String KEY_OLDERUSER = "isOldUser";
|
||||
public static final String KEY_SEARCHKEY = "searchKey";
|
||||
@ -143,6 +170,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_COMMUNITY_ARTICLE_ID = "communityArticleId";
|
||||
public static final String KEY_ARTICLE_COMMENT_ID = "articleCommentId";
|
||||
public static final String KEY_SHOW_ARTICLE_COMMENT = "showArticleComment";
|
||||
public static final String KEY_SCROLL_TO_COMMENT_AREA = "scroll_to_comment_area";
|
||||
public static final String KEY_RATING_STAR_COUNT = "ratingStarCount";
|
||||
public static final String KEY_QUESTION_MODERATOR_PATCH = "questionModeratorPatch";
|
||||
public static final String KEY_SKIP_GAME_COMMENT = "skipGameComment";
|
||||
@ -164,11 +192,15 @@ public class EntranceUtils {
|
||||
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_PAGINATION_TYPE = "paginationType";//活动分页方式
|
||||
public static final String KEY_REQUIRE_REDIRECT = "require_redirect"; // 标记需要再跳转
|
||||
public static final String KEY_FIELD_ID = "field_id"; // 专区板块id
|
||||
public static final String KEY_SECTION_NAME = "section_name"; // 专区专题名
|
||||
public static final String KEY_COLUMNNAME = "columnName";
|
||||
public static final String KEY_QA_ID = "qaId";
|
||||
public static final String KEY_QA_CONTENT_ID = "qaContentId";
|
||||
public static final String KEY_QA_CATEGORY_NAME = "qaCategoryName";
|
||||
public static final String KEY_QA_TITLE = "qa_title";
|
||||
public static final String KEY_QA_COLLECTION_ID = "qaCollectionId";
|
||||
public static final String KEY_SHOW_EDIT_DRAFT = "showEditDraft";
|
||||
public static final String KEY_ARTICLE_OPEN_IN_NEW_PAGE = "openArticleInNewPage";
|
||||
@ -176,6 +208,19 @@ public class EntranceUtils {
|
||||
public static final String KEY_KAIFU_SELECT_TIME = "kaifuSelectTime";
|
||||
public static final String KEY_POSTER_PATH = "posterPath";
|
||||
public static final String KEY_BLACK_THEME = "blackTheme";
|
||||
public static final String KEY_FROM_LOGIN = "fromLogin";
|
||||
public static final String KEY_CHANGE_PHONE = "changePhone";
|
||||
public static final String KEY_CONFLICT_PHONE = "conflictPhone";
|
||||
public static final String KEY_CONFLICT_USER = "conflictUser";
|
||||
public static final String KEY_BBS_ID = "bbs_id";
|
||||
public static final String KEY_DIAGNOSIS = "diagnosis";
|
||||
public static final String KEY_SIMULATOR = "simulator";
|
||||
public static final String KEY_MARKET_DETAILS = "market_details";
|
||||
public static final String KEY_CATALOG_ID = "catalogId";
|
||||
public static final String KEY_PRIMARY_CATALOG_ID = "primaryCatalogId";
|
||||
public static final String KEY_PRIMARY_CATALOG_NAME = "primaryCatalogName";
|
||||
public static final String KEY_CATALOG_TITLE = "catalog_title";
|
||||
public static final String KEY_CATALOG_INIT_TITLE = "catalog_init_title";
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
@ -231,4 +276,82 @@ public class EntranceUtils {
|
||||
context.startActivity(SplashScreenActivity.getSplashScreenIntent(context, bundle));
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveShortcut(String activityName, @Nullable Bundle bundle) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
if (activityName.contains("MainActivity")) {
|
||||
SPUtils.setString(EntranceUtils.KEY_BUNDLE, "");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bundle == null) bundle = new Bundle();
|
||||
try {
|
||||
Set<String> keys = bundle.keySet();
|
||||
json.put(KEY_TO, activityName);
|
||||
for (String key : keys) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
Object object = bundle.get(key);
|
||||
if (object instanceof Parcelable) {
|
||||
if (object.toString().toLowerCase().contains("gameentity")) {
|
||||
Utils.toast(HaloApp.getInstance().getApplication(), "暂不支持带游戏实体的页面保存捷径");
|
||||
return;
|
||||
}
|
||||
|
||||
String parcelableName = key + ":parcelable";
|
||||
String parcelableType = object.getClass().getName();
|
||||
String objectJsonString = GsonUtils.toJson(object);
|
||||
JSONObject jObject = new JSONObject(objectJsonString);
|
||||
json.put(parcelableName, parcelableType);
|
||||
json.put(key, jObject);
|
||||
} else {
|
||||
json.put(key, JSONObject.wrap(bundle.get(key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Utils.toast(HaloApp.getInstance().getApplication(), "保存捷径成功");
|
||||
SPUtils.setString(EntranceUtils.KEY_BUNDLE, json.toString());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
SPUtils.setString(EntranceUtils.KEY_BUNDLE, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void jumpShortcut(Activity activity) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
if (!hasShortcut()) return;
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(SPUtils.getString(EntranceUtils.KEY_BUNDLE));
|
||||
Iterator iter = jsonObject.keys();
|
||||
String parcelableName = "";
|
||||
while (iter.hasNext()) {
|
||||
String key = (String) iter.next();
|
||||
String value = jsonObject.getString(key);
|
||||
if (key.contains(":parcelable")) {
|
||||
parcelableName = value;
|
||||
} else {
|
||||
if (!TextUtils.isEmpty(parcelableName)) {
|
||||
Class<?> gClass = Class.forName(parcelableName);
|
||||
bundle.putParcelable(key, ((Parcelable) GsonUtils.fromJson(value, gClass)));
|
||||
} else {
|
||||
bundle.putString(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
jumpActivity(activity, bundle);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasShortcut() {
|
||||
return !TextUtils.isEmpty(SPUtils.getString(EntranceUtils.KEY_BUNDLE));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -116,6 +116,8 @@ object ErrorHelper {
|
||||
403078 -> Utils.toast(context, "已点赞")
|
||||
403072 -> Utils.toast(context, R.string.comment_failed_userblocked)
|
||||
403082 -> Utils.toast(context, "作者已关闭评论")
|
||||
403022 -> Utils.toast(context, "不能回复自己")
|
||||
403056 -> Utils.toast(context, "发布失败,字数已达上限")
|
||||
|
||||
403020 -> if (showHighPriorityHint) {
|
||||
DialogUtils.showAlertDialog(context,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.animation.Animator
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.Build
|
||||
import android.text.*
|
||||
import android.text.style.ClickableSpan
|
||||
@ -11,7 +13,10 @@ import android.text.style.URLSpan
|
||||
import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
@ -33,13 +38,17 @@ import com.gh.common.view.ExpandTextView
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.ObservableTransformer
|
||||
import io.reactivex.SingleTransformer
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import java.net.URI
|
||||
@ -64,6 +73,14 @@ inline fun <reified VM : ViewModel> Fragment.viewModelProviderFromParent(
|
||||
) =
|
||||
ViewModelProviders.of(requireActivity(), provider).get(VM::class.java)
|
||||
|
||||
/**
|
||||
* 创建以 activity 为观察者上下文的 viewModel
|
||||
*/
|
||||
inline fun <reified VM : ViewModel> FragmentActivity.viewModelProviderFromParent(
|
||||
provider: ViewModelProvider.Factory? = null
|
||||
) =
|
||||
ViewModelProviders.of(this, provider).get(VM::class.java)
|
||||
|
||||
/**
|
||||
* 创建以 fragment 为观察者上下文的 viewModel
|
||||
*/
|
||||
@ -111,6 +128,20 @@ fun ViewPager.addOnScrollStateChanged(onStateChanged: ((state: Int) -> Unit)? =
|
||||
addOnPageChangeListener(listener)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fragment related
|
||||
*/
|
||||
inline fun <reified T : Fragment> Fragment.fragmentFromActivity() =
|
||||
parentFragmentManager.findFragmentByTag(T::class.java.simpleName) as? T
|
||||
?: parentFragmentManager.fragmentFactory.instantiate(requireContext().classLoader, T::class.java.canonicalName) as T
|
||||
|
||||
|
||||
inline fun <reified T : Fragment> Fragment.fragmentFromParentFragment() =
|
||||
childFragmentManager.findFragmentByTag(T::class.java.simpleName) as? T
|
||||
?: childFragmentManager.fragmentFactory.instantiate(requireContext().classLoader, T::class.java.canonicalName) as T
|
||||
|
||||
|
||||
/**
|
||||
* RecyclerView Extensions
|
||||
*/
|
||||
@ -162,6 +193,21 @@ fun View.removeSelectableItemBackground() {
|
||||
background = null
|
||||
}
|
||||
|
||||
fun View.setRoundedColorBackground(@ColorRes color: Int, radius: Float) {
|
||||
val shape = GradientDrawable()
|
||||
shape.cornerRadius = radius.dip2px().toFloat()
|
||||
shape.setColor(ContextCompat.getColor(context, color))
|
||||
background = shape
|
||||
}
|
||||
|
||||
fun View.setDebouncedClickListener(action: () -> Unit) {
|
||||
setOnClickListener { debounceActionWithInterval(interval = 300L) { action.invoke() } }
|
||||
}
|
||||
|
||||
fun isPublishEnv(): Boolean {
|
||||
return BuildConfig.FLAVOR != "internal"
|
||||
}
|
||||
|
||||
/**
|
||||
* LiveData Extensions
|
||||
*/
|
||||
@ -223,6 +269,29 @@ fun String.containHtmlTag(): Boolean {
|
||||
return matcher.find()
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户行为相关
|
||||
*/
|
||||
fun Fragment.showRegulationTestDialogIfNeeded(action: (() -> Unit)) {
|
||||
if (UserManager.getInstance().userShouldTakeRegulationBaseOnLastRemind()) {
|
||||
DialogUtils.showRegulationTestDialog(requireContext(),
|
||||
{ DirectUtils.directToRegulationTestPage(requireContext()) },
|
||||
{ action.invoke() })
|
||||
} else {
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.showRegulationTestDialogIfNeeded(action: (() -> Unit)) {
|
||||
if (UserManager.getInstance().userShouldTakeRegulationBaseOnLastRemind()) {
|
||||
DialogUtils.showRegulationTestDialog(this,
|
||||
{ DirectUtils.directToRegulationTestPage(this) },
|
||||
{ action.invoke() })
|
||||
} else {
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在限定 interval 里只触发一次 action
|
||||
*/
|
||||
@ -278,6 +347,15 @@ fun throwExceptionInDebug(message: String = "", predicate: Boolean = true) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在自动打包的包里弹 toast
|
||||
*/
|
||||
fun toastInInternalRelease(content: String) {
|
||||
if (BuildConfig.BUILD_TIME != 0L) {
|
||||
Utils.toast(HaloApp.getInstance(), content)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动抛出异常
|
||||
*/
|
||||
@ -337,11 +415,25 @@ fun String.getFirstElementDividedByDivider(divider: String): String {
|
||||
return this
|
||||
}
|
||||
|
||||
fun String.copyText() {
|
||||
this.copyTextAndToast("")
|
||||
}
|
||||
|
||||
fun String.copyTextAndToast(toastText: String = "复制成功") {
|
||||
val application = HaloApp.getInstance().application
|
||||
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
cmb.text = this
|
||||
ToastUtils.showToast(toastText)
|
||||
try {
|
||||
val application = HaloApp.getInstance().application
|
||||
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText(null, this)
|
||||
cmb.primaryClip = clip
|
||||
|
||||
if (!TextUtils.isEmpty(toastText)) {
|
||||
ToastUtils.showToast(toastText)
|
||||
}
|
||||
} catch (e: SecurityException) {
|
||||
// 在一些情况下会报以下这样的错误,可能是以浮动窗口显示然后没有焦点?(https://developer.android.com/about/versions/10/privacy/changes#clipboard-data)
|
||||
// java.lang.Throwable: java.lang.SecurityException: com.xunmeng.pinduoduo from uid 10317 not allowed to perform READ_CLIPBOARD
|
||||
ToastUtils.showToast("复制失败,请重试")
|
||||
}
|
||||
}
|
||||
|
||||
fun Map<String, String>.createRequestBody(): RequestBody {
|
||||
@ -380,6 +472,12 @@ fun Float.px2dip(): Int {
|
||||
return (this / scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
fun Float.sp2px(): Int {
|
||||
val scale: Float = HaloApp.getInstance().application.resources.displayMetrics.scaledDensity
|
||||
return (this * scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* PopupWindow 自动适配方向
|
||||
* 弹出与锚点右对齐
|
||||
@ -460,6 +558,15 @@ fun FragmentActivity.checkStoragePermissionBeforeAction(action: (() -> Unit)) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* List related.
|
||||
*/
|
||||
|
||||
// Returns the second element, or `null` if the list is empty.
|
||||
fun <T> List<T>.secondOrNull(): T? {
|
||||
return if (isEmpty() || size == 1) null else this[1]
|
||||
}
|
||||
|
||||
/**
|
||||
* TextView related.
|
||||
*/
|
||||
@ -494,6 +601,19 @@ fun TextView.setTextChangedListener(action: (s: CharSequence, start: Int, before
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayList related
|
||||
*/
|
||||
fun <T> ArrayList<T>.safelyGetInRelease(index: Int): T? {
|
||||
return if (index >= size) {
|
||||
throwExceptionInDebug("这里触发了数组越界,请检查")
|
||||
toastInInternalRelease("这个操作可能触发闪退,请确定复现方式并联系开发处理")
|
||||
null
|
||||
} else {
|
||||
this[index]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截 TextView 中的 Url Span,用应用内页面的形式打开链接
|
||||
* @param shrankText 未展开时的文字
|
||||
@ -589,10 +709,22 @@ fun DownloadEntity.addMetaExtra(key: String, value: String?) {
|
||||
value?.let { meta[key] = value }
|
||||
}
|
||||
|
||||
fun DownloadEntity.getMetaExtra(key: String) : String {
|
||||
fun DownloadEntity.getMetaExtra(key: String): String {
|
||||
return meta[key] ?: ""
|
||||
}
|
||||
|
||||
fun DownloadEntity.isSilentUpdate(): Boolean {
|
||||
return Constants.SILENT_UPDATE == getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)
|
||||
}
|
||||
|
||||
fun DownloadEntity.isSimulatorDownload(): Boolean {
|
||||
return Constants.SIMULATOR_DOWNLOAD == getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)
|
||||
}
|
||||
|
||||
fun DownloadEntity.isSimulatorGame(): Boolean {
|
||||
return getMetaExtra(Constants.SIMULATOR_GAME).isNotEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* Process related
|
||||
*/
|
||||
@ -744,4 +876,46 @@ fun List<String>?.checkSameFromStringArray(check2: List<String>?): Boolean {
|
||||
if (!this.contains(tag)) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* EditText弹出软键盘
|
||||
*/
|
||||
fun EditText.showKeyBoard() {
|
||||
this.postDelayed({
|
||||
this.requestFocus()
|
||||
val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
inputMethodManager.showSoftInput(this, 0)
|
||||
}, 300)
|
||||
}
|
||||
|
||||
|
||||
fun SeekBar.doOnSeekBarChangeListener(progressChange: ((progress: Int) -> Unit)? = null, onStopTrackingTouch: (() -> Unit)? = null) {
|
||||
this.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||
progressChange?.invoke(progress)
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||
onStopTrackingTouch?.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun <T> observableToMain(): ObservableTransformer<T, T> {
|
||||
return ObservableTransformer { upstream ->
|
||||
upstream.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> singleToMain(): SingleTransformer<T, T> {
|
||||
return SingleTransformer { upstream ->
|
||||
upstream.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
}
|
||||
23
app/src/main/java/com/gh/common/util/FastClickUtils.kt
Normal file
23
app/src/main/java/com/gh/common/util/FastClickUtils.kt
Normal file
@ -0,0 +1,23 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.gh.common.OnFastClickListener
|
||||
import io.reactivex.disposables.Disposable
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
object FastClickUtils {
|
||||
|
||||
private var disposable: Disposable? = null
|
||||
private var ref: WeakReference<OnFastClickListener>? = null
|
||||
|
||||
fun click(duration: Int = 500, onClick: OnFastClickListener) {
|
||||
ref = WeakReference(onClick)
|
||||
disposable?.dispose()
|
||||
ref?.get()?.invoke(false)
|
||||
disposable = rxTimer(1) {
|
||||
if (it >= duration) {
|
||||
ref?.get()?.invoke(true)
|
||||
disposable?.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,9 +5,8 @@ import android.graphics.Color;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.simulator.SimulatorGameManager;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
@ -24,6 +23,8 @@ import com.lightgame.download.DownloadStatus;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class GameUtils {
|
||||
|
||||
/**
|
||||
@ -116,16 +117,27 @@ public class GameUtils {
|
||||
installCount++;
|
||||
}
|
||||
}
|
||||
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
|
||||
DownloadEntity simulatorDownloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apkEntity.getUrl());
|
||||
if (simulatorDownloadEntity != null && gameEntity.getSimulator() != null) {
|
||||
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(context, gameEntity.getSimulator().getApk().getPackageName());
|
||||
if (isInstalled) {
|
||||
installCount++;
|
||||
} else {
|
||||
doneCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (doneCount != 0) {
|
||||
return context.getString(R.string.install);
|
||||
} else if (pluginCount != 0) {
|
||||
return context.getString(R.string.pluggable);
|
||||
} else if (updateCount != 0) {
|
||||
return context.getString(R.string.update);
|
||||
} else if (installCount != 0) {
|
||||
if (installCount != 0) {
|
||||
return context.getString(R.string.launch);
|
||||
} else if (gameEntity.getVersionNumber().contains("无版号") && Config.isGameDomeSwitchOpen()) {
|
||||
} else if (pluginCount != 0 && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
|
||||
return context.getString(R.string.pluggable);
|
||||
} else if (updateCount != 0 && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
|
||||
return context.getString(R.string.update);
|
||||
} else if (doneCount != 0) {
|
||||
return context.getString(R.string.install);
|
||||
} else if (gameEntity.getVersionNumber().contains("无版号") && Config.isGameDomeSwitchOpen() && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
|
||||
return context.getString(R.string.attempt);
|
||||
} else {
|
||||
return context.getString(R.string.download);
|
||||
@ -238,7 +250,7 @@ public class GameUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
collectionEntity.setSaveApkEntity(saveApkEntity);
|
||||
return collectionEntity;
|
||||
}
|
||||
|
||||
@ -10,6 +10,8 @@ import org.json.JSONArray
|
||||
* Created by khy on 11/10/17.
|
||||
*/
|
||||
object GsonUtils {
|
||||
|
||||
@JvmStatic
|
||||
val gson: Gson = Gson()
|
||||
val gsonThatIgnoreNull: Gson = GsonBuilder().serializeNulls().create()
|
||||
|
||||
@ -20,14 +22,22 @@ object GsonUtils {
|
||||
|
||||
@JvmStatic
|
||||
fun <T> fromJsonList(json: JSONArray): List<T> {
|
||||
val type = object : TypeToken<List<T>>() {}.type
|
||||
return gson.fromJson(json.toString(), type)
|
||||
return try {
|
||||
val type = object : TypeToken<List<T>>() {}.type
|
||||
return gson.fromJson(json.toString(), type)
|
||||
} catch (e: Exception) {
|
||||
listOf()
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun <T> fromJsonList(json: String): List<T> {
|
||||
val type = object : TypeToken<List<T>>() {}.type
|
||||
return gson.fromJson(json, type)
|
||||
return try {
|
||||
val type = object : TypeToken<List<T>>() {}.type
|
||||
gson.fromJson(json, type)
|
||||
} catch (e: Exception) {
|
||||
listOf()
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@ -15,7 +15,7 @@ object HomePluggableHelper {
|
||||
if (apkList.isNotEmpty()) {
|
||||
val apk = apkList.first()
|
||||
val tag = if (isNever) "never" else apk.version ?: ""
|
||||
mHomePluggableFilterDao.addData(HomePluggableFilterEntity(pkgName = apk.packageName, tag = tag, active = isNever))
|
||||
tryCatchInRelease { mHomePluggableFilterDao.addData(HomePluggableFilterEntity(pkgName = apk.packageName, tag = tag, active = isNever)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ object HomePluggableHelper {
|
||||
for (entity in filterList) {
|
||||
entity.active = true
|
||||
}
|
||||
mHomePluggableFilterDao.addData(filterList)
|
||||
tryCatchInRelease { mHomePluggableFilterDao.addData(filterList) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -67,4 +67,15 @@ public class HtmlUtils {
|
||||
|
||||
return htmlStr.trim(); //返回文本字符串
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤掉标签,保留标签内容
|
||||
*/
|
||||
public static String filterHtmlLabel(String htmlStr) {
|
||||
String regEx_html = "<[^>]+>([\\s\\S]*?)<\\/[^>]+>"; //定义HTML标签的正则表达式
|
||||
Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
|
||||
Matcher m_html = p_html.matcher(htmlStr);
|
||||
htmlStr = m_html.replaceAll("$1"); //过滤html标签
|
||||
return htmlStr.trim(); //返回文本字符串
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,15 +10,22 @@ import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.facebook.common.executors.CallerThreadExecutor
|
||||
import com.facebook.common.references.CloseableReference
|
||||
import com.facebook.datasource.DataSource
|
||||
import com.facebook.drawee.backends.pipeline.Fresco
|
||||
import com.facebook.drawee.controller.BaseControllerListener
|
||||
import com.facebook.drawee.controller.ControllerListener
|
||||
import com.facebook.drawee.drawable.ScalingUtils
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
||||
import com.facebook.imagepipeline.image.CloseableImage
|
||||
import com.facebook.imagepipeline.image.ImageInfo
|
||||
import com.facebook.imagepipeline.request.ImageRequest
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.structure.FixedSizeLinkedHashSet
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.squareup.picasso.Picasso
|
||||
@ -27,11 +34,16 @@ import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
|
||||
object ImageUtils {
|
||||
|
||||
private const val PIC_MAX_FILE_SIZE: Long = 10 * 1024 * 1024
|
||||
|
||||
private val TINY_GIF_SIZE = 30F.dip2px()
|
||||
private val LARGE_GIF_SIZE = 80F.dip2px()
|
||||
private val STANDARD_GIF_SIZE = 60F.dip2px()
|
||||
|
||||
private val mImageUrlCacheSet by lazy { FixedSizeLinkedHashSet<String>(maxSize = 200) }
|
||||
|
||||
@JvmStatic
|
||||
fun getUploadFileMaxSize(): Long {
|
||||
val uploadLimitSize = Config.getSettings()?.image?.uploadLimitSize
|
||||
@ -217,11 +229,44 @@ object ImageUtils {
|
||||
.build()
|
||||
}
|
||||
|
||||
// 获取bitmap (使用 fresco 获取 gif bitmap 会为空,https://github.com/facebook/fresco/issues/241)
|
||||
// 所以这里换用 picasso
|
||||
/**
|
||||
* 获取bitmap (使用 fresco 获取 gif 的 bitmap 会为空,https://github.com/facebook/fresco/issues/241)
|
||||
* 所以当 url 以 .gif 结尾时换用 picasso 获取
|
||||
* 优先使用 fresco 是因为可能已经有了缓存
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun getBitmap(url: String, callback: BiCallback<Bitmap, Boolean>) {
|
||||
if (url.endsWith(".gif")) {
|
||||
getBitmapWithPicasso(url, callback)
|
||||
} else {
|
||||
getBitmapWithFresco(url, callback)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBitmapWithFresco(url: String, callback: BiCallback<Bitmap, Boolean>) {
|
||||
val imageRequest = ImageRequestBuilder
|
||||
.newBuilderWithSource(Uri.parse(url))
|
||||
.build()
|
||||
Fresco.getImagePipeline()
|
||||
.fetchDecodedImage(imageRequest, HaloApp.getInstance().application)
|
||||
.subscribe(object : BaseBitmapDataSubscriber() {
|
||||
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
|
||||
callback.onSecond(true)
|
||||
}
|
||||
|
||||
override fun onNewResultImpl(bitmap: Bitmap?) {
|
||||
if (bitmap != null) {
|
||||
callback.onFirst(bitmap)
|
||||
} else {
|
||||
callback.onSecond(true)
|
||||
}
|
||||
}
|
||||
}, CallerThreadExecutor.getInstance())
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun getBitmapWithPicasso(url: String, callback: BiCallback<Bitmap, Boolean>) {
|
||||
Single.just(url)
|
||||
.map { Picasso.with(HaloApp.getInstance().application).load(url).priority(Picasso.Priority.HIGH).get() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -234,35 +279,74 @@ object ImageUtils {
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun display(view: SimpleDraweeView?, url: String?) {
|
||||
display(view, url, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则 width>0 Wifi/4G:x2 traffic:x1
|
||||
* 第一种方案:通过LayoutParams获取 可以快速(无延迟)获取宽高,但是无法获取wrap_content和match_parent的View
|
||||
* 第二种方案(备用方案):有延迟,View的宽高需要在Measure过程后才能确定,能够在这里获取到正确的宽高
|
||||
* @param isAutoPlayGif 是否禁止播放动图
|
||||
*/
|
||||
@JvmStatic
|
||||
fun display(view: SimpleDraweeView?, url: String?) {
|
||||
url?.let {
|
||||
// 图片是以 gif 结尾的就
|
||||
if (it.endsWith(".gif") && view?.getTag(R.id.tag_show_gif) != false) {
|
||||
if (view?.tag == url) return@let
|
||||
fun display(view: SimpleDraweeView?, url: String?, isAutoPlayGif: Boolean = true) {
|
||||
if (url == null) return
|
||||
|
||||
val controller = Fresco.newDraweeControllerBuilder()
|
||||
.setUri(url)
|
||||
.setAutoPlayAnimations(true)
|
||||
.build()
|
||||
view?.controller = controller
|
||||
} else {
|
||||
val width = view?.layoutParams?.width
|
||||
if (width != null && width > 0) {
|
||||
view.setImageURI(getTransformLimitUrl(url, width, view.context))
|
||||
} else {
|
||||
view?.post {
|
||||
view.setImageURI(getTransformLimitUrl(url, view.width, view.context))
|
||||
}
|
||||
}
|
||||
val width = view?.layoutParams?.width
|
||||
val height = view?.layoutParams?.height
|
||||
|
||||
var lowResUrl = ""
|
||||
var highResUrl = ""
|
||||
|
||||
// 找同一图片地址已加载过的图片作为低质量预览图
|
||||
// TODO 根据实际请求大小(w_width)来避免小图用大图作为低质量图片
|
||||
for (cachedImageUrl in mImageUrlCacheSet) {
|
||||
if (url.isNotEmpty() && cachedImageUrl.contains(url)) {
|
||||
lowResUrl = cachedImageUrl
|
||||
break
|
||||
}
|
||||
view?.tag = url
|
||||
}
|
||||
|
||||
val loadImageClosure: (autoPlay: Boolean, highResUrl: String, lowResUrl: String) -> Unit = { autoPlay, hUrl, lUrl ->
|
||||
view?.controller = Fresco.newDraweeControllerBuilder()
|
||||
.setImageRequest(ImageRequest.fromUri(hUrl))
|
||||
.apply {
|
||||
if (lUrl.isNotEmpty()
|
||||
&& lUrl != hUrl
|
||||
&& hUrl != view?.getTag(R.string.highResImageTag)) {
|
||||
lowResImageRequest = ImageRequest.fromUri(lUrl)
|
||||
}
|
||||
autoPlayAnimations = autoPlay
|
||||
}
|
||||
.build()
|
||||
|
||||
view?.setTag(R.string.highResImageTag, highResUrl)
|
||||
}
|
||||
|
||||
val shouldLoadAsGif = url.endsWith(".gif") && isAutoPlayGif && view?.getTag(R.id.tag_show_gif) != false
|
||||
|
||||
if (shouldLoadAsGif && view?.tag == url) return
|
||||
|
||||
if (width != null && width > 0) {
|
||||
highResUrl = if (shouldLoadAsGif) {
|
||||
resizeGif(url, width, height ?: 0)
|
||||
} else {
|
||||
getTransformLimitUrl(url, width, view.context) ?: ""
|
||||
}
|
||||
loadImageClosure(shouldLoadAsGif, highResUrl, lowResUrl)
|
||||
} else {
|
||||
view?.post {
|
||||
highResUrl = if (shouldLoadAsGif) {
|
||||
resizeGif(url, view.width, height ?: 0)
|
||||
} else {
|
||||
getTransformLimitUrl(url, view.width, view.context) ?: ""
|
||||
}
|
||||
loadImageClosure(shouldLoadAsGif, highResUrl, lowResUrl)
|
||||
}
|
||||
}
|
||||
view?.tag = url
|
||||
}
|
||||
|
||||
// Wifi/4G:x2 traffic:x1
|
||||
@ -270,12 +354,13 @@ object ImageUtils {
|
||||
fun getTransformLimitUrl(url: String?, width: Int?, context: Context?): String? {
|
||||
var transformUrl: String? = url
|
||||
if (width != null && width > 0) {
|
||||
// 加载大小是实际 ImageView 大小两倍的图片真的有意义吗?
|
||||
val transformUrlX2 = addLimitWidth(url, width * 2)
|
||||
val transformUrlX1 = addLimitWidth(url, width)
|
||||
// 当网络为 WIFI 或 4G, 且系统版本大于 5.0 && 手机内存大于 1G 才用高清图片
|
||||
if (NetworkUtils.isWifiOr4GConnected(context)
|
||||
&& Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP
|
||||
&& DeviceUtils.getTotalRamSizeOfDevice(context) > 1000) {
|
||||
&& HaloApp.getInstance().deviceRamSize > 1024) {
|
||||
transformUrl = transformUrlX2
|
||||
} else {
|
||||
// 检查X2大图是否被缓存
|
||||
@ -287,7 +372,7 @@ object ImageUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Utils.log("displayPost::viewWidth->$width----transformUrl->$transformUrl")
|
||||
addCachedUrl(transformUrl ?: "")
|
||||
return transformUrl
|
||||
}
|
||||
|
||||
@ -297,15 +382,19 @@ object ImageUtils {
|
||||
val width = view?.layoutParams?.width
|
||||
if (width != null && width > 0) {
|
||||
view.setImageURI(addLimitWidth(url, width * 2))
|
||||
// Utils.log("displayIcon::viewWidth->" + view.width + "---transformUrl->" + transformUrl)
|
||||
} else {
|
||||
view?.post {
|
||||
view.setImageURI(addLimitWidth(url, view.width * 2))
|
||||
// Utils.log("displayIcon::viewWidth->" + view.width + "---transformUrl->" + transformUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addCachedUrl(url: String) {
|
||||
if (url.startsWith("http")) {
|
||||
mImageUrlCacheSet.add(url)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun bmpToByteArray(bmp: Bitmap, needRecycle: Boolean): ByteArray {
|
||||
val output = ByteArrayOutputStream()
|
||||
@ -338,6 +427,23 @@ object ImageUtils {
|
||||
imagePipeline.prefetchToDiskCache(imageRequest, HaloApp.getInstance().application)
|
||||
}
|
||||
|
||||
private fun resizeGif(url: String, width: Int, height: Int): String {
|
||||
val idealSize = getIdealGifSize(width, height)
|
||||
return "$url?x-oss-process=image/resize,h_$idealSize,w_$idealSize".also { addCachedUrl(it) }
|
||||
}
|
||||
|
||||
private fun getIdealGifSize(width: Int, height: Int): String {
|
||||
return if (width > LARGE_GIF_SIZE || height > LARGE_GIF_SIZE) {
|
||||
"256"
|
||||
} else if (width >= STANDARD_GIF_SIZE || height >= STANDARD_GIF_SIZE) {
|
||||
"192"
|
||||
} else if (width > TINY_GIF_SIZE || height > TINY_GIF_SIZE) {
|
||||
"128"
|
||||
} else {
|
||||
"64"
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnImageloadListener {
|
||||
fun onLoadFinal(imageInfo: ImageInfo?)
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ public class InstallUtils {
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.what == INSTALL_WHAT && packageManager != null) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<PackageInfo> packageInfos = packageManager.getInstalledPackages(0);
|
||||
List<PackageInfo> packageInfos = PackageUtils.getInstalledPackages(context, 0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
list.add(packageInfo.packageName);
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@ -19,11 +18,11 @@ public class Installation {
|
||||
private static String sID = null;
|
||||
|
||||
public synchronized static String getUUID(Context context) {
|
||||
String imei = Util_System_Phone_State.getDeviceId(context);
|
||||
String imei = MetaUtil.getIMEI();
|
||||
if (!TextUtils.isEmpty(imei)) {
|
||||
return imei;
|
||||
}
|
||||
String android_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
String android_id = MetaUtil.getAndroidId();
|
||||
if (!TextUtils.isEmpty(android_id)) {
|
||||
return android_id;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user