Compare commits
601 Commits
v3.6.6
...
v3.7.1_gam
| Author | SHA1 | Date | |
|---|---|---|---|
| 045dea265d | |||
| 998cf70723 | |||
| eb112b358e | |||
| b860ab912a | |||
| 1facde123e | |||
| 8f9d6ed2ce | |||
| e43902be79 | |||
| 0f5f8861a7 | |||
| cb08886d27 | |||
| 322ec56787 | |||
| 60b12a3bdf | |||
| 26a66e3a2b | |||
| e86e78a665 | |||
| 3ba68abbee | |||
| a46ba32f06 | |||
| 82348b519a | |||
| 8315a50d49 | |||
| dca07831db | |||
| d568dd0791 | |||
| 9dbfc68488 | |||
| 0b46e0ef8e | |||
| 472604bc15 | |||
| 58a2d38518 | |||
| c91186be8a | |||
| 03235438bc | |||
| d015285f1a | |||
| 45323a6817 | |||
| bcc8d35654 | |||
| 9137b65f4a | |||
| fbc9dac99e | |||
| c27a6e06ad | |||
| 07970fcbae | |||
| 0b3e250386 | |||
| 13b1ba613d | |||
| 5a1feb4500 | |||
| cc7accbc95 | |||
| 42a83ea0c5 | |||
| 39f84442cd | |||
| 047c25b0b7 | |||
| 045f21beac | |||
| 8a64460097 | |||
| 195d039904 | |||
| bcf77433b9 | |||
| 3a122a7137 | |||
| 354d286a98 | |||
| bfccc1c9b8 | |||
| 80767c17b2 | |||
| 0a9185462e | |||
| c058d3f8c1 | |||
| 70655da2e7 | |||
| 51f8c15af6 | |||
| 20d6984057 | |||
| f26813c137 | |||
| e2a265c3c7 | |||
| e840daa340 | |||
| c54df5336d | |||
| 4ec97409a8 | |||
| 31b5568dfa | |||
| 10cfc6521d | |||
| bfdbc7fc92 | |||
| ead332d863 | |||
| b8fd666e84 | |||
| fb6e3637de | |||
| 2db519f9e0 | |||
| f55aeaf3d4 | |||
| 2340d4957b | |||
| 7bed914a92 | |||
| 4b9f86a4bb | |||
| a1844e15e1 | |||
| 148589a6c5 | |||
| 2902a8b441 | |||
| b410016fae | |||
| 0d56448bfd | |||
| 326c292572 | |||
| afdaef1a64 | |||
| 9bcd4b8e95 | |||
| 4d455f13b6 | |||
| 94eea3aa90 | |||
| b00f47dd99 | |||
| 20a4427e08 | |||
| 3287f31e2c | |||
| fbb6b01585 | |||
| f07d1b7257 | |||
| 45d2d958a2 | |||
| 2ba2498f6b | |||
| d76dada9f8 | |||
| 28b63ee21b | |||
| 90ea78eb39 | |||
| 0cda0e93f0 | |||
| 2e0469f915 | |||
| fdfbd23963 | |||
| 5f8b11f8e0 | |||
| a1df2f6ca6 | |||
| 1d0d0e40de | |||
| b3e5144cea | |||
| aed74449b0 | |||
| 45dc231024 | |||
| c1a223f120 | |||
| 4a926997aa | |||
| ae764b95fb | |||
| 7bba3f8b4d | |||
| b2ad804d3c | |||
| c49fa5cd3d | |||
| 92b5e28675 | |||
| 4afa5f6bc6 | |||
| fbdc31aa97 | |||
| 4eedfadc22 | |||
| 3432a6c39f | |||
| 7e7c2180ce | |||
| 0386446a00 | |||
| 09853e4187 | |||
| 40020fa617 | |||
| cc68c15824 | |||
| 7aa874a0e3 | |||
| 8203e5b568 | |||
| 4f54bca286 | |||
| 087479325d | |||
| 357b2c2a60 | |||
| e1918b56e2 | |||
| 1f31d1e614 | |||
| f5468c5f11 | |||
| 672cf331ea | |||
| 348ad0faed | |||
| ae742547d8 | |||
| ff1c01c836 | |||
| a645a3c929 | |||
| 37c590400e | |||
| 785e2d8cf5 | |||
| 03d25cb102 | |||
| 869dd9ac11 | |||
| f647e172bd | |||
| 7069200c6e | |||
| c61cfcbed9 | |||
| 67eddc99ef | |||
| 03fd5aaf09 | |||
| 31a8f5e5c7 | |||
| b7c6460c0e | |||
| 538c096b8f | |||
| d05c738696 | |||
| 976035da22 | |||
| d47fd51c7c | |||
| a047c65efd | |||
| 5bbb6b1c89 | |||
| 95432cb591 | |||
| 04862e7f22 | |||
| abafd0bb24 | |||
| aa83617796 | |||
| a5b8806997 | |||
| 7a70c0158e | |||
| 74f5972874 | |||
| b01a29d2e9 | |||
| 88bd0dc9f5 | |||
| c7b6d44874 | |||
| 8b6e01929b | |||
| 2ecba00d2a | |||
| 851fcaab13 | |||
| e1b9504421 | |||
| 247e8ed6cc | |||
| 996d1be136 | |||
| a249d4d572 | |||
| c91d52d753 | |||
| 0c37db444a | |||
| eb93f1d915 | |||
| 74e6c9b145 | |||
| f15e630fd1 | |||
| 01ee84caa8 | |||
| 311a1916d1 | |||
| ae43ae1b97 | |||
| d9814bbb1f | |||
| dba8abacf2 | |||
| 3ee1474535 | |||
| 8481e923ee | |||
| 53cfb0f078 | |||
| 233277f6e8 | |||
| dbd75cb513 | |||
| bae14a54a1 | |||
| 9c48afca77 | |||
| 54ebc460fa | |||
| 901e9a39f9 | |||
| 2ebd12c6db | |||
| c762529b8b | |||
| 3c371038cf | |||
| 0350c19c81 | |||
| ebace67201 | |||
| cbe6e2e3bd | |||
| 4adefc885b | |||
| cade2882e4 | |||
| 8c0f2fd527 | |||
| 56809d8d66 | |||
| 14772494be | |||
| 4bbec7344f | |||
| 9907863ef5 | |||
| adfbe36fdf | |||
| 3cfb9ac1c3 | |||
| 2004b85a12 | |||
| 7dd3b5f122 | |||
| c849746a6f | |||
| a9582bc295 | |||
| fd49defe00 | |||
| 650a24775a | |||
| b62a864a7d | |||
| b76e10bdfc | |||
| 4311205e62 | |||
| 69bc1c971d | |||
| f13c720bcc | |||
| 63f66e9714 | |||
| 25d8ed079c | |||
| b923714b42 | |||
| 178295596a | |||
| 2e1dae86e0 | |||
| 4bb0206d2d | |||
| 23cda9c121 | |||
| a1d0b59e28 | |||
| 9de8e61b1b | |||
| be1188e8e4 | |||
| fdaefa52ab | |||
| d667e70b90 | |||
| 6184acc144 | |||
| 6f012dc459 | |||
| 94774c674a | |||
| 3bda3354f0 | |||
| 8a56459375 | |||
| aeb689648f | |||
| 761d4c3354 | |||
| 90899e7d1f | |||
| 9e9d8b7149 | |||
| f774df532c | |||
| d85c4533b7 | |||
| 79aeca832a | |||
| 50931b1fb6 | |||
| 63bd0cdebb | |||
| 8880d381db | |||
| 4eccd3b2ac | |||
| 716ba77d3e | |||
| 4053eec64c | |||
| b11463b0f7 | |||
| 109ada8e8b | |||
| ab32670b40 | |||
| 92f82099b5 | |||
| e41b7434c9 | |||
| 9c79df6d6e | |||
| fe1f491104 | |||
| 652bdf9f1d | |||
| 36b13d6d28 | |||
| 53b58b63a2 | |||
| 6b0f298a2d | |||
| 08bc8bc49e | |||
| c8b436de94 | |||
| 82b6323f72 | |||
| 6664bc9e62 | |||
| 544dc67d0d | |||
| d55c4d12bc | |||
| 707bc9bb1a | |||
| 41806eab54 | |||
| 443c3bf26a | |||
| 7ac6e82624 | |||
| 87106de6d6 | |||
| c52d94b003 | |||
| 5ac13f2107 | |||
| baa22ae9c9 | |||
| dba3854e40 | |||
| 1f06810592 | |||
| 2861e8cfee | |||
| 9269548d64 | |||
| 712399e9da | |||
| 1654d36126 | |||
| 245e113d76 | |||
| 8b35993e99 | |||
| 3dcaf7b50e | |||
| 58d4b5e612 | |||
| caf0852f28 | |||
| 558fe249ac | |||
| 20b0c83fc0 | |||
| 0c3020f7b3 | |||
| fce10714ae | |||
| 8055856dd7 | |||
| a8c540f122 | |||
| ccf117656a | |||
| 6b5cf36957 | |||
| 201f0317a2 | |||
| ea9bb99afa | |||
| 51609dea83 | |||
| d9788434f3 | |||
| b0d433b5c8 | |||
| df3dd297c1 | |||
| 1a9ee5e3cb | |||
| a22da040e0 | |||
| 4c0ee93826 | |||
| 759a22fc52 | |||
| 066b667bd8 | |||
| 91e5e4f53b | |||
| 7cfd1a9c7d | |||
| ed78421d9b | |||
| 0e85be5dc6 | |||
| 23721ad189 | |||
| 50c7f6514e | |||
| 7818370d7e | |||
| 2f05256103 | |||
| ed1dc14bc5 | |||
| ae2b0e9d7e | |||
| b9d23115c6 | |||
| c72da10e56 | |||
| a4f4b0c3f9 | |||
| 5c0a51be73 | |||
| 069b6d7df6 | |||
| fea7aee20b | |||
| 26dd26d7c0 | |||
| 4e06147b82 | |||
| 1065abcd44 | |||
| cf5e40788b | |||
| 93ff2651c4 | |||
| de9689c1a2 | |||
| 24379be99d | |||
| 75bec6e967 | |||
| c3eb5f8d08 | |||
| 13c1866fa2 | |||
| 4ab8a5b7bb | |||
| 821434bd7c | |||
| ab3d29d449 | |||
| 1ee5a1d110 | |||
| 19910ab0a8 | |||
| 727f513431 | |||
| 5eac22f0be | |||
| 360efccf4c | |||
| 57ac0a0bb9 | |||
| 80c2e34460 | |||
| 78e652ea27 | |||
| fc7d36ac22 | |||
| 1a4e4fedb6 | |||
| 5ff7c58503 | |||
| 25488e9100 | |||
| d4bf86f717 | |||
| 1cd463968e | |||
| 6388941e81 | |||
| 48dd87ce26 | |||
| 76643aae59 | |||
| 86c9c077bf | |||
| 6510e620ba | |||
| 7d2149ad23 | |||
| 87b3c35ba2 | |||
| f7fdadd4f4 | |||
| d6ef599b08 | |||
| 4b7a5ad049 | |||
| 6f3ad4bec4 | |||
| 87047fe38d | |||
| 5627cd9ca2 | |||
| 0bfab3ba9c | |||
| 10b692bb2b | |||
| 663c415a57 | |||
| 5f60126333 | |||
| 986b99479d | |||
| cbbf4b71c2 | |||
| 4398bea8d4 | |||
| e85ac755ae | |||
| fa2f91cb24 | |||
| ff30c8d288 | |||
| fd5807d404 | |||
| 719133a636 | |||
| 5650f65214 | |||
| 7bc4c8e661 | |||
| 48c7d94edc | |||
| 2d63db64b2 | |||
| 3a26750e15 | |||
| 517bd63ac0 | |||
| ef77fca3bb | |||
| dde7ed096a | |||
| 834db84d43 | |||
| 93e81879fd | |||
| 9263805bb4 | |||
| 5467df5850 | |||
| 02836a2dee | |||
| 9747ff1056 | |||
| ce38932e86 | |||
| fc76d98fbc | |||
| 4a4f1b86df | |||
| 6f75f212b8 | |||
| 1051d46a79 | |||
| 41bb08d899 | |||
| afef9847b1 | |||
| 2fe83bcf14 | |||
| 8529980040 | |||
| fbf11eff3d | |||
| 1d0e8505f6 | |||
| 332f63e823 | |||
| f5062d554e | |||
| 5d6f3f249b | |||
| f6e524ca14 | |||
| f5768ee8ae | |||
| 53df43b5a8 | |||
| 817004f96d | |||
| e54262a320 | |||
| 26ab8355fd | |||
| 633b5532e2 | |||
| 68809149c5 | |||
| 5d8d65f5b5 | |||
| d29122af52 | |||
| 53898a0465 | |||
| 9038a41301 | |||
| 52349dc043 | |||
| 26eca76036 | |||
| 7deb934b5a | |||
| b8e02f1ab9 | |||
| 07b2cf3d95 | |||
| 0f06b1e401 | |||
| 432553d90b | |||
| 8a51187f01 | |||
| c63a1a1fd2 | |||
| ab03b4d88e | |||
| bcce233795 | |||
| fe77112ca6 | |||
| e3a4dbbbb3 | |||
| 4a19e7beed | |||
| 6b6ed81c4a | |||
| d69717d08d | |||
| e8e43a28d2 | |||
| 03a89a1553 | |||
| 71eb06ba2c | |||
| 4e7a73a450 | |||
| a893303517 | |||
| 4ccb5fe7f2 | |||
| 21f3ff57bc | |||
| d07d743de9 | |||
| 6c41b1cb9f | |||
| 1d5206fa8d | |||
| d2d7a84446 | |||
| 91218c90fb | |||
| 1db3872cbb | |||
| 766aca3708 | |||
| 04a05a4017 | |||
| a46cee919f | |||
| f2877e36a6 | |||
| c8056c5ba9 | |||
| 1eb95269e8 | |||
| 23906131ec | |||
| 23ca0bfb6f | |||
| 8c055620d0 | |||
| ead2d66295 | |||
| 39b9cce4d8 | |||
| 3567909675 | |||
| d79cc1499f | |||
| 9674515171 | |||
| 2ee39c249c | |||
| 2ae6829a65 | |||
| 9c9fb54932 | |||
| 713cb287bb | |||
| b47805cbbf | |||
| 6aa5c7cd74 | |||
| 97da1506dd | |||
| ed193f99a4 | |||
| 96f86ff0eb | |||
| f2bcb18688 | |||
| b5f7d78a26 | |||
| 08cdab0f50 | |||
| 2a2f5b089d | |||
| a21ceabfdf | |||
| fe4dc13b84 | |||
| 70730e8628 | |||
| adceb92796 | |||
| 55336f6be4 | |||
| 25663d114a | |||
| d80592fbb7 | |||
| 7fab331b90 | |||
| 6c5c43d595 | |||
| 1b49aaa6fc | |||
| ed1725f9cc | |||
| 8d5cc4e983 | |||
| 8a03017ccd | |||
| 884d5d81f9 | |||
| 95be563b43 | |||
| 6ae6a4e14a | |||
| 9b069a97d1 | |||
| 25f217217d | |||
| 322f4fd268 | |||
| da55afb712 | |||
| 5788052262 | |||
| 4a56da6f2e | |||
| 770543fea5 | |||
| ed83feb112 | |||
| 223f264972 | |||
| 6c6f9f63f6 | |||
| 58f761862f | |||
| 3a45de8eb3 | |||
| 9a0ffb29e0 | |||
| 1d62818348 | |||
| 5be789d100 | |||
| 7dd79bd4bb | |||
| d0b6ee897c | |||
| 2f03656869 | |||
| 5ac51c84b7 | |||
| ce71384dd9 | |||
| 2a7db59e6b | |||
| e561c13f28 | |||
| 12981bd7ff | |||
| 208250d030 | |||
| d4598ac96f | |||
| 293451e527 | |||
| fe19c84049 | |||
| 7e0d5c3416 | |||
| 319fe2f556 | |||
| 6f6bffdeb7 | |||
| 7c6271d4e9 | |||
| 5d3f082771 | |||
| abf6935653 | |||
| 6eecad6bb6 | |||
| 12cea1f263 | |||
| 3150a182e6 | |||
| 56160193a9 | |||
| 859470aabf | |||
| ad2dc5ac4b | |||
| d32816aa65 | |||
| 64e99338b0 | |||
| 88bcb2883c | |||
| a70520f04f | |||
| 09521ec26a | |||
| f5b8049dd7 | |||
| fe230d647a | |||
| 33daa22e49 | |||
| 80965dcbc9 | |||
| 89f0cfb6a7 | |||
| 89884d4cd7 | |||
| e9590f81be | |||
| 83159e4153 | |||
| 21dc20dff1 | |||
| 3ec6526aa4 | |||
| ba918b9144 | |||
| 3a63d049dc | |||
| 13011804ab | |||
| 1e2e621055 | |||
| f53c3ff8ae | |||
| b30e60dfde | |||
| 34ac30cdfe | |||
| 8bd30d1a0f | |||
| cbc575fcd0 | |||
| 9720812714 | |||
| b9a8f3217f | |||
| cb812d2d6c | |||
| 572b35c4dc | |||
| 043486a53f | |||
| df68f8fb9c | |||
| ee146b20e5 | |||
| 936ca7d4ba | |||
| 57e37419cf | |||
| 86934a789e | |||
| 9552d3ac25 | |||
| 9782e2a615 | |||
| 7b8f5dfc5b | |||
| f3fd311d70 | |||
| 5e7e71f6cc | |||
| 6cc4178cb3 | |||
| 49be7e9d12 | |||
| 8f50626a3d | |||
| 89cfd1a8ba | |||
| 2e9ec0bde0 | |||
| b77491e91e | |||
| 65b84b0e4a | |||
| e9cb8fcde8 | |||
| aa04f67f43 | |||
| 3710a2b729 | |||
| 96cadd05f1 | |||
| 114f014091 | |||
| 960c596db8 | |||
| fe6ebd8aa7 | |||
| f121b04e66 | |||
| 4724b809dd | |||
| 5353581cf1 | |||
| 68f60db4c0 | |||
| e90e514f8b | |||
| 6ab04cf056 | |||
| 219270b10d | |||
| b070998a73 | |||
| 14e3edf5dd | |||
| bb604b3922 | |||
| f43f8e9fb1 | |||
| 9c4c5badcd | |||
| e511d48667 | |||
| 8f6ddfef06 | |||
| 2b9e0b167e | |||
| cb874dc77a | |||
| b561cbc8f7 | |||
| f252e004b2 | |||
| 177c027bf7 | |||
| cc386bfe48 | |||
| 1254dd7209 | |||
| 3054ad8471 | |||
| a3cfa69174 | |||
| 82b32da523 | |||
| 91a1ffe113 | |||
| d3b6b81e64 | |||
| a2b61a8447 | |||
| cd6c9ca460 | |||
| 49a189d19f | |||
| d972b94ce8 | |||
| 0a552fd378 | |||
| 3538a629cb | |||
| ef1652c4f4 | |||
| 9d5250294c | |||
| 8e2aab5dbe | |||
| 75d6267f68 | |||
| 63bbee19a4 | |||
| 67f78c2f95 | |||
| f558954d22 |
@ -90,6 +90,8 @@ android {
|
||||
|
||||
buildConfigField "String", "EXPOSURE_REPO", "\"test\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E3\""
|
||||
|
||||
multiDexKeepProguard file("tinker_multidexkeep.pro")
|
||||
}
|
||||
release {
|
||||
debuggable false
|
||||
@ -100,6 +102,8 @@ android {
|
||||
|
||||
buildConfigField "String", "EXPOSURE_REPO", "\"exposure\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E3\""
|
||||
|
||||
multiDexKeepProguard file("tinker_multidexkeep.pro")
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,6 +197,7 @@ dependencies {
|
||||
kapt "androidx.lifecycle:lifecycle-compiler:${lifeCycle}"
|
||||
implementation "androidx.room:room-runtime:${room}"
|
||||
implementation "androidx.room:room-rxjava2:${room}"
|
||||
implementation "androidx.core:core-ktx:${ktx}"
|
||||
kapt "androidx.room:room-compiler:${room}"
|
||||
kapt "androidx.databinding:databinding-compiler:${databinding}"
|
||||
|
||||
@ -235,10 +240,10 @@ dependencies {
|
||||
// bugly with tinker support
|
||||
implementation "com.tencent.bugly:crashreport_upgrade:${buglyTinkerSupport}"
|
||||
|
||||
implementation "pub.devrel:easypermissions:${easypermissions}"
|
||||
|
||||
implementation 'com.google.android:flexbox:1.1.0'
|
||||
|
||||
implementation "pub.devrel:easypermissions:${easypermissions}"
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
implementation 'com.contrarywind:Android-PickerView:4.1.3'
|
||||
@ -251,9 +256,14 @@ dependencies {
|
||||
|
||||
implementation "top.zibin:Luban:${luban}"
|
||||
|
||||
implementation "com.squareup.picasso:picasso:${picasso}"
|
||||
|
||||
// for video streaming
|
||||
implementation "cn.jzvd:jiaozivideoplayer:${jiaoziVideoView}"
|
||||
implementation "com.danikula:videocache:${videoCache}"
|
||||
implementation "com.shuyu:gsyVideoPlayer-java:$gsyVideo"
|
||||
implementation "com.shuyu:gsyVideoPlayer-armv7a:$gsyVideo"
|
||||
implementation "com.shuyu:gsyVideoPlayer-x86:$gsyVideo"
|
||||
|
||||
implementation "com.github.wendux:DSBridge-Android:$dsBridge"
|
||||
|
||||
implementation "android.arch.work:work-runtime:${workManager}"
|
||||
|
||||
@ -266,6 +276,13 @@ dependencies {
|
||||
implementation "com.tencent.mm.opensdk:wechat-sdk-android-without-mta:5.3.1"
|
||||
implementation 'com.walkud.rom.checker:RomChecker:1.0.0'
|
||||
|
||||
debugImplementation "com.github.nichbar.chucker:library:$chucker"
|
||||
releaseImplementation "com.github.nichbar.chucker:library-no-op:$chucker"
|
||||
|
||||
implementation 'com.aliyun.dpa:oss-android-sdk:2.9.2'
|
||||
|
||||
implementation "com.airbnb.android:lottie:$lottie"
|
||||
|
||||
implementation project(':libraries:LGLibrary')
|
||||
implementation project(':libraries:MTA')
|
||||
implementation project(':libraries:QQShare')
|
||||
|
||||
Binary file not shown.
BIN
app/libs/GDTActionSDK.min.1.4.9.jar
Normal file
BIN
app/libs/GDTActionSDK.min.1.4.9.jar
Normal file
Binary file not shown.
@ -225,4 +225,19 @@
|
||||
-keep class com.qq.gdt.action.** {*;}
|
||||
|
||||
### AndroidX
|
||||
-keep class androidx.core.app.CoreComponentFactory { *; }
|
||||
-keep class androidx.core.app.CoreComponentFactory { *; }
|
||||
|
||||
#阿里云上传
|
||||
-keep class com.alibaba.sdk.android.oss.** { *; }
|
||||
-dontwarn okio.**
|
||||
-dontwarn org.apache.commons.codec.binary.**
|
||||
|
||||
#视频相关
|
||||
-keep class com.shuyu.gsyvideoplayer.video.** { *; }
|
||||
-dontwarn com.shuyu.gsyvideoplayer.video.**
|
||||
-keep class com.shuyu.gsyvideoplayer.video.base.** { *; }
|
||||
-dontwarn com.shuyu.gsyvideoplayer.video.base.**
|
||||
-keep class com.shuyu.gsyvideoplayer.utils.** { *; }
|
||||
-dontwarn com.shuyu.gsyvideoplayer.utils.**
|
||||
-keep class tv.danmaku.ijk.** { *; }
|
||||
-dontwarn tv.danmaku.ijk.**
|
||||
@ -1,504 +1,559 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android = "http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools = "http://schemas.android.com/tools"
|
||||
package = "com.gh.gamecenter" >
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.gh.gamecenter">
|
||||
|
||||
<!-- 允许应用程序访问网络连接 -->
|
||||
<uses-permission android:name = "android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- 允许应用程序写入外部存储,如SD卡上写文件 -->
|
||||
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<!-- 允许应用程序读取扩展存储器 -->
|
||||
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<!-- 允许挂载和反挂载文件系统可移动存储 -->
|
||||
<uses-permission android:name = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
|
||||
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
|
||||
<!-- 允许应用程序访问Wi-Fi网络状态信息 -->
|
||||
<uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<!-- 允许应用程序获取网络信息状态 -->
|
||||
<uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<!-- 允许应用程序读取电话状态 -->
|
||||
<uses-permission android:name = "android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<!-- 允许应用程序获取当前或最近运行的应用 -->
|
||||
<uses-permission android:name = "android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<!-- 允许访问振动设备 -->
|
||||
<uses-permission android:name = "android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<!-- 允许应用程序改变Wi-Fi连接状态 -->
|
||||
<uses-permission android:name = "android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<!-- 允许应用程序打开系统窗口,显示其他应用程序 -->
|
||||
<uses-permission android:name = "android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<!-- 修改系统设置的权限 -->
|
||||
<uses-permission android:name = "android.permission.WRITE_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
|
||||
<!-- bugly with tinker -->
|
||||
<uses-permission android:name = "android.permission.READ_LOGS" />
|
||||
<uses-permission android:name = "android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.READ_LOGS" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
<uses-sdk tools:overrideLibrary="com.shuyu.gsyvideoplayer,
|
||||
com.shuyu.gsyvideoplayer.lib,
|
||||
com.shuyu.gsyvideoplayer.armv7a,
|
||||
com.shuyu.gsyvideoplayer.x86,
|
||||
com.shuyu.gsy.base,
|
||||
shuyu.com.androidvideocache" />
|
||||
|
||||
<!-- 去掉 SDK 一些流氓权限 -->
|
||||
<uses-permission android:name = "android.permission.READ_CONTACTS" tools:node = "remove"/>
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_CONTACTS"
|
||||
tools:node="remove" />
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity = "true"
|
||||
android:largeScreens = "true"
|
||||
android:normalScreens = "true"
|
||||
android:resizeable = "true"
|
||||
android:smallScreens = "true" />
|
||||
android:anyDensity="true"
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:resizeable="true"
|
||||
android:smallScreens="true" />
|
||||
|
||||
<!--android:largeHeap = "true"-->
|
||||
<application
|
||||
android:name = "com.halo.assistant.TinkerApp"
|
||||
android:allowBackup = "true"
|
||||
android:icon = "@mipmap/logo"
|
||||
android:label = "@string/app_name"
|
||||
android:resizeableActivity = "true"
|
||||
android:theme = "@style/AppCompatTheme.APP"
|
||||
tools:targetApi = "n" >
|
||||
android:name="com.halo.assistant.TinkerApp"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/logo"
|
||||
android:label="@string/app_name"
|
||||
android:largeHeap="true"
|
||||
android:resizeableActivity="true"
|
||||
android:theme="@style/AppCompatTheme.APP"
|
||||
tools:targetApi="n">
|
||||
|
||||
<!--android:launchMode = "singleTask"-->
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SplashScreenActivity"
|
||||
android:configChanges = "keyboardHidden|orientation|screenSize"
|
||||
android:screenOrientation = "portrait"
|
||||
android:theme = "@style/AppGuideTheme" >
|
||||
<intent-filter >
|
||||
<action android:name = "android.intent.action.MAIN" />
|
||||
android:name="com.gh.gamecenter.SplashScreenActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.Launcher">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name = "android.intent.category.LAUNCHER" />
|
||||
</intent-filter >
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</activity >
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MainActivity"
|
||||
android:launchMode = "singleTask"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateAlwaysHidden|adjustResize" />
|
||||
android:name="com.gh.gamecenter.MainActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppCompatTheme.APP"
|
||||
android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.DownloadManagerActivity"
|
||||
android:launchMode = "singleTask"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.DownloadManagerActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!--android:theme = "@android:style/Theme.Black.NoTitleBar.Fullscreen" 退出时屏幕抖动 -->
|
||||
<activity android:name = "com.gh.gamecenter.ViewImageActivity" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SearchActivity"
|
||||
android:configChanges = "keyboardHidden"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.NewsDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SettingActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ConcernActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.subject.SubjectActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.NewsSearchActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.GameNewsActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.CropImageActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.WebActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ShareCardPicActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ShareCardActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MessageDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.LibaoActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.LibaoDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ShareGhWfifActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ShareGhActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.CleanApkActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.kuaichuan.view.KcSelectGameActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.kuaichuan.view.ChooseReceiverActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.kuaichuan.view.ReceiverWaitingActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.kuaichuan.view.FileSenderActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.kuaichuan.view.FileReceiverActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SelectUserIconActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.AboutActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.CommentDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.mygame.MyGameActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.GameDetailActivity"
|
||||
android:configChanges = "orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SuggestSelectActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SuggestionActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.VoteActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateAlwaysHidden|adjustResize" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ToolBoxActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
<activity android:name="com.gh.gamecenter.ViewImageActivity" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.WeiBoShareActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
android:name="com.gh.gamecenter.SearchActivity"
|
||||
android:configChanges="keyboardHidden"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppCompatTheme.APP" />
|
||||
|
||||
<activity
|
||||
android:name = ".category.CategoryDirectoryActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.amway.search.AmwaySearchActivity"
|
||||
android:configChanges="keyboardHidden"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppCompatTheme.APP" />
|
||||
|
||||
<activity
|
||||
android:name = ".category.CategoryListActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ShellActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.LoginActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
android:name="com.gh.gamecenter.NewsDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.UserInfoActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.SettingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.UserRegionActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ConcernActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.CollectionActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.subject.SubjectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MessageActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.NewsSearchActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.UserInfoEditActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.KaiFuActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.GameNewsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.search.AskSearchActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.CropImageActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.WebActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ShareCardPicActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = ".qa.answer.fold.AnswerFoldActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ShareCardActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.answer.edit.AnswerEditActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.MessageDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ConcernInfoActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.LibaoActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.InfoActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.LibaoDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MessageKeFuActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.ShareGhActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.select.CommunitiesSelectActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.CleanApkActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.subject.CommunitySubjectActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.SelectUserIconActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MessageInviteActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.AboutActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.MessageVoteActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.CommentDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = ".qa.questions.invite.QuestionsInviteActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.mygame.MyGameActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.myqa.MyAskActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.GameDetailActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.column.order.AskTabOrderActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.SuggestSelectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.questions.edit.QuestionEditActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.SuggestionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.VoteActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.kaifu.add.AddKaiFuActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden" />
|
||||
android:name="com.gh.gamecenter.ToolBoxActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.kaifu.patch.PatchKaifuActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.WeiBoShareActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.BlockActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name=".category.CategoryDirectoryActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name=".category.CategoryListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.NetworkDiagnosisActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.LoginActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.personalhome.fans.FansActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.UserInfoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.personalhome.followers.FollowersActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.UserRegionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.PersonalHomeActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.CollectionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.personalhome.answer.PersonalAnswerActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.MessageActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.personalhome.question.PersonalQuestionActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.UserInfoEditActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.article.edit.ArticleEditActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.search.AskSearchActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.article.MyArticleActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.article.draft.ArticleDraftActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.article.detail.ArticleDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name=".qa.answer.fold.AnswerFoldActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.draft.CommunityDraftWrapperActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.answer.edit.AnswerEditActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateVisible" />
|
||||
android:name="com.gh.gamecenter.ConcernInfoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.questions.edit.manager.HistoryDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.InfoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.questions.edit.manager.HistoryActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.MessageKeFuActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.select.CommunitiesSelectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.editor.GameActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.subject.CommunitySubjectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.MessageInviteActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.gamedetail.rating.RatingReplyActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.MessageVoteActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.history.HistoryActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name=".qa.questions.invite.QuestionsInviteActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.kuaichuan.view.FileShareActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.myqa.MyAskActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.personalhome.rating.RatingActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.column.order.AskTabOrderActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.gamedetail.rating.logs.CommentLogsActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.qa.questions.edit.QuestionEditActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.tag.TagsActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
|
||||
<activity android:name = "com.gh.gamecenter.qa.article.SimpleArticleListActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:name="com.gh.gamecenter.servers.add.AddKaiFuActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.comment.CommentActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:theme = "@style/Theme.Transparent"
|
||||
android:windowSoftInputMode = "adjustNothing" />
|
||||
android:name="com.gh.gamecenter.servers.patch.PatchKaifuActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.BlockActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.amway.AmwayActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.NetworkDiagnosisActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.personalhome.fans.FansActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.personalhome.followers.FollowersActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.personalhome.UserHomeActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.edit.ArticleEditActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.MyArticleActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.draft.ArticleDraftActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.detail.ArticleDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.draft.CommunityDraftWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateVisible" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.questions.edit.manager.HistoryDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.questions.edit.manager.HistoryActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.editor.GameActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.rating.RatingReplyActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.history.HistoryActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.personalhome.rating.RatingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.rating.logs.CommentLogsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.tag.TagsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.article.SimpleArticleListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.videomanager.VideoManagerActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.upload.view.UploadVideoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.game.GameVideoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.editor.VideoActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.mygame.PlayedGameActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.servers.GameServersActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.game.upload.GameSubmissionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.comment.CommentActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.Transparent"
|
||||
android:windowSoftInputMode="adjustNothing" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.detail.VideoDetailActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar" />
|
||||
|
||||
<!-- 使用小米/华为推送弹窗功能提高推送成功率-->
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.PushProxyActivity"
|
||||
android:exported = "true"
|
||||
android:theme = "@android:style/Theme.Translucent" />
|
||||
android:name="com.gh.gamecenter.PushProxyActivity"
|
||||
android:exported="true"
|
||||
android:theme="@android:style/Theme.Translucent" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SkipActivity"
|
||||
android:theme = "@style/Theme.AppCompat.Light.Fullscreen.Transparent" >
|
||||
<intent-filter >
|
||||
<data android:scheme = "ghzhushou" />
|
||||
android:name="com.gh.gamecenter.SkipActivity"
|
||||
android:theme="@style/Theme.AppCompat.Light.Fullscreen.Transparent">
|
||||
<intent-filter>
|
||||
<data android:scheme="ghzhushou" />
|
||||
|
||||
<category android:name = "android.intent.category.DEFAULT" />
|
||||
<action android:name = "android.intent.action.VIEW" />
|
||||
<category android:name = "android.intent.category.BROWSABLE" />
|
||||
</intent-filter >
|
||||
</activity >
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name = "${applicationId}.wxapi.WXEntryActivity"
|
||||
android:exported = "true"
|
||||
android:label = "@string/app_name"
|
||||
android:launchMode = "singleTop"
|
||||
android:screenOrientation = "portrait"
|
||||
android:theme = "@android:style/Theme.Translucent.NoTitleBar" ></activity >
|
||||
android:name="${applicationId}.wxapi.WXEntryActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
|
||||
|
||||
<provider
|
||||
android:name = "androidx.core.content.FileProvider"
|
||||
android:authorities = "${applicationId}"
|
||||
android:exported = "false"
|
||||
android:grantUriPermissions = "true" >
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name = "android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource = "@xml/provider_paths" />
|
||||
</provider >
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
<receiver
|
||||
android:name = "com.gh.gamecenter.receiver.DownloadReceiver"
|
||||
android:exported = "false" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.DOWNLOAD" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
android:name="com.gh.gamecenter.receiver.DownloadReceiver"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.DOWNLOAD" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name = "com.gh.gamecenter.receiver.InstallReceiver"
|
||||
android:exported = "false" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.INSTALL" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
android:name="com.gh.gamecenter.receiver.InstallReceiver"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.INSTALL" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name = "com.gh.gamecenter.receiver.ActivitySkipReceiver"
|
||||
android:exported = "true" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.ACTIVITYSKIP" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
android:name="com.gh.gamecenter.receiver.ActivitySkipReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.ACTIVITYSKIP" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name = "com.gh.gamecenter.receiver.UmengMessageReceiver" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.UMENG" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
<receiver android:name="com.gh.gamecenter.receiver.UmengMessageReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.UMENG" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!--魅族push应用定义消息receiver声明 -->
|
||||
<receiver android:name = "com.gh.gamecenter.receiver.MeizuPushReceiver" >
|
||||
<intent-filter >
|
||||
<receiver android:name="com.gh.gamecenter.receiver.MeizuPushReceiver">
|
||||
<intent-filter>
|
||||
<!-- 接收push消息 -->
|
||||
<action android:name = "com.meizu.flyme.push.intent.MESSAGE" />
|
||||
<action android:name="com.meizu.flyme.push.intent.MESSAGE" />
|
||||
<!-- 接收register消息 -->
|
||||
<action android:name = "com.meizu.flyme.push.intent.REGISTER.FEEDBACK" />
|
||||
<action android:name="com.meizu.flyme.push.intent.REGISTER.FEEDBACK" />
|
||||
<!-- 接收unregister消息-->
|
||||
<action android:name = "com.meizu.flyme.push.intent.UNREGISTER.FEEDBACK" />
|
||||
<action android:name="com.meizu.flyme.push.intent.UNREGISTER.FEEDBACK" />
|
||||
<!-- 兼容低版本Flyme3推送服务配置 -->
|
||||
<action android:name = "com.meizu.c2dm.intent.REGISTRATION" />
|
||||
<action android:name = "com.meizu.c2dm.intent.RECEIVE" />
|
||||
<action android:name="com.meizu.c2dm.intent.REGISTRATION" />
|
||||
<action android:name="com.meizu.c2dm.intent.RECEIVE" />
|
||||
|
||||
<category android:name = "${applicationId}" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
<category android:name="${applicationId}" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name = "com.gh.common.im.ImReceiver"
|
||||
android:enabled = "true" >
|
||||
<intent-filter android:priority = "2147483647" >
|
||||
<action android:name = "com.gh.im" />
|
||||
<action android:name = "action_finish" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
android:name="com.gh.common.im.ImReceiver"
|
||||
android:enabled="true">
|
||||
<intent-filter android:priority="2147483647">
|
||||
<action android:name="com.gh.im" />
|
||||
<action android:name="action_finish" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name = "com.gh.base.GHUmengNotificationService" />
|
||||
<service android:name="com.gh.base.GHUmengNotificationService" />
|
||||
|
||||
<!--<service android:name = "com.gh.gamecenter.statistics.AppStaticService" />-->
|
||||
|
||||
</application >
|
||||
</application>
|
||||
|
||||
</manifest >
|
||||
</manifest>
|
||||
@ -1,69 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/html">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>光环助手</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<style>
|
||||
body {
|
||||
font: 100%/1.0 'Microsoft YaHei','Helvetica Neue',Helvetica,Arial,sans-serif;
|
||||
background-color: #fff;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
header {
|
||||
}
|
||||
|
||||
article {
|
||||
width:100%;
|
||||
max-width:720px;
|
||||
clear: both;
|
||||
margin: 0 auto;
|
||||
margin-top: 20%;
|
||||
text-align: center;
|
||||
margin-bottom:20%;
|
||||
}
|
||||
.title{margin-top: 4%;font-size:1.7em;color:#191919;text-align:center;}
|
||||
.info{margin-top: 18%;font-size:1.0em;color:#191919;line-height:1.3em;}
|
||||
.download {text-align: center;}
|
||||
.download a{font-size:1.8em;padding:0.2em; text-align:center;color:#ffffff;margin: 0 auto;width:56%;background-color:#2999f9;border-radius:8px; text-decoration:none;display:block;line-height:1.8em;}
|
||||
|
||||
@media only screen and (min-width: 1080px) {
|
||||
article {
|
||||
width:100%;
|
||||
max-width:720px;
|
||||
clear: both;
|
||||
margin: 0 auto;
|
||||
margin-top: 5%;
|
||||
text-align: center;
|
||||
margin-bottom:20%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<img src="http://192.168.43.1:3100/image/gh_icon.png" width="28%">
|
||||
<p class="title">光环助手</p>
|
||||
<br class="info">乐于分享的人是最帅的^_^ </p>
|
||||
<div class="download">
|
||||
<a href="http://192.168.43.1:3100/download/ghzs.apk">免流量下载</a>
|
||||
</div>
|
||||
<p class="title"><font color="#9A9A9A" size="3em">仅限安卓系统 </font></p>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
||||
@ -4,12 +4,14 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" type="text/css" href="normalize.css">
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<link rel="stylesheet" type="text/css" href="video-js.min.css">
|
||||
<!--<link rel="stylesheet" type="text/css" href="https://resource.ghzs.com/css/halo_app.css">-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="editor" contenteditable="false"></div>
|
||||
<script type="text/javascript" src="zepto.min.js"></script>
|
||||
<script type="text/javascript" src="rich_editor.js"></script>
|
||||
<script type="text/javascript" src="video.min.js"></script>
|
||||
<!--<script type="text/javascript" src="content.js"></script>-->
|
||||
<!--<script type="text/javascript" src="https://resource.ghzs.com/js/halo_app.js"></script>-->
|
||||
</body>
|
||||
|
||||
@ -229,7 +229,7 @@ RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
// console.log(imageClassName)
|
||||
if (imageClassName == "image-link") continue;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if(img.src.indexOf("?") > 0) continue;
|
||||
// console.log(i)
|
||||
var tbImg
|
||||
@ -268,7 +268,7 @@ RE.replaceAllDfImage = function(imgRuleFlag, gifRuleFlag) {
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link") continue;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if(img.src.indexOf("web_load_dfimg_icon") > 0) {
|
||||
img.parentNode.removeChild(img.parentNode.childNodes[0]);
|
||||
i--;
|
||||
@ -294,7 +294,7 @@ RE.hideShowBigPic = function() {
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link") continue;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if(img.src.indexOf(",thumbnail") > 0 && img.src.indexOf(".gif") == -1) {
|
||||
j++;
|
||||
}
|
||||
@ -305,7 +305,7 @@ RE.hideShowBigPic = function() {
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link") continue;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if(img.src.indexOf("web_load_dfimg_icon") > 0) {
|
||||
img.parentNode.removeChild(img.parentNode.childNodes[0]);
|
||||
break;
|
||||
@ -319,7 +319,7 @@ RE.replaceDfImageByUrl = function(imgUrl, imgRuleFlag, gifRuleFlag) {
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link") continue;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if (img.src.indexOf(imgUrl) != -1) {
|
||||
img.style.cssText = "max-width: 100%; display:block; margin:8px auto; height: auto;"
|
||||
if(img.src.indexOf(".gif") > 0) {
|
||||
@ -337,7 +337,7 @@ RE.ImageClickListener = function() {
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link") continue;
|
||||
if (imageClassName == "image-link"|| img.className == "poster") continue;
|
||||
window.imagelistener.imageArr(img.src);
|
||||
img.onclick = function() {
|
||||
window.imagelistener.imageClick(this.src);
|
||||
|
||||
1
app/src/main/assets/score_fireworks.json
Normal file
1
app/src/main/assets/score_fireworks.json
Normal file
File diff suppressed because one or more lines are too long
@ -1,12 +1,13 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
@ -18,12 +19,14 @@ import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.common.util.StringUtils;
|
||||
import com.gh.common.util.TeaHelper;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.LoginActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.SuggestionActivity;
|
||||
import com.gh.gamecenter.eventbus.EBShowDialog;
|
||||
import com.gh.gamecenter.suggest.SuggestType;
|
||||
import com.lightgame.BaseAppCompatActivity;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.tencent.tauth.Tencent;
|
||||
@ -31,12 +34,9 @@ import com.tencent.tauth.Tencent;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
@ -44,17 +44,29 @@ import pub.devrel.easypermissions.EasyPermissions;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
|
||||
public abstract class BaseActivity extends BaseToolBarActivity implements EasyPermissions.PermissionCallbacks {
|
||||
/**
|
||||
* 只提供基础的服务(EventBus/ButterKnife/Share/GlobalDialog/Permissions)
|
||||
* <p>
|
||||
* 需要通道工具栏的页面请继承{@link ToolBarActivity}
|
||||
*/
|
||||
|
||||
public abstract class BaseActivity extends BaseAppCompatActivity implements EasyPermissions.PermissionCallbacks {
|
||||
|
||||
// global dialog key
|
||||
public final static String DOWNLOAD_HIJACK = "hijack";
|
||||
public final static String DOWNLOAD_NOT_FOUND = "notfound";
|
||||
public final static String LOGIN_EXCEPTION = "loginException";
|
||||
public final static String PLUGGABLE = "plugin";
|
||||
|
||||
@NonNull
|
||||
protected String mEntrance;
|
||||
|
||||
private boolean mIsPause;
|
||||
private boolean mIsExistLogoutDialog;
|
||||
|
||||
protected final Handler mBaseHandler = new BaseHandler(this);
|
||||
|
||||
protected static class BaseHandler extends Handler {
|
||||
|
||||
private final WeakReference<BaseActivity> mActivityWeakReference;
|
||||
|
||||
BaseHandler(BaseActivity activity) {
|
||||
@ -83,25 +95,9 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
}
|
||||
}
|
||||
|
||||
// 小米沉浸式黑色字体
|
||||
public void setStatusBarDarkMode(boolean darkmode, Activity activity) {
|
||||
Class<? extends Window> clazz = activity.getWindow().getClass();
|
||||
try {
|
||||
int darkModeFlag = 0;
|
||||
Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setStatusBarDarkMode(true, this);
|
||||
EventBus.getDefault().register(this);
|
||||
ButterKnife.bind(this);
|
||||
mEntrance = getIntent().getStringExtra(KEY_ENTRANCE);
|
||||
@ -121,26 +117,26 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onNavigationIconClicked() {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
|
||||
Utils.toast(this, msg);
|
||||
Utils.toast(this, msg);
|
||||
}
|
||||
|
||||
public void toast(int msg) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
|
||||
toast(getString(msg));
|
||||
toast(getString(msg));
|
||||
}
|
||||
|
||||
public void showShare(String url, String icon, String shareTitle, String shareSummary, ShareUtils.ShareType shareType) {
|
||||
|
||||
ShareUtils.getInstance(this).showShareWindows(this, getWindow().getDecorView(), url, icon, shareTitle, shareSummary, shareType);
|
||||
|
||||
public void showShare(String url,
|
||||
String icon,
|
||||
String shareTitle,
|
||||
String shareSummary,
|
||||
ShareUtils.ShareType shareType) {
|
||||
ShareUtils.getInstance(this).showShareWindows(this,
|
||||
getWindow().getDecorView(),
|
||||
url,
|
||||
icon,
|
||||
shareTitle,
|
||||
shareSummary,
|
||||
shareType);
|
||||
if (shareType == ShareUtils.ShareType.game || shareType == ShareUtils.ShareType.plugin) {
|
||||
DataUtils.onEvent(this, "内容分享", shareTitle + shareSummary);
|
||||
} else {
|
||||
@ -150,21 +146,19 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(final EBShowDialog showDialog) {
|
||||
if (!mIsPause && this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
if ("hijack".equals(showDialog.getType())) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
|
||||
&& this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
if (DOWNLOAD_HIJACK.equals(showDialog.getType())) {
|
||||
DialogUtils.showQqSessionDialog(this, "2586716223");// 建议用户联系客服
|
||||
} else if ("plugin".equals(showDialog.getType())) {
|
||||
DialogUtils.showPluginDialog(this, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
toast(R.string.install_failure_hint);
|
||||
} else {
|
||||
startActivity(PackageUtils.getUninstallIntent(BaseActivity.this, showDialog.getPath()));
|
||||
}
|
||||
} else if (PLUGGABLE.equals(showDialog.getType())) {
|
||||
DialogUtils.showPluginDialog(this, () -> {
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
toast(R.string.install_failure_hint);
|
||||
} else {
|
||||
startActivity(PackageUtils.getUninstallIntent(BaseActivity.this, showDialog.getPath()));
|
||||
}
|
||||
});
|
||||
} else if ("loginException".equals(showDialog.getType())) {
|
||||
} else if (LOGIN_EXCEPTION.equals(showDialog.getType())) {
|
||||
if (mIsExistLogoutDialog) return;
|
||||
mIsExistLogoutDialog = true;
|
||||
try {
|
||||
@ -179,34 +173,35 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
"你的账号已在另外一台设备登录多设备-重新登录"))
|
||||
);
|
||||
mBaseHandler.postDelayed(() -> mIsExistLogoutDialog = false, 5000);
|
||||
} catch (JSONException e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if ("notfound".equals(showDialog.getType())) {
|
||||
} else if (DOWNLOAD_NOT_FOUND.equals(showDialog.getType())) {
|
||||
DialogUtils.showAlertDialog(this, "下载失败", "下载链接已失效,建议提交反馈"
|
||||
, "立即反馈", "取消"
|
||||
, () -> {
|
||||
SuggestionActivity.startSuggestionActivity(this, SuggestType.gameQuestion,
|
||||
null, showDialog.getPath() + ",问题反馈:下载链接失效");
|
||||
}, null);
|
||||
, () -> SuggestionActivity.startSuggestionActivity(this,
|
||||
SuggestType.gameQuestion, null,
|
||||
(showDialog.getPath() + ",问题反馈:下载链接失效")), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
TeaHelper.onPause(this);
|
||||
super.onPause();
|
||||
mIsPause = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
TeaHelper.onResume(this);
|
||||
super.onResume();
|
||||
mIsPause = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
@NonNull String[] permissions,
|
||||
@NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
|
||||
}
|
||||
@ -221,7 +216,27 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
|
||||
}
|
||||
|
||||
protected void setStatusBarColor(int color) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
window.setStatusBarColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供当前 activity 的中文名 (不重载的话为类名)
|
||||
*/
|
||||
public String getActivityNameInChinese() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entrance 上一个页面的链式入口名称
|
||||
* @param path 当前页面名称
|
||||
* @return 完整的链式入口名称
|
||||
*/
|
||||
public static String mergeEntranceAndPath(String entrance, String path) {
|
||||
if (TextUtils.isEmpty(entrance) && TextUtils.isEmpty(path)) return "";
|
||||
if (TextUtils.isEmpty(entrance) && !TextUtils.isEmpty(path)) {
|
||||
@ -232,4 +247,5 @@ public abstract class BaseActivity extends BaseToolBarActivity implements EasyPe
|
||||
}
|
||||
return StringUtils.buildString(entrance, "+(", path, ")");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,15 +2,16 @@ package com.gh.base;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.base.adapter.FragmentAdapter;
|
||||
import com.gh.common.view.TabIndicatorView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.lightgame.view.NoScrollableViewPager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -22,7 +23,7 @@ import butterknife.BindView;
|
||||
* Created by khy on 15/03/18.
|
||||
*/
|
||||
|
||||
public abstract class BaseActivity_TabLayout extends BaseActivity implements ViewPager.OnPageChangeListener {
|
||||
public abstract class BaseActivity_TabLayout extends ToolBarActivity implements ViewPager.OnPageChangeListener {
|
||||
|
||||
public static final String PAGE_INDEX = "PAGE_INDEX";
|
||||
|
||||
|
||||
@ -10,12 +10,15 @@ import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.webkit.JavascriptInterface
|
||||
import butterknife.OnClick
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.view.RichEditor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.MyVideoEntity
|
||||
import com.gh.gamecenter.qa.editor.GameActivity
|
||||
import com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity
|
||||
import com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity
|
||||
import com.gh.gamecenter.qa.editor.VideoActivity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.ArticleEntity
|
||||
import com.gh.gamecenter.qa.entity.EditorInsertEntity
|
||||
@ -24,7 +27,7 @@ import com.lightgame.utils.Utils
|
||||
import com.lightgame.view.CheckableImageView
|
||||
import kotterknife.bindView
|
||||
|
||||
abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
|
||||
val mRichEditor by bindView<RichEditor>(R.id.rich_editor)
|
||||
|
||||
@ -49,6 +52,7 @@ abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
DialogUtils.fixWebViewKeyboardNotWorking(this)
|
||||
if (resultCode != Activity.RESULT_OK) return
|
||||
var insertData: EditorInsertEntity? = null
|
||||
when (requestCode) {
|
||||
@ -64,6 +68,11 @@ abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
val game = data?.getParcelableExtra<GameEntity>(GameEntity::class.java.simpleName)
|
||||
if (game != null) insertData = EditorInsertEntity.transform(game)
|
||||
}
|
||||
INSERT_VIDEO_CODE -> {
|
||||
val video = data?.getParcelableExtra<MyVideoEntity>(MyVideoEntity::class.java.simpleName)
|
||||
if (video != null) mRichEditor.insertCustomVideo(video)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
mRichEditor.insertCustomStyleLink(insertData)
|
||||
@ -84,7 +93,7 @@ abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
R.id.editor_paragraph_h1, R.id.editor_paragraph_h2, R.id.editor_paragraph_h3,
|
||||
R.id.editor_paragraph_h4, R.id.editor_font_container, R.id.editor_paragraph_container,
|
||||
R.id.editor_paragraph_quote, R.id.editor_link_answer, R.id.editor_link_article,
|
||||
R.id.editor_link_game)
|
||||
R.id.editor_link_game, R.id.editor_link_video)
|
||||
fun onRichClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.editor_font -> {
|
||||
@ -173,7 +182,10 @@ abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
startActivityForResult(InsertArticleWrapperActivity.getIntent(this), INSERT_ARTICLE_CODE)
|
||||
}
|
||||
R.id.editor_link_game -> {
|
||||
startActivityForResult(GameActivity.getIntent(this), INSERT_GAME_CODE)
|
||||
startActivityForResult(GameActivity.getIntent(this, "插入游戏"), INSERT_GAME_CODE)
|
||||
}
|
||||
R.id.editor_link_video -> {
|
||||
startActivityForResult(VideoActivity.getIntent(this), INSERT_VIDEO_CODE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -232,5 +244,6 @@ abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
const val INSERT_ANSWER_CODE = 411
|
||||
const val INSERT_ARTICLE_CODE = 412
|
||||
const val INSERT_GAME_CODE = 413
|
||||
const val INSERT_VIDEO_CODE = 414
|
||||
}
|
||||
}
|
||||
@ -1,154 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.normal.ToolbarController;
|
||||
import com.lightgame.BaseAppCompatActivity;
|
||||
import com.lightgame.OnTitleClickListener;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by csheng on 15-10-12.
|
||||
*/
|
||||
|
||||
public abstract class BaseToolBarActivity extends BaseAppCompatActivity implements ToolbarController, Toolbar.OnMenuItemClickListener {
|
||||
|
||||
private Toolbar mToolbar;
|
||||
private TextView mTitleTv;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
initToolbar();
|
||||
}
|
||||
|
||||
private void initToolbar() {
|
||||
mToolbar = findViewById(R.id.normal_toolbar);
|
||||
mTitleTv = findViewById(R.id.normal_title);
|
||||
if (mToolbar != null) {
|
||||
// setSupportActionBar(mToolbar); // 替换actionBar后 toolBar无法控制
|
||||
mToolbar.setNavigationIcon(provideNavigationIcon());
|
||||
mToolbar.setNavigationOnClickListener(view -> onBackPressed());
|
||||
mTitleTv.setOnClickListener(view -> {
|
||||
final List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
|
||||
for (Fragment fragment : fragmentList) {
|
||||
if (fragment instanceof OnTitleClickListener) {
|
||||
((OnTitleClickListener) fragment).onTitleClick();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public int provideNavigationIcon() {
|
||||
return R.drawable.ic_bar_back; // default navigation icon
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNavigationTitle(String title) {
|
||||
if (mTitleTv != null) mTitleTv.setText(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNavigationTitle(@StringRes int res) {
|
||||
setNavigationTitle(getString(res));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写此方法以将标题靠左显示
|
||||
*/
|
||||
public boolean showToolbarAtLeft() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setToolbarMenu(int res) {
|
||||
if (mToolbar == null) return;
|
||||
mToolbar.inflateMenu(res);
|
||||
mToolbar.setOnMenuItemClickListener(this);
|
||||
|
||||
Menu menu = mToolbar.getMenu();
|
||||
for (int i = 0; i < menu.size(); i++) {
|
||||
MenuItem menuItem = menu.getItem(i);
|
||||
// menu设置actionLayout后,无法捕捉点击事件,以icon为tag,如果icon is null 手动设置menuItem点击事件
|
||||
if (menuItem != null && menuItem.getIcon() == null) {
|
||||
if (menuItem.getActionView() != null) {
|
||||
menuItem.getActionView().setOnClickListener((v) -> this.onMenuItemClick(menuItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 限制标题实际宽度 防止标题挡住toolbar menu按钮
|
||||
if (menu.size() > 2 && mTitleTv != null) {
|
||||
ViewGroup.LayoutParams layoutParams = mTitleTv.getLayoutParams();
|
||||
if (layoutParams instanceof RelativeLayout.LayoutParams) {
|
||||
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) layoutParams;
|
||||
if (showToolbarAtLeft()) {
|
||||
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
|
||||
params.addRule(RelativeLayout.CENTER_VERTICAL);
|
||||
params.setMargins(DisplayUtils.dip2px(55), 0, DisplayUtils.dip2px(48 * menu.size()), 0);
|
||||
} else {
|
||||
params.setMargins(DisplayUtils.dip2px(90), 0, DisplayUtils.dip2px(90), 0);
|
||||
}
|
||||
mTitleTv.setLayoutParams(params);
|
||||
}
|
||||
} else {
|
||||
if (showToolbarAtLeft()) {
|
||||
ViewGroup.LayoutParams layoutParams = mTitleTv.getLayoutParams();
|
||||
if (layoutParams instanceof RelativeLayout.LayoutParams) {
|
||||
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) layoutParams;
|
||||
params.addRule(RelativeLayout.CENTER_VERTICAL);
|
||||
params.setMargins(DisplayUtils.dip2px(55), 0, DisplayUtils.dip2px(48 * menu.size()), 0);
|
||||
mTitleTv.setLayoutParams(params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuItem getMenuItem(int res) {
|
||||
if (mToolbar == null) return null; //后续页面做好判断
|
||||
return mToolbar.getMenu().findItem(res);
|
||||
}
|
||||
|
||||
public void clearMenu() {
|
||||
if (mToolbar != null) {
|
||||
mToolbar.getMenu().clear();
|
||||
}
|
||||
}
|
||||
|
||||
public Menu getMenu() {
|
||||
return mToolbar.getMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
return onNavigationIconClicked();
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
protected abstract boolean onNavigationIconClicked();
|
||||
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.gamecenter.GameDetailActivity;
|
||||
import com.gh.gamecenter.NewsDetailActivity;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.subject.SubjectActivity;
|
||||
import com.umeng.message.UmengNotificationClickHandler;
|
||||
import com.umeng.message.entity.UMessage;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
||||
public class GHUmengNotificationClickHandler extends UmengNotificationClickHandler {
|
||||
|
||||
@Override
|
||||
public void launchApp(Context context, UMessage uMessage) {
|
||||
// super.launchApp(context, uMessage);
|
||||
|
||||
try {
|
||||
String content = uMessage.extra.get(EntranceUtils.KEY_DATA);
|
||||
JSONObject response = new JSONObject(content);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, EntranceUtils.ENTRANCE_UMENG);
|
||||
String type = response.getString(EntranceUtils.KEY_TYPE);
|
||||
String target = response.getString(EntranceUtils.KEY_TARGET);
|
||||
switch (type) {
|
||||
case EntranceUtils.HOST_ARTICLE:
|
||||
bundle.putString(EntranceUtils.KEY_TO, NewsDetailActivity.class.getSimpleName());
|
||||
bundle.putString(EntranceUtils.KEY_NEWSID, target);
|
||||
break;
|
||||
case EntranceUtils.HOST_GAME:
|
||||
bundle.putString(EntranceUtils.KEY_TO, GameDetailActivity.class.getSimpleName());
|
||||
bundle.putString(EntranceUtils.KEY_GAMEID, target);
|
||||
break;
|
||||
case EntranceUtils.HOST_COLUMN:
|
||||
bundle.putString(EntranceUtils.KEY_TO, SubjectActivity.class.getName());
|
||||
bundle.putString(EntranceUtils.KEY_ID, target);
|
||||
break;
|
||||
case EntranceUtils.HOST_WEB:
|
||||
bundle.putString(EntranceUtils.KEY_TO, WebActivity.class.getSimpleName());
|
||||
bundle.putString(EntranceUtils.KEY_URL, target);
|
||||
break;
|
||||
}
|
||||
EntranceUtils.jumpActivity(context, bundle);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,15 +9,14 @@ import android.view.View;
|
||||
* Created by khy on 25/04/18.
|
||||
*/
|
||||
|
||||
public abstract class onDoubleTapListener implements View.OnTouchListener {
|
||||
public abstract class OnDoubleTapListener implements View.OnTouchListener {
|
||||
private GestureDetector mGestureDetector;
|
||||
|
||||
public onDoubleTapListener(Context context) {
|
||||
protected OnDoubleTapListener(Context context) {
|
||||
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap(MotionEvent e) {
|
||||
onDoubleTapListener.this.onDoubleTap();
|
||||
OnDoubleTapListener.this.onDoubleTap();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@ -26,7 +25,7 @@ public abstract class onDoubleTapListener implements View.OnTouchListener {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
mGestureDetector.onTouchEvent(event);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract void onDoubleTap();
|
||||
@ -2,6 +2,6 @@ package com.gh.base;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
public interface OnViewClickListener {
|
||||
void onClick(View v, Object data);
|
||||
public interface OnViewClickListener<T> {
|
||||
void onClick(View v, T data);
|
||||
}
|
||||
|
||||
245
app/src/main/java/com/gh/base/ToolBarActivity.java
Normal file
245
app/src/main/java/com/gh/base/ToolBarActivity.java
Normal file
@ -0,0 +1,245 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.normal.ToolbarController;
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel;
|
||||
import com.lightgame.OnTitleClickListener;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
/**
|
||||
* 需要用到工具栏的页面使用
|
||||
* <p>
|
||||
* 特殊页面请参考{@link BaseActivity}
|
||||
*/
|
||||
|
||||
public abstract class ToolBarActivity extends BaseActivity implements ToolbarController, Toolbar.OnMenuItemClickListener {
|
||||
|
||||
@Nullable
|
||||
private PackageViewModel mPackageViewModel;
|
||||
|
||||
protected Toolbar mToolbar;
|
||||
|
||||
protected TextView mTitleTv;
|
||||
|
||||
@Nullable
|
||||
private TextView mDownloadCountHint;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setStatusBarDarkMode(true, this);
|
||||
initToolbar();
|
||||
|
||||
if (showDownloadMenu()) {
|
||||
mPackageViewModel = ViewModelProviders.of(this, new PackageViewModel.Factory()).get(PackageViewModel.class);
|
||||
mPackageViewModel.getFilterSameUpdateLiveData().observe(this, this::updateDownloadCountHint);
|
||||
}
|
||||
}
|
||||
|
||||
// 小米沉浸式黑色字体
|
||||
@SuppressLint("PrivateApi")
|
||||
public void setStatusBarDarkMode(boolean darkmode, Activity activity) {
|
||||
Class<? extends Window> clazz = activity.getWindow().getClass();
|
||||
try {
|
||||
Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
int darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void initToolbar() {
|
||||
mToolbar = findViewById(R.id.normal_toolbar);
|
||||
mTitleTv = findViewById(R.id.normal_title);
|
||||
if (mToolbar != null) {
|
||||
// setSupportActionBar(mToolbar); // 替换actionBar后 toolBar无法控制
|
||||
mToolbar.setNavigationIcon(provideNavigationIcon());
|
||||
mToolbar.setNavigationOnClickListener(provideNavigationItemClickListener());
|
||||
if (mTitleTv != null) {
|
||||
mTitleTv.setOnClickListener(view -> {
|
||||
final List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
|
||||
for (Fragment fragment : fragmentList) {
|
||||
if (fragment instanceof OnTitleClickListener) {
|
||||
((OnTitleClickListener) fragment).onTitleClick();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public int provideNavigationIcon() {
|
||||
return R.drawable.ic_bar_back; // default navigation icon
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNavigationTitle(String title) {
|
||||
if (mTitleTv != null) mTitleTv.setText(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNavigationTitle(@StringRes int res) {
|
||||
setNavigationTitle(getString(res));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写此方法以将标题靠左显示
|
||||
*/
|
||||
public boolean showToolbarAtLeft() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setToolbarMenu(int res) {
|
||||
if (mToolbar == null) return;
|
||||
mToolbar.inflateMenu(res);
|
||||
mToolbar.setOnMenuItemClickListener(this);
|
||||
|
||||
if (showDownloadMenu()) {
|
||||
createDownloadMenu(res);
|
||||
}
|
||||
|
||||
Menu menu = mToolbar.getMenu();
|
||||
for (int i = 0; i < menu.size(); i++) {
|
||||
MenuItem menuItem = menu.getItem(i);
|
||||
// menu设置actionLayout后,无法捕捉点击事件,以icon为tag,如果icon is null 手动设置menuItem点击事件
|
||||
if (menuItem != null && menuItem.getIcon() == null) {
|
||||
if (menuItem.getActionView() != null) {
|
||||
menuItem.getActionView().setOnClickListener((v) -> this.onMenuItemClick(menuItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 限制标题实际宽度 防止标题挡住toolbar menu按钮
|
||||
if (menu.size() > 2 && mTitleTv != null) {
|
||||
ViewGroup.LayoutParams layoutParams = mTitleTv.getLayoutParams();
|
||||
if (layoutParams instanceof RelativeLayout.LayoutParams) {
|
||||
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) layoutParams;
|
||||
if (showToolbarAtLeft()) {
|
||||
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
|
||||
params.addRule(RelativeLayout.CENTER_VERTICAL);
|
||||
params.setMargins(DisplayUtils.dip2px(55), 0, DisplayUtils.dip2px(48 * menu.size()), 0);
|
||||
} else {
|
||||
params.setMargins(DisplayUtils.dip2px(90), 0, DisplayUtils.dip2px(90), 0);
|
||||
}
|
||||
mTitleTv.setLayoutParams(params);
|
||||
}
|
||||
} else {
|
||||
if (showToolbarAtLeft()) {
|
||||
ViewGroup.LayoutParams layoutParams = mTitleTv.getLayoutParams();
|
||||
if (layoutParams instanceof RelativeLayout.LayoutParams) {
|
||||
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) layoutParams;
|
||||
params.addRule(RelativeLayout.CENTER_VERTICAL);
|
||||
params.setMargins(DisplayUtils.dip2px(55), 0, DisplayUtils.dip2px(48 * menu.size()), 0);
|
||||
mTitleTv.setLayoutParams(params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createDownloadMenu(int res) {
|
||||
if (res != R.menu.menu_download) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_download, mToolbar.getMenu());
|
||||
}
|
||||
|
||||
if (mPackageViewModel != null) {
|
||||
updateDownloadCountHint(mPackageViewModel.getFilterSameUpdateLiveData().getValue());
|
||||
}
|
||||
|
||||
View downloadMenuView = mToolbar.getMenu().findItem(R.id.menu_download).getActionView();
|
||||
mDownloadCountHint = downloadMenuView.findViewById(R.id.menu_download_count_hint);
|
||||
}
|
||||
|
||||
private void updateDownloadCountHint(List<GameUpdateEntity> updateList) {
|
||||
if (mDownloadCountHint == null) return;
|
||||
|
||||
int count = DownloadManager.getInstance(getApplicationContext()).getDownloadOrUpdateCount(updateList);
|
||||
if (count != 0) {
|
||||
mDownloadCountHint.setVisibility(View.VISIBLE);
|
||||
mDownloadCountHint.setText(String.valueOf(count));
|
||||
} else {
|
||||
mDownloadCountHint.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBDownloadStatus status) {
|
||||
if (showDownloadMenu() && mPackageViewModel != null) {
|
||||
updateDownloadCountHint(mPackageViewModel.getFilterSameUpdateLiveData().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuItem getMenuItem(int res) {
|
||||
if (mToolbar == null) return null; //后续页面做好判断
|
||||
return mToolbar.getMenu().findItem(res);
|
||||
}
|
||||
|
||||
public void clearMenu() {
|
||||
if (mToolbar != null) {
|
||||
mToolbar.getMenu().clear();
|
||||
}
|
||||
}
|
||||
|
||||
public Menu getMenu() {
|
||||
return mToolbar.getMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.menu_download) {
|
||||
MtaHelper.onEvent("下载管理", "下载管理入口", getActivityNameInChinese());
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(this, mEntrance);
|
||||
startActivity(intent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected View.OnClickListener provideNavigationItemClickListener() {
|
||||
return view -> onBackPressed();
|
||||
}
|
||||
|
||||
protected boolean showDownloadMenu() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,13 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.app.Dialog;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import android.view.KeyEvent;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
import com.gh.common.util.ClickUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -27,7 +28,7 @@ public class BaseDialogFragment extends DialogFragment {
|
||||
final Dialog dialog = new Dialog(getActivity(), R.style.DialogWindowTransparent);
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
dialog.setOnKeyListener((dialog1, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && ClickUtils.isFastDoubleClick()) { //会多次响应??
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && !ClickUtils.isFastDoubleClick()) {
|
||||
return onBack();
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -181,13 +181,11 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
}
|
||||
|
||||
public void toast(@StringRes int res) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
|
||||
toast(getString(res));
|
||||
toast(getString(res));
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
|
||||
Utils.toast(getContext(), msg);
|
||||
Utils.toast(getContext(), msg);
|
||||
}
|
||||
|
||||
public void toastLong(@StringRes int msg) {
|
||||
|
||||
@ -10,13 +10,20 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Checkable;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* ViewPager 配合ViewGroup Checkable实现双切换<br/>
|
||||
@ -31,6 +38,8 @@ public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_View
|
||||
|
||||
protected ViewGroup mCheckableGroup;
|
||||
|
||||
private int mLastPosition = MainWrapperFragment.INDEX_HOME;
|
||||
|
||||
@IdRes
|
||||
protected abstract int getCheckableGroupId();
|
||||
|
||||
@ -68,6 +77,33 @@ public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_View
|
||||
@Override
|
||||
public void onPageSelected(int index) {
|
||||
onPageChanged(index);
|
||||
try {
|
||||
// 补充Viewpager Fragment的生命周期
|
||||
if (mFragmentsList.size() > index) {
|
||||
Fragment fragment = mFragmentsList.get(index);
|
||||
fragment.onResume();
|
||||
|
||||
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
|
||||
List<Fragment> fragments = childFragmentManager.getFragments();
|
||||
for (Fragment childFragment : fragments) {
|
||||
childFragment.onResume();
|
||||
}
|
||||
}
|
||||
|
||||
if (mFragmentsList.size() > mLastPosition) {
|
||||
Fragment fragment = mFragmentsList.get(mLastPosition);
|
||||
fragment.onPause();
|
||||
|
||||
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
|
||||
List<Fragment> fragments = childFragmentManager.getFragments();
|
||||
for (Fragment childFragment : fragments) {
|
||||
childFragment.onPause();
|
||||
}
|
||||
}
|
||||
mLastPosition = index;
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
5
app/src/main/java/com/gh/common/Base64ImageHolder.kt
Normal file
5
app/src/main/java/com/gh/common/Base64ImageHolder.kt
Normal file
@ -0,0 +1,5 @@
|
||||
package com.gh.common
|
||||
|
||||
object Base64ImageHolder {
|
||||
var image: String = ""
|
||||
}
|
||||
153
app/src/main/java/com/gh/common/DefaultJsApi.kt
Normal file
153
app/src/main/java/com/gh/common/DefaultJsApi.kt
Normal file
@ -0,0 +1,153 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.webkit.JavascriptInterface
|
||||
import androidx.annotation.Keep
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.LoginActivity
|
||||
import com.gh.gamecenter.ViewImageActivity
|
||||
import com.gh.gamecenter.entity.Badge
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.room.AppDatabase
|
||||
import com.gh.gamecenter.user.LoginTag
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
import wendu.dsbridge.CompletionHandler
|
||||
|
||||
class DefaultJsApi(var context: Context) {
|
||||
|
||||
@JavascriptInterface
|
||||
fun isGhzs(msg: Any): String {
|
||||
return "true"
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun toast(msg: Any) {
|
||||
Utils.toast(HaloApp.getInstance().application, msg.toString())
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun logMtaEvent(event: Any) {
|
||||
val mtaEvent = event.toString().toObject() ?: MtaEvent()
|
||||
|
||||
MtaHelper.onEvent(mtaEvent.name, mtaEvent.key, mtaEvent.value)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getUserInfo(msg: Any): String {
|
||||
return UserManager.getInstance().userInfoEntity.toJson()
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getUserToken(msg: Any): String {
|
||||
return UserManager.getInstance().loginTokenEntity.accessToken.value
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun login(msg: Any) {
|
||||
val intent = LoginActivity.getIntent(context, "浏览器")
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun refreshUserInfoBadge(msg: Any) {
|
||||
val userInfoEntity = UserManager.getInstance().userInfoEntity
|
||||
if (msg.toString().isNotEmpty()) {
|
||||
val badge = msg.toString().toObject() ?: Badge()
|
||||
userInfoEntity.badge = badge
|
||||
} else {
|
||||
userInfoEntity.badge = null
|
||||
}
|
||||
UserManager.getInstance().userInfoEntity = userInfoEntity
|
||||
AppDatabase.getInstance(context).userInfoDao().updateUserInfo(userInfoEntity)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getChannel(msg: Any): String {
|
||||
return HaloApp.getInstance().channel
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun bindWechat(msg: Any, handler: CompletionHandler<Any>) {
|
||||
context.ifLogin("浏览器") {
|
||||
LoginHelper.loginWithWechat(object : LoginHelper.LoginCallback {
|
||||
@SuppressLint("CheckResult")
|
||||
override fun onLoginSuccess(loginType: LoginTag, jsonContent: JSONObject) {
|
||||
|
||||
val wechatLoginInfoMap = hashMapOf<String, String>()
|
||||
wechatLoginInfoMap["openid"] = jsonContent.getString("openid")
|
||||
wechatLoginInfoMap["unionid"] = jsonContent.getString("unionid")
|
||||
wechatLoginInfoMap["access_token"] = jsonContent.getString("access_token")
|
||||
wechatLoginInfoMap["refresh_token"] = jsonContent.getString("refresh_token")
|
||||
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.api
|
||||
.postBindWechat(wechatLoginInfoMap.createRequestBody())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
handler.complete(true)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
handler.complete(false)
|
||||
if (exception is HttpException) {
|
||||
ErrorHelper.handleError(HaloApp.getInstance().application, exception.response().errorBody()?.string())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onLoginFailure(loginType: LoginTag, error: String) {
|
||||
handler.complete(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun copyText(msg: Any) {
|
||||
msg.toString().copyTextAndToast()
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun startApp(msg: Any) {
|
||||
val packageName = msg.toString()
|
||||
PackageUtils.launchApplicationByPackageName(HaloApp.getInstance().application, packageName)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun openImage(event: Any) {
|
||||
val imageEvent = event.toString().toObject() ?: ImageEvent()
|
||||
|
||||
val context = CurrentActivityHolder.getCurrentActivity()
|
||||
|
||||
context?.startActivity(ViewImageActivity.getViewImageIntent(context, imageEvent.imageList, imageEvent.position, "浏览器"))
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun openBase64Image(event: Any) {
|
||||
val context = CurrentActivityHolder.getCurrentActivity()
|
||||
|
||||
Base64ImageHolder.image = event.toString()
|
||||
|
||||
context?.startActivity(ViewImageActivity.getBase64ViewImageIntent(context, true))
|
||||
}
|
||||
|
||||
@Keep
|
||||
internal data class MtaEvent(var name: String = "", var key: String = "", var value: String = "")
|
||||
|
||||
@Keep
|
||||
internal data class ImageEvent(var imageList: ArrayList<String> = arrayListOf(), var position: Int = 0)
|
||||
|
||||
}
|
||||
116
app/src/main/java/com/gh/common/DefaultWebViewUrlHandler.kt
Normal file
116
app/src/main/java/com/gh/common/DefaultWebViewUrlHandler.kt
Normal file
@ -0,0 +1,116 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.LibaoDetailActivity
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
object DefaultWebViewUrlHandler {
|
||||
|
||||
@JvmStatic
|
||||
fun interceptUrl(context: Context, url: String, entrance: String): Boolean {
|
||||
val uri = Uri.parse(url)
|
||||
if ("ghzhushou" == uri.scheme) {
|
||||
Utils.log("url = $url")
|
||||
Utils.log("url = " + uri.scheme!!)
|
||||
val host = uri.host
|
||||
val path = uri.path
|
||||
var id = ""
|
||||
if (!TextUtils.isEmpty(path)) {
|
||||
id = path!!.substring(1)
|
||||
}
|
||||
val intent: Intent
|
||||
when (host) {
|
||||
"article" -> context.startActivity(NewsDetailActivity.getIntentById(context, id, entrance))
|
||||
|
||||
"game" -> GameDetailActivity.startGameDetailActivity(context, id, entrance)
|
||||
|
||||
"column" -> SubjectActivity.startSubjectActivity(context, id, uri.getQueryParameter("name"), false, entrance)
|
||||
|
||||
"libao" -> context.startActivity(LibaoDetailActivity.getIntentById(context, id, entrance))
|
||||
|
||||
"qq" -> try {
|
||||
DirectUtils.directToQqConversation(context, id)
|
||||
} catch (e: Exception) {
|
||||
Utils.toast(context, "请检查是否已经安装手机QQ")
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
"qqqun" -> {
|
||||
val key = uri.getQueryParameter("key")
|
||||
if (!DirectUtils.directToQqGroup(context, key)) {
|
||||
Utils.toast(context, "请检查是否已经安装手机QQ")
|
||||
}
|
||||
}
|
||||
|
||||
"inurl" -> {
|
||||
intent = Intent(context, WebActivity::class.java)
|
||||
intent.putExtra(EntranceUtils.KEY_URL, uri.getQueryParameter("url"))
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
"outurl" -> {
|
||||
intent = Intent()
|
||||
intent.action = Intent.ACTION_VIEW
|
||||
intent.data = Uri.parse(uri.getQueryParameter("url"))
|
||||
try {
|
||||
context.startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
Utils.toast(context, "请检查是否已经安装手机浏览器")
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
"question" -> DirectUtils.directToQuestionDetail(context, id, entrance, "文章链接")
|
||||
|
||||
"community" -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = id
|
||||
community.name = uri.getQueryParameter("name")
|
||||
DirectUtils.directToCommunity(context, community)
|
||||
}
|
||||
|
||||
"answer" -> DirectUtils.directToAnswerDetail(context, id, entrance, "文章链接")
|
||||
|
||||
"communities" -> {
|
||||
// ghzhushou://communities/5a32405b2397ab000f688de3/articles/5c99d262c140b321564f04e3
|
||||
var communityId = ""
|
||||
var type = ""
|
||||
var typeId = ""
|
||||
val split = id.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
for (text in split) {
|
||||
if (TextUtils.isEmpty(communityId)) {
|
||||
communityId = text
|
||||
continue
|
||||
}
|
||||
if (TextUtils.isEmpty(type)) {
|
||||
type = text
|
||||
continue
|
||||
}
|
||||
if (TextUtils.isEmpty(typeId)) {
|
||||
typeId = text
|
||||
}
|
||||
}
|
||||
if ("articles" == type) {
|
||||
DirectUtils.directToCommunityArticle(
|
||||
context, typeId, communityId,
|
||||
entrance, "文章链接")
|
||||
}
|
||||
}
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -27,35 +27,36 @@ import org.json.JSONObject
|
||||
object PushManager {
|
||||
|
||||
var deviceToken: String? = ""
|
||||
var previousAlias: AliasEntity? = null
|
||||
var application = HaloApp.getInstance().application
|
||||
|
||||
private var mPreviousAlias: AliasEntity? = null
|
||||
private var mApplication = HaloApp.getInstance().application
|
||||
|
||||
const val SP_PUSH_ALIAS = "push_alias"
|
||||
|
||||
@JvmStatic
|
||||
fun init(channel: String) {
|
||||
//初始化友盟推送
|
||||
UMConfigure.init(application,
|
||||
UMConfigure.init(mApplication,
|
||||
Config.UMENG_APPKEY, channel,
|
||||
UMConfigure.DEVICE_TYPE_PHONE,
|
||||
Config.UMENG_MESSAGE_SECRET)
|
||||
|
||||
// 注册小米、华为和魅族通道
|
||||
MiPushRegistar.register(application, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
|
||||
HuaWeiRegister.register(application)
|
||||
MeizuRegister.register(application, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
|
||||
MiPushRegistar.register(mApplication, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
|
||||
HuaWeiRegister.register(mApplication)
|
||||
MeizuRegister.register(mApplication, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
|
||||
|
||||
//友盟推送
|
||||
val pushAgent = PushAgent.getInstance(application)
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
pushAgent.onAppStart() // 开启App统计
|
||||
|
||||
//注册推送服务,每次调用register方法都会回调该接口
|
||||
registerDevice()
|
||||
|
||||
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(application).getString(SP_PUSH_ALIAS, "")
|
||||
previousAlias = aliasInSp?.toObject()
|
||||
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(mApplication).getString(SP_PUSH_ALIAS, "")
|
||||
mPreviousAlias = aliasInSp?.toObject()
|
||||
|
||||
if (previousAlias == null) {
|
||||
if (mPreviousAlias == null) {
|
||||
getAndSetAlias()
|
||||
}
|
||||
|
||||
@ -64,7 +65,7 @@ object PushManager {
|
||||
}
|
||||
|
||||
private fun registerDevice() {
|
||||
PushAgent.getInstance(application).register(object : IUmengRegisterCallback {
|
||||
PushAgent.getInstance(mApplication).register(object : IUmengRegisterCallback {
|
||||
override fun onSuccess(dToken: String) {
|
||||
//注册成功会返回device token
|
||||
deviceToken = dToken
|
||||
@ -100,7 +101,7 @@ object PushManager {
|
||||
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
|
||||
RetrofitManager.getInstance(application).api.getAlias(body)
|
||||
RetrofitManager.getInstance(mApplication).api.getAlias(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(
|
||||
{ setAlias(it) },
|
||||
@ -110,11 +111,11 @@ object PushManager {
|
||||
|
||||
@JvmStatic
|
||||
fun setAlias(alias: AliasEntity) {
|
||||
val pushAgent = PushAgent.getInstance(application)
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
|
||||
previousAlias = alias
|
||||
PreferenceManager.getDefaultSharedPreferences(application).edit {
|
||||
putString(SP_PUSH_ALIAS, previousAlias?.toJson())
|
||||
mPreviousAlias = alias
|
||||
PreferenceManager.getDefaultSharedPreferences(mApplication).edit {
|
||||
putString(SP_PUSH_ALIAS, mPreviousAlias?.toJson())
|
||||
}
|
||||
|
||||
pushAgent.setAlias(alias.alias, alias.aliasType) { b, s ->
|
||||
@ -124,16 +125,16 @@ object PushManager {
|
||||
|
||||
@JvmStatic
|
||||
fun deleteAlias() {
|
||||
val pushAgent = PushAgent.getInstance(application)
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
|
||||
previousAlias?.let {
|
||||
mPreviousAlias?.let {
|
||||
pushAgent.deleteAlias(it.alias, it.aliasType) { b, s ->
|
||||
Utils.log("删除别名 $b + $s")
|
||||
}
|
||||
}
|
||||
PreferenceManager.getDefaultSharedPreferences(application).edit {
|
||||
PreferenceManager.getDefaultSharedPreferences(mApplication).edit {
|
||||
putString(SP_PUSH_ALIAS, "")
|
||||
}
|
||||
previousAlias = null
|
||||
mPreviousAlias = null
|
||||
}
|
||||
}
|
||||
@ -3,9 +3,10 @@ package com.gh.common.constant;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import androidx.annotation.Nullable;
|
||||
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.SPUtils;
|
||||
@ -54,6 +55,7 @@ public class Config {
|
||||
public static final String FIX_ARTICLE_KEY = "isFixArticle";
|
||||
public static final String FIX_COMMUNITY_KEY = "isFixCommunity";
|
||||
|
||||
public static final int VIDEO_PAGE_SIZE = 21; // 视频列表大多都是一行3个
|
||||
|
||||
public static boolean isShow() {
|
||||
if (getPreferences().getBoolean(FIX_DOWNLOAD_KEY, false)) return true;
|
||||
|
||||
@ -17,12 +17,24 @@ public class Constants {
|
||||
|
||||
public static final String DEVICE_KEY = "deviceKey";
|
||||
|
||||
public static final String HAS_REQUESTED_NOTIFICATION_PERMISSIONS = "has_requested_notification_permissions";
|
||||
|
||||
public static final String SHOULD_SHOW_VIDEO_MOBILE_WARNING = "should_show_video_mobile_warning";
|
||||
|
||||
public static final String GAME_DETAIL_COME_IN = "game_detail_come_in"; // 从游戏详情进入
|
||||
|
||||
public static final String XPOSED_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
|
||||
|
||||
public static final String EB_QUIT_LOGIN = "quit_login";
|
||||
|
||||
// 最近显示的弹窗信息
|
||||
public static final String SP_LAST_OPENING_ID = "last_opening_dialog_id";
|
||||
public static final String SP_LAST_OPENING_TIME = "last_opening_dialog_time";
|
||||
|
||||
public static final String SP_SHOWED_NOTIFICATION_HINT = "show_notification_hint";
|
||||
//标记安装的游戏为已玩过弹窗,最多取消2次
|
||||
public static final String SP_MARK_INSTALLED_GAME = "mark_installed_game";
|
||||
|
||||
//手机号码匹配规则
|
||||
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
|
||||
public static final String REGEX_ACCOUNT = "^[a-zA-Z_]\\w{5,17}$";
|
||||
@ -31,6 +43,14 @@ public class Constants {
|
||||
//输入规则
|
||||
public static final String INPUT_RULE = "0123456789abcdefghijklnmopqrstuvwxyzABCDEFGHIJKLNMOPQRSTUVWXYZ_";
|
||||
|
||||
// 微信绑定地址地址
|
||||
public static final String WECHAT_BIND_ADDRESS_DEV = "https://resource.ghzs.com/page/wechat_dev/index.html#/";
|
||||
public static final String WECHAT_BIND_ADDRESS = "https://resource.ghzs.com/page/wechat_pro/index.html#/";
|
||||
|
||||
// 徽章
|
||||
public static final String BADGE_ADDRESS_DEV = "http://resource.ghzs.com/page/badge_dev/index.html#/";
|
||||
public static final String BADGE_ADDRESS = "http://resource.ghzs.com/page/badge_pro/index.html#/";
|
||||
|
||||
//最少需要多少数据才能上传
|
||||
public static final int DATA_AMOUNT = 20;
|
||||
|
||||
@ -50,4 +70,6 @@ public class Constants {
|
||||
public static final String[] REPORT_LIST = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息", "违法有害信息", "其它"};
|
||||
|
||||
public static final String ENTRANCE_UNKNOWN = "(unknown)";
|
||||
|
||||
public static final String DEFAULT_TEXT_WRAPPER = "###";
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ public class ItemViewType {
|
||||
public static final int GAME_SLIDE = 1; // 滚动图布局
|
||||
public static final int GAME_NORMAL = 2; // 正常游戏布局
|
||||
public static final int GAME_SUBJECT = 19;
|
||||
public static final int GAME_SUBJECT_SLIDE = 26;
|
||||
public static final int GAME_TEST = 3; // 测试游戏布局
|
||||
public static final int GAME_IMAGE = 4; // 游戏大图布局
|
||||
public static final int NEWS_HEADER = 5; // 新闻头部布局
|
||||
@ -28,6 +29,9 @@ public class ItemViewType {
|
||||
public static final int ITEM_EMPTY = 20;
|
||||
public static final int ASK_CONCERN = 21; // 问答精选 关注
|
||||
public static final int RATING_ITEM = 22; // 问答精选 关注
|
||||
public static final int IMAGE_SLIDE_ITEM = 23;
|
||||
public static final int VERTICAL_SLIDE_ITEM = 24;
|
||||
public static final int COLUMN_COLLECTION = 25;
|
||||
|
||||
/**
|
||||
* 普通列表
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
package com.gh.common.databind;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
@ -9,6 +13,8 @@ import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.BindingAdapter;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
@ -16,8 +22,11 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.OnViewClickListener;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.ReserveDialogFragment;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
@ -28,10 +37,12 @@ import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.NewsUtils;
|
||||
import com.gh.common.util.NumberUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PermissionHelper;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.StringUtils;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.common.view.DownloadDialog;
|
||||
import com.gh.common.view.DownloadProgressBar;
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -40,10 +51,12 @@ import com.gh.gamecenter.databinding.KaifuAddItemBinding;
|
||||
import com.gh.gamecenter.databinding.KaifuDetailItemRowBinding;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.KaiFuCalendarEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.entity.ServerCalendarEntity;
|
||||
import com.gh.gamecenter.entity.TagStyleEntity;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.gh.gamecenter.qa.entity.CommunityVideoEntity;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -76,7 +89,7 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
@BindingAdapter({"addDetailKaiFuView", "addDetailKaiFuViewListener", "isReadyPatch"})
|
||||
public static void addDetailKaiFuView(LinearLayout view, List<KaiFuCalendarEntity> list
|
||||
public static void addDetailKaiFuView(LinearLayout view, List<ServerCalendarEntity> list
|
||||
, OnViewClickListener listener, Boolean isReadyPatch) {
|
||||
if (list == null) return;
|
||||
view.removeAllViews();
|
||||
@ -88,7 +101,7 @@ public class BindingAdapters {
|
||||
if (i == 0) {
|
||||
binding.setIsTitle(true);
|
||||
} else {
|
||||
KaiFuCalendarEntity serverEntity = list.get(i - 1);
|
||||
ServerCalendarEntity serverEntity = list.get(i - 1);
|
||||
binding.setEntity(serverEntity);
|
||||
binding.getRoot().setOnClickListener(v -> {
|
||||
listener.onClick(v, isReadyPatch != null && isReadyPatch ? serverEntity : null);
|
||||
@ -117,7 +130,7 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
@BindingAdapter({"addKaiFuView", "clickListener"})
|
||||
public static void addKaiFuView(LinearLayout view, List<KaiFuCalendarEntity> list, OnViewClickListener listener) {
|
||||
public static void addKaiFuView(LinearLayout view, List<ServerCalendarEntity> list, OnViewClickListener listener) {
|
||||
if (list == null) return;
|
||||
view.removeAllViews();
|
||||
view.addView(LayoutInflater.from(view.getContext()).inflate(R.layout.kaifu_add_item_title, null));
|
||||
@ -306,8 +319,14 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
// 大图下的进度条
|
||||
@BindingAdapter({"downloadButton", "traceEvent"})
|
||||
public static void setDownloadButton(DownloadProgressBar progressBar, GameEntity gameEntity, ExposureEvent traceEvent) {
|
||||
@BindingAdapter({"downloadButton", "traceEvent", "clickCallBack", "entrance", "location"})
|
||||
public static void setDownloadButton(DownloadProgressBar progressBar,
|
||||
GameEntity gameEntity,
|
||||
ExposureEvent traceEvent,
|
||||
@Nullable View.OnClickListener clickCallBack,
|
||||
@Nullable String entrance,
|
||||
@Nullable String location) {
|
||||
|
||||
// 判断是否显示按钮
|
||||
if (gameEntity != null
|
||||
&& Config.isShowDownload(gameEntity.getId())
|
||||
@ -318,9 +337,102 @@ public class BindingAdapters {
|
||||
return;
|
||||
}
|
||||
|
||||
// 点击事件
|
||||
progressBar.setOnClickListener(v -> {
|
||||
if (clickCallBack != null) clickCallBack.onClick(v);
|
||||
switch (progressBar.getDownloadType()) {
|
||||
case DOWNLOADING_PLUGIN:
|
||||
case DOWNLOADING_NORMAL:
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(v.getContext(),
|
||||
gameEntity.getApk().get(0).getUrl(), entrance);
|
||||
v.getContext().startActivity(intent);
|
||||
break;
|
||||
case NONE:
|
||||
Utils.toast(v.getContext(), "该游戏已关闭下载");
|
||||
break;
|
||||
case NORMAL:
|
||||
case PLUGIN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
ApkEntity apk = gameEntity.getApk().get(0);
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
apk,
|
||||
() -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
});
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
entrance, location + gameEntity.getName(), traceEvent);
|
||||
}
|
||||
break;
|
||||
case LAUNCH_OR_OPEN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
DataUtils.onGameLaunchEvent(v.getContext(), gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), location);
|
||||
PackageUtils.launchApplicationByPackageName(v.getContext(), gameEntity.getApk().get(0).getPackageName());
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
entrance, location + gameEntity.getName(), traceEvent);
|
||||
}
|
||||
break;
|
||||
case INSTALL_PLUGIN:
|
||||
case INSTALL_NORMAL:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(progressBar.getContext()).getDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
|
||||
if (downloadEntity != null) {
|
||||
PackageUtils.launchSetup(v.getContext(), downloadEntity.getPath());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RESERVABLE:
|
||||
CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> {
|
||||
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(progressBar.getContext(), () -> {
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
|
||||
gameEntity,
|
||||
() -> updateReservation(progressBar, gameEntity));
|
||||
dialogFragment.show(((AppCompatActivity) progressBar.getContext()).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
});
|
||||
break;
|
||||
case RESERVED:
|
||||
if ("download".equals(gameEntity.getReserveStatus())) {
|
||||
ReservationHelper.showDeleteReservationDialog(progressBar.getContext(), () -> {
|
||||
ReservationHelper.deleteReservation(gameEntity, () -> {
|
||||
updateReservation(progressBar, gameEntity);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ReservationHelper.showCancelReservationDialog(progressBar.getContext(), () -> {
|
||||
ReservationHelper.cancelReservation(gameEntity, () -> {
|
||||
updateReservation(progressBar, gameEntity);
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// 显示预约
|
||||
if (gameEntity.isReservable()) {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
|
||||
progressBar.setText("预约");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.RESERVABLE);
|
||||
} else {
|
||||
progressBar.setText("已预约");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.RESERVED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示下载按钮状态
|
||||
if (gameEntity.getApk().isEmpty()) {
|
||||
progressBar.setText("暂无下载");
|
||||
if (gameEntity.getApk().isEmpty() || gameEntity.getDownloadOffStatus() != null) {
|
||||
String offStatus = gameEntity.getDownloadOffStatus();
|
||||
if (offStatus != null && "dialog".equals(offStatus)) {
|
||||
progressBar.setText("查看");
|
||||
} else {
|
||||
progressBar.setText("暂无");
|
||||
}
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
} else {
|
||||
String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity, PluginLocation.only_game);
|
||||
@ -375,61 +487,30 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 点击事件
|
||||
progressBar.setOnClickListener(v -> {
|
||||
switch (progressBar.getDownloadType()) {
|
||||
case DOWNLOADING_PLUGIN:
|
||||
case DOWNLOADING_NORMAL:
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(v.getContext(),
|
||||
gameEntity.getApk().get(0).getUrl(), "(我的光环:我的游戏)");
|
||||
v.getContext().startActivity(intent);
|
||||
break;
|
||||
case NONE:
|
||||
Utils.toast(v.getContext(), "该游戏已关闭下载");
|
||||
break;
|
||||
case NORMAL:
|
||||
case PLUGIN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
ApkEntity apk = gameEntity.getApk().get(0);
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
apk,
|
||||
() -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe));
|
||||
});
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
"(我的光环:我的游戏)", "我的光环-我的游戏:" + gameEntity.getName(), traceEvent);
|
||||
}
|
||||
break;
|
||||
case LAUNCH_OR_OPEN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
DataUtils.onGameLaunchEvent(v.getContext(), gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), "我的光环-我的游戏");
|
||||
PackageUtils.launchApplicationByPackageName(v.getContext(), gameEntity.getApk().get(0).getPackageName());
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
"(我的光环:我的游戏)", "我的光环-我的游戏:" + gameEntity.getName(), traceEvent);
|
||||
}
|
||||
break;
|
||||
case INSTALL_PLUGIN:
|
||||
case INSTALL_NORMAL:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(progressBar.getContext()).getDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
|
||||
if (downloadEntity != null) {
|
||||
PackageUtils.launchSetup(v.getContext(), downloadEntity.getPath());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static void updateReservation(DownloadProgressBar progressBar, GameEntity gameEntity) {
|
||||
// 显示预约
|
||||
if (gameEntity.isReservable()) {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
|
||||
progressBar.setText("预约");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.RESERVABLE);
|
||||
} else {
|
||||
progressBar.setText("已预约");
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.RESERVED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 开始下载
|
||||
private static void download(DownloadProgressBar progressBar, GameEntity
|
||||
gameEntity, ExposureEvent traceEvent, boolean isSubscribe) {
|
||||
private static void download(DownloadProgressBar progressBar,
|
||||
GameEntity gameEntity,
|
||||
ExposureEvent traceEvent,
|
||||
boolean isSubscribe,
|
||||
String entrance,
|
||||
String location) {
|
||||
String str = progressBar.getText();
|
||||
String method;
|
||||
if (str.contains("更新")) {
|
||||
@ -442,7 +523,7 @@ public class BindingAdapters {
|
||||
ApkEntity apkEntity = gameEntity.getApk().get(0);
|
||||
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity.getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(progressBar.getContext(), gameEntity.getName(), apkEntity.getPlatform(), "(我的光环:我的游戏)", "下载开始", method);
|
||||
DataUtils.onGameDownloadEvent(progressBar.getContext(), gameEntity.getName(), apkEntity.getPlatform(), entrance, "下载开始", method);
|
||||
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, ExposureUtils.DownloadType.DOWNLOAD);
|
||||
|
||||
@ -450,7 +531,8 @@ public class BindingAdapters {
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
method,
|
||||
StringUtils.buildString("(我的光环:我的游戏)"), "我的光环-我的游戏:" + gameEntity.getName(),
|
||||
entrance,
|
||||
location + gameEntity.getName(),
|
||||
isSubscribe,
|
||||
downloadExposureEvent);
|
||||
|
||||
@ -487,9 +569,7 @@ public class BindingAdapters {
|
||||
|
||||
@BindingAdapter("isRefreshing")
|
||||
public static void isRefreshing(SwipeRefreshLayout layout, LoadStatus status) {
|
||||
if (status == LoadStatus.INIT_LOADING) {
|
||||
layout.setRefreshing(true);
|
||||
} else {
|
||||
if (status != LoadStatus.INIT_LOADING && status != LoadStatus.LIST_LOADING) {
|
||||
layout.setRefreshing(false);
|
||||
}
|
||||
}
|
||||
@ -505,4 +585,59 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@BindingAdapter({"setCommunityImage", "setCommunityVideoImage"})
|
||||
public static void setCommunityImage(SimpleDraweeView imageView, List<String> images, List<CommunityVideoEntity> videos) {
|
||||
if (videos.size() > 0) {
|
||||
CommunityVideoEntity videoEntity = videos.get(0);
|
||||
ImageUtils.display(imageView, videoEntity.getPoster());
|
||||
imageView.setVisibility(View.VISIBLE);
|
||||
} else if (images.size() > 0) {
|
||||
imageView.setVisibility(View.VISIBLE);
|
||||
ImageUtils.display(imageView, images.get(0));
|
||||
} else {
|
||||
imageView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"setCommunityVideoDuration"})
|
||||
public static void setCommunityVideoDuration(TextView mVideoDuration, List<CommunityVideoEntity> videos) {
|
||||
if (videos != null && videos.size() > 0) {
|
||||
CommunityVideoEntity videoEntity = videos.get(0);
|
||||
mVideoDuration.setBackground(DrawableView.getOvalDrawable(R.color.black_alpha_80, 999F));
|
||||
mVideoDuration.setText(videoEntity.getDuration());
|
||||
mVideoDuration.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mVideoDuration.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"setGameTags", "setMaxGameTags"})
|
||||
public static void setGameTags(TextView view, List<TagStyleEntity> tags, int maxTags) {
|
||||
if (tags == null) {
|
||||
view.setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
int showCount = tags.size() > maxTags ? maxTags : tags.size(); // 最多显示3个
|
||||
|
||||
StringBuilder content = new StringBuilder();
|
||||
for (int i = 0; i < showCount; i++) {
|
||||
TagStyleEntity tag = tags.get(i);
|
||||
content.append(tag.getName());
|
||||
if (i != showCount - 1) content.append("/");
|
||||
}
|
||||
|
||||
Spannable span = new SpannableString(content);
|
||||
int index = 0;
|
||||
for (int i = 0; i < showCount; i++) {
|
||||
TagStyleEntity tag = tags.get(i);
|
||||
int start = index;
|
||||
int end = start + tag.getName().length() + ((i != showCount - 1) ? 1 : 0);
|
||||
index = end;
|
||||
span.setSpan(new ForegroundColorSpan(Color.parseColor("#" + tag.getColor())),
|
||||
start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
view.setText(span);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.lightgame.dialog.BaseDialogFragment
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* 对 dialog 操作进行 MTA 事件记录的 dialog fragment
|
||||
*/
|
||||
abstract class BaseTrackableDialogFragment : BaseDialogFragment() {
|
||||
|
||||
abstract fun getEvent(): String
|
||||
abstract fun getKey(): String
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
private val mIsCanceledByClickOutsideOfDialog = AtomicBoolean(true)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (getEvent().isEmpty()) {
|
||||
throw IllegalStateException("需要提供非空的 Event 来供 MTA 进行事件记录")
|
||||
}
|
||||
|
||||
if (getKey().isEmpty()) {
|
||||
throw IllegalStateException("需要提供非空的 Key 来供 MTA 进行事件记录")
|
||||
}
|
||||
|
||||
onEvent("出现弹窗")
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
dialog?.setOnKeyListener { _, keyCode, event ->
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
|
||||
mIsCanceledByClickOutsideOfDialog.set(false)
|
||||
onEvent("点击返回")
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun onEvent(value: String) {
|
||||
if (trackWithBasicDeviceInfo()) {
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), value)
|
||||
} else {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCancel(dialog: DialogInterface) {
|
||||
super.onCancel(dialog)
|
||||
if (mIsCanceledByClickOutsideOfDialog.get()) {
|
||||
onEvent("点击空白")
|
||||
}
|
||||
}
|
||||
|
||||
open fun trackWithBasicDeviceInfo() = false
|
||||
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.graphics.Paint
|
||||
import android.os.Bundle
|
||||
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 androidx.core.content.ContextCompat
|
||||
import androidx.core.text.HtmlCompat
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import kotlinx.android.synthetic.main.dialog_game_off_service.*
|
||||
|
||||
// 游戏关闭下载弹窗
|
||||
class GameOffServiceDialogFragment : BaseTrackableDialogFragment() {
|
||||
private var mDialog: GameEntity.Dialog? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.dialog_game_off_service, null)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mDialog?.run {
|
||||
titleTv.text = title
|
||||
contentTv.text = HtmlCompat.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||
|
||||
for (site in sites) {
|
||||
val siteTv = TextView(context)
|
||||
siteTv.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
|
||||
topMargin = DisplayUtils.dip2px(12f)
|
||||
}
|
||||
siteTv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
|
||||
siteTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme))
|
||||
siteTv.text = site.text
|
||||
siteTv.paintFlags = siteTv.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
||||
siteTv.setOnClickListener {
|
||||
MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
|
||||
DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)")
|
||||
dismiss()
|
||||
}
|
||||
|
||||
container.addView(siteTv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEvent(): String {
|
||||
return "游戏下载状态按钮"
|
||||
}
|
||||
|
||||
override fun getKey(): String {
|
||||
return "查看详情弹窗"
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(dialog: GameEntity.Dialog) = GameOffServiceDialogFragment().apply {
|
||||
mDialog = dialog
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
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 com.gh.common.util.MtaHelper
|
||||
import com.gh.common.util.PermissionHelper
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.NotificationHint
|
||||
import kotlinx.android.synthetic.main.dialog_notification_hint.*
|
||||
|
||||
// 通知权限弹窗
|
||||
class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
private var mNotificationHint: NotificationHint? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.dialog_notification_hint, null)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
titleTv.text = mNotificationHint?.title
|
||||
|
||||
contentContainer.removeAllViews()
|
||||
for (item in mNotificationHint?.content!!) {
|
||||
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)
|
||||
}
|
||||
|
||||
activateTv.setOnClickListener {
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击立即开启")
|
||||
dismiss()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
//这种方案适用于 API 26, 即8.0(含8.0)以上可以用
|
||||
val intent = Intent()
|
||||
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
|
||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
PermissionHelper.toPermissionSetting(requireActivity())
|
||||
}
|
||||
}
|
||||
|
||||
laterTv.setOnClickListener {
|
||||
dismiss()
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击以后再说")
|
||||
}
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
}
|
||||
|
||||
override fun getEvent(): String {
|
||||
return "推送引导弹窗"
|
||||
}
|
||||
|
||||
override fun getKey(): String {
|
||||
return "引导弹窗"
|
||||
}
|
||||
|
||||
override fun trackWithBasicDeviceInfo() = true
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(hint: NotificationHint) = NotificationHintDialogFragment().apply {
|
||||
mNotificationHint = hint
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -22,12 +22,13 @@ import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.lightgame.dialog.BaseDialogFragment
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
|
||||
class ReserveDialogFragment : BaseDialogFragment() {
|
||||
// 预约弹窗
|
||||
class ReserveDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
@BindView(R.id.reserve_hint_tv)
|
||||
lateinit var reserveHintTv: TextView
|
||||
@ -61,6 +62,14 @@ class ReserveDialogFragment : BaseDialogFragment() {
|
||||
return inflater.inflate(R.layout.dialog_reserve_game, null)
|
||||
}
|
||||
|
||||
override fun getEvent(): String {
|
||||
return "预约游戏"
|
||||
}
|
||||
|
||||
override fun getKey(): String {
|
||||
return "预约功能操作"
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@ -75,14 +84,14 @@ class ReserveDialogFragment : BaseDialogFragment() {
|
||||
|
||||
mViewModel.reservation.observeNonNull(this) {
|
||||
if (it.success) {
|
||||
showSuccessDialog(it.withMobile)
|
||||
showSuccessDialog(it.withMobile, it.boundWechat)
|
||||
mSuccessCallback?.onSuccess()
|
||||
}
|
||||
}
|
||||
dialog.setCanceledOnTouchOutside(true)
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
}
|
||||
|
||||
private fun showSuccessDialog(withMobile: Boolean) {
|
||||
private fun showSuccessDialog(withMobile: Boolean, boundWechat: Boolean) {
|
||||
reserveHintTv.text = "游戏预约成功"
|
||||
reserveContainer.visibility = View.GONE
|
||||
reserveCompletedContainer.visibility = View.VISIBLE
|
||||
@ -90,13 +99,14 @@ class ReserveDialogFragment : BaseDialogFragment() {
|
||||
val reservation = Config.getSettings()?.appointment
|
||||
val dialogConfig = if (withMobile) reservation?.withMobile else reservation?.withoutMobile
|
||||
|
||||
reserveCompletedContentTv.text = Html.fromHtml(dialogConfig?.htmlContent)
|
||||
reserveCompletedContentTv.text = dialogConfig?.htmlContent?.fromHtml()
|
||||
if (dialogConfig?.text.isNullOrEmpty()
|
||||
|| dialogConfig?.toLinkEntity()?.link.isNullOrEmpty()) {
|
||||
|| (dialogConfig?.type == "wechat_bind" && boundWechat)) {
|
||||
customizableBtn.visibility = View.GONE
|
||||
} else {
|
||||
customizableBtn.text = dialogConfig?.text
|
||||
customizableBtn.setOnClickListener {
|
||||
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击跳转按钮")
|
||||
DirectUtils.directToLinkPage(
|
||||
requireContext(),
|
||||
dialogConfig!!.toLinkEntity(),
|
||||
@ -114,6 +124,7 @@ class ReserveDialogFragment : BaseDialogFragment() {
|
||||
fun onClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.reserve_without_mobile_btn -> {
|
||||
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击无手机号预约")
|
||||
mViewModel.reserve(gameId = mGameId, gameName = mGameName)
|
||||
}
|
||||
|
||||
@ -124,10 +135,12 @@ class ReserveDialogFragment : BaseDialogFragment() {
|
||||
return
|
||||
}
|
||||
|
||||
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击立即预约")
|
||||
mViewModel.reserve(gameId = mGameId, gameName = mGameName, mobile = mobile)
|
||||
}
|
||||
|
||||
R.id.close_btn -> {
|
||||
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击关闭")
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
@ -164,7 +177,12 @@ class ReserveViewModel(application: Application) : AndroidViewModel(application)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
reservation.postValue(Reservation(success = true, withMobile = mobile.isNotEmpty()))
|
||||
var boundWechat = false
|
||||
tryWithDefaultCatch {
|
||||
boundWechat = JSONObject(data.string() ?: "").getBoolean("wechat_bind")
|
||||
}
|
||||
|
||||
reservation.postValue(Reservation(success = true, withMobile = mobile.isNotEmpty(), boundWechat = boundWechat))
|
||||
ReservationRepository.addReservationToMemoryAndRefresh(gameId)
|
||||
|
||||
MtaHelper.onEvent("预约游戏", "预约", gameName)
|
||||
@ -176,6 +194,5 @@ class ReserveViewModel(application: Application) : AndroidViewModel(application)
|
||||
})
|
||||
}
|
||||
|
||||
class Reservation(var success: Boolean = false, var withMobile: Boolean = false)
|
||||
|
||||
class Reservation(var success: Boolean = false, var withMobile: Boolean = false, var boundWechat: Boolean = false)
|
||||
}
|
||||
47
app/src/main/java/com/gh/common/dialog/TrackableDialog.kt
Normal file
47
app/src/main/java/com/gh/common/dialog/TrackableDialog.kt
Normal file
@ -0,0 +1,47 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import com.gh.common.util.MtaHelper
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
open class TrackableDialog(context: Context,
|
||||
themeResId: Int,
|
||||
private var mEvent: String,
|
||||
private var mKey: String,
|
||||
private var mCancelValue: String? = null,
|
||||
private var mKeyBackValue: String? = null,
|
||||
private var mLogShowEvent: Boolean = true)
|
||||
: Dialog(context, themeResId) {
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
private val mIsCanceledByClickOutsideOfDialog = AtomicBoolean(true)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setOnCancelListener {
|
||||
if (mIsCanceledByClickOutsideOfDialog.get()) {
|
||||
MtaHelper.onEvent(mEvent, mKey, mCancelValue ?: "点击空白")
|
||||
}
|
||||
}
|
||||
|
||||
setOnKeyListener { _, keyCode, event ->
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
|
||||
mIsCanceledByClickOutsideOfDialog.set(false)
|
||||
MtaHelper.onEvent(mEvent, mKey, mKeyBackValue ?: "点击返回")
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
super.show()
|
||||
if (mLogShowEvent) {
|
||||
MtaHelper.onEvent(mEvent, mKey, "出现弹窗")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,15 +17,15 @@ import com.gh.gamecenter.room.dao.GameDao
|
||||
import com.gh.gamecenter.room.dao.NewsHistoryDao
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class], version = 3, exportSchema = false)
|
||||
@TypeConverters(*[
|
||||
CountConverter::class,
|
||||
CommunityConverter::class,
|
||||
TimeConverter::class,
|
||||
AnswerUserConverter::class,
|
||||
ThumbnailConverter::class,
|
||||
TagStyleListConverter::class,
|
||||
StringArrayListConverter::class])
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class], version = 4, exportSchema = false)
|
||||
@TypeConverters(CountConverter::class,
|
||||
CommunityConverter::class,
|
||||
TimeConverter::class,
|
||||
AnswerUserConverter::class,
|
||||
ThumbnailConverter::class,
|
||||
TagStyleListConverter::class,
|
||||
StringArrayListConverter::class,
|
||||
CommunityVideoConverter::class)
|
||||
|
||||
abstract class HistoryDatabase : RoomDatabase() {
|
||||
|
||||
@ -42,9 +42,17 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_3_4: Migration = object : Migration(3, 4) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("Alter TABLE AnswerEntity add videos TEXT NOT NULL DEFAULT ''")
|
||||
database.execSQL("Alter TABLE ArticleEntity add videos TEXT NOT NULL DEFAULT ''")
|
||||
}
|
||||
}
|
||||
|
||||
val instance by lazy {
|
||||
Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE")
|
||||
.addMigrations(MIGRATION_2_3)
|
||||
.addMigrations(MIGRATION_3_4)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.gh.common.history
|
||||
import com.gh.common.runOnIoThread
|
||||
import com.gh.common.util.clearHtmlFormatCompletely
|
||||
import com.gh.common.util.removeInsertedContent
|
||||
import com.gh.common.util.removeVideoContent
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.HistoryGameEntity
|
||||
import com.gh.gamecenter.entity.NewsEntity
|
||||
@ -78,7 +79,11 @@ object HistoryHelper {
|
||||
val articleEntity = ArticleEntity()
|
||||
|
||||
articleEntity.id = articleDetailEntity.id
|
||||
articleEntity.brief = articleDetailEntity.content.removeInsertedContent().clearHtmlFormatCompletely().replace(" +".toRegex()," ")
|
||||
articleEntity.brief = articleDetailEntity.content.
|
||||
removeVideoContent().
|
||||
removeInsertedContent().
|
||||
clearHtmlFormatCompletely().
|
||||
replace(" +".toRegex()," ")
|
||||
articleEntity.count = articleDetailEntity.count
|
||||
articleEntity.community = articleDetailEntity.community
|
||||
articleEntity.time = articleDetailEntity.time
|
||||
@ -99,7 +104,11 @@ object HistoryHelper {
|
||||
answerEntity.vote = answerDetailEntity.vote
|
||||
answerEntity.user = answerDetailEntity.user
|
||||
answerEntity.orderTag = System.currentTimeMillis()
|
||||
answerEntity.brief = answerDetailEntity.content.removeInsertedContent().clearHtmlFormatCompletely().replace(" +".toRegex(), " ")
|
||||
answerEntity.brief = answerDetailEntity.content.
|
||||
removeVideoContent().
|
||||
removeInsertedContent().
|
||||
clearHtmlFormatCompletely().
|
||||
replace(" +".toRegex(), " ")
|
||||
answerEntity.time = answerDetailEntity.time
|
||||
|
||||
return answerEntity
|
||||
|
||||
@ -22,7 +22,7 @@ object ActivationHelper {
|
||||
@JvmStatic
|
||||
fun sendActivationInfo() {
|
||||
// 能获取到 IMEI 并且之前没发送过激活信息才发
|
||||
if (mHasSentActivatedInfo
|
||||
if (!mHasSentActivatedInfo
|
||||
&& Util_System_Phone_State.canGetImei(HaloApp.getInstance().application)) {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.api.postActivationInfo()
|
||||
|
||||
@ -1,9 +1,16 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class ClassUtils {
|
||||
|
||||
@Nullable
|
||||
public static Class<?> forName(String name) {
|
||||
if (TextUtils.isEmpty(name)) return null;
|
||||
|
||||
if ("NewsActivity".equals(name)) {
|
||||
name = "NewsDetailActivity";
|
||||
} else if ("GameDetailsActivity".equals(name)) {
|
||||
|
||||
@ -50,16 +50,30 @@ object CommentHelper {
|
||||
listener = listener)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showVideoCommentOptions(context: Context,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
videoId: String,
|
||||
listener: OnCommentCallBackListener?) {
|
||||
showCommentOptions(context = context,
|
||||
commentEntity = commentEntity,
|
||||
showConversation = showConversation,
|
||||
videoId = videoId,
|
||||
listener = listener)
|
||||
}
|
||||
|
||||
private fun showCommentOptions(context: Context,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
articleId: String? = null,
|
||||
communityId: String? = null,
|
||||
answerId: String? = null,
|
||||
videoId: String? = null,
|
||||
listener: OnCommentCallBackListener? = null) {
|
||||
val dialogOptions = ArrayList<String>()
|
||||
|
||||
if (commentEntity.me == null || !commentEntity.me?.isAnswerCommented!!) {
|
||||
if (commentEntity.me == null || !commentEntity.me?.isCommentOwner!!) {
|
||||
dialogOptions.add("回复")
|
||||
}
|
||||
|
||||
@ -117,8 +131,10 @@ object CommentHelper {
|
||||
|
||||
if (answerId != null) {
|
||||
PostCommentUtils.postAnswerReportData(context, commentEntity.id, answerId, reportType, commentListener)
|
||||
} else {
|
||||
} else if (articleId != null) {
|
||||
PostCommentUtils.reportCommunityArticleComment(context, communityId, articleId, commentEntity.id, reportType, commentListener)
|
||||
} else {
|
||||
PostCommentUtils.reportVideoComment(context, videoId, commentEntity.id, reportType, commentListener)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,9 +144,12 @@ object CommentHelper {
|
||||
if (answerId != null) {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getAnswerCommentIntent(context, commentEntity.id, answerId, null))
|
||||
} else {
|
||||
} else if (articleId != null) {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getCommunityArticleCommentIntent(context, articleId, commentEntity.id, communityId, null))
|
||||
} else {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getVideoCommentIntent(context, commentEntity.id, videoId, null))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -154,7 +173,7 @@ object CommentHelper {
|
||||
|| me.moderatorPermissions.topCommunityArticleComment > Permissions.GUEST) {
|
||||
dialogOptions.add(highlight)
|
||||
if (me.moderatorPermissions.topAnswerComment > Permissions.REPORTER
|
||||
|| me.moderatorPermissions.topCommunityArticleComment > Permissions.REPORTER ) {
|
||||
|| me.moderatorPermissions.topCommunityArticleComment > Permissions.REPORTER) {
|
||||
canHighlightCommentDirectly = true
|
||||
}
|
||||
}
|
||||
@ -163,7 +182,7 @@ object CommentHelper {
|
||||
|| me.moderatorPermissions.hideCommunityArticleComment > Permissions.GUEST) {
|
||||
dialogOptions.add(hide)
|
||||
if (me.moderatorPermissions.hideAnswerComment > Permissions.REPORTER
|
||||
|| me.moderatorPermissions.hideCommunityArticleComment > Permissions.REPORTER ) {
|
||||
|| me.moderatorPermissions.hideCommunityArticleComment > Permissions.REPORTER) {
|
||||
canHideCommentDirectly = true
|
||||
}
|
||||
}
|
||||
@ -187,7 +206,7 @@ object CommentHelper {
|
||||
}
|
||||
|
||||
comment.me?.let {
|
||||
if (it.isAnswerCommented) {
|
||||
if (it.isCommentOwner) {
|
||||
disabledOptions.add(highlight)
|
||||
}
|
||||
}
|
||||
@ -201,7 +220,7 @@ object CommentHelper {
|
||||
}
|
||||
|
||||
comment.me?.let { me ->
|
||||
if (me.isAnswerCommented) {
|
||||
if (me.isCommentOwner) {
|
||||
Utils.toast(context, "不能置顶自己的评论")
|
||||
return@showListDialog
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
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 androidx.core.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
@ -21,11 +21,17 @@ import com.gh.gamecenter.entity.CommentEntity;
|
||||
import com.gh.gamecenter.entity.MeEntity;
|
||||
import com.gh.gamecenter.entity.UserInfoEntity;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
@ -33,6 +39,10 @@ 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;
|
||||
import retrofit2.HttpException;
|
||||
|
||||
/**
|
||||
@ -87,7 +97,7 @@ public class CommentUtils {
|
||||
|
||||
List<String> dialogType = new ArrayList<>();
|
||||
|
||||
if (commentEntity.getMe() == null || !commentEntity.getMe().isCommentOwn()) {
|
||||
if (commentEntity.getMe() == null || !commentEntity.getMe().isCommentOwner()) {
|
||||
dialogType.add("回复");
|
||||
}
|
||||
|
||||
@ -259,9 +269,15 @@ public class CommentUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public static void postVoteToAnswerComment(final Context context, String answerId, String articleId,
|
||||
String articleCommunityId, final CommentEntity commentEntity,
|
||||
final TextView commentLikeCountTv, final ImageView commentLikeIv, final OnVoteListener listener) {
|
||||
public static void likeComment(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 = "回答详情-评论-点赞";
|
||||
if (TextUtils.isEmpty(articleId)) {
|
||||
@ -278,7 +294,7 @@ public class CommentUtils {
|
||||
commentLikeCountTv.setText(NumberUtils.transSimpleCount(commentEntity.getVote()));
|
||||
commentLikeCountTv.setVisibility(View.VISIBLE);
|
||||
|
||||
PostCommentUtils.voteAnswerComment(context, answerId, articleId, articleCommunityId, commentEntity.getId(),
|
||||
PostCommentUtils.likeComment(context, answerId, articleId, articleCommunityId, videoId, commentEntity.getId(),
|
||||
new PostCommentUtils.PostCommentListener() {
|
||||
@Override
|
||||
public void postSuccess(JSONObject response) {
|
||||
@ -289,7 +305,6 @@ public class CommentUtils {
|
||||
|
||||
@Override
|
||||
public void postFailed(Throwable e) {
|
||||
|
||||
commentEntity.setVote(commentEntity.getVote() - 1);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.hint));
|
||||
commentLikeIv.setImageResource(R.drawable.vote_icon_unselect);
|
||||
@ -330,7 +345,7 @@ public class CommentUtils {
|
||||
if (entity.getVote() == 0) {
|
||||
holder.commentLikeCountTv.setVisibility(View.GONE);
|
||||
} else { // 检查是否已点赞
|
||||
if (userDataEntity != null && (userDataEntity.isCommentVoted() || userDataEntity.isAnswerCommentVoted())) {
|
||||
if (userDataEntity != null && (userDataEntity.isCommentVoted())) {
|
||||
holder.commentLikeCountTv.setTextColor(ContextCompat.getColor(mContext, R.color.theme));
|
||||
holder.commentLikeIv.setImageResource(R.drawable.vote_icon_select);
|
||||
}
|
||||
@ -338,10 +353,20 @@ public class CommentUtils {
|
||||
holder.commentLikeCountTv.setText(NumberUtils.transSimpleCount(entity.getVote()));
|
||||
}
|
||||
|
||||
if (entity.getUser().getBadge() != null) {
|
||||
holder.userBadgeSdv.setVisibility(View.VISIBLE);
|
||||
holder.badgeNameTv.setVisibility(View.VISIBLE);
|
||||
ImageUtils.display(holder.userBadgeSdv, entity.getUser().getBadge().getIcon());
|
||||
holder.badgeNameTv.setText(entity.getUser().getBadge().getName());
|
||||
} else {
|
||||
holder.userBadgeSdv.setVisibility(View.GONE);
|
||||
holder.badgeNameTv.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
//检查是否是自身评论
|
||||
UserInfoEntity userInfo = UserManager.getInstance().getUserInfoEntity();
|
||||
if (userDataEntity != null && userDataEntity.isCommentOwn() && userInfo != null) {
|
||||
if (entity.getMe() != null && entity.getMe().isAnswerOwn()) {
|
||||
if (userDataEntity != null && userDataEntity.isCommentOwner() && userInfo != null) {
|
||||
if (entity.getMe() != null && entity.getMe().isContentOwner()) {
|
||||
holder.commentUserNameTv.setText(userInfo.getName() + "(作者)");
|
||||
} else {
|
||||
holder.commentUserNameTv.setText(userInfo.getName());
|
||||
@ -353,7 +378,7 @@ public class CommentUtils {
|
||||
}
|
||||
ImageUtils.displayIcon(holder.commentUserIconDv, userInfo.getIcon());
|
||||
} else {
|
||||
if (entity.getMe() != null && entity.getMe().isAnswerOwn()) {
|
||||
if (entity.getMe() != null && entity.getMe().isContentOwner()) {
|
||||
holder.commentUserNameTv.setText(entity.getUser().getName() + "(作者)");
|
||||
} else {
|
||||
holder.commentUserNameTv.setText(entity.getUser().getName());
|
||||
@ -371,6 +396,36 @@ public class CommentUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public static void isUserCommentedOnThisGame(String gameId, WeakReference<SimpleCallback<Boolean>> callback) {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
|
||||
.getApi()
|
||||
.isUserCommentedOnThisGame(UserManager.getInstance().getUserId(), gameId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new BiResponse<ResponseBody>() {
|
||||
@Override
|
||||
public void onSuccess(ResponseBody data) {
|
||||
SimpleCallback<Boolean> cb = callback.get();
|
||||
if (cb != null) {
|
||||
try {
|
||||
JSONObject object = new JSONObject(data.string());
|
||||
cb.onCallback(object.getBoolean("status"));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Exception exception) {
|
||||
Utils.toast(HaloApp.getInstance().getApplication(), "网络异常");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//复制文字
|
||||
public static void copyText(String copyContent, Context context) {
|
||||
ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
|
||||
@ -33,7 +33,11 @@ public class DetailDownloadUtils {
|
||||
|
||||
if (viewHolder.gameEntity.isReservable()) {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(viewHolder.gameEntity.getId())) {
|
||||
viewHolder.mDownloadPb.setText("预约《" + viewHolder.gameEntity.getName() + "》");
|
||||
if (TextUtils.isEmpty(viewHolder.downloadAddWord)) {
|
||||
viewHolder.mDownloadPb.setText(String.format("预约" + "《%s》", viewHolder.gameEntity.getName()));
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(String.format("预约" + "《%s》%s", viewHolder.gameEntity.getName(), viewHolder.downloadAddWord));
|
||||
}
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.RESERVABLE);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText("已预约《" + viewHolder.gameEntity.getName() + "》");
|
||||
@ -42,9 +46,14 @@ public class DetailDownloadUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewHolder.gameEntity.getApk().isEmpty()) {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "暂无下载" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
if (viewHolder.gameEntity.getApk().isEmpty() || viewHolder.gameEntity.getDownloadOffStatus() != null) {
|
||||
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "查看详情" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE_WITH_HINT);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "暂无下载" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
} else {
|
||||
String status = GameUtils.getDownloadBtnText(viewHolder.context, viewHolder.gameEntity, PluginLocation.only_game);
|
||||
switch (status) {
|
||||
|
||||
@ -11,7 +11,7 @@ import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.gh.gamecenter.kuaichuan.WifiMgr;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.tencent.stat.StatConfig;
|
||||
|
||||
@ -164,7 +164,7 @@ public class DeviceUtils {
|
||||
}
|
||||
|
||||
} else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
|
||||
return WifiMgr.getInstance(context).getCurrentIpAddress();
|
||||
return getCurrentIpAddress();
|
||||
}
|
||||
} else {
|
||||
//当前无网络连接,请在设置中打开网络
|
||||
@ -266,4 +266,21 @@ public class DeviceUtils {
|
||||
return memInfo.totalMem / (1024 * 1024);
|
||||
}
|
||||
|
||||
|
||||
// 只能获取WiFi的IpAddress
|
||||
public static String getCurrentIpAddress() {
|
||||
String ipAddress;
|
||||
WifiManager wifiManager = (WifiManager) HaloApp.getInstance().
|
||||
getApplication().
|
||||
getApplicationContext().
|
||||
getSystemService(Context.WIFI_SERVICE);
|
||||
int address = wifiManager.getDhcpInfo().ipAddress;
|
||||
ipAddress = ((address & 0xFF)
|
||||
+ "." + ((address >> 8) & 0xFF)
|
||||
+ "." + ((address >> 16) & 0xFF)
|
||||
+ "." + ((address >> 24) & 0xFF));
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
93
app/src/main/java/com/gh/common/util/DialogHelper.kt
Normal file
93
app/src/main/java/com/gh/common/util/DialogHelper.kt
Normal file
@ -0,0 +1,93 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Window
|
||||
import android.widget.TextView
|
||||
import com.gh.common.dialog.TrackableDialog
|
||||
import com.gh.common.util.DialogUtils.checkDialogContext
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
object DialogHelper {
|
||||
|
||||
/**
|
||||
* Material Design 风格弹窗
|
||||
*
|
||||
* @param context
|
||||
* @param title 标题
|
||||
* @param content 内容
|
||||
* @param positiveText 确认按钮文本
|
||||
* @param negativeText 取消按钮文本
|
||||
* @param positiveClickCallback 确认按钮监听
|
||||
* @param negativeClickCallback 取消按钮监听
|
||||
* @param trackMtaEvent 是否记录出现、关闭弹窗MTA事件
|
||||
* @param mtaEvent MTA 的事件名
|
||||
* @param mtaKey MTA 的事件 Key
|
||||
*/
|
||||
fun showDialog(context: Context,
|
||||
title: String,
|
||||
content: CharSequence,
|
||||
positiveText: String,
|
||||
negativeText: String,
|
||||
positiveClickCallback: (() -> Unit)? = null,
|
||||
negativeClickCallback: (() -> Unit)? = null,
|
||||
trackMtaEvent: Boolean = false,
|
||||
mtaEvent: String = "",
|
||||
mtaKey: String = ""): Dialog {
|
||||
val solidContext = checkDialogContext(context)
|
||||
|
||||
val dialog = if (trackMtaEvent) {
|
||||
TrackableDialog(solidContext, R.style.GhAlertDialog, mtaEvent, mtaKey)
|
||||
} else {
|
||||
Dialog(solidContext, R.style.GhAlertDialog)
|
||||
}
|
||||
|
||||
val contentView = LayoutInflater.from(solidContext).inflate(R.layout.dialog_alert, null)
|
||||
val contentTv = contentView.findViewById<TextView>(R.id.dialog_content)
|
||||
val titleTv = contentView.findViewById<TextView>(R.id.dialog_title)
|
||||
val negativeTv = contentView.findViewById<TextView>(R.id.dialog_negative)
|
||||
val positiveTv = contentView.findViewById<TextView>(R.id.dialog_positive)
|
||||
contentTv.text = content
|
||||
titleTv.text = title
|
||||
negativeTv.text = negativeText
|
||||
positiveTv.text = positiveText
|
||||
|
||||
negativeTv.setOnClickListener {
|
||||
if (trackMtaEvent) MtaHelper.onEvent(mtaEvent, mtaKey, "点击" + negativeText)
|
||||
|
||||
negativeClickCallback?.invoke()
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
positiveTv.setOnClickListener {
|
||||
if (trackMtaEvent) MtaHelper.onEvent(mtaEvent, mtaKey, "点击$positiveText")
|
||||
|
||||
positiveClickCallback?.invoke()
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog.setContentView(contentView)
|
||||
dialog.show()
|
||||
return dialog
|
||||
}
|
||||
|
||||
/**
|
||||
* For legacy java invocation
|
||||
*/
|
||||
@JvmStatic
|
||||
fun showDialog(context: Context,
|
||||
title: String,
|
||||
content: CharSequence,
|
||||
positiveText: String,
|
||||
negativeText: String,
|
||||
positiveClickCallback: EmptyCallback,
|
||||
negativeClickCallback: EmptyCallback,
|
||||
trackMtaEvent: Boolean = false,
|
||||
mtaEvent: String = "",
|
||||
mtaKey: String = ""): Dialog {
|
||||
return showDialog(context, title, content, positiveText, negativeText, { positiveClickCallback.onCallback() }, { negativeClickCallback.onCallback() }, trackMtaEvent, mtaEvent, mtaKey)
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,11 +5,7 @@ import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.os.Handler;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
@ -17,37 +13,29 @@ import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.view.Display;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.gamecenter.AboutActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.kuaichuan.WifiMgr;
|
||||
import com.gh.gamecenter.kuaichuan.view.KcSelectGameActivity;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.AppManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class DialogUtils {
|
||||
|
||||
@ -65,161 +53,6 @@ public class DialogUtils {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
// 快传成绩单
|
||||
public static void showKuaiChuanResult(final Activity activity, Handler handler, int requestCode, final String picName) {
|
||||
|
||||
HaloApp.remove(KcSelectGameActivity.KEY_FILE_INFO);
|
||||
|
||||
List<Map<String, String>> mapList = (List<Map<String, String>>) HaloApp.get("sendData", true);
|
||||
if (mapList == null || mapList.size() == 0) return;
|
||||
|
||||
WifiMgr.getInstance(activity).disconnectCurrentNetwork(); // 断开当前WiFi
|
||||
|
||||
int filesCount = mapList.size();
|
||||
int filesSize = 0;
|
||||
int sendTime = 0;
|
||||
|
||||
View view = View.inflate(activity, R.layout.dialog_kuaichuan, null);
|
||||
final LinearLayout mShareLl = view.findViewById(R.id.kuaichuan_dialog_ll);
|
||||
final LinearLayout mShareBottomLl = view.findViewById(R.id.kuaichuan_dialog_share_rl);
|
||||
LinearLayout shareIconLl = view.findViewById(R.id.kuaichuan_icon_ll);
|
||||
ImageView qrCode = view.findViewById(R.id.kuaichuan_qrcode);
|
||||
TextView dateTv = view.findViewById(R.id.kuaichuan_dialog_date);
|
||||
TextView countTv = view.findViewById(R.id.kuaichuan_send_count);
|
||||
TextView sizeTv = view.findViewById(R.id.kuaichuan_send_size);
|
||||
TextView speedTv = view.findViewById(R.id.kuaichuan_send_speed);
|
||||
TextView timeCount = view.findViewById(R.id.kuaichuan_time_count);
|
||||
TextView timeTv = view.findViewById(R.id.kuaichuan_time_tv);
|
||||
TextView sendCountTv = view.findViewById(R.id.dialog_send_tv);
|
||||
ImageView closeIv = view.findViewById(R.id.kuaichuan_dialog_colse);
|
||||
|
||||
final Dialog dialog = new Dialog(activity);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
dialog.setContentView(view);
|
||||
dialog.show();
|
||||
|
||||
Window dialogWindow = dialog.getWindow();
|
||||
WindowManager m = activity.getWindowManager();
|
||||
Display d = m.getDefaultDisplay();
|
||||
if (dialogWindow != null) {
|
||||
WindowManager.LayoutParams p = dialogWindow.getAttributes();
|
||||
p.height = (int) (d.getHeight() * 0.82);
|
||||
p.width = (int) (d.getWidth() * 0.80);
|
||||
dialogWindow.setAttributes(p);
|
||||
}
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日", Locale.getDefault());
|
||||
dateTv.setText(format.format(new Date().getTime()));
|
||||
|
||||
for (Map<String, String> map : mapList) {
|
||||
int size = Integer.parseInt(map.get("apkSize"));
|
||||
int time = 10;
|
||||
try {
|
||||
time = Integer.parseInt(map.get("sendTime"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
String apkPath = map.get("apkPath");
|
||||
filesSize = filesSize + size;
|
||||
sendTime = sendTime + time;
|
||||
|
||||
if (shareIconLl.getChildCount() >= 5) continue;
|
||||
|
||||
android.content.pm.PackageManager pm = activity.getPackageManager();
|
||||
PackageInfo info = pm.getPackageArchiveInfo(apkPath,
|
||||
android.content.pm.PackageManager.GET_ACTIVITIES);
|
||||
if (info != null) {
|
||||
ApplicationInfo appInfo = info.applicationInfo;
|
||||
appInfo.sourceDir = apkPath;
|
||||
appInfo.publicSourceDir = apkPath;
|
||||
Bitmap bitmap = BitmapUtils.drawableToBitmap(appInfo.loadIcon(pm), true);
|
||||
|
||||
ImageView imageView = new ImageView(activity);
|
||||
imageView.setLayoutParams(new LinearLayout.LayoutParams(DisplayUtils.dip2px(activity, 25)
|
||||
, DisplayUtils.dip2px(activity, 24)));
|
||||
imageView.setImageBitmap(bitmap);
|
||||
shareIconLl.addView(imageView);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestCode == 0x170) { // 发送
|
||||
qrCode.setImageResource(R.drawable.kc_qrcode_120);
|
||||
sendCountTv.setText("成功传送游戏");
|
||||
} else {
|
||||
qrCode.setImageResource(R.drawable.kc_qrcode_110);
|
||||
sendCountTv.setText("成功接收游戏");
|
||||
}
|
||||
|
||||
double size = (((float) filesSize / 1024) / 1024);
|
||||
String sizeName;
|
||||
if (size > 1024) {
|
||||
DecimalFormat df = new DecimalFormat("#.0");
|
||||
sizeName = df.format(size / 1024) + "GB";
|
||||
} else {
|
||||
DecimalFormat df = new DecimalFormat("#.0");
|
||||
sizeName = df.format(size) + "MB";
|
||||
}
|
||||
|
||||
if (sendTime < 1000) { // 最少设置发送时间为1s(为了简易计算)
|
||||
sendTime = 1000;
|
||||
}
|
||||
|
||||
int i = (filesSize / 1024) / (sendTime / 1000);
|
||||
String speed;
|
||||
if (i >= 1000) {
|
||||
float mSpeed = i / 1024f;
|
||||
DecimalFormat df = new DecimalFormat("#.0");
|
||||
String str = df.format(mSpeed);
|
||||
if (str.length() > 4) {
|
||||
str = str.substring(0, 4);
|
||||
}
|
||||
speed = str + "MB/s";
|
||||
} else {
|
||||
speed = i + "KB/s";
|
||||
}
|
||||
|
||||
if (sendTime > 60000) {
|
||||
timeCount.setText(String.valueOf(sendTime / 1000 / 60));
|
||||
timeTv.setText("分钟传送完成");
|
||||
} else {
|
||||
timeCount.setText(String.valueOf(sendTime / 1000));
|
||||
timeTv.setText("秒传送完成");
|
||||
}
|
||||
|
||||
sizeTv.setText(sizeName);
|
||||
speedTv.setText(speed);
|
||||
countTv.setText(filesCount + "个");
|
||||
|
||||
// 延迟操作,等待截图部分绘制完成
|
||||
handler.postDelayed(() -> {
|
||||
mShareLl.setDrawingCacheEnabled(true);
|
||||
mShareLl.buildDrawingCache();
|
||||
Bitmap drawingCache = mShareLl.getDrawingCache();
|
||||
saveBitmap(drawingCache, activity, picName);
|
||||
MessageShareUtils.getInstance(activity).showShareWindows(activity, mShareBottomLl, drawingCache, picName, 2);
|
||||
mShareBottomLl.setVisibility(View.VISIBLE);
|
||||
}, 200);
|
||||
|
||||
closeIv.setOnClickListener(v -> dialog.cancel());
|
||||
}
|
||||
|
||||
public static void saveBitmap(Bitmap bm, Activity activity, String picName) {
|
||||
File externalCacheDir = activity.getExternalCacheDir();
|
||||
if (externalCacheDir == null) return;
|
||||
|
||||
File file = new File(externalCacheDir.getPath() + "/ShareImg");
|
||||
if (!file.isDirectory()) {
|
||||
file.delete();
|
||||
file.mkdirs();
|
||||
}
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
MessageShareUtils.getInstance(activity).writeBitmap(file.getPath(), picName, bm, false);
|
||||
|
||||
}
|
||||
|
||||
public static void showInstallHintDialog(Context context, final ConfirmListener cmListener) {
|
||||
context = checkDialogContext(context);
|
||||
@ -567,8 +400,6 @@ public class DialogUtils {
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -589,7 +420,7 @@ public class DialogUtils {
|
||||
contentTv.setText(message);
|
||||
titleTv.setText(title);
|
||||
negativeTv.setText(negative);
|
||||
negativeTv.setTextColor(ContextCompat.getColor(context, R.color.hint));
|
||||
//negativeTv.setTextColor(ContextCompat.getColor(context, R.color.hint));
|
||||
positiveTv.setText(positive);
|
||||
|
||||
negativeTv.setOnClickListener(new View.OnClickListener() {
|
||||
@ -805,6 +636,29 @@ public class DialogUtils {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showLowSystemVersionDialog(Context context) {
|
||||
final Context activityContext = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(activityContext, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_alert, null);
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
|
||||
titleTv.setText("提示");
|
||||
contentTv.setText("抱歉,您当前系统版本过低,暂不支持视频功能");
|
||||
positiveTv.setText("我知道了");
|
||||
|
||||
positiveTv.setOnClickListener(view -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showListDialog(Context context,
|
||||
List<String> selectionList,
|
||||
DialogInterface.OnClickListener onClickListener) {
|
||||
@ -934,35 +788,36 @@ public class DialogUtils {
|
||||
|
||||
public static void showPrivacyPolicyDialog(Context context, String title, String content, EmptyCallback callback) {
|
||||
final Context activityContext = checkDialogContext(context);
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
AtomicBoolean isCanceledByClickOutsideOfDialog = new AtomicBoolean(true);
|
||||
|
||||
String privacyPolicyContent;
|
||||
String privacyPolicyTitle = (TextUtils.isEmpty(title)) ? "个人信息保护指引" : title;
|
||||
if (TextUtils.isEmpty(content)) {
|
||||
privacyPolicyContent = "你的个人信息安全对我们来说至关重要。一直以来,光环助手都致力于为每位用户提供更安全的互联网环境" +
|
||||
"。我们将依据《中华人民共和国网络安全法》、《信息安全技术个人信息安全规范》(GB/T 35273-2017)" +
|
||||
"以及其他相关法律法规和技术规范来收集和使用你的个人信息,以帮助我们向你提供更优质的产品和服务。" +
|
||||
"<br/>1.为帮助你浏览内容、互动交流、注册认证等,我们会收集部分必要的信息" +
|
||||
"<br/>2.为提供上述服务,我们可能需要获取 IMEI号码、IMSI号码 等信息的读取权限" +
|
||||
"<br/>3.以上获取个人信息的权限均不会默认开启,只有在运行相关功能或服务时才会明确提示授权,光环助手不会在未经你同意的情况下收集相关信息";
|
||||
privacyPolicyContent = "光环助手致力于为每位用户提供更安全的互联网环境,我们将依据相关法律法规和技术规范来收集和使用你的个人信息。" +
|
||||
"<br/>1.为帮助你浏览内容、互动交流、注册认证等,我们需要获取一些必要的信息,以实现完整的功能;" +
|
||||
"<br/>2.日常使用中,我们可能需要开启 IMEI号码、IMSI号码、定位、相册 等信息的读取权限;" +
|
||||
"<br/>3.以上信息的读取权限均不会默认开启,只有在运行相关功能或服务时才会明确提示授权,光环助手不会在未经你同意的情况下收集相关信息。";
|
||||
} else {
|
||||
privacyPolicyContent = content;
|
||||
}
|
||||
|
||||
final Dialog dialog = new Dialog(activityContext, R.style.GhAlertDialog);
|
||||
|
||||
|
||||
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
|
||||
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_privacy_policy, null);
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
TextView skipTv = contentView.findViewById(R.id.dialog_skip);
|
||||
|
||||
SpannableStringBuilder skipText = new SpannableStringBuilder("查看完整版的 隐私政策");
|
||||
SpannableStringBuilder skipText = new SpannableStringBuilder("你可以查看完整版的 隐私政策");
|
||||
skipText.setSpan(new ClickableSpan() {
|
||||
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setColor(ContextCompat.getColor(activityContext, R.color.theme));
|
||||
ds.setColor(ContextCompat.getColor(activityContext, R.color.text_1383EB));
|
||||
ds.setUnderlineText(false);
|
||||
}
|
||||
|
||||
@ -989,12 +844,83 @@ public class DialogUtils {
|
||||
dialog.setOnDismissListener(d -> {
|
||||
callback.onCallback();
|
||||
});
|
||||
|
||||
dialog.setOnCancelListener(cd -> {
|
||||
if (isCanceledByClickOutsideOfDialog.get()) {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击空白");
|
||||
}
|
||||
});
|
||||
|
||||
dialog.setOnKeyListener((dialog1, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
|
||||
isCanceledByClickOutsideOfDialog.set(false);
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击返回");
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "出现弹窗");
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
try {
|
||||
dialog.show();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 特殊:目前只在提交问题错误返回时弹出
|
||||
*/
|
||||
public static Dialog showUploadDraftDialog(Context context,
|
||||
final CancelListener clListener,
|
||||
final ConfirmListener cmListener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_video_upload_draft, null);
|
||||
TextView negativeTv = contentView.findViewById(R.id.negative);
|
||||
TextView positiveTv = contentView.findViewById(R.id.positive);
|
||||
TextView content = contentView.findViewById(R.id.content);
|
||||
positiveTv.setBackground(DrawableView.getOvalDrawable(R.color.text_f5f5f5, 999));
|
||||
negativeTv.setBackground(DrawableView.getOvalDrawable(R.color.theme, 999));
|
||||
content.setText(Html.fromHtml(context.getString(R.string.video_upload_draft_dialog_content)));
|
||||
|
||||
negativeTv.setOnClickListener(view -> {
|
||||
if (clListener != null) {
|
||||
clListener.onCancel();
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
positiveTv.setOnClickListener(view -> {
|
||||
if (cmListener != null) {
|
||||
cmListener.onConfirm();
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static Dialog fixWebViewKeyboardNotWorking(Activity activity) {
|
||||
final Dialog dialog = new Dialog(activity, R.style.TransparentDialog);
|
||||
View view = new View(activity);
|
||||
view.setOnClickListener(v -> dialog.dismiss());
|
||||
view.postDelayed(() -> {
|
||||
if (!activity.isFinishing()) {
|
||||
dialog.show();
|
||||
dialog.dismiss();
|
||||
}
|
||||
}, 500);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(view);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -3,6 +3,7 @@ package com.gh.common.util
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import com.gh.base.BaseActivity
|
||||
@ -10,22 +11,29 @@ import com.gh.base.fragment.BaseFragment_TabLayout
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.util.EntranceUtils.*
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.amway.AmwayActivity
|
||||
import com.gh.gamecenter.category.CategoryDirectoryActivity
|
||||
import com.gh.gamecenter.download.DownloadFragment.Companion.INDEX_UPDATE
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.eventbus.EBReuse
|
||||
import com.gh.gamecenter.eventbus.EBSkip
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment
|
||||
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.qa.AskFragment
|
||||
import com.gh.gamecenter.mygame.PlayedGameActivity
|
||||
import com.gh.gamecenter.personalhome.UserHomeActivity
|
||||
import com.gh.gamecenter.qa.CommunityFragment
|
||||
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
|
||||
import com.gh.gamecenter.qa.article.SimpleArticleListActivity
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity
|
||||
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
|
||||
import com.gh.gamecenter.qa.subject.CommunitySubjectActivity
|
||||
import com.gh.gamecenter.servers.GameServersActivity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.gh.gamecenter.suggest.SuggestType
|
||||
import com.gh.gamecenter.tag.TagsActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailActivity
|
||||
import com.lightgame.utils.Util_System_ClipboardManager
|
||||
import com.lightgame.utils.Utils
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
@ -122,10 +130,27 @@ object DirectUtils {
|
||||
display = linkEntity.display ?: Display())))
|
||||
}
|
||||
|
||||
"column_collection" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
|
||||
|
||||
"server" -> {
|
||||
context.startActivity(GameServersActivity.getIntent(context, entrance, path))
|
||||
}
|
||||
|
||||
"top_game_comment" -> directToAmway(context, null, entrance, path)
|
||||
|
||||
"wechat_bind" -> context.startActivity(WebActivity.getBindWechatIntent(context))
|
||||
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至专题合集
|
||||
*/
|
||||
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String) {
|
||||
context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance))
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到新闻详情
|
||||
*/
|
||||
@ -135,7 +160,23 @@ object DirectUtils {
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, NewsDetailActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_NEWSID, id)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至个人主页
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToHomeActivity(context: Context, userId: String?, entrance: String? = null, path: String? = null) {
|
||||
context.startActivity(UserHomeActivity.getIntent(context, userId ?: "", entrance, path))
|
||||
}
|
||||
|
||||
/**
|
||||
* 回到首页
|
||||
*/
|
||||
fun directToMainActivity(context: Context) {
|
||||
val intent = Intent(context, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_CLEAR_TOP }
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,7 +189,12 @@ object DirectUtils {
|
||||
bundle.putString(KEY_TO, GameDetailActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
bundle.putBoolean(KEY_AUTO_DOWNLOAD, autoDownload ?: false)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
// 跳转至用户玩过的游戏
|
||||
fun directToPlayedGame(context: Context, userId: String, entrance: String = "", path: String = "") {
|
||||
context.startActivity(PlayedGameActivity.getIntent(context, userId, entrance, path))
|
||||
}
|
||||
|
||||
// 专栏
|
||||
@ -159,7 +205,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, SubjectActivity::class.java.name)
|
||||
bundle.putParcelable(EntranceUtils.KEY_SUBJECT_DATA, subjectData)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
// 反馈
|
||||
@ -171,7 +217,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_CONTENT, content)
|
||||
bundle.putString(KEY_SUGGEST_HINT_TYPE, KEY_PLUGIN)
|
||||
bundle.putSerializable(EntranceUtils.KEY_SUGGESTTYPE, SuggestType.gameQuestion)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -179,7 +225,7 @@ object DirectUtils {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, DownloadManagerActivity.TAG)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -194,7 +240,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_GAMEID, gameId)
|
||||
bundle.putString(KEY_PACKAGENAME, packageName)
|
||||
bundle.putBoolean(KEY_AUTO_DOWNLOAD, true)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,7 +252,17 @@ object DirectUtils {
|
||||
bundle.putString(KEY_GAMEID, gameId)
|
||||
bundle.putString(KEY_PACKAGENAME, packageName)
|
||||
bundle.putInt(BaseFragment_TabLayout.PAGE_INDEX, INDEX_UPDATE)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToToolbox(context: Context, gameId: String, toolboxUrl: String, entrance: String = ENTRANCE_BROWSER) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_TO, ToolBoxActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_GAMEID, gameId)
|
||||
bundle.putString(KEY_URL, toolboxUrl)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -216,7 +272,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_TO, AnswerDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_ANSWER_ID, id)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -226,7 +282,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_TO, QuestionsDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_QUESTIONS_ID, id)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -235,7 +291,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, WebActivity::class.java.simpleName)
|
||||
bundle.putString(EntranceUtils.KEY_URL, url)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
// 个人-系统消息
|
||||
@ -244,7 +300,7 @@ object DirectUtils {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, MessageKeFuActivity::class.java.simpleName)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -302,7 +358,7 @@ object DirectUtils {
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, LibaoDetailActivity::class.java.simpleName)
|
||||
bundle.putString(EntranceUtils.KEY_ID, giftId)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -319,8 +375,8 @@ object DirectUtils {
|
||||
|
||||
// 这里换个线程操作是为了做一点延时
|
||||
AppExecutor.ioExecutor.execute {
|
||||
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_GAMEFRAGMENT, 1))
|
||||
EventBus.getDefault().post(EBReuse(AskFragment.EB_RETRY_PAGE))
|
||||
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_ASK))
|
||||
EventBus.getDefault().post(EBReuse(CommunityFragment.EB_RETRY_PAGE))
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,4 +404,45 @@ object DirectUtils {
|
||||
bundle.putParcelable(KEY_COMMUNITY_DATA, community)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fromLocation 可见 [VideoDetailContainerViewModel.Location]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, entrance: String? = null, path: String? = "") {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, VideoDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_ID, videoId)
|
||||
bundle.putString(KEY_LOCATION, fromLocation)
|
||||
bundle.putBoolean(KEY_SHOW_COMMENT, showComment)
|
||||
jumpActivity(context, bundle)
|
||||
} else {
|
||||
DialogUtils.showLowSystemVersionDialog(context)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至安利墙
|
||||
* @param fixedTopAmwayCommentId 需要置顶的安利Id
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToAmway(context: Context, fixedTopAmwayCommentId: String? = null, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, AmwayActivity::class.java.name)
|
||||
bundle.putString(KEY_ID, fixedTopAmwayCommentId)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至徽章墙
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToBadgeWall(context: Context, userId: String?, name: String?, icon: String?) {
|
||||
context.startActivity(WebActivity.getBadgeCenterIntent(context, userId, name, icon))
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,23 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.halo.assistant.HaloApp;
|
||||
|
||||
public class DisplayUtils {
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class DisplayUtils {
|
||||
|
||||
/**
|
||||
* 根据手机的分辨率从 dip(像素) 的单位 转成为 px
|
||||
*/
|
||||
@ -14,7 +25,7 @@ public class DisplayUtils {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据手机的分辨率从 px(像素) 的单位 转成为 dip
|
||||
*/
|
||||
@ -22,16 +33,19 @@ public class DisplayUtils {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (pxValue / scale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据手机的分辨率从 dip(像素) 的单位 转成为 px
|
||||
*/
|
||||
public static int dip2px(float dpValue) {
|
||||
final float scale = HaloApp.getInstance().getApplication().getResources().getDisplayMetrics().density;
|
||||
final float scale = HaloApp.getInstance()
|
||||
.getApplication()
|
||||
.getResources()
|
||||
.getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 将px值转换为sp值,保证文字大小不变
|
||||
*
|
||||
@ -43,7 +57,7 @@ public class DisplayUtils {
|
||||
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
|
||||
return (int) (pxValue / fontScale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将sp值转换为px值,保证文字大小不变
|
||||
*
|
||||
@ -55,7 +69,7 @@ public class DisplayUtils {
|
||||
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
|
||||
return (int) (spValue * fontScale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取状态栏的高度
|
||||
*
|
||||
@ -65,7 +79,7 @@ public class DisplayUtils {
|
||||
public static int getStatusBarHeight(Resources resources) {
|
||||
return getInternalDimensionSize(resources, "status_bar_height");
|
||||
}
|
||||
|
||||
|
||||
public static int getInternalDimensionSize(Resources res, String key) {
|
||||
int result = 0;
|
||||
int resourceId = res.getIdentifier(key, "dimen", "android");
|
||||
@ -74,5 +88,107 @@ public class DisplayUtils {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void transparentStatusBar(Activity activity) {
|
||||
//make full transparent statusBar
|
||||
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
|
||||
setWindowFlag(activity, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, true);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
setWindowFlag(activity, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false);
|
||||
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
public static void transparentStatusAndNavigation(Activity activity) {
|
||||
//make full transparent statusBar
|
||||
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
|
||||
setWindowFlag(activity, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, true);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
setWindowFlag(activity, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, false);
|
||||
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
|
||||
activity.getWindow().setNavigationBarColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setWindowFlag(Activity activity, final int bits, boolean on) {
|
||||
Window win = activity.getWindow();
|
||||
WindowManager.LayoutParams winParams = win.getAttributes();
|
||||
if (on) {
|
||||
winParams.flags |= bits;
|
||||
} else {
|
||||
winParams.flags &= ~bits;
|
||||
}
|
||||
win.setAttributes(winParams);
|
||||
}
|
||||
|
||||
public static void setLightStatusBar(Activity activity, boolean lightStatusBar) {
|
||||
boolean isMIUI = setMIUIStatusBarStyle(activity, lightStatusBar);
|
||||
|
||||
if (!isMIUI) {
|
||||
Window window = activity.getWindow();
|
||||
View decor = window.getDecorView();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (lightStatusBar) {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
} else {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
} else {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean setMIUIStatusBarStyle(Activity activity, boolean lightStatusBar) {
|
||||
boolean result = false;
|
||||
Window window = activity.getWindow();
|
||||
if (window != null) {
|
||||
Class clazz = window.getClass();
|
||||
try {
|
||||
int darkModeFlag = 0;
|
||||
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
extraFlagField.invoke(window, lightStatusBar ? darkModeFlag : 0, darkModeFlag);//状态栏透明且黑色字体
|
||||
result = true;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && lightStatusBar) {
|
||||
//开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void setStatusBarColor(Activity activity, int color, boolean lightStatusBar) {
|
||||
Window window = activity.getWindow();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.setStatusBarColor(ContextCompat.getColor(activity,color));
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
|
||||
setLightStatusBar(activity,lightStatusBar);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -167,13 +167,21 @@ public class DownloadItemUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gameEntity.getApk() == null || gameEntity.getApk().isEmpty()) {
|
||||
if (gameEntity.getApk().isEmpty() || gameEntity.getDownloadOffStatus() != null) {
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.news_detail_comment);
|
||||
holder.gameDownloadBtn.setText("暂无");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.button_gray));
|
||||
|
||||
String offStatus = gameEntity.getDownloadOffStatus();
|
||||
if ("dialog".equals(offStatus)) {
|
||||
holder.gameDownloadBtn.setText("查看");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.white));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setText("暂无");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.button_gray));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.news_detail_comment);
|
||||
}
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
updateNormalItem(context, holder, gameEntity, isShowPlatform, pluginLocation);
|
||||
@ -360,6 +368,9 @@ public class DownloadItemUtils {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
CheckLoginUtils.checkLogin(context, entrance, () -> {
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(context, () -> {
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
|
||||
gameEntity,
|
||||
@ -367,13 +378,13 @@ public class DownloadItemUtils {
|
||||
);
|
||||
dialogFragment.show(((AppCompatActivity) context).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
if ("download".equals(gameEntity.getReserveStatus())) {
|
||||
ReservationHelper.showDeleteReservationDialog(context, () -> {
|
||||
ReservationHelper.deleteReservation(gameEntity, () -> {
|
||||
@ -395,10 +406,10 @@ public class DownloadItemUtils {
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
EmptyCallback clickRunnable = () -> {
|
||||
onNormalClick(context, downloadBtn, gameEntity, position, adapter, entrance, location, traceEvent);
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
onNormalClick(context, downloadBtn, gameEntity, position, adapter, entrance, location, traceEvent);
|
||||
};
|
||||
|
||||
// 启动不需要请求存储权限
|
||||
@ -410,11 +421,11 @@ public class DownloadItemUtils {
|
||||
});
|
||||
} else {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(context, () -> {
|
||||
DownloadDialog.getInstance(context).showPopupWindow(v, gameEntity, entrance, location, traceEvent);
|
||||
if (clickCallback != null) {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@ package com.gh.common.util;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.gamecenter.MainActivity;
|
||||
import com.gh.gamecenter.NormalActivity;
|
||||
@ -25,6 +24,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_URL = "url";
|
||||
public static final String KEY_GAMENAME = "gameName";
|
||||
public static final String HOST_ARTICLE = "article";
|
||||
public static final String HOST_VIDEO = "video";
|
||||
public static final String HOST_COMMUNITY_ARTICLE = "community_article";
|
||||
public static final String HOST_COMMUNITY_COLUMN = "community_column";
|
||||
public static final String HOST_GAME = "game";
|
||||
@ -39,12 +39,14 @@ public class EntranceUtils {
|
||||
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 KEY_DATA = "data";
|
||||
public static final String KEY_MESSAGE = "message";
|
||||
public static final String KEY_MESSAGE_ID = "message_id";
|
||||
public static final String KEY_TYPE = "type";
|
||||
public static final String KEY_LINK = "link";
|
||||
public static final String KEY_NAME = "name";
|
||||
public static final String KEY_POSITION = "position";
|
||||
public static final String KEY_ENTRANCE = "entrance";
|
||||
public static final String KEY_TARGET = "target";
|
||||
public static final String ENTRANCE_BROWSER = "(浏览器)";
|
||||
@ -61,8 +63,10 @@ public class EntranceUtils {
|
||||
public static final String KEY_VERSION = "version";
|
||||
public static final String KEY_CONTENT = "content";
|
||||
public static final String KEY_PLUGIN = "plugin";
|
||||
public static final String KEY_LOCATION = "location";
|
||||
public static final String KEY_CURRENTITEM = "currentItem";
|
||||
public static final String KEY_COMMENTID = "commentId";
|
||||
public static final String KEY_SHOW_KEYBOARD_IF_NEEDED = "show_key_board_if_needed";
|
||||
public static final String KEY_PATH = "path";
|
||||
public static final String KEY_OUTER_INFO = "outerInfo";
|
||||
public static final String KEY_OLDERUSER = "isOldUser";
|
||||
@ -83,6 +87,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_INVITE_SEARCH_KEY = "inviteSearchKey";
|
||||
public static final String KEY_MESSAGE_TYPE = "messageType";
|
||||
public static final String KEY_QUESTIONS_SEARCH_KEY = "questionsSearchKey";
|
||||
public static final String KEY_SHOW_COMMENT = "showComment";
|
||||
public static final String KEY_SHOW_ANSWER_COMMENT = "showAnswerComment";
|
||||
public static final String KEY_RECOMMENDS_CONTENTS = "isRecommendsContents";
|
||||
public static final String KEY_VERSION_UPDATE = "versionUpdate";
|
||||
@ -113,6 +118,13 @@ public class EntranceUtils {
|
||||
public static final String KEY_SKIP_GAME_COMMENT = "skipGameComment";
|
||||
public static final String KEY_OPEN_PLATFORM_WINDOW = "openPlatformWindow";
|
||||
public static final String KEY_OPEN_KEYBOARD = "openKeyboard";
|
||||
public static final String KEY_PATH_VIDEO = "pathVideo";
|
||||
public static final String KEY_VIDEO_ID = "videoId";
|
||||
public static final String KEY_DIRECT_COMMENT = "directComment";
|
||||
public static final String KEY_SORT = "sort";
|
||||
public static final String KEY_AMWAY = "amway";
|
||||
public static final String KEY_COLLECTION_ID = "collectionId";
|
||||
public static final String KEY_NAVIGATION_TITLE = "navigationTitle";
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
|
||||
@ -121,18 +133,15 @@ public class EntranceUtils {
|
||||
&& MainActivity.class.getName().equals(RunningUtils.getBaseActivity(context))) {
|
||||
// 应用正在运行,前台或后台
|
||||
String to = bundle.getString(KEY_TO);
|
||||
if (!TextUtils.isEmpty(to)) {
|
||||
Class<?> clazz = ClassUtils.forName(to);
|
||||
if (clazz != null) {
|
||||
if (NormalFragment.class.isAssignableFrom(clazz)) { // 兼容NormalFragment
|
||||
NormalActivity.startFragmentNewTask(context, (Class<? extends NormalFragment>) clazz, bundle);
|
||||
} else {
|
||||
Intent intent1 = new Intent(context, clazz);
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent1.putExtras(bundle);
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
}
|
||||
Class<?> clazz = ClassUtils.forName(to);
|
||||
if (clazz == null) clazz = MainActivity.class;
|
||||
if (NormalFragment.class.isAssignableFrom(clazz)) { // 兼容NormalFragment
|
||||
NormalActivity.startFragmentNewTask(context, (Class<? extends NormalFragment>) clazz, bundle);
|
||||
} else {
|
||||
Intent intent1 = new Intent(context, clazz);
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent1.putExtras(bundle);
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
} else {
|
||||
// 应用未在运行
|
||||
|
||||
@ -4,7 +4,6 @@ import android.content.Context
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.ErrorEntity
|
||||
import com.halo.assistant.fragment.WebFragment
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
/**
|
||||
@ -86,6 +85,7 @@ object ErrorHelper {
|
||||
403045,
|
||||
403054,
|
||||
403069,
|
||||
403071,
|
||||
403047 -> handleErrorWithCommunityBannedDialog(context, errorEntity)
|
||||
|
||||
403057,
|
||||
@ -109,6 +109,10 @@ object ErrorHelper {
|
||||
404001 -> Utils.toast(context, "请求的资源不存在")
|
||||
403016 -> Utils.toast(context, "标签内容可能包含敏感信息,请修改后再提交")
|
||||
403018 -> Utils.toast(context, R.string.comment_failed_unable)
|
||||
403070 -> Utils.toast(context, "请勿重复提交~")
|
||||
403073 -> Utils.toast(context, "标题可能包含敏感词,请修改后再提交")
|
||||
403074 -> Utils.toast(context, "该微信号(${errorEntity.data?.nickname})已绑定")
|
||||
403078 -> Utils.toast(context, "已点赞")
|
||||
|
||||
403020 -> if (showHighPriorityHint) {
|
||||
DialogUtils.showAlertDialog(context,
|
||||
@ -130,8 +134,8 @@ object ErrorHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleErrorWithCommentBannedDialog(context: Context, errorEntity: ErrorEntity) {
|
||||
val bannedType = if (errorEntity.data?.alwaysBlock!!) {
|
||||
private fun handleErrorWithCommentBannedDialog(context: Context, errorEntity: ErrorEntity?) {
|
||||
val bannedType = if (errorEntity?.data?.alwaysBlock == true) {
|
||||
""
|
||||
} else {
|
||||
"(非永久)"
|
||||
@ -146,7 +150,7 @@ object ErrorHelper {
|
||||
}
|
||||
|
||||
private fun handleErrorWithCommunityBannedDialog(context: Context, errorEntity: ErrorEntity) {
|
||||
val bannedType = if (errorEntity.data?.alwaysBlock!!) {
|
||||
val bannedType = if (errorEntity.data?.alwaysBlock == true) {
|
||||
""
|
||||
} else {
|
||||
"(非永久)"
|
||||
@ -154,7 +158,7 @@ object ErrorHelper {
|
||||
val dialogContext = DialogUtils.checkDialogContext(context)
|
||||
DialogUtils.showAlertDialog(dialogContext,
|
||||
"提示",
|
||||
"你因违反《问答版块规则》,已被禁言$bannedType,如有疑问,请联系客服(QQ:3467475980)",
|
||||
"你因违反《问答版块规则》,已被禁言$bannedType,如有疑问,请联系客服(QQ:1562479331)",
|
||||
"去看看", "关闭", {
|
||||
dialogContext.startActivity(WebActivity.getCommunityRuleIntent(dialogContext))
|
||||
}, null)
|
||||
|
||||
@ -2,15 +2,26 @@ package com.gh.common.util
|
||||
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.text.Editable
|
||||
import android.text.Html
|
||||
import android.text.Spanned
|
||||
import android.text.TextWatcher
|
||||
import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.*
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.HaloApp
|
||||
@ -18,6 +29,7 @@ import com.lightgame.utils.Utils
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import java.net.URI
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* 创建以 activity 为观察者上下文的 viewModel
|
||||
@ -67,6 +79,43 @@ fun ViewPager.addOnPageChangeListener(onSelected: ((position: Int) -> Unit)? = n
|
||||
addOnPageChangeListener(listener)
|
||||
}
|
||||
|
||||
fun ViewPager.addOnScrollStateChanged(onStateChanged: ((state: Int) -> Unit)? = null) {
|
||||
val listener = object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
onStateChanged?.invoke(state)
|
||||
}
|
||||
}
|
||||
addOnPageChangeListener(listener)
|
||||
}
|
||||
|
||||
/**
|
||||
* RecyclerView Extensions
|
||||
*/
|
||||
|
||||
// 监听滚动距离
|
||||
fun RecyclerView.doOnScrolledSpecificDistance(distanceX: Int = 0, distanceY: Int = 0, singleTimeEvent: Boolean = false, action: () -> Unit) {
|
||||
val listener = object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
|
||||
if ((distanceX != 0 && abs(dx) > distanceX) || (distanceY != 0 && abs(dy) > distanceY)) {
|
||||
action.invoke()
|
||||
if (singleTimeEvent) {
|
||||
removeOnScrollListener(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addOnScrollListener(listener)
|
||||
}
|
||||
|
||||
/**
|
||||
* View Extensions
|
||||
*/
|
||||
@ -86,6 +135,16 @@ fun View.goneIf(predicate: Boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
fun View.addSelectableItemBackground() {
|
||||
val outValue = TypedValue()
|
||||
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, outValue, true)
|
||||
setBackgroundResource(outValue.resourceId);
|
||||
}
|
||||
|
||||
fun View.removeSelectableItemBackground() {
|
||||
background = null
|
||||
}
|
||||
|
||||
/**
|
||||
* LiveData Extensions
|
||||
*/
|
||||
@ -161,16 +220,21 @@ inline fun tryWithDefaultCatch(action: (() -> Unit)) {
|
||||
* String related
|
||||
*/
|
||||
fun String.fromHtml(): Spanned {
|
||||
return Html.fromHtml(this)
|
||||
return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||
}
|
||||
|
||||
// 去掉文章/答案的插入内容
|
||||
fun String.removeInsertedContent(): String {
|
||||
val textRegex = "(?s)<div class=\"gh-internal-content content-right\".*?</div>"
|
||||
|
||||
return this.replace(textRegex.toRegex(), "")
|
||||
}
|
||||
|
||||
// 去除视频相关文本
|
||||
fun String.removeVideoContent(): String {
|
||||
val videoRegex = "(?s)<div class=\"insert-video-container\".*?</div>"
|
||||
return this.replace(videoRegex.toRegex(), "")
|
||||
}
|
||||
|
||||
// 完全地清除所有 Html 格式
|
||||
fun String.clearHtmlFormatCompletely(): String {
|
||||
return Html.fromHtml(this).toString().replace('\n', 32.toChar())
|
||||
@ -211,15 +275,23 @@ fun Float.dip2px(): Int {
|
||||
return (this * scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据手机的分辨率从 px(像素) 的单位 转成为 dip
|
||||
*/
|
||||
fun Float.px2dip(): Int {
|
||||
val scale = HaloApp.getInstance().application.resources.displayMetrics.density
|
||||
return (this / scale + 0.5f).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* PopupWindow 自动适配方向
|
||||
*/
|
||||
fun PopupWindow.showAutoOrientation(anchorView: View) {
|
||||
fun PopupWindow.showAutoOrientation(anchorView: View, distanceY: Int = 0) {
|
||||
val windowPos = IntArray(2)
|
||||
val anchorLoc = IntArray(2)
|
||||
// 获取锚点View在屏幕上的左上角坐标位置
|
||||
anchorView.getLocationOnScreen(anchorLoc)
|
||||
val anchorHeight = anchorView.height
|
||||
val anchorHeight = anchorView.height + distanceY
|
||||
// 获取屏幕的高宽
|
||||
val screenHeight = anchorView.context.resources.displayMetrics.heightPixels
|
||||
val screenWidth = anchorView.context.resources.displayMetrics.widthPixels
|
||||
@ -267,4 +339,96 @@ fun Fragment.checkStoragePermissionBeforeAction(action: (() -> Unit)) {
|
||||
action.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun FragmentActivity.checkReadPhoneStateAndStoragePermissionBeforeAction(action: (() -> Unit)) {
|
||||
PermissionHelper.checkReadPhoneStateAndStoragePermissionBeforeAction(this, object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
action.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun FragmentActivity.checkReadPhoneStatePermissionBeforeAction(action: (() -> Unit)) {
|
||||
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(this, object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
action.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun FragmentActivity.checkStoragePermissionBeforeAction(action: (() -> Unit)) {
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(this, object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
action.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* TextView related.
|
||||
*/
|
||||
fun TextView.setTextWithHighlightedTextWrappedInsideWrapper(text: CharSequence,
|
||||
wrapper: String = Constants.DEFAULT_TEXT_WRAPPER,
|
||||
@ColorRes
|
||||
highlightColorId: Int = R.color.theme,
|
||||
copyClickedText: Boolean = false,
|
||||
highlightedTextClickListener: (() -> Unit)? = null) {
|
||||
TextHelper.highlightTextThatIsWrappedInsideWrapper(this, text, wrapper, highlightColorId, object : SimpleCallback<String> {
|
||||
override fun onCallback(arg: String) {
|
||||
if (copyClickedText) {
|
||||
arg.copyTextAndToast("已复制:$arg")
|
||||
}
|
||||
highlightedTextClickListener?.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun TextView.setTextChangedListener(action: (s: CharSequence, start: Int, before: Int, count: Int) -> Unit) {
|
||||
this.addTextChangedListener(object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
||||
}
|
||||
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
action.invoke(s ?: "", start, before, count)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun Int.toColor(): Int {
|
||||
return HaloApp.getInstance().application.resources.getColor(this)
|
||||
}
|
||||
|
||||
fun Int.toResString(): String {
|
||||
return HaloApp.getInstance().application.resources.getString(this)
|
||||
}
|
||||
|
||||
fun Int.toSimpleCount(): String {
|
||||
return NumberUtils.transSimpleCount(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Image related
|
||||
*/
|
||||
fun SimpleDraweeView.display(url: String) {
|
||||
ImageUtils.display(this, url)
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试用包裹
|
||||
*/
|
||||
inline fun debugOnly(f: () -> Unit) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun testChannelOnly(f: () -> Unit) {
|
||||
if (HaloApp.getInstance().channel == Config.DEFAULT_CHANNEL) {
|
||||
f()
|
||||
}
|
||||
}
|
||||
@ -147,6 +147,7 @@ public class GameUtils {
|
||||
gameUpdateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
gameUpdateEntity.setBrief(gameEntity.getBrief());
|
||||
gameUpdateEntity.setPlugin(apkEntity.getPlugin());
|
||||
gameUpdateEntity.setDownload(gameEntity.getDownload());
|
||||
return gameUpdateEntity;
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,8 @@ import org.json.JSONObject
|
||||
|
||||
/**
|
||||
* 广点通辅助类 [https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/403]
|
||||
*
|
||||
* 更换帐号 [https://gitlab.ghzs.com/pm/yunying/issues/893]
|
||||
*/
|
||||
object GdtHelper {
|
||||
|
||||
@ -21,7 +23,7 @@ object GdtHelper {
|
||||
const val PLATFORM = "PLATFORM"
|
||||
|
||||
fun init(application: Application) {
|
||||
GDTAction.init(application, "1108222478", "0b2bb2b971c8221be45a8454f05a0b1f")
|
||||
GDTAction.init(application, "1110071928", "7fe03caa04ed382e9dce401312b1d0ae")
|
||||
}
|
||||
|
||||
fun logAction(type: String) {
|
||||
|
||||
@ -1,303 +0,0 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.user.LoginTag;
|
||||
import com.lightgame.utils.RuntimeUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.sina.weibo.sdk.WbSdk;
|
||||
import com.sina.weibo.sdk.auth.AuthInfo;
|
||||
import com.sina.weibo.sdk.auth.Oauth2AccessToken;
|
||||
import com.sina.weibo.sdk.auth.WbAuthListener;
|
||||
import com.sina.weibo.sdk.auth.WbConnectErrorMessage;
|
||||
import com.sina.weibo.sdk.auth.sso.SsoHandler;
|
||||
import com.tencent.mm.opensdk.modelmsg.SendAuth;
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI;
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
|
||||
import com.tencent.tauth.IUiListener;
|
||||
import com.tencent.tauth.Tencent;
|
||||
import com.tencent.tauth.UiError;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* Created by khy on 14/06/17.
|
||||
* <p>
|
||||
* 获取第三方登录数据
|
||||
*/
|
||||
|
||||
public class GetLoginDataUtils {
|
||||
|
||||
private static GetLoginDataUtils instance;
|
||||
|
||||
private Context mContext;
|
||||
private OnLoginDataListener mLoginListener; //登录成功回调
|
||||
|
||||
private Tencent mTencent;
|
||||
private IWXAPI mIWXAPI;
|
||||
private SsoHandler mSsoHandler;
|
||||
|
||||
private Oauth2AccessToken mAccessToken; // weibo
|
||||
public static final String SCOPE =
|
||||
"email,direct_messages_read,direct_messages_write,"
|
||||
+ "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"
|
||||
+ "follow_app_official_microblog," + "invitation_write"; // weiboCode
|
||||
|
||||
private GetLoginDataUtils(Context context) {
|
||||
mContext = context;
|
||||
mTencent = Tencent.createInstance(Config.TENCENT_APPID, mContext); //初始化QQ分享
|
||||
|
||||
mIWXAPI = WXAPIFactory.createWXAPI(mContext, Config.WECHAT_APPID, true); //初始化微信分享
|
||||
|
||||
WbSdk.install(context, new AuthInfo(mContext, Config.WEIBO_APPKEY, "http://www.sina.com", SCOPE));
|
||||
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "initLogin");
|
||||
}
|
||||
|
||||
public static GetLoginDataUtils getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
instance = new GetLoginDataUtils(context.getApplicationContext());
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
//QQ登录回调处理
|
||||
public IUiListener QqLoginListener = new IUiListener() {
|
||||
@Override
|
||||
public void onComplete(Object o) {
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQ 登录成功");
|
||||
if (o instanceof JSONObject) {
|
||||
JSONObject jsonObject = (JSONObject) o;
|
||||
String s = jsonObject.toString();
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQLoginComplete::" + s);
|
||||
try {
|
||||
mTencent.setOpenId(jsonObject.getString("openid"));
|
||||
mTencent.setAccessToken(jsonObject.getString("access_token"), jsonObject.getString("expires_in"));
|
||||
|
||||
JSONObject content = new JSONObject();
|
||||
content.put("openid", jsonObject.getString("openid"));
|
||||
content.put("access_token_expire", Utils.getTime(mContext) + jsonObject.getLong("expires_in"));
|
||||
content.put("access_token", jsonObject.getString("access_token"));
|
||||
if (mLoginListener != null) {
|
||||
mLoginListener.OnLoginData(content, LoginTag.qq);// QQ 登录回调
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQ登录数据回调异常::" + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// QQToken qqToken = mTencent.getQQToken();
|
||||
// UserInfo userInfo = new UserInfo(mContext, qqToken);
|
||||
// userInfo.getUserInfo(new IUiListener() { // 获取QQ用户信息
|
||||
// @Override
|
||||
// public void onComplete(Object o) {
|
||||
// Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQUserInfo::" + o.toString());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onError(UiError uiError) {
|
||||
// Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQUserInfoUiError::" + uiError.errorDetail + "==" + uiError.errorMessage + "==" + uiError.errorCode);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onCancel() {
|
||||
// Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQUserInfoonCancel");
|
||||
// }
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(UiError uiError) {
|
||||
Utils.toast(mContext, "登录失败");
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQ 登录失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
Utils.toast(mContext, "登录取消");
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQ 登录取消");
|
||||
}
|
||||
};
|
||||
|
||||
public void onQQCallback(int requestCode, int resultCode, Intent data) {
|
||||
Tencent.onActivityResultData(requestCode, resultCode, data, QqLoginListener);
|
||||
}
|
||||
|
||||
// QQ登录
|
||||
public void QQLogin(OnLoginDataListener listener, Activity activity) {
|
||||
mLoginListener = listener;
|
||||
if (mTencent != null && !mTencent.isSessionValid()) {
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "QQLogin");
|
||||
mTencent.login(activity, "all", QqLoginListener);
|
||||
}
|
||||
}
|
||||
|
||||
public void QQLogout() {
|
||||
if (mTencent != null && mTencent.isSessionValid()) {
|
||||
mTencent.logout(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 微信登录
|
||||
public void WCLogin(OnLoginDataListener listener) {
|
||||
mLoginListener = listener;
|
||||
if (mIWXAPI != null) {
|
||||
boolean register = mIWXAPI.registerApp(Config.WECHAT_APPID);
|
||||
|
||||
SendAuth.Req req = new SendAuth.Req();
|
||||
req.scope = "snsapi_userinfo";
|
||||
req.state = mContext.getString(R.string.app_name);
|
||||
boolean b = mIWXAPI.sendReq(req);
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "微信注册状态::" + register + "\n 发送状态::" + b);
|
||||
if (!register || !b) {
|
||||
Utils.toast(mContext, "请检查是否安装微信客户端");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WCLoginCallBack(JSONObject content) {
|
||||
if (mLoginListener != null) {
|
||||
mLoginListener.OnLoginData(content, LoginTag.wechat);
|
||||
}
|
||||
}
|
||||
|
||||
public void onWeiboCallback(int requestCode, int resultCode, Intent data) {
|
||||
if (mSsoHandler != null) {
|
||||
mSsoHandler.authorizeCallBack(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
// 微博登录
|
||||
public void WeiBoLogin(OnLoginDataListener listener, Activity context) {
|
||||
mSsoHandler = new SsoHandler(context);
|
||||
mLoginListener = listener;
|
||||
mSsoHandler.authorizeClientSso(new SelfWbAuthListener());
|
||||
// 第一次启动本应用,AccessToken 不可用
|
||||
mAccessToken = AccessTokenKeeper.readAccessToken(mContext);
|
||||
|
||||
// if (mAccessToken.isSessionValid()) {
|
||||
// updateTokenView(true);
|
||||
// }
|
||||
}
|
||||
|
||||
// 微博登录回调处理
|
||||
private class SelfWbAuthListener implements WbAuthListener {
|
||||
|
||||
@Override
|
||||
public void onSuccess(final Oauth2AccessToken token) {
|
||||
RuntimeUtils.getInstance().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mAccessToken = token;
|
||||
if (mAccessToken.isSessionValid()) {
|
||||
// 显示 Token
|
||||
// updateTokenView(false);
|
||||
// 保存 Token 到 SharedPreferences
|
||||
AccessTokenKeeper.writeAccessToken(mContext, mAccessToken);
|
||||
Toast.makeText(mContext, "授权成功", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JSONObject content = new JSONObject();
|
||||
try {
|
||||
content.put("uid", token.getUid());
|
||||
content.put("access_token", token.getToken());
|
||||
content.put("access_token_expire", Utils.getTime(mContext) + token.getExpiresTime());
|
||||
content.put("refresh_token", token.getRefreshToken());
|
||||
// content.put("refresh_token_expire", Utils.getTime(mContext) + 86400 * 30); // refresh_token 有效期30天
|
||||
if (mLoginListener != null) {
|
||||
mLoginListener.OnLoginData(content, LoginTag.weibo);// 微博 登录回调
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// AppController.MAIN_EXECUTOR.execute(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// getWeiBoUserInfo(token.getToken(), token.getUid());
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
Utils.toast(mContext, "取消授权");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(WbConnectErrorMessage errorMessage) {
|
||||
Utils.toast(mContext, "微博登录需要客户端支持,请先安装微博");
|
||||
}
|
||||
}
|
||||
|
||||
//微博 获取用户信息
|
||||
private void getWeiBoUserInfo(String accessToken, String uid) {
|
||||
String path = "https://api.weibo.com/2/users/show.json?access_token=" + accessToken + "&uid=" + uid;
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "getWeiBoUserInfo-url::" + path);
|
||||
|
||||
try {
|
||||
URL url = new URL(path);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setDoInput(true);
|
||||
int code = conn.getResponseCode();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "getWeiBoUserInfo-RequestCode::" + code);
|
||||
if (code == 200) {
|
||||
InputStream is = conn.getInputStream();
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, len);
|
||||
}
|
||||
String str = new String(baos.toByteArray());
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "getWeiBoUserInfo-Body::" + str);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 微博显示当前 Token 信息。
|
||||
*
|
||||
* @param hasExisted 配置文件中是否已存在 token 信息并且合法
|
||||
*/
|
||||
private void updateTokenView(boolean hasExisted) {
|
||||
String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(
|
||||
new java.util.Date(mAccessToken.getExpiresTime()));
|
||||
String format = "Token:%1$s \\n有效期:%2$s";
|
||||
String token = String.format(format, mAccessToken.getToken(), date);
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "::WB_TOKEN::" + token);
|
||||
String message = String.format(format, mAccessToken.getToken(), date);
|
||||
if (hasExisted) {
|
||||
message = "Token 仍在有效期内,无需再次登录。" + "\n" + message;
|
||||
}
|
||||
Utils.log(GetLoginDataUtils.class.getSimpleName(), "::WB_MESSAGE::" + message);
|
||||
}
|
||||
|
||||
// 登录成功回调
|
||||
public interface OnLoginDataListener {
|
||||
void OnLoginData(JSONObject content, LoginTag loginTag);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import com.lightgame.utils.Utils
|
||||
import com.zhihu.matisse.filter.ApplyFilter
|
||||
import com.zhihu.matisse.internal.entity.Item
|
||||
|
||||
class GhMatisseVideoApplyFilter : ApplyFilter() {
|
||||
|
||||
override fun applyFiltering(context: Context, itemList: MutableList<Item>, callBack: OnApplyFilterCallBack) {
|
||||
if (!NetworkUtils.isNetworkConnected(context)) {
|
||||
Utils.toast(context, "网络异常,请检查手机网络状态")
|
||||
} else if (!NetworkUtils.isWifiConnected(context)) {
|
||||
DialogUtils.showAlertDialog(context, "提示",
|
||||
"您当前正在使用移动网络上传视频,确定继续上传吗?",
|
||||
"继续上传", "暂时不了",
|
||||
DialogUtils.ConfirmListener { callBack.onApply() }, null)
|
||||
} else {
|
||||
callBack.onApply()
|
||||
}
|
||||
}
|
||||
}
|
||||
27
app/src/main/java/com/gh/common/util/GhMatisseVideoFilter.kt
Normal file
27
app/src/main/java/com/gh/common/util/GhMatisseVideoFilter.kt
Normal file
@ -0,0 +1,27 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import com.zhihu.matisse.MimeType
|
||||
import com.zhihu.matisse.filter.Filter
|
||||
import com.zhihu.matisse.internal.entity.IncapableCause
|
||||
import com.zhihu.matisse.internal.entity.Item
|
||||
|
||||
class GhMatisseVideoFilter : Filter() {
|
||||
|
||||
override fun constraintTypes(): MutableSet<MimeType> {
|
||||
return MimeType.ofVideo()
|
||||
}
|
||||
|
||||
override fun filter(context: Context, item: Item): IncapableCause? {
|
||||
if (!needFiltering(context, item)) return null
|
||||
if (item.mimeType != MimeType.MP4.toString()) {
|
||||
return IncapableCause(IncapableCause.TOAST, "请把视频格式转换为Mp4后再上传")
|
||||
}
|
||||
|
||||
if (item.size > 500 * 1024 * 1024) {
|
||||
return IncapableCause(IncapableCause.TOAST, "视频大小限制为500M")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import org.json.JSONArray
|
||||
|
||||
|
||||
/**
|
||||
@ -14,11 +16,11 @@ object GsonUtils {
|
||||
return gson.fromJson(json, t)
|
||||
}
|
||||
|
||||
// @JvmStatic
|
||||
// fun <T> fromJsonList(json: String): List<T> {
|
||||
// val type = object : TypeToken<List<T>>() {}.type
|
||||
// return gson.fromJson(json, type)
|
||||
// }
|
||||
@JvmStatic
|
||||
fun <T> fromJsonList(json: JSONArray): List<T> {
|
||||
val type = object : TypeToken<List<T>>() {}.type
|
||||
return gson.fromJson(json.toString(), type)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun toJson(any: Any?): String {
|
||||
|
||||
33
app/src/main/java/com/gh/common/util/HomeBottomBarHelper.kt
Normal file
33
app/src/main/java/com/gh/common/util/HomeBottomBarHelper.kt
Normal file
@ -0,0 +1,33 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.gh.gamecenter.entity.Display
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
|
||||
object HomeBottomBarHelper {
|
||||
private const val GAME_BAR_KEY = "game_bar_key"
|
||||
|
||||
@JvmStatic
|
||||
fun getDefaultGameBarData(): SubjectRecommendEntity {
|
||||
try {
|
||||
val json = SPUtils.getString(GAME_BAR_KEY)
|
||||
if (json.isNotEmpty()) {
|
||||
return GsonUtils.fromJson(json, SubjectRecommendEntity::class.java)
|
||||
}
|
||||
} catch (ignore: Exception) {
|
||||
|
||||
}
|
||||
return SubjectRecommendEntity(link = "5de21b5d75e6fa054f784882",
|
||||
type = "block",
|
||||
text = "游戏库",
|
||||
name = "游戏库",
|
||||
iconSelect = "https://resource.ghzs.com/image/game/library/entrance/5de3a2ac2ab874001c5ff0e9.png",
|
||||
iconUnselect = "https://resource.ghzs.com/image/game/library/entrance/5de3a2b16b6b89001d48e779.png",
|
||||
default = false,
|
||||
display = Display())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun updateDefaultGameBarData(data: SubjectRecommendEntity) {
|
||||
SPUtils.setString(GAME_BAR_KEY, data.toJson())
|
||||
}
|
||||
}
|
||||
@ -23,13 +23,8 @@ import org.json.JSONObject;
|
||||
* Created by khy on 2/01/18.
|
||||
*/
|
||||
public class LogUtils {
|
||||
|
||||
public static void uploadCommunityArticle(String tracers,
|
||||
String articleId,
|
||||
String articleTitle,
|
||||
int readTime,
|
||||
CommunityEntity community,
|
||||
SpecialColumn specialColumn) {
|
||||
|
||||
public static void uploadCommunityArticle(String tracers, String articleId, String articleTitle, int readTime, CommunityEntity community, SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("subject", "community_article");
|
||||
@ -53,10 +48,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
upload(object);
|
||||
}
|
||||
|
||||
|
||||
public static void uploadDevice(LunchType launchType) {
|
||||
JSONObject object = new JSONObject();
|
||||
Application application = HaloApp.getInstance().getApplication();
|
||||
@ -68,17 +63,11 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
upload(object);
|
||||
}
|
||||
|
||||
public static void uploadAnswerReadTime(String tracers,
|
||||
int readTime,
|
||||
String answerId,
|
||||
Questions questions,
|
||||
String communityId,
|
||||
String CommunityName,
|
||||
SpecialColumn specialColumn) {
|
||||
|
||||
public static void uploadAnswerReadTime(String tracers, int readTime, String answerId, Questions questions, String communityId, String CommunityName, SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("subject", "answer");
|
||||
@ -103,16 +92,11 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
upload(object);
|
||||
}
|
||||
|
||||
public static void uploadQuestionReadTime(String tracers,
|
||||
int readTime,
|
||||
Questions questions,
|
||||
String communityId,
|
||||
String communityName,
|
||||
SpecialColumn specialColumn) {
|
||||
|
||||
public static void uploadQuestionReadTime(String tracers, int readTime, Questions questions, String communityId, String communityName, SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("subject", "question");
|
||||
@ -136,13 +120,13 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
upload(object);
|
||||
}
|
||||
|
||||
|
||||
public static void uploadSearch(String searchKey) {
|
||||
if (TextUtils.isEmpty(searchKey)) return;
|
||||
|
||||
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("community_id", UserManager.getInstance().getCommunity().getId());
|
||||
@ -152,11 +136,11 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
upload(object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static void communityRefresh(int dataCount, boolean manualRefresh) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -168,10 +152,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
upload(object);
|
||||
}
|
||||
|
||||
|
||||
public static void login(String loginStep, String loginType, String entrance) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -182,15 +166,29 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
upload(object);
|
||||
}
|
||||
|
||||
|
||||
public static void qaAccess(String access, CommunityEntity communityEntity) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("subject", "qa_access");
|
||||
object.put("access", access);
|
||||
object.put("community_id", communityEntity.getId());
|
||||
object.put("community_name", communityEntity.getName());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
}
|
||||
|
||||
private static void upload(JSONObject object) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->" + object.toString());
|
||||
}
|
||||
|
||||
|
||||
Context context = HaloApp.getInstance().getApplication();
|
||||
try {
|
||||
object.put("version", PackageUtils.getVersionName());
|
||||
@ -201,12 +199,13 @@ public class LogUtils {
|
||||
object.put("user_id", UserManager.getInstance().getUserId());
|
||||
object.put("device_system", android.os.Build.VERSION.RELEASE);
|
||||
object.put("device_model", android.os.Build.MODEL);
|
||||
object.put("imei", Util_System_Phone_State.getImei(HaloApp.getInstance().getApplication()));
|
||||
object.put("imei", Util_System_Phone_State.getImei(HaloApp.getInstance()
|
||||
.getApplication()));
|
||||
object.put("G_ID", UserManager.getInstance().getDeviceId());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
// 暂时除了曝光外的数据都是扔到 community 这个库的,要是不是这个这个库的话这里要改一下
|
||||
LogHubUtils.uploadLog(DeviceUtils.getIPAddress(context), object, "community");
|
||||
}
|
||||
|
||||
196
app/src/main/java/com/gh/common/util/LoginHelper.kt
Normal file
196
app/src/main/java/com/gh/common/util/LoginHelper.kt
Normal file
@ -0,0 +1,196 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.widget.Toast
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.user.LoginTag
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.RuntimeUtils
|
||||
import com.lightgame.utils.Utils
|
||||
import com.sina.weibo.sdk.WbSdk
|
||||
import com.sina.weibo.sdk.auth.AuthInfo
|
||||
import com.sina.weibo.sdk.auth.Oauth2AccessToken
|
||||
import com.sina.weibo.sdk.auth.WbAuthListener
|
||||
import com.sina.weibo.sdk.auth.WbConnectErrorMessage
|
||||
import com.sina.weibo.sdk.auth.sso.SsoHandler
|
||||
import com.tencent.mm.opensdk.modelmsg.SendAuth
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory
|
||||
import com.tencent.tauth.IUiListener
|
||||
import com.tencent.tauth.Tencent
|
||||
import com.tencent.tauth.UiError
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
||||
|
||||
/**
|
||||
* 第三方登录辅助类
|
||||
*/
|
||||
object LoginHelper {
|
||||
|
||||
const val WEIBO_SCOPE = (
|
||||
"email,direct_messages_read,direct_messages_write,"
|
||||
+ "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"
|
||||
+ "follow_app_official_microblog," + "invitation_write") // weiboCode
|
||||
|
||||
private var mTencent: Tencent // QQ
|
||||
private var mIWXAPI: IWXAPI // 微信
|
||||
private var mSsoHandler: SsoHandler? = null // 微博 // TODO 完成回调时清掉这个 handler ?
|
||||
|
||||
private var mQqLoginListener: IUiListener
|
||||
|
||||
private var mAccessToken: Oauth2AccessToken? = null // weibo
|
||||
private var mLoginCallback: LoginCallback? = null
|
||||
|
||||
init {
|
||||
val context = HaloApp.getInstance().application.applicationContext
|
||||
mTencent = Tencent.createInstance(Config.TENCENT_APPID, context) //初始化QQ分享
|
||||
mIWXAPI = WXAPIFactory.createWXAPI(context, Config.WECHAT_APPID, true) //初始化微信分享
|
||||
|
||||
mQqLoginListener = object : IUiListener {
|
||||
override fun onComplete(o: Any?) {
|
||||
Utils.log("QQ 登录成功")
|
||||
if (o is JSONObject) {
|
||||
val s = o.toString()
|
||||
Utils.log("QQLoginComplete::$s")
|
||||
try {
|
||||
mTencent.openId = o.getString("openid")
|
||||
mTencent.setAccessToken(o.getString("access_token"), o.getString("expires_in"))
|
||||
|
||||
val content = JSONObject()
|
||||
content.put("openid", o.getString("openid"))
|
||||
content.put("access_token_expire", Utils.getTime(context) + o.getLong("expires_in"))
|
||||
content.put("access_token", o.getString("access_token"))
|
||||
|
||||
mLoginCallback?.onLoginSuccess(LoginTag.qq, content) // 回调QQ登录成功
|
||||
} catch (e: JSONException) {
|
||||
val errorString = "QQ登录数据回调异常::$e"
|
||||
|
||||
mLoginCallback?.onLoginFailure(LoginTag.qq, errorString) // 回调QQ登录失败
|
||||
|
||||
Utils.log(errorString)
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCancel() {
|
||||
mLoginCallback?.onLoginFailure(LoginTag.qq,"登录取消")
|
||||
Utils.log("QQ 登录取消")
|
||||
}
|
||||
|
||||
override fun onError(p0: UiError?) {
|
||||
mLoginCallback?.onLoginFailure(LoginTag.qq,"登录失败")
|
||||
Utils.log("QQ 登录失败")
|
||||
}
|
||||
}
|
||||
|
||||
WbSdk.install(context, AuthInfo(context, Config.WEIBO_APPKEY, "http://www.sina.com", WEIBO_SCOPE))
|
||||
|
||||
Utils.log("LoginHelper initialization")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onQQLoginCallback(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
Tencent.onActivityResultData(requestCode, resultCode, data, mQqLoginListener);
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onWechatLoginSuccess(content: JSONObject) {
|
||||
mLoginCallback?.onLoginSuccess(LoginTag.wechat, content)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onWechatLoginFailure(error: String) {
|
||||
mLoginCallback?.onLoginFailure(LoginTag.wechat, error)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onWeiboLoginCallback(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
mSsoHandler?.authorizeCallBack(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
// QQ登录
|
||||
@JvmStatic
|
||||
fun loginWithQQ(loginCallback: LoginCallback, activity: Activity) {
|
||||
mLoginCallback = loginCallback
|
||||
if (!mTencent.isSessionValid) {
|
||||
Utils.log("QQLogin")
|
||||
mTencent.login(activity, "all", mQqLoginListener)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logoutWithQQ() {
|
||||
if (mTencent.isSessionValid) {
|
||||
mTencent.logout(HaloApp.getInstance().application.applicationContext)
|
||||
}
|
||||
}
|
||||
|
||||
// 微信登录
|
||||
@JvmStatic
|
||||
fun loginWithWechat(loginCallback: LoginCallback) {
|
||||
mLoginCallback = loginCallback
|
||||
val register = mIWXAPI.registerApp(Config.WECHAT_APPID)
|
||||
|
||||
val req = SendAuth.Req()
|
||||
req.scope = "snsapi_userinfo"
|
||||
req.state = HaloApp.getInstance().application.getString(R.string.app_name)
|
||||
val b = mIWXAPI.sendReq(req)
|
||||
Utils.log("微信注册状态::$register\n 发送状态::$b")
|
||||
if (!register || !b) {
|
||||
loginCallback.onLoginFailure(LoginTag.wechat, "请检查是否安装微信客户端")
|
||||
Utils.toast(HaloApp.getInstance().application, "请检查是否安装微信客户端")
|
||||
}
|
||||
}
|
||||
|
||||
// 微博登录
|
||||
@JvmStatic
|
||||
fun loginWithWeibo(loginCallback: LoginCallback, context: Activity) {
|
||||
mLoginCallback = loginCallback
|
||||
mSsoHandler = SsoHandler(context)
|
||||
mSsoHandler?.authorizeClientSso(object : WbAuthListener {
|
||||
override fun onSuccess(token: Oauth2AccessToken?) {
|
||||
token?.let {
|
||||
RuntimeUtils.getInstance().runOnUiThread {
|
||||
mAccessToken = token
|
||||
if (mAccessToken?.isSessionValid == true) {
|
||||
// 保存 Token 到 SharedPreferences
|
||||
AccessTokenKeeper.writeAccessToken(context, mAccessToken)
|
||||
Toast.makeText(context, "授权成功", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
val content = JSONObject()
|
||||
tryWithDefaultCatch {
|
||||
content.put("uid", token.uid)
|
||||
content.put("access_token", token.token)
|
||||
content.put("access_token_expire", Utils.getTime(context) + token.expiresTime)
|
||||
content.put("refresh_token", token.refreshToken)
|
||||
// content.put("refresh_token_expire", Utils.getTime(mContext) + 86400 * 30); // refresh_token 有效期30天
|
||||
mLoginCallback?.onLoginSuccess(LoginTag.weibo, content)// 微博 登录回调
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(p0: WbConnectErrorMessage?) {
|
||||
mLoginCallback?.onLoginFailure(LoginTag.weibo, "微博登录需要客户端支持,请先安装微博")
|
||||
}
|
||||
|
||||
override fun cancel() {
|
||||
mLoginCallback?.onLoginFailure(LoginTag.weibo, "取消授权")
|
||||
}
|
||||
})
|
||||
// 第一次启动本应用,AccessToken 不可用
|
||||
mAccessToken = AccessTokenKeeper.readAccessToken(context)
|
||||
}
|
||||
|
||||
interface LoginCallback {
|
||||
fun onLoginSuccess(loginType: LoginTag, jsonContent: JSONObject)
|
||||
|
||||
fun onLoginFailure(loginType: LoginTag, error: String)
|
||||
}
|
||||
|
||||
}
|
||||
@ -16,8 +16,10 @@ object MtaHelper {
|
||||
val prop = Properties()
|
||||
|
||||
if (kv.size == 1) {
|
||||
prop.setProperty(kv[0], "")
|
||||
prop.setProperty(kv[0], kv[0])
|
||||
StatService.trackCustomKVEvent(HaloApp.getInstance().application, eventId, prop)
|
||||
Utils.log("MTA","$eventId + [${kv.joinToString(" , ")}]")
|
||||
return
|
||||
}
|
||||
|
||||
for (i in kv.indices) {
|
||||
@ -47,6 +49,10 @@ object MtaHelper {
|
||||
}
|
||||
}
|
||||
|
||||
if (prop.size == 0 && kv.size == 1) {
|
||||
prop.setProperty(kv[0], kv[0])
|
||||
}
|
||||
|
||||
if (prop.size == 0) return
|
||||
Utils.log("MTA","$eventId + [${kv.joinToString(" , ")}] + last $time seconds")
|
||||
StatService.trackCustomKVTimeIntervalEvent(HaloApp.getInstance().application, time, eventId, prop)
|
||||
|
||||
@ -67,12 +67,9 @@ public class NetworkUtils {
|
||||
*/
|
||||
public static boolean isMobileConnected(Context context) {
|
||||
if (context != null) {
|
||||
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo mMobileNetworkInfo = mConnectivityManager
|
||||
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
|
||||
if (mMobileNetworkInfo != null) {
|
||||
return mMobileNetworkInfo.isAvailable();
|
||||
if (isNetworkConnected(context)) {
|
||||
String network = DeviceUtils.getNetwork(context);
|
||||
return !"WIFI".equals(network);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -127,41 +124,31 @@ public class NetworkUtils {
|
||||
* @return 当前移动网络连接的类型信息
|
||||
*/
|
||||
public static String getMobileNetworkType(Context context) {
|
||||
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
|
||||
|
||||
if (info == null) return "unknown";
|
||||
|
||||
switch (info.getType()) {
|
||||
// Unknown
|
||||
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
|
||||
return "unknown";
|
||||
// Cellular Data–2G
|
||||
case TelephonyManager.NETWORK_TYPE_EDGE:
|
||||
TelephonyManager mTelephonyManager = (TelephonyManager)
|
||||
context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
int networkType = mTelephonyManager.getNetworkType();
|
||||
switch (networkType) {
|
||||
case TelephonyManager.NETWORK_TYPE_GPRS:
|
||||
case TelephonyManager.NETWORK_TYPE_EDGE:
|
||||
case TelephonyManager.NETWORK_TYPE_CDMA:
|
||||
case TelephonyManager.NETWORK_TYPE_IDEN:
|
||||
case TelephonyManager.NETWORK_TYPE_1xRTT:
|
||||
case TelephonyManager.NETWORK_TYPE_IDEN:
|
||||
return "2G";
|
||||
// Cellular Data–3G
|
||||
case TelephonyManager.NETWORK_TYPE_UMTS:
|
||||
case TelephonyManager.NETWORK_TYPE_HSDPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPAP:
|
||||
case TelephonyManager.NETWORK_TYPE_HSUPA:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_0:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_A:
|
||||
case TelephonyManager.NETWORK_TYPE_HSDPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSUPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPA:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_B:
|
||||
case TelephonyManager.NETWORK_TYPE_EHRPD:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPAP:
|
||||
return "3G";
|
||||
// Cellular Data–4G
|
||||
case TelephonyManager.NETWORK_TYPE_LTE:
|
||||
return "4G";
|
||||
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
29
app/src/main/java/com/gh/common/util/NotificationHelper.kt
Normal file
29
app/src/main/java/com/gh/common/util/NotificationHelper.kt
Normal file
@ -0,0 +1,29 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.dialog.NotificationHintDialogFragment
|
||||
import com.gh.gamecenter.entity.NotificationHint
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
object NotificationHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun showEnableNotificationDialogIfItsDisabled(activity: AppCompatActivity, notificationHint: NotificationHint) {
|
||||
if (notificationIsEnable()) {
|
||||
Utils.log("notification is enable")
|
||||
} else {
|
||||
NotificationHintDialogFragment.getInstance(notificationHint).show(activity.supportFragmentManager, "notification")
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_HINT, true)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun notificationIsEnable(): Boolean {
|
||||
val manager = NotificationManagerCompat.from(HaloApp.getInstance().application)
|
||||
return manager.areNotificationsEnabled()
|
||||
}
|
||||
|
||||
}
|
||||
@ -7,9 +7,9 @@ object NumberUtils {
|
||||
@JvmStatic
|
||||
fun transSimpleCount(count: Int): String {
|
||||
val s: String
|
||||
s = if (count > 100000) {
|
||||
s = if (count > 10000) {
|
||||
val number = count / 10000f
|
||||
val fmt = DecimalFormat("#")
|
||||
val fmt = DecimalFormat("#.0")
|
||||
fmt.format(number) + "万"
|
||||
} else {
|
||||
count.toString()
|
||||
|
||||
@ -72,6 +72,7 @@ public class PackageUtils {
|
||||
updateEntity.setBrief(gameEntity.getBrief());
|
||||
updateEntity.setTag(gameEntity.getTag());
|
||||
updateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
updateEntity.setDownload(gameEntity.getDownload());
|
||||
updateList.add(updateEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,51 +2,96 @@ package com.gh.common.util
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.tbruyelle.rxpermissions2.RxPermissions
|
||||
|
||||
object PermissionHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun requestReadPhoneStateAndStoragePermissionFromStartUp(context: Context) {
|
||||
if (context is FragmentActivity) {
|
||||
val rxPermission = RxPermissions(context)
|
||||
|
||||
var requestCount = 0
|
||||
val permissionsStatusMap = hashMapOf<String, Boolean>()
|
||||
permissionsStatusMap[Manifest.permission.READ_PHONE_STATE] = false
|
||||
permissionsStatusMap[Manifest.permission.READ_EXTERNAL_STORAGE] = false
|
||||
permissionsStatusMap[Manifest.permission.WRITE_EXTERNAL_STORAGE] = false
|
||||
|
||||
tryWithDefaultCatch {
|
||||
rxPermission
|
||||
.requestEach(Manifest.permission.READ_PHONE_STATE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.subscribe { permission ->
|
||||
requestCount++
|
||||
permissionsStatusMap[permission.name] = permission.granted
|
||||
|
||||
if (requestCount == 2) {
|
||||
val hasReadPhoneStatePermission = permissionsStatusMap[Manifest.permission.READ_PHONE_STATE] == true
|
||||
val hasReadStoragePermission = permissionsStatusMap[Manifest.permission.READ_EXTERNAL_STORAGE] == true
|
||||
|
||||
if (hasReadPhoneStatePermission && hasReadStoragePermission) {
|
||||
MtaHelper.onEvent("授权情况", "启动授权", "都授权")
|
||||
} else if (!hasReadPhoneStatePermission && !hasReadStoragePermission) {
|
||||
MtaHelper.onEvent("授权情况", "启动授权", "都不授权")
|
||||
} else if (hasReadPhoneStatePermission) {
|
||||
MtaHelper.onEvent("授权情况", "启动授权", "只授权IMEI")
|
||||
} else if (hasReadStoragePermission) {
|
||||
MtaHelper.onEvent("授权情况", "启动授权", "只授权存储")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun checkStoragePermissionBeforeAction(context: Context, emptyCallback: EmptyCallback) {
|
||||
if (context is FragmentActivity) {
|
||||
val rxPermission = RxPermissions(context)
|
||||
rxPermission
|
||||
.requestEachCombined(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.subscribe { permission ->
|
||||
when {
|
||||
permission.granted -> {
|
||||
emptyCallback.onCallback()
|
||||
}
|
||||
permission.shouldShowRequestPermissionRationale -> {
|
||||
DialogUtils.showPermissionDialog(context,
|
||||
"权限申请",
|
||||
"光环助手需要存储权限,以保证能正常使用相关功能",
|
||||
"重试",
|
||||
"放弃",
|
||||
{ checkStoragePermissionBeforeAction(context, emptyCallback) },
|
||||
null)
|
||||
}
|
||||
else -> {
|
||||
DialogUtils.showPermissionDialog(context,
|
||||
"权限申请",
|
||||
"在设置-应用-光环助手-权限中开启存储权限,以保证能正常使用相关功能",
|
||||
"去设置",
|
||||
"放弃",
|
||||
{
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intent.data = Uri.parse("package:" + context.getPackageName())
|
||||
context.startActivity(intent)
|
||||
},
|
||||
null)
|
||||
|
||||
tryWithDefaultCatch {
|
||||
rxPermission
|
||||
.requestEachCombined(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.subscribe { permission ->
|
||||
when {
|
||||
permission.granted -> {
|
||||
emptyCallback.onCallback()
|
||||
}
|
||||
permission.shouldShowRequestPermissionRationale -> {
|
||||
DialogUtils.showPermissionDialog(context,
|
||||
"权限申请",
|
||||
"光环助手需要存储权限,以保证能正常使用相关功能",
|
||||
"重试",
|
||||
"放弃",
|
||||
{ checkStoragePermissionBeforeAction(context, emptyCallback) },
|
||||
null)
|
||||
}
|
||||
else -> {
|
||||
DialogUtils.showPermissionDialog(context,
|
||||
"权限申请",
|
||||
"在设置-应用-光环助手-权限中开启存储权限,以保证能正常使用相关功能",
|
||||
"去设置",
|
||||
"放弃",
|
||||
{
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intent.data = Uri.parse("package:" + context.getPackageName())
|
||||
context.startActivity(intent)
|
||||
},
|
||||
null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,36 +100,39 @@ object PermissionHelper {
|
||||
fun checkReadPhoneStateAndStoragePermissionBeforeAction(context: Context, emptyCallback: EmptyCallback) {
|
||||
if (context is FragmentActivity) {
|
||||
val rxPermission = RxPermissions(context)
|
||||
rxPermission
|
||||
.requestEachCombined(
|
||||
Manifest.permission.READ_PHONE_STATE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.subscribe { permission ->
|
||||
when {
|
||||
permission.granted -> {
|
||||
emptyCallback.onCallback()
|
||||
|
||||
ActivationHelper.sendActivationInfo()
|
||||
}
|
||||
permission.shouldShowRequestPermissionRationale -> {
|
||||
DialogUtils.showPermissionDialog(context, "权限申请",
|
||||
"光环助手需要获取存储权限和手机信息权限,以保证能正常使用相关功能", "重试", "放弃",
|
||||
{ checkStoragePermissionBeforeAction(context, emptyCallback) }, null)
|
||||
}
|
||||
else -> {
|
||||
DialogUtils.showPermissionDialog(context, "权限申请",
|
||||
"在设置-应用-光环助手-权限中开启获取存储权限和手机信息,以保证能正常使用相关功能",
|
||||
"去设置",
|
||||
"放弃",
|
||||
{
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intent.data = Uri.parse("package:" + context.getPackageName())
|
||||
context.startActivity(intent)
|
||||
}, null)
|
||||
tryWithDefaultCatch {
|
||||
rxPermission
|
||||
.requestEachCombined(
|
||||
Manifest.permission.READ_PHONE_STATE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
.subscribe { permission ->
|
||||
when {
|
||||
permission.granted -> {
|
||||
emptyCallback.onCallback()
|
||||
|
||||
ActivationHelper.sendActivationInfo()
|
||||
}
|
||||
permission.shouldShowRequestPermissionRationale -> {
|
||||
DialogUtils.showPermissionDialog(context, "权限申请",
|
||||
"光环助手需要获取存储权限和手机信息权限,以保证能正常使用相关功能", "重试", "放弃",
|
||||
{ checkStoragePermissionBeforeAction(context, emptyCallback) }, null)
|
||||
}
|
||||
else -> {
|
||||
DialogUtils.showPermissionDialog(context, "权限申请",
|
||||
"在设置-应用-光环助手-权限中开启获取存储权限和手机信息,以保证能正常使用相关功能",
|
||||
"去设置",
|
||||
"放弃",
|
||||
{
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intent.data = Uri.parse("package:" + context.getPackageName())
|
||||
context.startActivity(intent)
|
||||
}, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,35 +141,85 @@ object PermissionHelper {
|
||||
fun checkReadPhoneStatePermissionBeforeAction(context: Context, emptyCallback: EmptyCallback) {
|
||||
if (context is FragmentActivity) {
|
||||
val rxPermission = RxPermissions(context)
|
||||
rxPermission
|
||||
.requestEachCombined(Manifest.permission.READ_PHONE_STATE)
|
||||
.subscribe { permission ->
|
||||
when {
|
||||
permission.granted -> {
|
||||
emptyCallback.onCallback()
|
||||
|
||||
ActivationHelper.sendActivationInfo()
|
||||
}
|
||||
permission.shouldShowRequestPermissionRationale -> {
|
||||
DialogUtils.showPermissionDialog(context, "权限申请",
|
||||
"光环助手需要获取手机信息权限,以保证能正常使用相关功能", "重试", "放弃",
|
||||
{ checkStoragePermissionBeforeAction(context, emptyCallback) }, null)
|
||||
}
|
||||
else -> {
|
||||
DialogUtils.showPermissionDialog(context, "权限申请",
|
||||
"在设置-应用-光环助手-权限中开启获取手机信息,以保证能正常使用相关功能",
|
||||
"去设置",
|
||||
"放弃",
|
||||
{
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intent.data = Uri.parse("package:" + context.getPackageName())
|
||||
context.startActivity(intent)
|
||||
}, null)
|
||||
tryWithDefaultCatch {
|
||||
rxPermission
|
||||
.requestEachCombined(Manifest.permission.READ_PHONE_STATE)
|
||||
.subscribe { permission ->
|
||||
when {
|
||||
permission.granted -> {
|
||||
emptyCallback.onCallback()
|
||||
|
||||
ActivationHelper.sendActivationInfo()
|
||||
}
|
||||
permission.shouldShowRequestPermissionRationale -> {
|
||||
DialogUtils.showPermissionDialog(context, "权限申请",
|
||||
"光环助手需要获取手机信息权限,以保证能正常使用相关功能", "重试", "放弃",
|
||||
{ checkStoragePermissionBeforeAction(context, emptyCallback) }, null)
|
||||
}
|
||||
else -> {
|
||||
DialogUtils.showPermissionDialog(context, "权限申请",
|
||||
"在设置-应用-光环助手-权限中开启获取手机信息,以保证能正常使用相关功能",
|
||||
"去设置",
|
||||
"放弃",
|
||||
{
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intent.data = Uri.parse("package:" + context.getPackageName())
|
||||
context.startActivity(intent)
|
||||
}, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到权限设置
|
||||
*
|
||||
* @param activity
|
||||
*/
|
||||
fun toPermissionSetting(activity: Activity) {
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
toSystemConfig(activity)
|
||||
} else {
|
||||
try {
|
||||
toApplicationInfo(activity)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
toSystemConfig(activity)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用信息界面
|
||||
*
|
||||
* @param activity
|
||||
*/
|
||||
private fun toApplicationInfo(activity: Activity) {
|
||||
val localIntent = Intent()
|
||||
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
localIntent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||
localIntent.data = Uri.fromParts("package", activity.packageName, null)
|
||||
activity.startActivity(localIntent)
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统设置界面
|
||||
*
|
||||
* @param activity
|
||||
*/
|
||||
private fun toSystemConfig(activity: Activity) {
|
||||
try {
|
||||
val intent = Intent(Settings.ACTION_SETTINGS)
|
||||
activity.startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -97,16 +97,23 @@ public class PostCommentUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public static void voteAnswerComment(final Context context, final String answerId, String articleId, String articleCommunityId,
|
||||
final String commentId, final PostCommentListener listener) {
|
||||
public static void likeComment(final Context context,
|
||||
final String answerId,
|
||||
String articleId,
|
||||
String articleCommunityId,
|
||||
String videoId,
|
||||
final String commentId,
|
||||
final PostCommentListener listener) {
|
||||
|
||||
|
||||
Observable<ResponseBody> observable;
|
||||
|
||||
if (!TextUtils.isEmpty(answerId)) {
|
||||
observable = RetrofitManager.getInstance(context).getApi().postVoteAnswerComment(answerId, commentId);
|
||||
} else {
|
||||
} else if (!TextUtils.isEmpty(articleId)) {
|
||||
observable = RetrofitManager.getInstance(context).getApi().postVoteCommunityArticleComment(articleCommunityId, articleId, commentId);
|
||||
} else {
|
||||
observable = RetrofitManager.getInstance(context).getApi().postVoteToVideo(videoId, commentId);
|
||||
}
|
||||
observable
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -215,6 +222,30 @@ public class PostCommentUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public static void reportVideoComment(final Context context,
|
||||
final String videoId,
|
||||
final String commentId,
|
||||
final String reportData,
|
||||
final PostCommentListener listener) {
|
||||
RequestBody body = RequestBody.create(MediaType.parse("application/json"), reportData);
|
||||
RetrofitManager.getInstance(context).getApi()
|
||||
.postVideoCommentReport(videoId, commentId, body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(ResponseBody response) {
|
||||
listener.postSuccess(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(HttpException e) {
|
||||
listener.postFailed(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public interface PostCommentListener {
|
||||
void postSuccess(JSONObject response);
|
||||
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import androidx.annotation.ColorRes;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Random;
|
||||
|
||||
@ -44,6 +48,7 @@ public class RandomUtils {
|
||||
|
||||
/**
|
||||
* 四舍五入取整
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static int getInt(double d) {
|
||||
@ -51,4 +56,13 @@ public class RandomUtils {
|
||||
return bigDecimal.intValue();
|
||||
}
|
||||
|
||||
public static final int[] placeholderColors = {
|
||||
R.color.placeholder_5C8399, R.color.placeholder_5C9599,
|
||||
R.color.placeholder_6F5EA8, R.color.placeholder_996283,
|
||||
R.color.placeholder_748054, R.color.placeholder_946262};
|
||||
|
||||
@ColorRes
|
||||
public static int getRandomPlaceholderColor() {
|
||||
return placeholderColors[nextInt(placeholderColors.length - 1)];
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,28 +65,32 @@ object ReservationHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun showDeleteReservationDialog(context: Context, emptyCallback: EmptyCallback) {
|
||||
DialogUtils.showAlertDialog(
|
||||
DialogHelper.showDialog(
|
||||
context,
|
||||
"删除预约",
|
||||
"游戏已上线,你可以删除此预约记录,确定删除吗?",
|
||||
"确定",
|
||||
"取消",
|
||||
{
|
||||
emptyCallback.onCallback()
|
||||
}, null)
|
||||
"确定删除",
|
||||
"暂不删除",
|
||||
{ emptyCallback.onCallback() },
|
||||
null,
|
||||
trackMtaEvent = true,
|
||||
mtaEvent = "预约游戏",
|
||||
mtaKey = "删除预约弹窗")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showCancelReservationDialog(context: Context, emptyCallback: EmptyCallback) {
|
||||
DialogUtils.showAlertDialog(
|
||||
DialogHelper.showDialog(
|
||||
context,
|
||||
"取消预约",
|
||||
"取消之后你将无法收到游戏上线的通知,确定取消预约吗?",
|
||||
"确定取消",
|
||||
"暂不取消",
|
||||
{
|
||||
emptyCallback.onCallback()
|
||||
}, null)
|
||||
{ emptyCallback.onCallback() },
|
||||
null,
|
||||
trackMtaEvent = true,
|
||||
mtaEvent = "预约游戏",
|
||||
mtaKey = "取消预约弹窗")
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.media.ThumbnailUtils;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
@ -23,9 +24,6 @@ import android.widget.PopupWindow;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
||||
@ -52,7 +50,10 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.gh.common.util.GetLoginDataUtils.SCOPE;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import static com.gh.common.util.LoginHelper.WEIBO_SCOPE;
|
||||
|
||||
/**
|
||||
* Created by khy on 2016/9/4.
|
||||
@ -87,7 +88,8 @@ public class ShareUtils {
|
||||
askInvite,
|
||||
askNormal, // 问答问题/答案
|
||||
shareGh,
|
||||
communityArticle
|
||||
communityArticle,
|
||||
video
|
||||
}
|
||||
|
||||
private String[] arrLabel = {"微信好友", "朋友圈", "QQ好友", "QQ空间", "新浪微博", "短信", "复制链接", "取消"};
|
||||
@ -120,7 +122,7 @@ public class ShareUtils {
|
||||
private ShareUtils(Context context) {
|
||||
mTencent = Tencent.createInstance(Config.TENCENT_APPID, context); //初始化QQ分享
|
||||
mIWXAPI = WXAPIFactory.createWXAPI(context, Config.WECHAT_APPID); //初始化微信分享
|
||||
WbSdk.install(context, new AuthInfo(context, Config.WEIBO_APPKEY, "http://www.sina.com", SCOPE));
|
||||
WbSdk.install(context, new AuthInfo(context, Config.WEIBO_APPKEY, "http://www.sina.com", WEIBO_SCOPE));
|
||||
mContext = context.getApplicationContext();
|
||||
}
|
||||
|
||||
@ -221,6 +223,7 @@ public class ShareUtils {
|
||||
mSummary += "(光环加速版)";
|
||||
break;
|
||||
case askNormal:
|
||||
case video:
|
||||
case communityArticle:
|
||||
mTitle += " - 光环助手";
|
||||
break;
|
||||
@ -261,6 +264,7 @@ public class ShareUtils {
|
||||
mSummary += "(光环加速版)";
|
||||
break;
|
||||
case askNormal:
|
||||
case video:
|
||||
case communityArticle:
|
||||
mTitle += " - 光环助手";
|
||||
break;
|
||||
@ -289,6 +293,12 @@ public class ShareUtils {
|
||||
ImageUtils.display(mContext, iconUrl, new BaseBitmapDataSubscriber() {
|
||||
@Override
|
||||
protected void onNewResultImpl(Bitmap bitmap) {
|
||||
if (mShareType == ShareType.video) {
|
||||
// 分享类型为视频时裁为正方形
|
||||
int dimension = Math.min(bitmap.getWidth(), bitmap.getHeight());
|
||||
bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension);
|
||||
}
|
||||
|
||||
Bitmap compressBp = compressBitmap(bitmap);
|
||||
if (mShareType == ShareType.askNormal || mShareType == ShareType.askInvite) {
|
||||
msg.thumbData = ImageUtils.bmpToByteArray(compressBp, true);
|
||||
@ -362,6 +372,7 @@ public class ShareUtils {
|
||||
mSummary += "(光环加速版)";
|
||||
break;
|
||||
case askNormal:
|
||||
case video:
|
||||
case communityArticle:
|
||||
mTitle += " - 光环助手";
|
||||
break;
|
||||
@ -411,6 +422,7 @@ public class ShareUtils {
|
||||
msg.title = mSummary;
|
||||
break;
|
||||
case askNormal:
|
||||
case video:
|
||||
case communityArticle:
|
||||
msg.title = mTitle + " - 光环助手";
|
||||
break;
|
||||
@ -472,6 +484,7 @@ public class ShareUtils {
|
||||
break;
|
||||
case askInvite:
|
||||
case askNormal:
|
||||
case video:
|
||||
case communityArticle:
|
||||
smsBody = mTitle + " - 光环助手" + shareUrl;
|
||||
break;
|
||||
|
||||
5
app/src/main/java/com/gh/common/util/SimpleCallback.kt
Normal file
5
app/src/main/java/com/gh/common/util/SimpleCallback.kt
Normal file
@ -0,0 +1,5 @@
|
||||
package com.gh.common.util
|
||||
|
||||
interface SimpleCallback<T> {
|
||||
fun onCallback(arg: T)
|
||||
}
|
||||
@ -82,4 +82,11 @@ object SPUtils {
|
||||
sp.edit().putString(key, value).apply()
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun remove(key: String) {
|
||||
val editor = sp.edit()
|
||||
editor.remove(key)
|
||||
editor.apply()
|
||||
}
|
||||
}
|
||||
61
app/src/main/java/com/gh/common/util/SpanBuilder.kt
Normal file
61
app/src/main/java/com/gh/common/util/SpanBuilder.kt
Normal file
@ -0,0 +1,61 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.style.AbsoluteSizeSpan
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.text.style.StrikethroughSpan
|
||||
import android.text.style.StyleSpan
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.view.CenterImageSpan
|
||||
|
||||
class SpanBuilder(content: String) {
|
||||
private var spannableString: SpannableStringBuilder = SpannableStringBuilder(content)
|
||||
|
||||
fun color(context: Context, start: Int, end: Int, colorRes: Int): SpanBuilder {
|
||||
val colorSpan = ForegroundColorSpan(ContextCompat.getColor(context, colorRes))
|
||||
spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return this
|
||||
}
|
||||
|
||||
fun size(start: Int, end: Int, dpSize: Int): SpanBuilder {
|
||||
val s = AbsoluteSizeSpan(dpSize, true)
|
||||
spannableString.setSpan(s, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return this
|
||||
}
|
||||
|
||||
//删除线
|
||||
fun strikeThrough(start: Int, end: Int): SpanBuilder {
|
||||
val strike = StrikethroughSpan()
|
||||
spannableString.setSpan(strike, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return this
|
||||
}
|
||||
|
||||
//加粗
|
||||
fun bold(start: Int, end: Int): SpanBuilder {
|
||||
val styleSpan = StyleSpan(Typeface.BOLD)
|
||||
spannableString.setSpan(styleSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return this
|
||||
}
|
||||
|
||||
//正常字体
|
||||
fun normal(start: Int, end: Int): SpanBuilder {
|
||||
val styleSpan = StyleSpan(Typeface.NORMAL)
|
||||
spannableString.setSpan(styleSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return this
|
||||
}
|
||||
|
||||
//添加图标
|
||||
fun image(context: Context, start: Int, end: Int, @DrawableRes res: Int): SpanBuilder {
|
||||
val imageSpan = CenterImageSpan(context, res)
|
||||
spannableString.setSpan(imageSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): SpannableStringBuilder {
|
||||
return spannableString
|
||||
}
|
||||
}
|
||||
@ -70,4 +70,49 @@ public class StringUtils {
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除尾部\n字符
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String deleteStringTailLineBreak(String str) {
|
||||
if (TextUtils.isEmpty(str)) {
|
||||
return str;
|
||||
}
|
||||
|
||||
if (str.length() == 1) {
|
||||
char ch = str.charAt(0);
|
||||
if (ch == '\n') {
|
||||
return "";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
int lastIdx = str.length() - 1;
|
||||
char last = str.charAt(lastIdx);
|
||||
|
||||
if (last == '\n') {
|
||||
return str.substring(0, lastIdx);
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符串末尾是否有\n
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static boolean isStringTailHasLineBreak(String str) {
|
||||
if (TextUtils.isEmpty(str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int lastIdx = str.length() - 1;
|
||||
char last = str.charAt(lastIdx);
|
||||
|
||||
return last == '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.gh.common.util
|
||||
import android.content.Context
|
||||
import com.ss.android.common.applog.TeaAgent
|
||||
import com.ss.android.common.applog.TeaConfigBuilder
|
||||
import com.ss.android.common.lib.EventUtils
|
||||
|
||||
/**
|
||||
* 今日头条的激活统计 SDK https://gitlab.ghzs.com/pm/halo-app-issues/issues/567
|
||||
@ -17,6 +18,19 @@ object TeaHelper {
|
||||
.setAid(163824)
|
||||
.createTeaConfig()
|
||||
)
|
||||
|
||||
EventUtils.setRegister("mobile", true)
|
||||
EventUtils.setPurchase(null, null, null, 0, null, null, true, 1)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onResume(context: Context) {
|
||||
TeaAgent.onResume(context)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onPause(context: Context) {
|
||||
TeaAgent.onPause(context)
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,10 +1,23 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.text.Editable
|
||||
import android.text.InputFilter
|
||||
import android.text.TextWatcher
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.text.*
|
||||
import android.text.style.ClickableSpan
|
||||
import android.text.style.RelativeSizeSpan
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.view.CustomLinkMovementMethod
|
||||
import com.gh.common.view.RoundStrokeBackgroundColorSpan
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
|
||||
object TextHelper {
|
||||
|
||||
@ -49,6 +62,151 @@ object TextHelper {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun highlightTextThatIsWrappedInsideWrapperByDefault(textView: TextView, text: String) {
|
||||
textView.text = getHighlightedSpannableStringThatIsWrappedInsideWrapper(textView.context, text, "###", R.color.theme, object : SimpleCallback<String> {
|
||||
override fun onCallback(arg: String) {
|
||||
val application = HaloApp.getInstance().application
|
||||
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
cmb.text = arg
|
||||
Utils.toast(application, "已复制:$arg")
|
||||
}
|
||||
})
|
||||
textView.movementMethod = CustomLinkMovementMethod.getInstance()
|
||||
textView.highlightColor = Color.TRANSPARENT
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun highlightTextThatIsWrappedInsideWrapper(textView: TextView,
|
||||
text: CharSequence,
|
||||
wrapper: String,
|
||||
@ColorRes
|
||||
highlightColorId: Int,
|
||||
highlightedTextClickListener: SimpleCallback<String>? = null) {
|
||||
textView.text = getHighlightedSpannableStringThatIsWrappedInsideWrapper(textView.context, text, wrapper, highlightColorId, highlightedTextClickListener)
|
||||
textView.movementMethod = CustomLinkMovementMethod.getInstance()
|
||||
textView.highlightColor = Color.TRANSPARENT
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getHighlightedSpannableStringThatIsWrappedInsideWrapper(
|
||||
context: Context,
|
||||
text: CharSequence,
|
||||
wrapper: String = "###",
|
||||
@ColorRes
|
||||
highlightColorId: Int = R.color.theme,
|
||||
highlightedTextClickListener: SimpleCallback<String>? = object : SimpleCallback<String> {
|
||||
override fun onCallback(arg: String) {
|
||||
val application = HaloApp.getInstance().application
|
||||
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
cmb.text = arg
|
||||
Utils.toast(application, "已复制:$arg")
|
||||
}
|
||||
}): SpannableStringBuilder {
|
||||
|
||||
var modifiedText = text
|
||||
if (modifiedText.endsWith(wrapper)) {
|
||||
// 若高亮符在最后一位就在后面加一个空格,避免整行都能点击
|
||||
modifiedText = "$modifiedText "
|
||||
}
|
||||
|
||||
val sBuilder = SpannableStringBuilder(modifiedText)
|
||||
val wrapperTextLength = wrapper.length
|
||||
|
||||
val matcher = Pattern.compile("$wrapper(.+?)$wrapper", Pattern.DOTALL).matcher(modifiedText)
|
||||
|
||||
val pair = TreeMap<Int, Int>()
|
||||
while (matcher.find()) {
|
||||
// 保存起始位置和结束位置
|
||||
pair[matcher.start(1)] = matcher.end(1)
|
||||
sBuilder.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = ContextCompat.getColor(context, highlightColorId)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
val tv = widget as TextView
|
||||
val s = tv.text as Spanned
|
||||
val start = s.getSpanStart(this)
|
||||
val end = s.getSpanEnd(this)
|
||||
highlightedTextClickListener?.onCallback(s.substring(start, end))
|
||||
}
|
||||
}, matcher.start(1), matcher.end(1), 0)
|
||||
}
|
||||
|
||||
// 反转 pair
|
||||
val reversePair = pair.descendingMap()
|
||||
|
||||
// 找到
|
||||
for (key in reversePair.keys) {
|
||||
val end = reversePair[key]
|
||||
|
||||
end?.let {
|
||||
sBuilder.replace(end, end + wrapperTextLength, "")
|
||||
sBuilder.replace(key - wrapperTextLength, key, "")
|
||||
}
|
||||
}
|
||||
|
||||
return sBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* [amwayStyle] 是否为安利墙列表样式,安利墙列表样式与其它地方略有不同
|
||||
*/
|
||||
fun getCommentLabelSpannableStringBuilder(comment: CharSequence,
|
||||
lineFeed: String = "\n",
|
||||
amwayStyle: Boolean = false,
|
||||
tagStrokeColor: String = "#FFDAA2",
|
||||
tagTextColor: String = "#FF9B06"): SpannableStringBuilder {
|
||||
val contents = SpannableStringBuilder()
|
||||
var count = 0
|
||||
val splits = comment.split("<tag>")
|
||||
splits.forEachIndexed { index, s ->
|
||||
if (index != 0) {
|
||||
val item = "<tag>$s"
|
||||
val pattern = Pattern.compile("<tag>(\\S+)</tag>(\\S+)")
|
||||
val matcher = pattern.matcher(item)
|
||||
if (matcher.find()) {
|
||||
val label = matcher.group(1)
|
||||
val content = matcher.group(2)
|
||||
val newLabel = " $label "
|
||||
val newContent = if (index != splits.size - 1) "$content$lineFeed" else content
|
||||
contents.append(newLabel)
|
||||
contents.setSpan(RelativeSizeSpan(0.8f), count, count + newLabel.length - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
contents.setSpan(
|
||||
getRoundStrokeBackgroundColorSpan(amwayStyle, tagStrokeColor, tagTextColor),
|
||||
count,
|
||||
count + newLabel.length - 1,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
count += newLabel.length
|
||||
contents.append(newContent)
|
||||
count += newContent.length
|
||||
}
|
||||
}
|
||||
}
|
||||
return contents
|
||||
}
|
||||
|
||||
private fun getRoundStrokeBackgroundColorSpan(amwayStyle: Boolean,
|
||||
tagStrokeColor: String,
|
||||
tagTextColor: String): RoundStrokeBackgroundColorSpan {
|
||||
return if (amwayStyle) {
|
||||
val strokeWidth = DisplayUtils.dip2px(1F)
|
||||
|
||||
RoundStrokeBackgroundColorSpan(
|
||||
Color.parseColor(tagStrokeColor),
|
||||
Color.parseColor(tagTextColor),
|
||||
strokeWidth,
|
||||
DisplayUtils.sp2px(HaloApp.getInstance().application, 10F))
|
||||
} else {
|
||||
RoundStrokeBackgroundColorSpan(
|
||||
Color.parseColor(tagStrokeColor),
|
||||
Color.parseColor(tagTextColor))
|
||||
}
|
||||
}
|
||||
|
||||
interface ExceedTextLengthLimitCallback {
|
||||
fun onExceed()
|
||||
}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import androidx.collection.ArrayMap;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.halo.assistant.HaloApp;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
@ -42,7 +44,7 @@ public class TimestampUtils {
|
||||
*/
|
||||
public static String addTimestamp(String url) {
|
||||
|
||||
if ("GH_REFRESH".equals(HaloApp.getInstance().getChannel())) {
|
||||
if (BuildConfig.DEBUG || "GH_REFRESH".equals(HaloApp.getInstance().getChannel())) {
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
@ -27,7 +27,9 @@ object UploadImageUtils {
|
||||
question,
|
||||
answer,
|
||||
suggestion,
|
||||
icon
|
||||
icon,
|
||||
poster,
|
||||
game_upload
|
||||
}
|
||||
|
||||
// 不处理图片,只是单纯的上传
|
||||
@ -179,6 +181,77 @@ object UploadImageUtils {
|
||||
return subscription
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片,每成功一个就回调
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun uploadImageListOneByOne(type: UploadType, imgs: List<String>, compressGif: Boolean, listener: OnUploadImageListCountListener):Disposable?{
|
||||
var subscription: Disposable? = null
|
||||
Observable.create(ObservableOnSubscribe<Map<String, String>> {
|
||||
//val compressList = compressImageList(imgs, compressGif)
|
||||
|
||||
for (img in imgs) {
|
||||
if (subscription?.isDisposed == true) return@ObservableOnSubscribe
|
||||
val file=File(img)
|
||||
val requestBody = FileRequestBody(file, object : RetrofitCallback<ResponseBody>() {
|
||||
override fun onProgress(total: Long, progress: Long) {
|
||||
|
||||
}
|
||||
})
|
||||
val part = MultipartBody.Part.createFormData("Filedata", getFileName(file), requestBody)
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.uploadApi.uploadImage(part, type.name)
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
if (subscription?.isDisposed == true) return
|
||||
val string = data.string()
|
||||
if (!string.isNullOrEmpty()) {
|
||||
val url = JSONObject(string).getString("url")
|
||||
if (!url.isNullOrEmpty()) {
|
||||
val map = LinkedHashMap<String, String>()
|
||||
map[file.path] = url
|
||||
it.onNext(map)
|
||||
return
|
||||
}
|
||||
}
|
||||
onFailure(IllegalAccessException("HeHe"))
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
// 若遇到错误且 subscription?.isDisposed 为 true 时会抛出 io.reactivex.exceptions.UndeliverableException 异常
|
||||
// if (subscription?.isDisposed == true) return
|
||||
// it.onError(exception) // fuck
|
||||
it.onNext(Collections.emptyMap())
|
||||
}
|
||||
})
|
||||
}
|
||||
it.onComplete()
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Observer<Map<String, String>?> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
subscription = d
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
listener.onFinish()
|
||||
}
|
||||
|
||||
override fun onNext(t: Map<String, String>) {
|
||||
if (t.isNotEmpty()) {
|
||||
listener.onSuccess(t)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.onError()
|
||||
e.printStackTrace()
|
||||
}
|
||||
})
|
||||
return subscription
|
||||
}
|
||||
|
||||
// 同步调用->避免在主线程调用以免阻塞主线程
|
||||
private fun compressImageList(imgs: List<String>, compressGif: Boolean): List<File> {
|
||||
val compressList: MutableList<File> = ArrayList()
|
||||
@ -215,4 +288,9 @@ object UploadImageUtils {
|
||||
fun onError() // 全部上传失败时回调
|
||||
fun onProgress(total: Long, progress: Long)
|
||||
}
|
||||
interface OnUploadImageListCountListener{
|
||||
fun onSuccess(map:Map<String, String>)//上传成功一个回调
|
||||
fun onFinish()//全部上传成功回调
|
||||
fun onError() // 全部上传失败时回调
|
||||
}
|
||||
}
|
||||
16
app/src/main/java/com/gh/common/view/BugFixedPopupWindow.kt
Normal file
16
app/src/main/java/com/gh/common/view/BugFixedPopupWindow.kt
Normal file
@ -0,0 +1,16 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.PaintDrawable
|
||||
import android.view.View
|
||||
import android.widget.PopupWindow
|
||||
|
||||
class BugFixedPopupWindow @JvmOverloads constructor(contentView: View? = null, width: Int = 0, height: Int = 0)
|
||||
: PopupWindow(contentView, width, height) {
|
||||
|
||||
init {
|
||||
// 若不设置这个可能在一些旧设备(小于6.0)上无法无法通过返回键和点击外部关闭
|
||||
setBackgroundDrawable(PaintDrawable(Color.TRANSPARENT))
|
||||
}
|
||||
|
||||
}
|
||||
55
app/src/main/java/com/gh/common/view/CenterImageSpan.java
Normal file
55
app/src/main/java/com/gh/common/view/CenterImageSpan.java
Normal file
@ -0,0 +1,55 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.style.ImageSpan;
|
||||
|
||||
/**
|
||||
* 图文中心对齐
|
||||
*/
|
||||
public class CenterImageSpan extends ImageSpan {
|
||||
public CenterImageSpan(Context context, int resourceId) {
|
||||
super(context, resourceId);
|
||||
}
|
||||
public CenterImageSpan(Drawable drawable) {
|
||||
super( drawable);
|
||||
}
|
||||
|
||||
public int getSize(Paint paint, CharSequence text, int start, int end,
|
||||
Paint.FontMetricsInt fm) {
|
||||
Drawable d = getDrawable();
|
||||
Rect rect = d.getBounds();
|
||||
if (fm != null) {
|
||||
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
|
||||
int fontHeight = fmPaint.bottom - fmPaint.top;
|
||||
int drHeight = rect.bottom - rect.top;
|
||||
|
||||
int top = drHeight / 2 - fontHeight / 4;
|
||||
int bottom = drHeight / 2 + fontHeight / 4;
|
||||
|
||||
fm.ascent = -bottom;
|
||||
fm.top = -bottom;
|
||||
fm.bottom = top;
|
||||
fm.descent = top;
|
||||
}
|
||||
return rect.right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, CharSequence text, int start, int end,
|
||||
float x, int top, int y, int bottom, Paint paint) {
|
||||
Drawable b = getDrawable();
|
||||
canvas.save();
|
||||
int transY;
|
||||
transY = ((bottom - top) - b.getBounds().bottom) / 2 + top;
|
||||
canvas.translate(x, transY);
|
||||
if (b.isVisible()) {
|
||||
b.draw(canvas);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
}
|
||||
147
app/src/main/java/com/gh/common/view/CircleProgressBar.java
Normal file
147
app/src/main/java/com/gh/common/view/CircleProgressBar.java
Normal file
@ -0,0 +1,147 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
public class CircleProgressBar extends View {
|
||||
private int height;
|
||||
private int width;
|
||||
private Paint mPaint;
|
||||
private int strokeWidth = 5;//线条宽度
|
||||
private RectF rectF;
|
||||
|
||||
|
||||
private int normalColor = Color.parseColor("#999999");//普通的颜色
|
||||
private int progressColor = Color.parseColor("#2496FF");//已经走了的进度条颜色
|
||||
private int textColor = Color.parseColor("#1F89EC");//文字颜色
|
||||
|
||||
private int disableNormalColor = Color.parseColor("#80999999");//禁用普通的颜色
|
||||
private int disableProgressColor = Color.parseColor("#999999");//禁用已经走了的进度条颜色
|
||||
private int disableTextColor = Color.parseColor("#999999");//禁用文字颜色
|
||||
|
||||
private int currentNormalColor = normalColor;
|
||||
private int currentProgressColor = progressColor;
|
||||
private int currentTextColor = textColor;
|
||||
|
||||
private float textSize = 20;//文字大小
|
||||
private int progress = 0;//进度条
|
||||
private String centerText = "0%";//中心填充文字
|
||||
private Paint fontPaint = null;
|
||||
private Paint.Style progress_style = Paint.Style.STROKE;//填充式还是环形式
|
||||
|
||||
public CircleProgressBar(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public CircleProgressBar(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar);
|
||||
textSize = array.getDimension(R.styleable.CircleProgressBar_text_size, textSize);
|
||||
centerText = array.getString(R.styleable.CircleProgressBar_text) == null ? centerText : array.getString(R.styleable.CircleProgressBar_text);
|
||||
strokeWidth = DisplayUtils.dip2px(array.getInteger(R.styleable.CircleProgressBar_stroke_width, strokeWidth));
|
||||
|
||||
textColor = array.getColor(R.styleable.CircleProgressBar_text_color, textColor);
|
||||
normalColor = array.getColor(R.styleable.CircleProgressBar_normal_color, normalColor);
|
||||
progressColor = array.getColor(R.styleable.CircleProgressBar_progress_color, progressColor);
|
||||
|
||||
disableTextColor = array.getColor(R.styleable.CircleProgressBar_disable_text_color, disableTextColor);
|
||||
disableNormalColor = array.getColor(R.styleable.CircleProgressBar_disable_normal_color, disableNormalColor);
|
||||
disableProgressColor = array.getColor(R.styleable.CircleProgressBar_disable_progress_color, disableProgressColor);
|
||||
|
||||
progress = array.getInt(R.styleable.CircleProgressBar_progress, progress);
|
||||
progress_style = array.getInt(R.styleable.CircleProgressBar_progress_style, 0) == 0 ? Paint.Style.STROKE : Paint.Style.FILL;
|
||||
|
||||
array.recycle();
|
||||
initPaint();
|
||||
}
|
||||
|
||||
// 2.初始化画笔
|
||||
private void initPaint() {
|
||||
mPaint = new Paint();
|
||||
mPaint.setColor(currentNormalColor); //设置画笔颜色
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setStyle(progress_style); //设置画笔模式为描边
|
||||
mPaint.setStrokeWidth(strokeWidth); //设置画笔宽度为10px
|
||||
|
||||
fontPaint = new Paint();
|
||||
fontPaint.setTextSize(textSize);
|
||||
fontPaint.setAntiAlias(true);
|
||||
fontPaint.setColor(currentTextColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
|
||||
if (height > width)//高大于宽的情况
|
||||
{
|
||||
rectF = new RectF(strokeWidth, (height / 2 - width / 2) + strokeWidth, width - strokeWidth, (height / 2 + width / 2) - strokeWidth);
|
||||
} else if (width > height)//宽大于高的情况
|
||||
{
|
||||
rectF = new RectF((width / 2 - height / 2) + strokeWidth, strokeWidth, (width / 2 + height / 2) - strokeWidth, height - strokeWidth);
|
||||
} else//宽等于高的情况
|
||||
{
|
||||
rectF = new RectF(strokeWidth, strokeWidth, width - strokeWidth, height - strokeWidth);
|
||||
}
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
Paint.FontMetrics fontMetrics = null;
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
mPaint.setColor(currentNormalColor);
|
||||
if (progress < 360) {
|
||||
canvas.drawArc(rectF, 270 + progress, 360 - progress, progress_style == Paint.Style.FILL, mPaint);
|
||||
}
|
||||
|
||||
mPaint.setColor(currentProgressColor);
|
||||
canvas.drawArc(rectF, 270, progress, progress_style == Paint.Style.FILL, mPaint);
|
||||
|
||||
fontMetrics = fontPaint.getFontMetrics();
|
||||
float textWidth = fontPaint.measureText(centerText);
|
||||
float textHeight = fontPaint.ascent() + fontPaint.descent();
|
||||
canvas.drawText(centerText, width / 2 - textWidth / 2, height / 2 - textHeight / 2, fontPaint);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新界面
|
||||
*
|
||||
* @param progress
|
||||
* @param text
|
||||
*/
|
||||
public void update(int progress, String text) {
|
||||
this.progress = progress;
|
||||
this.centerText = text;
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否禁用
|
||||
*
|
||||
* @param isDisable
|
||||
*/
|
||||
public void isDisable(boolean isDisable) {
|
||||
currentNormalColor = isDisable ? disableNormalColor : normalColor;
|
||||
currentProgressColor = isDisable ? disableProgressColor : progressColor;
|
||||
currentTextColor = isDisable ? disableTextColor : textColor;
|
||||
fontPaint.setColor(currentTextColor);
|
||||
postInvalidate();
|
||||
}
|
||||
}
|
||||
@ -8,28 +8,39 @@ import android.view.ViewParent;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class CustomLinkMovementMethod extends LinkMovementMethod {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
|
||||
boolean b = super.onTouchEvent(widget, buffer, event);
|
||||
//解决点击事件冲突问题
|
||||
if (!b && event.getAction() == MotionEvent.ACTION_UP) {
|
||||
ViewParent parent = widget.getParent();//处理widget的父控件点击事件
|
||||
if (parent instanceof ViewGroup) {
|
||||
ViewParent parent = iterateViewParentForClicking(widget.getParent());//处理widget的父控件点击事件
|
||||
if (parent != null && parent instanceof ViewGroup) {
|
||||
return ((ViewGroup) parent).performClick();
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ViewParent iterateViewParentForClicking(ViewParent parent) {
|
||||
if (parent instanceof ViewGroup) {
|
||||
if (((ViewGroup) parent).hasOnClickListeners()) {
|
||||
return parent;
|
||||
} else {
|
||||
return iterateViewParentForClicking(parent.getParent());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CustomLinkMovementMethod getInstance() {
|
||||
if (sInstance == null)
|
||||
sInstance = new CustomLinkMovementMethod();
|
||||
|
||||
if (sInstance == null) sInstance = new CustomLinkMovementMethod();
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static CustomLinkMovementMethod sInstance;
|
||||
|
||||
|
||||
}
|
||||
@ -22,14 +22,16 @@ import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
public class DownloadProgressBar extends ProgressBar {
|
||||
private static final int MAX_LENGTH = 1000;
|
||||
private static final int DOWNLOAD_NORMAL_STYLE = 0;
|
||||
private static final int DOWNLOAD_RECT_STYLE = 1;
|
||||
private static final int DOWNLOAD_IMAGE_STYLE = 2;
|
||||
public static final int MAX_LENGTH = 1000;
|
||||
public static final int DOWNLOAD_NORMAL_STYLE = 0;
|
||||
public static final int DOWNLOAD_RECT_STYLE = 1;
|
||||
public static final int DOWNLOAD_IMAGE_STYLE = 2;
|
||||
public static final int DOWNLOAD_SLIDE_STYLE = 3;
|
||||
|
||||
public enum DownloadType {
|
||||
NORMAL,
|
||||
NONE,
|
||||
NONE_WITH_HINT,
|
||||
PLUGIN,
|
||||
LAUNCH_OR_OPEN,
|
||||
INSTALL_NORMAL,
|
||||
@ -53,6 +55,8 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
private int mDefaultColor;
|
||||
private int mTextSize;
|
||||
|
||||
private boolean mShowDownloadPercent = false;
|
||||
|
||||
private Rect mTextBound = new Rect();
|
||||
|
||||
public DownloadProgressBar(Context context) {
|
||||
@ -65,6 +69,7 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.DownloadProgressBar);
|
||||
mDownloadStyle = ta.getInteger(R.styleable.DownloadProgressBar_downloadStyle, DOWNLOAD_NORMAL_STYLE);
|
||||
mTextSize = ta.getDimensionPixelSize(R.styleable.DownloadProgressBar_textSize, DisplayUtils.sp2px(getContext(), 14));
|
||||
mShowDownloadPercent = ta.getBoolean(R.styleable.DownloadProgressBar_showDownloadPercent, false);
|
||||
ta.recycle();
|
||||
}
|
||||
setMax(MAX_LENGTH);
|
||||
@ -102,11 +107,17 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
|
||||
canvas.getClipBounds(mTextBound); //The dimensions of your canvas
|
||||
int width = mTextBound.width() - 20; //10 to keep some space on the right for the "..."
|
||||
String txt = TextUtils.ellipsize(mText, mFakeTextPaint, width, TextUtils.TruncateAt.END).toString();
|
||||
String txt = TextUtils.ellipsize(mText, mFakeTextPaint, width, TextUtils.TruncateAt.END).toString();
|
||||
srcCanvas.drawText(txt, getWidth() / 2, baseline, mPaint);
|
||||
mPaint.setXfermode(mDuffXFerMode);
|
||||
if (getProgress() != 0) {
|
||||
mPaint.setColor(DOWNLOAD_IMAGE_STYLE == mDownloadStyle ? Color.BLACK : Color.WHITE); // 反向颜色
|
||||
int color = Color.WHITE;
|
||||
if (DOWNLOAD_IMAGE_STYLE == mDownloadStyle) {
|
||||
color = Color.BLACK;
|
||||
} else if (DOWNLOAD_SLIDE_STYLE == mDownloadStyle) {
|
||||
color = getResources().getColor(R.color.theme);
|
||||
}
|
||||
mPaint.setColor(color); // 反向颜色
|
||||
}
|
||||
|
||||
srcCanvas.drawRect(rectF, mPaint);
|
||||
@ -119,16 +130,40 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
if (mText != null && mText.contains("%")) {
|
||||
return getResources().getString(R.string.downloading);
|
||||
}
|
||||
return mText;
|
||||
}
|
||||
|
||||
public void setText(@StringRes int res) {
|
||||
setText(getResources().getString(res));
|
||||
if (mShowDownloadPercent && res == R.string.downloading) {
|
||||
setText(getProgressPercent());
|
||||
} else {
|
||||
setText(getResources().getString(res));
|
||||
}
|
||||
}
|
||||
|
||||
public void setDownloadStyle(int downloadStyle) {
|
||||
this.mDownloadStyle = downloadStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setProgress(int progress) {
|
||||
super.setProgress(progress);
|
||||
if (getResources().getString(R.string.downloading).equals(mText)) {
|
||||
setText(getProgressPercent());
|
||||
}
|
||||
}
|
||||
|
||||
private String getProgressPercent() {
|
||||
return getProgress() / 10 + "%";
|
||||
}
|
||||
|
||||
public void setDownloadType(DownloadType downloadType) {
|
||||
switch (downloadType) {
|
||||
case NORMAL:
|
||||
case NONE_WITH_HINT:
|
||||
case INSTALL_NORMAL:
|
||||
switch (mDownloadStyle) {
|
||||
case DOWNLOAD_RECT_STYLE:
|
||||
@ -183,6 +218,7 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.theme);
|
||||
break;
|
||||
case DOWNLOAD_IMAGE_STYLE:
|
||||
case DOWNLOAD_SLIDE_STYLE:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_downloading_normal_image_style));
|
||||
mDefaultColor = Color.WHITE;
|
||||
break;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
@ -7,6 +8,18 @@ import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
import android.graphics.drawable.StateListDrawable
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.gh.common.util.dip2px
|
||||
import com.j256.ormlite.stmt.query.In
|
||||
import android.graphics.Shader
|
||||
import android.graphics.LinearGradient
|
||||
import android.graphics.drawable.shapes.RectShape
|
||||
import android.graphics.drawable.ShapeDrawable
|
||||
import android.opengl.ETC1.getHeight
|
||||
import com.gh.gamecenter.R
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
|
||||
object DrawableView {
|
||||
@ -16,7 +29,6 @@ object DrawableView {
|
||||
return getServerDrawable(ContextCompat.getColor(HaloApp.getInstance().application, colorId))
|
||||
}
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun getServerDrawable(colorCode: String): Drawable {
|
||||
return getServerDrawable(Color.parseColor(colorCode))
|
||||
@ -31,10 +43,62 @@ object DrawableView {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getOvalDrawable(@ColorRes colorId: Int): Drawable {
|
||||
fun getOvalDrawable(@ColorRes colorId: Int, radius: Float = 999F): Drawable {
|
||||
val drawable = GradientDrawable()
|
||||
drawable.setColor(ContextCompat.getColor(HaloApp.getInstance().application, colorId))
|
||||
drawable.cornerRadius = DisplayUtils.dip2px(999F).toFloat()
|
||||
drawable.cornerRadius = DisplayUtils.dip2px(radius).toFloat()
|
||||
return drawable
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getOvalSelectorStyle(@ColorRes defaultColorId: Int, @ColorRes checkColorId: Int): StateListDrawable {
|
||||
val res = StateListDrawable()
|
||||
res.addState(intArrayOf(android.R.attr.state_checked), getOvalDrawable(checkColorId))
|
||||
res.addState(intArrayOf(), getOvalDrawable(defaultColorId))
|
||||
return res
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getSelectorColorStyle(@ColorRes defaultColorId: Int, @ColorRes checkColorId: Int): ColorStateList {
|
||||
val states = arrayOf(
|
||||
intArrayOf(-android.R.attr.state_checked),
|
||||
intArrayOf(android.R.attr.state_checked))
|
||||
val colors = intArrayOf(
|
||||
ContextCompat.getColor(HaloApp.getInstance().application, defaultColorId),
|
||||
ContextCompat.getColor(HaloApp.getInstance().application, checkColorId))
|
||||
return ColorStateList(states, colors)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getStrokeDrawable(@ColorRes colorCode: Int, strokeWidth: Float = 1F, radius: Float = 999F): Drawable {
|
||||
val drawable = GradientDrawable()
|
||||
drawable.setStroke(strokeWidth.dip2px(), ContextCompat.getColor(HaloApp.getInstance().application, colorCode))
|
||||
drawable.cornerRadius = radius
|
||||
return drawable
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setTextDrawable(textView: TextView, @DrawableRes drawableId: Int?, text: String? = null) {
|
||||
val drawable = if (drawableId != null) {
|
||||
ContextCompat.getDrawable(HaloApp.getInstance().application, drawableId)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
drawable?.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
|
||||
textView.setCompoundDrawables(drawable, null, null, null)
|
||||
if (text != null) textView.text = text
|
||||
}
|
||||
|
||||
// 需要跳转角度请自行设置 x0,y0,x1,y1
|
||||
@JvmStatic
|
||||
fun getGradientDrawable(width: Int, startColor: Int, endColor: Int): Drawable {
|
||||
val drawable = ShapeDrawable(RectShape())
|
||||
drawable.paint.shader = LinearGradient(0f, 0F, width.toFloat(), 0F, startColor, endColor, Shader.TileMode.REPEAT)
|
||||
return drawable
|
||||
}
|
||||
|
||||
fun convertAlphaKey(percent: Int): String {
|
||||
val hexString = Integer.toHexString(Math.round((255 * percent / 100).toFloat()))
|
||||
return (if (hexString.length < 2) "0" else "") + hexString
|
||||
}
|
||||
}
|
||||
52
app/src/main/java/com/gh/common/view/EllipsizeTextView.kt
Normal file
52
app/src/main/java/com/gh/common/view/EllipsizeTextView.kt
Normal file
@ -0,0 +1,52 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
|
||||
|
||||
/**
|
||||
* TextView using Spannable - ellipsize doesn't work
|
||||
* https://stackoverflow.com/questions/14691511/textview-using-spannable-ellipsize-doesnt-work
|
||||
*/
|
||||
class EllipsizeTextView : AppCompatTextView {
|
||||
constructor(context: Context) : super(context)
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
super.onLayout(changed, left, top, right, bottom)
|
||||
if (lineCount > maxLines) {
|
||||
val lastLineEnd = layout.getLineEnd(maxLines - 1)
|
||||
val secondLastLineEnd = layout.getLineEnd(maxLines - 2)
|
||||
val charSequence: CharSequence
|
||||
|
||||
val width = paint.measureText(text.subSequence(secondLastLineEnd, lastLineEnd).toString() + "...")
|
||||
if (width > layout.width) {
|
||||
val lastLineText = text.subSequence(secondLastLineEnd, lastLineEnd)
|
||||
for (i in 0 until lastLineText.length) {
|
||||
val cutWidth = paint.measureText(text.subSequence(secondLastLineEnd, lastLineEnd - i).toString() + "...")
|
||||
if (cutWidth <= layout.width) {
|
||||
charSequence = text.subSequence(0, lastLineEnd - i)
|
||||
text = "$charSequence..."
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
charSequence = text.subSequence(0, lastLineEnd)
|
||||
text = charSequence
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 阻止TextView移动
|
||||
* https://stackoverflow.com/questions/24027108/how-do-i-completely-prevent-a-textview-from-scrolling
|
||||
*/
|
||||
override fun scrollTo(x: Int, y: Int) {
|
||||
//super.scrollTo(x, y)
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
@ -12,16 +12,15 @@ import android.text.style.ClickableSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
public class ExpendTextView extends AppCompatTextView {
|
||||
|
||||
private CharSequence mSnapshotText;
|
||||
private CharSequence mCloseText;
|
||||
|
||||
private String mExpendText = "...全文";
|
||||
|
||||
@ -48,7 +47,6 @@ public class ExpendTextView extends AppCompatTextView {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
if (mInitLayout && !mOpenLayout && getLineCount() > mMaxLines) {
|
||||
mSnapshotText = getText();
|
||||
mCloseText = getText();
|
||||
mInitLayout = false;
|
||||
showExpendButton();
|
||||
}
|
||||
@ -93,39 +91,31 @@ public class ExpendTextView extends AppCompatTextView {
|
||||
}
|
||||
}
|
||||
}
|
||||
SpannableStringBuilder msp = new SpannableStringBuilder(mCloseText);
|
||||
SpannableStringBuilder msp = new SpannableStringBuilder(mSnapshotText);
|
||||
int length = msp.length();
|
||||
int startPosition = content.length() - mExpendText.length();
|
||||
startPosition = startPosition < 0 ? 0 : startPosition;
|
||||
msp.replace(startPosition, length, mExpendText);
|
||||
msp.setSpan(
|
||||
new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setColor(ContextCompat.getColor(getContext(), R.color.theme));
|
||||
ds.setUnderlineText(false);
|
||||
}
|
||||
msp.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setColor(ContextCompat.getColor(getContext(), R.color.theme));
|
||||
ds.setUnderlineText(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
mOpenLayout = true;
|
||||
setMaxLines(Integer.MAX_VALUE);
|
||||
setText(mSnapshotText);
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
mOpenLayout = true;
|
||||
setMaxLines(Integer.MAX_VALUE);
|
||||
setText(mSnapshotText);
|
||||
|
||||
if (mExpandCallback != null) {
|
||||
mExpandCallback.onExpand();
|
||||
}
|
||||
}
|
||||
},
|
||||
startPosition,
|
||||
msp.length(),
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
msp.setSpan(
|
||||
new BackgroundColorSpan(Color.WHITE),
|
||||
startPosition,
|
||||
msp.length(),
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
if (mExpandCallback != null) {
|
||||
mExpandCallback.onExpand();
|
||||
}
|
||||
}
|
||||
}, startPosition + 3, msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
msp.setSpan(new BackgroundColorSpan(Color.WHITE), startPosition, msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
setText(msp);
|
||||
setMovementMethod(CustomLinkMovementMethod.getInstance());
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class FixLinearLayoutManager extends LinearLayoutManager {
|
||||
|
||||
public FixLinearLayoutManager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FixLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
|
||||
super(context, orientation, reverseLayout);
|
||||
}
|
||||
|
||||
public FixLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
try {
|
||||
super.onLayoutChildren(recycler, state);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,58 +5,59 @@ import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* Created by khy on 2017/3/28.
|
||||
*/
|
||||
public class GridDivider extends RecyclerView.ItemDecoration {
|
||||
public final int[] ATRRS = new int[]{android.R.attr.listDivider};
|
||||
private Drawable mDividerDarwable;
|
||||
|
||||
private Paint mColorPaint;
|
||||
|
||||
private int mDividerHight = 1;
|
||||
private int mGridCount;
|
||||
private int mSpanCount;
|
||||
private int mDividerStrokeWidth = 1;
|
||||
|
||||
private boolean mIsFilterLast;
|
||||
|
||||
/*
|
||||
int dividerHight 分割线的线宽
|
||||
int dividerColor 分割线的颜色
|
||||
private Paint mColorPaint;
|
||||
private Drawable mDividerDrawable;
|
||||
|
||||
/**
|
||||
* @param dividerStrokeWidth 分割线的线宽
|
||||
* @param dividerColor 分割线的颜色
|
||||
*/
|
||||
public GridDivider(Context context, int dividerHight, int gridCount, int dividerColor) {
|
||||
public GridDivider(Context context, int dividerStrokeWidth, int spanCount, int dividerColor) {
|
||||
this(context);
|
||||
mDividerHight = dividerHight;
|
||||
mGridCount = gridCount;
|
||||
mDividerStrokeWidth = dividerStrokeWidth;
|
||||
mSpanCount = spanCount;
|
||||
mColorPaint = new Paint();
|
||||
mColorPaint.setColor(dividerColor);
|
||||
}
|
||||
|
||||
public GridDivider(Context context, int dividerHight, int gridCount, int dividerColor, boolean isFilterLast) {
|
||||
public GridDivider(Context context, int dividerStrokeWidth, int spanCount, int dividerColor, boolean isFilterLast) {
|
||||
this(context);
|
||||
mDividerHight = dividerHight;
|
||||
mGridCount = gridCount;
|
||||
mDividerStrokeWidth = dividerStrokeWidth;
|
||||
mSpanCount = spanCount;
|
||||
mColorPaint = new Paint();
|
||||
mColorPaint.setColor(dividerColor);
|
||||
mIsFilterLast = isFilterLast;
|
||||
}
|
||||
|
||||
public GridDivider(Context context) {
|
||||
final TypedArray ta = context.obtainStyledAttributes(ATRRS);
|
||||
this.mDividerDarwable = ta.getDrawable(0);
|
||||
int[] attrs = new int[]{android.R.attr.listDivider};
|
||||
final TypedArray ta = context.obtainStyledAttributes(attrs);
|
||||
this.mDividerDrawable = ta.getDrawable(0);
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
/*
|
||||
int dividerHight 分割线的线宽
|
||||
Drawable dividerDrawable 图片分割线
|
||||
/**
|
||||
* @param dividerStrokeWidth 分割线的线宽
|
||||
* @param dividerDrawable 图片分割线
|
||||
*/
|
||||
public GridDivider(Context context, int dividerHight, Drawable dividerDrawable) {
|
||||
public GridDivider(Context context, int dividerStrokeWidth, Drawable dividerDrawable) {
|
||||
this(context);
|
||||
mDividerHight = dividerHight;
|
||||
mDividerDarwable = dividerDrawable;
|
||||
mDividerStrokeWidth = dividerStrokeWidth;
|
||||
mDividerDrawable = dividerDrawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -67,46 +68,45 @@ public class GridDivider extends RecyclerView.ItemDecoration {
|
||||
drawVerticalDivider(c, parent);
|
||||
}
|
||||
|
||||
public void drawHorizontalDivider(Canvas c, RecyclerView parent) {
|
||||
|
||||
private void drawHorizontalDivider(Canvas c, RecyclerView parent) {
|
||||
final int childCount = parent.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
if (mIsFilterLast && i == childCount - 1) continue;
|
||||
final View child = parent.getChildAt(i);
|
||||
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||
|
||||
final int left = child.getLeft() - params.leftMargin - mDividerHight;
|
||||
final int left = child.getLeft() - params.leftMargin - mDividerStrokeWidth;
|
||||
final int right = child.getRight() + params.rightMargin;
|
||||
int top = 0;
|
||||
int bottom = 0;
|
||||
|
||||
// 最上面一行
|
||||
if ((i / mGridCount) == 0) {
|
||||
if ((i / mSpanCount) == 0) {
|
||||
//当前item最上面的分割线
|
||||
top = child.getTop();
|
||||
//当前item下面的分割线
|
||||
bottom = top + mDividerHight;
|
||||
mDividerDarwable.setBounds(left, top, right, bottom);
|
||||
mDividerDarwable.draw(c);
|
||||
bottom = top + mDividerStrokeWidth;
|
||||
mDividerDrawable.setBounds(left, top, right, bottom);
|
||||
mDividerDrawable.draw(c);
|
||||
if (mColorPaint != null) {
|
||||
c.drawRect(left, top, right, bottom, mColorPaint);
|
||||
}
|
||||
top = child.getBottom() + params.bottomMargin;
|
||||
bottom = top + mDividerHight;
|
||||
bottom = top + mDividerStrokeWidth;
|
||||
} else {
|
||||
top = child.getBottom() + params.bottomMargin;
|
||||
bottom = top + mDividerHight;
|
||||
bottom = top + mDividerStrokeWidth;
|
||||
}
|
||||
//画分割线
|
||||
mDividerDarwable.setBounds(left, top, right, bottom);
|
||||
mDividerDarwable.draw(c);
|
||||
mDividerDrawable.setBounds(left, top, right, bottom);
|
||||
mDividerDrawable.draw(c);
|
||||
if (mColorPaint != null) {
|
||||
c.drawRect(left, top, right, bottom, mColorPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawVerticalDivider(Canvas c, RecyclerView parent) {
|
||||
private void drawVerticalDivider(Canvas c, RecyclerView parent) {
|
||||
final int childCount = parent.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final View child = parent.getChildAt(i);
|
||||
@ -119,26 +119,26 @@ public class GridDivider extends RecyclerView.ItemDecoration {
|
||||
int right = 0;
|
||||
|
||||
//左边第一列
|
||||
if ((i % mGridCount) == 0) {
|
||||
if ((i % mSpanCount) == 0) {
|
||||
//item左边分割线
|
||||
left = child.getLeft();
|
||||
right = left + mDividerHight;
|
||||
mDividerDarwable.setBounds(left, top, right, bottom);
|
||||
mDividerDarwable.draw(c);
|
||||
right = left + mDividerStrokeWidth;
|
||||
mDividerDrawable.setBounds(left, top, right, bottom);
|
||||
mDividerDrawable.draw(c);
|
||||
if (mColorPaint != null) {
|
||||
c.drawRect(left, top, right, bottom, mColorPaint);
|
||||
}
|
||||
//item右边分割线
|
||||
left = child.getRight() + params.rightMargin - mDividerHight;
|
||||
right = left + mDividerHight;
|
||||
left = child.getRight() + params.rightMargin - mDividerStrokeWidth;
|
||||
right = left + mDividerStrokeWidth;
|
||||
} else {
|
||||
//非左边第一列
|
||||
left = child.getRight() + params.rightMargin - mDividerHight;
|
||||
right = left + mDividerHight;
|
||||
left = child.getRight() + params.rightMargin - mDividerStrokeWidth;
|
||||
right = left + mDividerStrokeWidth;
|
||||
}
|
||||
//画分割线
|
||||
mDividerDarwable.setBounds(left, top, right, bottom);
|
||||
mDividerDarwable.draw(c);
|
||||
mDividerDrawable.setBounds(left, top, right, bottom);
|
||||
mDividerDrawable.draw(c);
|
||||
if (mColorPaint != null) {
|
||||
c.drawRect(left, top, right, bottom, mColorPaint);
|
||||
}
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.graphics.Rect
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
|
||||
class GridSpacingItemDecoration(private val mSpanCount: Int,
|
||||
private val mSpacing: Int,
|
||||
private val mIncludeEdge: Boolean) : RecyclerView.ItemDecoration() {
|
||||
|
||||
private var mTopDecoration = 0
|
||||
|
||||
constructor(spanCount: Int,
|
||||
spacing: Int,
|
||||
includeEdge: Boolean,
|
||||
topDecoration: Int) : this(spanCount, spacing, includeEdge) {
|
||||
this.mTopDecoration = topDecoration
|
||||
}
|
||||
|
||||
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
|
||||
val position = parent.getChildAdapterPosition(view)
|
||||
val column = position % mSpanCount
|
||||
|
||||
if (mIncludeEdge) {
|
||||
outRect.left = mSpacing - column * mSpacing / mSpanCount
|
||||
|
||||
outRect.right = (column + 1) * mSpacing / mSpanCount
|
||||
|
||||
if (position < mSpanCount) {
|
||||
outRect.top = mSpacing
|
||||
}
|
||||
|
||||
outRect.bottom = mSpacing
|
||||
} else {
|
||||
outRect.left = column * mSpacing / mSpanCount
|
||||
outRect.right = mSpacing - (column + 1) * mSpacing / mSpanCount
|
||||
if (position >= mSpanCount) {
|
||||
outRect.top = mSpacing
|
||||
}
|
||||
}
|
||||
|
||||
if (mTopDecoration != 0 && position < mSpanCount) {
|
||||
outRect.top = outRect.top + mTopDecoration
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.widget.TextView
|
||||
import com.gh.common.util.SimpleCallback
|
||||
import com.gh.common.util.TextHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
/**
|
||||
* 默认用 ###高亮内容### 格式来高亮文字并添加点击复制至剪贴板功能的 TextView
|
||||
*/
|
||||
class HighlightableTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : TextView(context, attrs) {
|
||||
init {
|
||||
movementMethod = CustomLinkMovementMethod.getInstance()
|
||||
highlightColor = Color.TRANSPARENT
|
||||
}
|
||||
|
||||
override fun setText(text: CharSequence?, type: BufferType?) {
|
||||
super.setText(TextHelper.getHighlightedSpannableStringThatIsWrappedInsideWrapper(context, text.toString(), "###", R.color.theme, object : SimpleCallback<String> {
|
||||
override fun onCallback(arg: String) {
|
||||
val application = HaloApp.getInstance().application
|
||||
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
cmb.text = arg
|
||||
Utils.toast(application, "已复制:$arg")
|
||||
}
|
||||
}), BufferType.SPANNABLE)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.view.WindowInsets
|
||||
import android.widget.FrameLayout
|
||||
|
||||
class MaterializedFrameLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
|
||||
: FrameLayout(context, attrs) {
|
||||
|
||||
/**
|
||||
* 将 windowInsets 传递给子 view [https://medium.com/androiddevelopers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec#.raoa9t506]
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
|
||||
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
|
||||
val childCount = childCount
|
||||
for (index in 0 until childCount) {
|
||||
getChildAt(index).dispatchApplyWindowInsets(insets)
|
||||
}
|
||||
return insets
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.view.WindowInsets
|
||||
import android.widget.RelativeLayout
|
||||
|
||||
class MaterializedRelativeLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
|
||||
: RelativeLayout(context, attrs) {
|
||||
|
||||
/**
|
||||
* 将 windowInsets 传递给子 view [https://medium.com/androiddevelopers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec#.raoa9t506]
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
|
||||
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
|
||||
val childCount = childCount
|
||||
for (index in 0 until childCount) {
|
||||
getChildAt(index).dispatchApplyWindowInsets(insets)
|
||||
}
|
||||
return insets
|
||||
}
|
||||
|
||||
}
|
||||
61
app/src/main/java/com/gh/common/view/NavigationBarView.kt
Normal file
61
app/src/main/java/com/gh/common/view/NavigationBarView.kt
Normal file
@ -0,0 +1,61 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.KeyCharacterMap
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.ViewConfiguration
|
||||
|
||||
/**
|
||||
* 导航栏占位 View
|
||||
*/
|
||||
class NavigationBarView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
val height = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
0
|
||||
} else {
|
||||
retrieveNavigationHeight()
|
||||
}
|
||||
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height)
|
||||
}
|
||||
|
||||
// TODO 将这部分移到通用方法去
|
||||
private fun hasSoftKeys(): Boolean {
|
||||
if (context !is Activity) return false
|
||||
|
||||
val hasSoftwareKeys: Boolean
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
val d = (context as Activity).windowManager.defaultDisplay
|
||||
|
||||
val realDisplayMetrics = DisplayMetrics()
|
||||
d.getRealMetrics(realDisplayMetrics)
|
||||
|
||||
val realHeight = realDisplayMetrics.heightPixels
|
||||
val realWidth = realDisplayMetrics.widthPixels
|
||||
|
||||
val displayMetrics = DisplayMetrics()
|
||||
d.getMetrics(displayMetrics)
|
||||
|
||||
val displayHeight = displayMetrics.heightPixels
|
||||
val displayWidth = displayMetrics.widthPixels
|
||||
|
||||
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0
|
||||
} else {
|
||||
val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
|
||||
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
|
||||
hasSoftwareKeys = !hasMenuKey && !hasBackKey
|
||||
}
|
||||
return hasSoftwareKeys
|
||||
}
|
||||
|
||||
private fun retrieveNavigationHeight(): Int {
|
||||
val resources = context.resources
|
||||
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
|
||||
return if (resourceId > 0 && hasSoftKeys()) resources.getDimensionPixelSize(resourceId) else 0
|
||||
}
|
||||
}
|
||||
@ -1,294 +0,0 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
import android.os.Handler
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import cn.jzvd.*
|
||||
import com.gh.common.observer.MuteCallback
|
||||
import com.gh.common.observer.VolumeObserver
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.util.NetworkUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import java.util.*
|
||||
|
||||
class PlayerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : JzvdStd(context, attrs) {
|
||||
|
||||
var showAlertDialogForTheFistTime: Boolean = true
|
||||
|
||||
var gameName: String = ""
|
||||
|
||||
lateinit var muteIv: ImageView
|
||||
lateinit var rotateIv: ImageView
|
||||
|
||||
val muteCallback = object : MuteCallback {
|
||||
override fun onMute(isMute: Boolean) {
|
||||
if (isMute) {
|
||||
muteIv.setImageResource(R.drawable.ic_volume_off)
|
||||
} else {
|
||||
muteIv.setImageResource(R.drawable.ic_volume_on)
|
||||
}
|
||||
}
|
||||
}
|
||||
var volumeObserver = VolumeObserver(context, Handler(), muteCallback)
|
||||
|
||||
override fun init(context: Context?) {
|
||||
super.init(context)
|
||||
|
||||
muteIv = findViewById(R.id.mute)
|
||||
rotateIv = findViewById(R.id.rotate)
|
||||
|
||||
muteIv.setOnClickListener(this)
|
||||
rotateIv.setOnClickListener(this)
|
||||
|
||||
Jzvd.WIFI_TIP_DIALOG_SHOWED = true
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
if (v.id == R.id.start || v.id == R.id.thumb) {
|
||||
if (Jzvd.CURRENT_STATE_PLAYING != currentState) {
|
||||
if ((currentScreen == SCREEN_WINDOW_NORMAL || currentScreen == SCREEN_WINDOW_LIST)) {
|
||||
MtaHelper.onEvent("游戏详情_新", "视频_点击播放", gameName)
|
||||
} else {
|
||||
MtaHelper.onEvent("游戏详情_新", "视频全屏_点击播放", gameName)
|
||||
}
|
||||
} else {
|
||||
MtaHelper.onEvent("游戏详情_新", "视频_点击暂停", gameName)
|
||||
}
|
||||
|
||||
if (showAlertDialogForTheFistTime
|
||||
&& !NetworkUtils.isWifiConnected(context)
|
||||
&& currentState != Jzvd.CURRENT_STATE_PLAYING) {
|
||||
showNetworkAlertDialog()
|
||||
} else {
|
||||
super.onClick(v)
|
||||
}
|
||||
} else {
|
||||
super.onClick(v)
|
||||
when (v.id) {
|
||||
R.id.rotate -> {
|
||||
if (Jzvd.FULLSCREEN_ORIENTATION != SCREEN_ORIENTATION_LANDSCAPE) {
|
||||
Jzvd.FULLSCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
JZUtils.setRequestedOrientation(context, Jzvd.FULLSCREEN_ORIENTATION)
|
||||
} else {
|
||||
Jzvd.FULLSCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
JZUtils.setRequestedOrientation(context, Jzvd.FULLSCREEN_ORIENTATION)
|
||||
}
|
||||
MtaHelper.onEvent("游戏详情_新", "视频全屏_点击旋转", gameName)
|
||||
}
|
||||
R.id.mute -> {
|
||||
toggleMute()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.player_view
|
||||
}
|
||||
|
||||
private fun toggleMute() {
|
||||
HaloApp.getInstance().isMute = !HaloApp.getInstance().isMute
|
||||
updateMuteStatus()
|
||||
}
|
||||
|
||||
private fun updateMuteStatus() {
|
||||
if (HaloApp.getInstance().isMute) {
|
||||
mute()
|
||||
} else {
|
||||
unmute()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showNetworkAlertDialog() {
|
||||
DialogUtils.showAlertDialog(context,
|
||||
"播放视频",
|
||||
"您当前使用的网络为2G/3G/4G,播放视频将会消耗移动流量,确定播放?",
|
||||
"确定",
|
||||
"取消",
|
||||
DialogUtils.ConfirmListener {
|
||||
showAlertDialogForTheFistTime = false
|
||||
startButton.performClick()
|
||||
},
|
||||
null
|
||||
).show()
|
||||
}
|
||||
|
||||
private fun mute() {
|
||||
muteIv.setImageResource(R.drawable.ic_volume_off)
|
||||
try {
|
||||
JZMediaManager.instance()?.jzMediaInterface?.setVolume(0f, 0f)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
MtaHelper.onEvent("游戏详情_新", "视频_点击静音", gameName)
|
||||
}
|
||||
|
||||
private fun unmute() {
|
||||
muteIv.setImageResource(R.drawable.ic_volume_on)
|
||||
try {
|
||||
JZMediaManager.instance()?.jzMediaInterface?.setVolume(1.0f, 1.0f)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
MtaHelper.onEvent("游戏详情_新", "视频_解除静音", gameName)
|
||||
}
|
||||
|
||||
override fun onStatePlaying() {
|
||||
super.onStatePlaying()
|
||||
// 默认加载完显示播放信息
|
||||
if (currentScreen != Jzvd.SCREEN_WINDOW_FULLSCREEN) {
|
||||
changeUiToPlayingShow()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStatePrepared() {
|
||||
super.onStatePrepared()
|
||||
updateMuteStatus()
|
||||
}
|
||||
|
||||
override fun onClickUiToggle() {
|
||||
// 仅在全屏状态下才会 toggle 播放信息
|
||||
if (currentScreen == Jzvd.SCREEN_WINDOW_FULLSCREEN) {
|
||||
if (bottomContainer.visibility != View.VISIBLE) {
|
||||
setSystemTimeAndBattery()
|
||||
clarity.text = jzDataSource.currentKey.toString()
|
||||
}
|
||||
if (currentState == Jzvd.CURRENT_STATE_PREPARING) {
|
||||
changeUiToPreparing()
|
||||
if (bottomContainer.visibility == View.VISIBLE) {
|
||||
} else {
|
||||
setSystemTimeAndBattery()
|
||||
}
|
||||
} else if (currentState == Jzvd.CURRENT_STATE_PLAYING) {
|
||||
if (bottomContainer.visibility == View.VISIBLE) {
|
||||
changeUiToPlayingClear()
|
||||
} else {
|
||||
changeUiToPlayingShow()
|
||||
}
|
||||
} else if (currentState == Jzvd.CURRENT_STATE_PAUSE) {
|
||||
if (bottomContainer.visibility == View.VISIBLE) {
|
||||
changeUiToPauseClear()
|
||||
} else {
|
||||
changeUiToPauseShow()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 小界面播放中或者准备中的时候点击直接进入全屏
|
||||
when (currentState) {
|
||||
Jzvd.CURRENT_STATE_PLAYING,
|
||||
Jzvd.CURRENT_STATE_PREPARING -> {
|
||||
startWindowFullscreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUp(jzDataSource: JZDataSource?, screen: Int) {
|
||||
super.setUp(jzDataSource, screen)
|
||||
batteryTimeLayout.visibility = View.INVISIBLE
|
||||
|
||||
// 初始化隐藏和置换一些原有资源
|
||||
if (currentScreen == SCREEN_WINDOW_NORMAL || currentScreen == SCREEN_WINDOW_LIST) {
|
||||
progressBar.visibility = View.INVISIBLE
|
||||
totalTimeTextView.visibility = View.INVISIBLE
|
||||
|
||||
muteIv.visibility = View.VISIBLE
|
||||
rotateIv.visibility = View.GONE
|
||||
|
||||
// 将右下角的按钮变成静音与否
|
||||
updateMuteStatus()
|
||||
} else {
|
||||
progressBar.visibility = View.VISIBLE
|
||||
totalTimeTextView.visibility = View.VISIBLE
|
||||
|
||||
muteIv.visibility = View.GONE
|
||||
rotateIv.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateStartImage() {
|
||||
when (currentState) {
|
||||
Jzvd.CURRENT_STATE_PLAYING -> {
|
||||
if (currentScreen == SCREEN_WINDOW_NORMAL || currentScreen == SCREEN_WINDOW_LIST) {
|
||||
startButton.visibility = View.INVISIBLE
|
||||
} else {
|
||||
startButton.visibility = View.VISIBLE
|
||||
startButton.setImageResource(cn.jzvd.R.drawable.jz_click_pause_selector)
|
||||
replayTextView.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
Jzvd.CURRENT_STATE_ERROR -> {
|
||||
startButton.visibility = View.INVISIBLE
|
||||
replayTextView.visibility = View.INVISIBLE
|
||||
}
|
||||
Jzvd.CURRENT_STATE_AUTO_COMPLETE -> {
|
||||
startButton.visibility = View.VISIBLE
|
||||
startButton.setImageResource(cn.jzvd.R.drawable.jz_click_replay_selector)
|
||||
replayTextView.visibility = View.VISIBLE
|
||||
}
|
||||
else -> {
|
||||
startButton.setImageResource(cn.jzvd.R.drawable.jz_click_play_selector)
|
||||
replayTextView.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun playOnThisJzvd() {
|
||||
super.playOnThisJzvd()
|
||||
|
||||
if (HaloApp.getInstance().isMute) {
|
||||
mute()
|
||||
}
|
||||
|
||||
// 处理从全屏跳转回小界面
|
||||
Jzvd.FULLSCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
if (currentScreen == SCREEN_WINDOW_NORMAL || currentScreen == SCREEN_WINDOW_LIST) {
|
||||
progressBar.visibility = View.INVISIBLE
|
||||
totalTimeTextView.visibility = View.INVISIBLE
|
||||
MtaHelper.onEvent("游戏详情_新", "视频全屏_点击后退", gameName)
|
||||
} else {
|
||||
progressBar.visibility = View.VISIBLE
|
||||
totalTimeTextView.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun startWindowFullscreen() {
|
||||
super.startWindowFullscreen()
|
||||
unmute()
|
||||
MtaHelper.onEvent("游戏详情_新", "视频_点击进入全屏", gameName)
|
||||
}
|
||||
|
||||
override fun startDismissControlViewTimer() {
|
||||
// 仅在全屏是才自动隐藏播放信息
|
||||
cancelDismissControlViewTimer()
|
||||
if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
|
||||
DISMISS_CONTROL_VIEW_TIMER = Timer()
|
||||
mDismissControlViewTimerTask = DismissControlViewTimerTask()
|
||||
DISMISS_CONTROL_VIEW_TIMER.schedule(mDismissControlViewTimerTask, 3000)
|
||||
}
|
||||
}
|
||||
|
||||
fun observeVolume(fragment: androidx.fragment.app.Fragment?) {
|
||||
fragment?.context?.applicationContext?.contentResolver?.registerContentObserver(
|
||||
android.provider.Settings.System.CONTENT_URI, true, volumeObserver)
|
||||
|
||||
fragment?.fragmentManager?.registerFragmentLifecycleCallbacks(
|
||||
object : androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks() {
|
||||
override fun onFragmentPaused(fm: FragmentManager, f: Fragment) {
|
||||
if (f === fragment) {
|
||||
fragment.context?.applicationContext?.contentResolver?.unregisterContentObserver(volumeObserver)
|
||||
fragment.fragmentManager?.unregisterFragmentLifecycleCallbacks(this)
|
||||
}
|
||||
}
|
||||
}, false)
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,254 +0,0 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by khy on 2017/2/16.
|
||||
* 快传接收方 的雷达动画
|
||||
*/
|
||||
public class RadarLayout extends FrameLayout {
|
||||
|
||||
public static final int INFINITE = 0;
|
||||
|
||||
private static final int DEFAULT_COUNT = 4;
|
||||
private static final int DEFAULT_COLOR = Color.rgb(0, 116, 193);
|
||||
private static final int DEFAULT_DURATION = 7000;
|
||||
private static final int DEFAULT_REPEAT = INFINITE;
|
||||
private static final int DEFAULT_STROKE_WIDTH = 2;
|
||||
|
||||
private int mCount;
|
||||
private int mDuration;
|
||||
private int mRepeat;
|
||||
|
||||
private AnimatorSet mAnimatorSet;
|
||||
|
||||
private Paint mPaint;
|
||||
private int mColor;
|
||||
private float mRadius;
|
||||
private float mCenterX;
|
||||
private float mCenterY;
|
||||
private int mStrokeWidth;
|
||||
private boolean mIsStarted;
|
||||
private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
mIsStarted = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
mIsStarted = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {
|
||||
mIsStarted = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animator) {
|
||||
}
|
||||
};
|
||||
private boolean mUseRing;
|
||||
|
||||
public RadarLayout(Context context) {
|
||||
super(context);
|
||||
initGlobalparams();
|
||||
}
|
||||
|
||||
private void initGlobalparams() {
|
||||
mColor = DEFAULT_COLOR;
|
||||
mCount = DEFAULT_COUNT;
|
||||
mDuration = DEFAULT_DURATION;
|
||||
mRepeat = DEFAULT_REPEAT;
|
||||
mUseRing = false;
|
||||
mStrokeWidth = dip2px(DEFAULT_STROKE_WIDTH);
|
||||
|
||||
build();
|
||||
}
|
||||
|
||||
private int dip2px(float dpValue) {
|
||||
final float scale = getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
private void build() {
|
||||
|
||||
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
|
||||
int repeatCount = (mRepeat == INFINITE) ? ObjectAnimator.INFINITE : mRepeat;
|
||||
|
||||
List animators = new ArrayList();
|
||||
for (int index = 0; index < mCount; index++) {
|
||||
RadarView radarView = new RadarView(getContext());
|
||||
radarView.setScaleX(0);
|
||||
radarView.setScaleY(0);
|
||||
radarView.setAlpha(1);
|
||||
|
||||
addView(radarView, index, params);
|
||||
|
||||
// 计算时间间隔
|
||||
long delay = index * mDuration / mCount;
|
||||
|
||||
// 属性动画
|
||||
animators.add(create(radarView, "scaleX", repeatCount, delay, 0, 1));
|
||||
animators.add(create(radarView, "scaleY", repeatCount, delay, 0, 1));
|
||||
animators.add(create(radarView, "alpha", repeatCount, delay, 1, 0));
|
||||
}
|
||||
|
||||
mAnimatorSet = new AnimatorSet();
|
||||
mAnimatorSet.playTogether(animators);
|
||||
mAnimatorSet.setInterpolator(new LinearInterpolator());
|
||||
mAnimatorSet.setDuration(mDuration);
|
||||
mAnimatorSet.addListener(mAnimatorListener);
|
||||
}
|
||||
|
||||
private ObjectAnimator create(View target, String propertyName, int repeatCount, long delay, float from, float to) {
|
||||
ObjectAnimator animator = ObjectAnimator.ofFloat(target, propertyName, from, to);
|
||||
animator.setRepeatCount(repeatCount);
|
||||
animator.setRepeatMode(ObjectAnimator.RESTART);
|
||||
animator.setStartDelay(delay);
|
||||
return animator;
|
||||
}
|
||||
|
||||
public RadarLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initGlobalparams();
|
||||
}
|
||||
|
||||
public RadarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initGlobalparams();
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return mCount;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
if (count < 0) {
|
||||
throw new IllegalArgumentException("Count cannot be negative");
|
||||
}
|
||||
|
||||
if (count != mCount) {
|
||||
mCount = count;
|
||||
reset();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
boolean isStarted = isStarted();
|
||||
|
||||
clear();
|
||||
build();
|
||||
|
||||
if (isStarted) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean isStarted() {
|
||||
return (mAnimatorSet != null && mIsStarted);
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
stop();
|
||||
removeAllViews();
|
||||
}
|
||||
|
||||
public synchronized void start() {
|
||||
if (mAnimatorSet == null || mIsStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
mAnimatorSet.start();
|
||||
}
|
||||
|
||||
public synchronized void stop() {
|
||||
if (mAnimatorSet == null || !mIsStarted) {
|
||||
return;
|
||||
}
|
||||
mAnimatorSet.end();
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return mDuration;
|
||||
}
|
||||
|
||||
public void setDuration(int millis) {
|
||||
if (millis < 0) {
|
||||
throw new IllegalArgumentException("Duration cannot be negative");
|
||||
}
|
||||
|
||||
if (millis != mDuration) {
|
||||
mDuration = millis;
|
||||
reset();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
if (mColor != color) {
|
||||
mColor = color;
|
||||
reset();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setUseRing(boolean useRing) {
|
||||
if (mUseRing != useRing) {
|
||||
mUseRing = useRing;
|
||||
reset();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
int width = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
|
||||
int height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
|
||||
|
||||
// 确定圆的圆点坐标及半径
|
||||
mCenterX = width * 0.5f;
|
||||
mCenterY = height * 0.5f;
|
||||
mRadius = Math.min(width, height) * 0.5f;
|
||||
}
|
||||
|
||||
private class RadarView extends View {
|
||||
|
||||
public RadarView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (null == mPaint) {
|
||||
mPaint = new Paint();
|
||||
mPaint.setColor(mColor);
|
||||
mPaint.setAntiAlias(true);
|
||||
// 注意Style的用法,【STROKE:画环】【FILL:画圆】
|
||||
mPaint.setStyle(mUseRing ? Paint.Style.STROKE : Paint.Style.FILL);
|
||||
mPaint.setStrokeWidth(mUseRing ? mStrokeWidth : 0);
|
||||
}
|
||||
// 画圆或环
|
||||
canvas.drawCircle(mCenterX, mCenterY, mUseRing ? mRadius - mStrokeWidth : mRadius, mPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,163 +0,0 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
/**
|
||||
* Created by khy on 22/06/17.
|
||||
*
|
||||
* 光环快传-扫描雷达动画
|
||||
*/
|
||||
|
||||
public class RadarView extends View {
|
||||
|
||||
private Context mContext;
|
||||
private boolean isSearching = false;// 标识是否处于扫描状态,默认为不在扫描状态
|
||||
private Paint mPaint;// 画笔
|
||||
private Bitmap mScanBmp;// 执行扫描运动的图片
|
||||
private int mOffsetArgs = 0;// 扫描运动偏移量参数
|
||||
private int mWidth, mHeight;// 宽高
|
||||
int mCx, mCy;// x、y轴中心点
|
||||
int mOutsideRadius, mInsideRadius;// 外、内圆半径
|
||||
|
||||
public RadarView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public RadarView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public RadarView(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提前初始化好需要使用的对象,避免在绘制过程中多次初始化
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private void init(Context context) {
|
||||
mPaint = new Paint();
|
||||
this.mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测量视图及其内容,以确定所测量的宽度和高度(测量获取控件尺寸).
|
||||
*/
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
// 获取控件区域宽高
|
||||
if (mWidth == 0 || mHeight == 0) {
|
||||
final int minimumWidth = getSuggestedMinimumWidth();
|
||||
final int minimumHeight = getSuggestedMinimumHeight();
|
||||
mWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
|
||||
mHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
|
||||
mScanBmp = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(
|
||||
mContext.getResources(), R.drawable.radar_scan_img), mWidth, mWidth, false);
|
||||
|
||||
// 获取x/y轴中心点
|
||||
mCx = mWidth / 2;
|
||||
mCy = mHeight / 2;
|
||||
|
||||
// 计算内、外半径
|
||||
mOutsideRadius = mWidth / 2;// 外圆的半径
|
||||
mInsideRadius = mWidth / 4 / 2;// 内圆的半径,除最外层,其它圆的半径=层数*insideRadius
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制视图--从外部向内部绘制
|
||||
*/
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
// 开始绘制最外层的圆
|
||||
mPaint.setAntiAlias(true);// 设置抗锯齿
|
||||
mPaint.setStyle(Paint.Style.FILL);// 设置填充样式
|
||||
mPaint.setColor(0xff327BD7);// 设置画笔颜色
|
||||
// 1.开始绘制圆形
|
||||
canvas.drawCircle(mCx, mCy, mOutsideRadius, mPaint);
|
||||
|
||||
// 开始绘制内3圆
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mPaint.setColor(Color.WHITE);
|
||||
canvas.drawCircle(mCx, mCy, mInsideRadius * 3, mPaint);
|
||||
|
||||
// 开始绘制内2圆
|
||||
canvas.drawCircle(mCx, mCy, mInsideRadius * 2, mPaint);
|
||||
|
||||
// 开始绘制内1圆
|
||||
canvas.drawCircle(mCx, mCy, mInsideRadius * 1, mPaint);
|
||||
|
||||
// 2.开始绘制对角线
|
||||
canvas.drawLine(0, mCy, mWidth, mCy, mPaint);// 绘制0°~180°对角线
|
||||
canvas.drawLine(mCx, mHeight , mCx, 0,
|
||||
mPaint);// 绘制90°~270°对角线
|
||||
|
||||
// 3.绘制扫描扇形图
|
||||
canvas.save();// 用来保存Canvas的状态.save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作.
|
||||
|
||||
if (isSearching) {// 判断是否处于扫描
|
||||
canvas.rotate(mOffsetArgs, mCx, mCy);// 绘制旋转角度,参数一:角度;参数二:x中心;参数三:y中心.
|
||||
canvas.drawBitmap(mScanBmp, mCx - mScanBmp.getWidth() / 2, mCy
|
||||
- mScanBmp.getHeight() / 2, null);// 绘制Bitmap扫描图片效果
|
||||
mOffsetArgs += 3;
|
||||
} else {
|
||||
canvas.drawBitmap(mScanBmp, mCx - mScanBmp.getWidth() / 2, mCy
|
||||
- mScanBmp.getHeight() / 2, null);
|
||||
}
|
||||
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setColor(Color.WHITE);
|
||||
canvas.drawCircle(mCx, mCy, mInsideRadius/4, mPaint);
|
||||
|
||||
if (isSearching)
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置扫描状态
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public void setSearching(boolean status) {
|
||||
this.isSearching = status;
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析获取控件宽高
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private int resolveMeasured(int measureSpec, int desired) {
|
||||
int result = 0;
|
||||
int specSize = MeasureSpec.getSize(measureSpec);
|
||||
switch (MeasureSpec.getMode(measureSpec)) {
|
||||
case MeasureSpec.UNSPECIFIED:
|
||||
result = desired;
|
||||
break;
|
||||
case MeasureSpec.AT_MOST:
|
||||
result = Math.min(specSize, desired);
|
||||
break;
|
||||
case MeasureSpec.EXACTLY:
|
||||
default:
|
||||
result = specSize;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -22,9 +22,12 @@ import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.RichEditorUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.MyVideoEntity;
|
||||
import com.gh.gamecenter.qa.entity.EditorInsertEntity;
|
||||
import com.halo.assistant.HaloApp;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
@ -123,7 +126,7 @@ public class RichEditor extends WebView {
|
||||
public RichEditor(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
addJavascriptInterface(new NativeCallBack(), NativeCallBack.class.getSimpleName());
|
||||
addJavascriptInterface(new NativeCallBack(), "NativeCallBack");
|
||||
|
||||
setVerticalScrollBarEnabled(false);
|
||||
setHorizontalScrollBarEnabled(false);
|
||||
@ -265,6 +268,28 @@ public class RichEditor extends WebView {
|
||||
exec("javascript:RE.insertCustomStyleLink('" + GsonUtils.toJson(entity) + "');");
|
||||
}
|
||||
|
||||
public void insertCustomVideo(MyVideoEntity entity) {
|
||||
try {
|
||||
JSONObject object = new JSONObject();
|
||||
object.put("poster", entity.getPoster());
|
||||
object.put("url", entity.getUrl());
|
||||
object.put("duration", formatDuration(entity.getLength()));
|
||||
object.put("id", entity.getId());
|
||||
exec("javascript:RE.insertCustomVideo('" + object.toString() + "');");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private String formatDuration(long seconds) {
|
||||
long absSeconds = Math.abs(seconds);
|
||||
@SuppressLint("DefaultLocale") String positive = String.format(
|
||||
"%02d:%02d",
|
||||
absSeconds / 60,
|
||||
absSeconds % 60);
|
||||
return seconds < 0 ? "-" + positive : positive;
|
||||
}
|
||||
|
||||
public void hideLinkStyle() {
|
||||
exec("javascript:RE.hideLinkStyle();");
|
||||
}
|
||||
@ -558,9 +583,8 @@ public class RichEditor extends WebView {
|
||||
|
||||
class NativeCallBack {
|
||||
|
||||
@SuppressLint("JavascriptInterface")
|
||||
@JavascriptInterface
|
||||
boolean isNativeBuildDebug() {
|
||||
public boolean isNativeBuildDebug() {
|
||||
return "internal".equals(BuildConfig.FLAVOR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.RectF
|
||||
import android.text.style.ReplacementSpan
|
||||
import androidx.annotation.Dimension
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
class RoundStrokeBackgroundColorSpan(private val strokeColor: Int,
|
||||
private val textColor: Int,
|
||||
private val strokeWidth: Int = 2,
|
||||
@Dimension(unit = Dimension.PX)
|
||||
private val textSize: Int = 0) : ReplacementSpan() {
|
||||
|
||||
private var halfStrokeWidth = 0
|
||||
|
||||
init {
|
||||
halfStrokeWidth = strokeWidth / 2
|
||||
}
|
||||
|
||||
override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int {
|
||||
return paint.measureText(text, start, end).toInt()
|
||||
}
|
||||
|
||||
override fun draw(canvas: Canvas, text: CharSequence, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {
|
||||
val originalColor = paint.color
|
||||
paint.color = this.strokeColor
|
||||
paint.style = Paint.Style.STROKE
|
||||
paint.strokeWidth = strokeWidth.toFloat()
|
||||
if (textSize != 0) {
|
||||
paint.textSize = textSize.toFloat()
|
||||
}
|
||||
val fontMetrics = paint.fontMetrics
|
||||
canvas.drawRoundRect(RectF(
|
||||
x + halfStrokeWidth,
|
||||
top.toFloat() + halfStrokeWidth,
|
||||
x + halfStrokeWidth + paint.measureText(text, start, end).toInt(),
|
||||
top + fontMetrics.bottom - fontMetrics.top + strokeWidth * 2 - halfStrokeWidth),
|
||||
DisplayUtils.dip2px(HaloApp.getInstance().application, 3f).toFloat(),
|
||||
DisplayUtils.dip2px(HaloApp.getInstance().application, 3f).toFloat(),
|
||||
paint)
|
||||
|
||||
paint.color = this.textColor
|
||||
paint.style = Paint.Style.FILL
|
||||
paint.strokeWidth = 0f
|
||||
canvas.drawText(text, start, end, x + halfStrokeWidth, y.toFloat() - strokeWidth, paint)
|
||||
|
||||
paint.color = originalColor
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
|
||||
class ScrimAwareCollapsingToolbarLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
|
||||
: CollapsingToolbarLayout(context, attrs) {
|
||||
|
||||
var scrimShownAction: ((shown: Boolean) -> Unit)? = null
|
||||
|
||||
override fun setScrimsShown(shown: Boolean) {
|
||||
scrimShownAction?.invoke(shown)
|
||||
|
||||
super.setScrimsShown(shown)
|
||||
}
|
||||
}
|
||||
18
app/src/main/java/com/gh/common/view/StatusBarView.kt
Normal file
18
app/src/main/java/com/gh/common/view/StatusBarView.kt
Normal file
@ -0,0 +1,18 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import com.gh.common.util.DisplayUtils
|
||||
|
||||
class StatusBarView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
val height = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
0
|
||||
} else {
|
||||
DisplayUtils.getStatusBarHeight(resources)
|
||||
}
|
||||
setMeasuredDimension(View.MeasureSpec.getSize(widthMeasureSpec), height)
|
||||
}
|
||||
}
|
||||
@ -1,88 +1,99 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
/**
|
||||
* Created by khy on 2/12/17.
|
||||
*/
|
||||
|
||||
public class TabIndicatorView extends View implements ViewPager.OnPageChangeListener {
|
||||
|
||||
|
||||
private TabLayout mTabLayout;
|
||||
|
||||
|
||||
private int mIndicatorSpace;
|
||||
|
||||
|
||||
private int mIndicatorHeight;
|
||||
|
||||
|
||||
private int mIndicatorWidth;
|
||||
|
||||
|
||||
|
||||
private int mIndicatorColor = 0;
|
||||
|
||||
private GradientDrawable mGradientDrawable;
|
||||
|
||||
public TabIndicatorView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
|
||||
public TabIndicatorView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
|
||||
public TabIndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabIndicatorView);
|
||||
if (a.hasValue(R.styleable.TabIndicatorView_indicatorColor)) {
|
||||
mIndicatorColor = a.getColor(R.styleable.TabIndicatorView_indicatorColor, 0);
|
||||
mGradientDrawable = new GradientDrawable();
|
||||
mGradientDrawable.setShape(GradientDrawable.RECTANGLE);
|
||||
mGradientDrawable.setColor(mIndicatorColor);
|
||||
mGradientDrawable.setCornerRadius(Integer.MAX_VALUE);
|
||||
}
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
mIndicatorHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||
}
|
||||
|
||||
|
||||
public void setupWithTabLayout(final TabLayout tableLayout) {
|
||||
mTabLayout = tableLayout;
|
||||
|
||||
|
||||
tableLayout.setSelectedTabIndicatorColor(Color.TRANSPARENT);
|
||||
tableLayout.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
|
||||
@Override
|
||||
public void onScrollChanged() {
|
||||
if (mTabLayout.getScrollX() != getScrollX())
|
||||
scrollTo(mTabLayout.getScrollX(), mTabLayout.getScrollY());
|
||||
}
|
||||
tableLayout.getViewTreeObserver().addOnScrollChangedListener(() -> {
|
||||
if (mTabLayout.getScrollX() != getScrollX())
|
||||
scrollTo(mTabLayout.getScrollX(), mTabLayout.getScrollY());
|
||||
});
|
||||
|
||||
|
||||
ViewCompat.setElevation(this, ViewCompat.getElevation(mTabLayout));
|
||||
|
||||
|
||||
//清除Tab background
|
||||
for (int tab = 0; tab < tableLayout.getTabCount(); tab++) {
|
||||
View tabView = getTabViewByPosition(tab);
|
||||
if (tabView != null) tabView.setBackgroundResource(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setupWithViewPager(ViewPager viewPager) {
|
||||
viewPager.addOnPageChangeListener(this);
|
||||
}
|
||||
|
||||
|
||||
public void setIndicatorWidth(int width) {
|
||||
if (width > 0) this.mIndicatorWidth = DisplayUtils.dip2px(getContext(), width);
|
||||
}
|
||||
|
||||
|
||||
public void setIndicatorSpace(int space) {
|
||||
this.mIndicatorSpace = DisplayUtils.dip2px(getContext(), space);
|
||||
}
|
||||
|
||||
|
||||
private int getIndicatorSpace() {
|
||||
if (mIndicatorSpace != 0) return mIndicatorSpace;
|
||||
if (mIndicatorWidth != 0) {
|
||||
@ -91,88 +102,91 @@ public class TabIndicatorView extends View implements ViewPager.OnPageChangeList
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
Drawable drawable = getResources().getDrawable(R.drawable.ask_tab_indicator_bg); // 固定Indicator背景 有需要可以自行更改
|
||||
Drawable drawable;
|
||||
if (mGradientDrawable != null) {
|
||||
drawable = mGradientDrawable;
|
||||
} else {
|
||||
drawable = getResources().getDrawable(R.drawable.ask_tab_indicator_bg); // 固定Indicator背景 有需要可以自行更改
|
||||
}
|
||||
drawable.setBounds(l, t, r, b);
|
||||
drawable.draw(canvas);
|
||||
}
|
||||
|
||||
|
||||
int l;
|
||||
int t;
|
||||
int r;
|
||||
int b;
|
||||
|
||||
private void generatePath(int position, float positionOffset) {
|
||||
|
||||
|
||||
public void generatePath(int position, float positionOffset) {
|
||||
RectF range = new RectF();
|
||||
View tabView = getTabViewByPosition(position);
|
||||
|
||||
if (tabView == null)
|
||||
return;
|
||||
|
||||
|
||||
if (tabView == null) return;
|
||||
|
||||
int left, top, right, bottom;
|
||||
left = top = right = bottom = 0;
|
||||
|
||||
|
||||
if (positionOffset > 0.f && position < mTabLayout.getTabCount() - 1) {
|
||||
View nextTabView = getTabViewByPosition(position + 1);
|
||||
if (nextTabView != null) {
|
||||
left += (int) (nextTabView.getLeft() * positionOffset + tabView.getLeft() * (1.f - positionOffset));
|
||||
right += (int) (nextTabView.getRight() * positionOffset + tabView.getRight() * (1.f - positionOffset));
|
||||
}
|
||||
|
||||
|
||||
left += getIndicatorSpace();
|
||||
right -= getIndicatorSpace();
|
||||
top = tabView.getTop() + getPaddingTop();
|
||||
bottom = tabView.getBottom() - getPaddingBottom();
|
||||
range.set(left, top, right, bottom);
|
||||
} else {
|
||||
|
||||
|
||||
left = tabView.getLeft() + getIndicatorSpace();
|
||||
right = tabView.getRight() - getIndicatorSpace();
|
||||
top = tabView.getTop() + getPaddingTop();
|
||||
bottom = tabView.getBottom() - getPaddingBottom();
|
||||
range.set(left, top, right, bottom);
|
||||
|
||||
if (range.isEmpty())
|
||||
return;
|
||||
|
||||
if (range.isEmpty()) return;
|
||||
}
|
||||
r = right;
|
||||
l = left;
|
||||
t = top;
|
||||
b = top + mIndicatorHeight;
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
private View getTabViewByPosition(int position) {
|
||||
if (mTabLayout != null && mTabLayout.getTabCount() > 0) {
|
||||
ViewGroup tabStrip = (ViewGroup) mTabLayout.getChildAt(0);
|
||||
return tabStrip != null ? tabStrip.getChildAt(position) : null;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
generatePath(position, positionOffset);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (mTabLayout.getSelectedTabPosition() != position) {
|
||||
TabLayout.Tab tab = mTabLayout.getTabAt(position);
|
||||
if (tab != null) tab.select();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
25
app/src/main/java/com/gh/common/view/WrapHeightViewPager.kt
Normal file
25
app/src/main/java/com/gh/common/view/WrapHeightViewPager.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
|
||||
class WrapHeightViewPager @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : ViewPager(context, attrs) {
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
var height = 0
|
||||
for (i in 0 until childCount) {
|
||||
val child = getChildAt(i)
|
||||
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
|
||||
val h = child.measuredHeight
|
||||
if (h > height) height = h
|
||||
}
|
||||
|
||||
val resultHeightMeasureSpec = if (height != 0) {
|
||||
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
|
||||
} else {
|
||||
heightMeasureSpec
|
||||
}
|
||||
super.onMeasure(widthMeasureSpec, resultHeightMeasureSpec)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user