Compare commits
363 Commits
v3.7.1
...
v3.7.2-bug
| Author | SHA1 | Date | |
|---|---|---|---|
| c118d7e4ad | |||
| babc55739b | |||
| df8790c6ff | |||
| 30ccdcd750 | |||
| 79d23bb203 | |||
| b2c5e6551b | |||
| ec49d7f20a | |||
| 5a35d13d70 | |||
| dcfa4fdaaf | |||
| 43324ca44e | |||
| 8e778e8172 | |||
| 928a98831e | |||
| 3dc678bc27 | |||
| d2b19a128d | |||
| cc75cb497d | |||
| 4840c5c604 | |||
| 347cfdb72d | |||
| 06ec87ba6d | |||
| 1206800a3d | |||
| d4763468c1 | |||
| 9c1a186a28 | |||
| bd9b914c18 | |||
| d40a57bcaa | |||
| 1892758288 | |||
| ca2e26756a | |||
| ed5696f4bd | |||
| cee34e7d76 | |||
| 54decbade3 | |||
| 11167670f8 | |||
| 37c7629cf0 | |||
| 947236f85d | |||
| eafa13ec76 | |||
| 7258812537 | |||
| e0a82f5050 | |||
| e0e7cbd2a3 | |||
| 554ec20493 | |||
| 31c3ed3bc5 | |||
| 466b690ac0 | |||
| 0420557f47 | |||
| c0edbf1a57 | |||
| 374610dbc0 | |||
| 080ac5f1d5 | |||
| 9dc967087d | |||
| 80a238253d | |||
| d7b7f11ebf | |||
| 9abb14e37f | |||
| 5fbb93cbee | |||
| 20b75ff046 | |||
| 73374017a5 | |||
| 73c3d5cd4d | |||
| 01a02a000f | |||
| 8998f1323f | |||
| bb77cf4624 | |||
| 772705ed0f | |||
| 6e2f568ad3 | |||
| df20c8235e | |||
| 4882cc5203 | |||
| 4fa6a41681 | |||
| f77e9d4949 | |||
| 1bc167fe7b | |||
| 98213ad3ee | |||
| 0b101d693d | |||
| 8655822d88 | |||
| 386923d16e | |||
| 013536b147 | |||
| 880eef90fb | |||
| 61e3784991 | |||
| 0664d92e62 | |||
| aab99b0c29 | |||
| 2e6ca9c524 | |||
| 0a402e4e92 | |||
| 7e75cd7859 | |||
| e3522d4160 | |||
| c9d0b813b6 | |||
| 3a7e28fac2 | |||
| 9aca24c02b | |||
| 9c818e1470 | |||
| 614ed0e7e2 | |||
| 55b1d43e73 | |||
| 25526f3666 | |||
| 773f2e798d | |||
| 58b5ec4eb9 | |||
| 007cef39a7 | |||
| ba1a702ea1 | |||
| 56d8b58f72 | |||
| f53c8377e6 | |||
| cfb1d86e8e | |||
| 8f0caa0949 | |||
| 8ef13cb4ff | |||
| e6d4f60d4f | |||
| e67f85c084 | |||
| 5318693650 | |||
| 3bf242b145 | |||
| 0ba82a334e | |||
| 0a385bb720 | |||
| 7658fd2a4f | |||
| e40e655bfa | |||
| cfa000bf88 | |||
| 12c35cebc4 | |||
| 92089e60ce | |||
| 141a6df8ab | |||
| 7719e9763d | |||
| 8d3307986d | |||
| d0b7ec39a7 | |||
| cfd198b4ab | |||
| a557c12c6d | |||
| 6b777d4ec8 | |||
| 882dd95190 | |||
| 7764bd29c8 | |||
| 08730f1ce9 | |||
| f9c15d3427 | |||
| 8e8668036e | |||
| cc65eed48d | |||
| 29f4e547a1 | |||
| 419003ae23 | |||
| 0519872d81 | |||
| e9b52bb70b | |||
| 681ea201c3 | |||
| a5466bb6ad | |||
| 3a3998ae84 | |||
| 7e27502430 | |||
| 8956885f1c | |||
| caeb0a1362 | |||
| cc094889b8 | |||
| 839386c5f4 | |||
| 6c5de65278 | |||
| 3aadac942c | |||
| dca9b49d75 | |||
| 8e764dc22a | |||
| 383cf4941e | |||
| 05510a8588 | |||
| eb611a9ff1 | |||
| 15aa3713e6 | |||
| 7d11713c49 | |||
| 66ff610078 | |||
| f351761d9e | |||
| 6bb5e18253 | |||
| c44e8cffcc | |||
| 39d4c35504 | |||
| d42b57f385 | |||
| 2142a1676e | |||
| b0fa41bded | |||
| 28f552ca19 | |||
| da0b256054 | |||
| 8b477c357a | |||
| 650075488d | |||
| 8cff41defa | |||
| 6519eca511 | |||
| 85d8463972 | |||
| c762a7c755 | |||
| 142859fd39 | |||
| d7f84ff3c8 | |||
| 6c4545e364 | |||
| a3d9f12414 | |||
| 412d2ff9dc | |||
| 65f8440637 | |||
| f06359f5c3 | |||
| 433088116e | |||
| c93e55f306 | |||
| e613066ed3 | |||
| 9aabfde5b0 | |||
| 9f4c9431b9 | |||
| 74f64d9782 | |||
| d79b3f10e8 | |||
| b29d32c8f2 | |||
| b8ec93c6a1 | |||
| dad3c9aee7 | |||
| 833e0406f0 | |||
| 3d6b556dfd | |||
| ad0a5525f0 | |||
| a012c3e3de | |||
| 6c2d489940 | |||
| 0ea56b01eb | |||
| f65c226657 | |||
| 006b82381b | |||
| 059414b9f8 | |||
| 93c1105346 | |||
| 7ca92e8b7f | |||
| eeb7415086 | |||
| 9a288e8870 | |||
| 351fefd57b | |||
| 4915cdc3ba | |||
| 9d044a4001 | |||
| 8e465c17dd | |||
| fa73ac790c | |||
| 899f442f14 | |||
| 698af5d584 | |||
| 66dea77546 | |||
| eed2eed992 | |||
| 913c0027a6 | |||
| a7884325c8 | |||
| a7caa063ef | |||
| ee99895cba | |||
| cf7a14e80a | |||
| 07a64d118a | |||
| 72329d0222 | |||
| 16e85e9222 | |||
| dd11883eab | |||
| be70ce8551 | |||
| d428c46957 | |||
| 516b956269 | |||
| 8bb90f4d4c | |||
| 2f9e9fe976 | |||
| bf2271ac06 | |||
| f279564e02 | |||
| 386eafa0bc | |||
| 619b5a3cc3 | |||
| d0391c779d | |||
| fc9d3f2e91 | |||
| 42c7123d2d | |||
| 8e66f80360 | |||
| b80fab06ad | |||
| 943c359c22 | |||
| 8631045874 | |||
| 5991a90353 | |||
| 8534455344 | |||
| 1a21fceeb7 | |||
| 274739c885 | |||
| 5134fa19be | |||
| 7342e94bdc | |||
| 28bf579518 | |||
| 9e490ef349 | |||
| 548206792e | |||
| c87d7f9c28 | |||
| cfe1584fc3 | |||
| 137a95f5ab | |||
| 6ab8b24353 | |||
| 1515cc1ddd | |||
| abfd4834ef | |||
| 03032a0dbd | |||
| 75545a5929 | |||
| 1425a95bc8 | |||
| 23674a1c55 | |||
| caf0a8d5f5 | |||
| b11928528c | |||
| cf9bd70c6c | |||
| c6ab68e9b4 | |||
| 899da43682 | |||
| 1825f713b3 | |||
| 760bc9b63c | |||
| 4974c105bf | |||
| 9c910ce6de | |||
| fcd1c2d418 | |||
| 5c0c227c3b | |||
| a69669a7ca | |||
| 166e2e341a | |||
| 8cb689cc99 | |||
| 1dd5c5fd40 | |||
| 92719c538e | |||
| 3448dfddef | |||
| b190b31afa | |||
| 083a62ed9d | |||
| 5f0bfd1184 | |||
| 15bb7d654c | |||
| f42278b91f | |||
| aa23d515c6 | |||
| b3417749ed | |||
| 4c33977568 | |||
| 1ecd83b6af | |||
| b202302a7e | |||
| 7450edd177 | |||
| 4c7ab844e8 | |||
| fd6581671d | |||
| 71cc0962d3 | |||
| 9c70d802b5 | |||
| ed6bec0cfc | |||
| 36834cfec7 | |||
| 7dfaf45dc2 | |||
| 5efddb05b3 | |||
| f46122787c | |||
| 1b8cde1c91 | |||
| 1694603cd0 | |||
| 4243f37126 | |||
| 63e0b9887c | |||
| 201efd9628 | |||
| c7c29b7ca8 | |||
| 0b3fd3a123 | |||
| 99e988a0d9 | |||
| eaa3b81e31 | |||
| dbbf9a846e | |||
| af8b336434 | |||
| ce84c0f9c9 | |||
| 0f8d9cd5d3 | |||
| cb70e12632 | |||
| a5ad403614 | |||
| e674a8313a | |||
| 1cef4bb53d | |||
| 3851aeb790 | |||
| 7680e2e125 | |||
| f674aa4a79 | |||
| be1533a5df | |||
| eca3bdd4e5 | |||
| c885579516 | |||
| 341d849e29 | |||
| 2bb5c79c38 | |||
| fa26e1a17b | |||
| 8ed76089eb | |||
| 678418da0b | |||
| 1c11fc4469 | |||
| 78f277fd6d | |||
| 5520fd7122 | |||
| cb6ce2e14f | |||
| 80933e82eb | |||
| e32dce2ef9 | |||
| e252a9ebf8 | |||
| 08936a22c8 | |||
| 3fea57d05f | |||
| 52ae5fc451 | |||
| 045dea265d | |||
| 501282f243 | |||
| 998cf70723 | |||
| 1a10fcac71 | |||
| ee5862eddd | |||
| c1527ec37e | |||
| eb112b358e | |||
| b860ab912a | |||
| b14ee68882 | |||
| 44065fcb06 | |||
| ec5305b76f | |||
| ddfb651d6a | |||
| 8a828a3250 | |||
| 31f5795e27 | |||
| dbde817b59 | |||
| 83e251492d | |||
| 5fa22c7f5d | |||
| b4ad18c806 | |||
| 61eb35cf31 | |||
| 07e54d5b5e | |||
| e0c27f721c | |||
| d2bf6bb211 | |||
| e2681494db | |||
| ac1d078681 | |||
| 624d9c1e2d | |||
| 892cc3cdde | |||
| fd7b9263bf | |||
| a9428ddb3b | |||
| 319f526e0f | |||
| 4755542933 | |||
| f221e20169 | |||
| a149666d3a | |||
| 0ff428b61a | |||
| cfedc72955 | |||
| 16de588c30 | |||
| 779d907397 | |||
| f91e2e41b6 | |||
| a04e4874f3 | |||
| d303b67e35 | |||
| 31c0c43d14 | |||
| fafb73d03c | |||
| e4ee4d9efe | |||
| 3a043b2704 | |||
| 8c9c7309a5 | |||
| 09330e9cbf | |||
| 08ad62dc70 | |||
| 464482a507 | |||
| d449b1266f | |||
| 6d0c4b18d6 | |||
| a83d1b5761 | |||
| 99d564278e | |||
| 482f45d43f | |||
| 21335a843a | |||
| d02a527b36 | |||
| 75883e11d8 |
@ -207,6 +207,7 @@ dependencies {
|
||||
|
||||
implementation "com.facebook.fresco:fresco:${fresco}"
|
||||
implementation "com.facebook.fresco:animated-gif:${fresco}"
|
||||
implementation "com.facebook.fresco:animated-drawable:${fresco}"
|
||||
|
||||
implementation "com.squareup.okhttp3:okhttp:${okHttp}"
|
||||
|
||||
@ -259,7 +260,9 @@ dependencies {
|
||||
implementation "com.squareup.picasso:picasso:${picasso}"
|
||||
|
||||
// for video streaming
|
||||
implementation "com.shuyu:gsyVideoPlayer-java:$gsyVideo"
|
||||
implementation ("com.shuyu:gsyVideoPlayer-java:$gsyVideo",{
|
||||
exclude module: "gsyvideoplayer-androidvideocache"
|
||||
})
|
||||
implementation "com.shuyu:gsyVideoPlayer-armv7a:$gsyVideo"
|
||||
implementation "com.shuyu:gsyVideoPlayer-x86:$gsyVideo"
|
||||
|
||||
@ -278,20 +281,25 @@ dependencies {
|
||||
|
||||
debugImplementation "com.github.nichbar.chucker:library:$chucker"
|
||||
releaseImplementation "com.github.nichbar.chucker:library-no-op:$chucker"
|
||||
implementation "com.bytedance.applog:RangersAppLog-Lite-cn:$bytedanceApplog"
|
||||
|
||||
implementation 'com.aliyun.dpa:oss-android-sdk:2.9.2'
|
||||
|
||||
implementation "com.airbnb.android:lottie:$lottie"
|
||||
|
||||
implementation("com.github.piasy:BigImageViewer:$bigImageViewer", {
|
||||
exclude group: 'com.squareup.okhttp3'
|
||||
})
|
||||
|
||||
implementation project(':libraries:LGLibrary')
|
||||
implementation project(':libraries:MTA')
|
||||
implementation project(':libraries:QQShare')
|
||||
implementation project(':libraries:TalkingData')
|
||||
implementation project(':libraries:UmengPush')
|
||||
// implementation project(':libraries:WechatShare')
|
||||
implementation project(':libraries:LogHub')
|
||||
implementation project(':libraries:im')
|
||||
implementation project(':libraries:Matisse')
|
||||
implementation project(path: ':libraries:gsyVideoPlayer-proxy_cache')
|
||||
}
|
||||
File propFile = file('sign.properties')
|
||||
if (propFile.exists()) {
|
||||
|
||||
Binary file not shown.
@ -28,6 +28,10 @@
|
||||
<!-- 修改系统设置的权限 -->
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.PACKAGE_USAGE_STATS"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
|
||||
<!-- bugly with tinker -->
|
||||
<uses-permission android:name="android.permission.READ_LOGS" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
@ -37,7 +41,8 @@
|
||||
com.shuyu.gsyvideoplayer.armv7a,
|
||||
com.shuyu.gsyvideoplayer.x86,
|
||||
com.shuyu.gsy.base,
|
||||
shuyu.com.androidvideocache" />
|
||||
shuyu.com.androidvideocache,
|
||||
pl.droidsonroids.gif" />
|
||||
|
||||
<!-- 去掉 SDK 一些流氓权限 -->
|
||||
<uses-permission
|
||||
@ -78,6 +83,7 @@
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.MainActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppCompatTheme.APP"
|
||||
@ -190,10 +196,6 @@
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SuggestSelectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SuggestionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -448,6 +450,19 @@
|
||||
android:name="com.gh.gamecenter.game.upload.GameSubmissionActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.halo.assistant.fragment.user.UserPortraitCropImageActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.HelpAndFeedbackActivity"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.help.HelpDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.comment.CommentActivity"
|
||||
android:screenOrientation="portrait"
|
||||
@ -456,8 +471,12 @@
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.video.detail.VideoDetailActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar" />
|
||||
<activity
|
||||
android:name=".gamedetail.myrating.MyRatingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!-- 使用小米/华为推送弹窗功能提高推送成功率-->
|
||||
<activity
|
||||
|
||||
1
app/src/main/assets/lottie/click_guide.json
Normal file
1
app/src/main/assets/lottie/click_guide.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.5.9","fr":60,"ip":0,"op":90,"w":1080,"h":202,"nm":"click","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"椭圆形","sr":1,"ks":{"o":{"a":0,"k":20,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204,1455,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[24,24],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"椭圆形","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":63,"s":[10]},{"t":70,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[204,1455,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":39,"s":[100,100,100]},{"t":49,"s":[110,110,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[36,36],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"圆环","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.531],"y":[0]},"t":28,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":38,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.526],"y":[0]},"t":48,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.446],"y":[0]},"t":63,"s":[50]},{"t":82,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[125.951,79.658,0],"ix":2},"a":{"a":0,"k":[205.951,1458.658,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.601,0.601,0.333],"y":[0,0,0]},"t":28,"s":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.528,0.528,0.333],"y":[0,0,0]},"t":38,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.526,0.526,0.333],"y":[0,0,0]},"t":48,"s":[120,120,100]},{"t":63,"s":[100,100,100]}],"ix":6}},"ao":0,"w":1080,"h":1920,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"点击手","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.596],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.515],"y":[0]},"t":63,"s":[100]},{"t":83,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.507],"y":[0]},"t":10,"s":[6]},{"t":30,"s":[2]}],"ix":10},"p":{"a":0,"k":[178.982,123.325,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.489,0.489,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"t":30,"s":[90,90,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-5.33,-8.3],[3.89,0.27],[-4.4,-1.68],[-4.33,-0.67],[-4.08,9.32],[3.33,5.44],[3.39,4.6],[0.87,-3.7],[3.6,-0.86],[1.03,-0.21],[2.34,-0.53],[0.96,1.15],[4.22,5.48],[-1.18,-4.56]],"o":[[1.11,1.71],[-3.89,-0.27],[6.42,2.5],[4.33,0.66],[1.63,-5.32],[-3.34,-5.45],[-1.68,-2.1],[-0.71,3.14],[-3.43,0.95],[-0.57,0.08],[-3.86,1.12],[-3.23,-3.94],[-1.89,-2.28],[2.42,4.64]],"v":[[-5.387,9.698],[-10.717,8.498],[-12.327,15.628],[5.813,21.748],[23.313,11.778],[20.273,-1.202],[11.563,-13.962],[5.393,-12.362],[1.083,-13.722],[-2.087,-9.742],[-5.707,-11.752],[-8.777,-7.572],[-18.297,-20.542],[-23.827,-17.832]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"路径备份 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}],"markers":[]}
|
||||
1
app/src/main/assets/lottie/slide_guide.json
Normal file
1
app/src/main/assets/lottie/slide_guide.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.5.9","fr":60,"ip":0,"op":120,"w":1080,"h":586,"nm":"上滑","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"手","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.642],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.558],"y":[0]},"t":60,"s":[100]},{"t":71,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.479,"y":0},"t":3,"s":[611,475,0],"to":[0,-62.75,0],"ti":[0,62.75,0]},{"t":40,"s":[611,98.5,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[90,90,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-7.78,-12.06],[5.68,0.39],[-6.42,-2.45],[-6.32,-0.97],[-5.95,13.55],[4.87,7.91],[4.94,6.69],[1.26,-5.37],[5.25,-1.25],[1.5,-0.3],[3.4,-0.77],[1.4,1.68],[6.15,7.98],[-1.73,-6.64]],"o":[[1.62,2.49],[-5.68,-0.39],[9.37,3.63],[6.31,0.98],[2.39,-7.74],[-4.87,-7.92],[-2.45,-3.05],[-1.05,4.57],[-4.99,1.39],[-0.83,0.13],[-5.63,1.63],[-4.71,-5.72],[-2.75,-3.31],[3.52,6.76]],"v":[[-7.86,14.26],[-15.64,12.52],[-17.99,22.89],[8.47,31.78],[33.98,17.29],[29.55,-1.59],[16.85,-20.15],[7.86,-17.83],[1.56,-19.8],[-3.05,-14.02],[-8.33,-16.94],[-12.44,-11.045],[-26.761,-30.19],[-34.75,-25.78]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"路径","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"矩形","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.715],"y":[0]},"t":57,"s":[100]},{"t":67,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[525,228.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.491,"y":0},"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[24.328,180.5],[-22,180.5],[-22,204.5],[24.328,204.5]],"c":true}]},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[24.328,-207.5],[-22,-207.5],[-22,204.5],[24.328,204.5]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"蒙版 1"}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[6,137],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":2,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,1,1,1,1,1,1,1,0,1,0.5,0.5,1,0],"ix":9}},"s":{"a":0,"k":[0,-68.5],"ix":5},"e":{"a":0,"k":[0,68.5],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":33,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":3,"op":123,"st":3,"bm":0}],"markers":[]}
|
||||
1
app/src/main/assets/lottie/tab_game.json
Normal file
1
app/src/main/assets/lottie/tab_game.json
Normal file
File diff suppressed because one or more lines are too long
1
app/src/main/assets/lottie/tab_home.json
Normal file
1
app/src/main/assets/lottie/tab_home.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.5.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"tab_index","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"椭圆形备份","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.596],"y":[0]},"t":0,"s":[0]},{"t":6,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,40.493,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.54,0.54,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.555,0.555,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.552,0.552,0.333],"y":[0,0,0]},"t":13,"s":[90,90,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[5,5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.635],"y":[0]},"t":0,"s":[0]},{"t":8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆形备份","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-0.5,"op":59.5,"st":-0.5,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"路径备份","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,32.993,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.508,0.508,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.488,0.488,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.502,0.502,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.534,0.534,0.333],"y":[0,0,0]},"t":13,"s":[95,95,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.24,-1.21],[-1.93,-1.89],[-0.24,-0.57],[0,-0.06],[0,-2.63],[1.76,0],[0,0],[0,1.72],[0,2.63],[-0.24,0.61],[-0.03,0.02],[-1.93,1.89]],"o":[[1.92,1.89],[0.02,0.02],[0.24,0.57],[0,2.63],[0,1.72],[0,0],[-1.76,0],[0,-2.62],[0,-0.07],[0.25,-0.61],[1.92,-1.89],[1.24,-1.21]],"v":[[2.26,-9.09],[8.03,-3.42],[8.76,-2.38],[9,-1.02],[9,6.88],[5.82,10],[-5.82,10],[-9,6.88],[-9,-0.99],[-8.71,-2.38],[-8.01,-3.43],[-2.23,-9.09]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.266,0.638,1,0.5,0.242,0.595,1,1,0.217,0.552,1],"ix":9}},"s":{"a":0,"k":[-4.902,-4.663],"ix":5},"e":{"a":0,"k":[8.159,8.646],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"路径备份","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]}
|
||||
1
app/src/main/assets/lottie/tab_video.json
Normal file
1
app/src/main/assets/lottie/tab_video.json
Normal file
@ -0,0 +1 @@
|
||||
{"v":"5.5.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"tab_video","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 1","parent":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.771],"y":[0]},"t":0,"s":[0]},{"t":5,"s":[100]}],"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-3.742,6.835,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[30.937,31.042,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sr","sy":2,"d":1,"pt":{"a":0,"k":3,"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":0,"k":0,"ix":5},"or":{"a":0,"k":29.286,"ix":7},"os":{"a":0,"k":75,"ix":9},"ix":1,"nm":"多边星形路径 1","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":13,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-20.75,-13.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[102.743,88.578],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"多边星形 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.657],"y":[0]},"t":0,"s":[0]},{"t":8,"s":[100]}],"ix":2},"o":{"a":0,"k":-115,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"路径 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33.004,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.508,0.508,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.488,0.488,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.502,0.502,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.534,0.534,0.333],"y":[0,0,0]},"t":13,"s":[95,95,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.16,0.38],[3.22,-0.55],[0.38,-2.16],[-0.55,-3.22],[-2.16,-0.38],[-1.63,0],[-1.61,0.27],[-0.38,2.16],[0.55,3.22]],"o":[[-0.38,-2.16],[-3.22,-0.55],[-2.16,0.38],[-0.55,3.22],[0.38,2.16],[1.61,0.27],[1.63,0],[2.16,-0.38],[0.55,-3.22],[0,0]],"v":[[9.09,-4.86],[4.86,-9.09],[-4.86,-9.09],[-9.09,-4.86],[-9.09,4.86],[-4.86,9.09],[0,9.5],[4.86,9.09],[9.09,4.86],[9.09,-4.86]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.266,0.638,1,0.5,0.242,0.595,1,1,0.217,0.552,1],"ix":9}},"s":{"a":0,"k":[-5.174,-4.43],"ix":5},"e":{"a":0,"k":[8.612,8.214],"ix":6},"t":1,"nm":"Gradient Fill 3","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"路径","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]}
|
||||
@ -63,6 +63,12 @@ RE.setHtml = function(contents) {
|
||||
RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
|
||||
}
|
||||
|
||||
// 后续初始化html代码,都用该方法
|
||||
RE.setHtmlByVideoStatus = function(contents) {
|
||||
RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
RE.getHtml = function() {
|
||||
return RE.editor.innerHTML;
|
||||
}
|
||||
|
||||
BIN
app/src/main/assets/tab_community.gif
Normal file
BIN
app/src/main/assets/tab_community.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
BIN
app/src/main/assets/tab_mine.gif
Normal file
BIN
app/src/main/assets/tab_mine.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@ -9,23 +9,17 @@ import android.text.TextUtils;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.common.util.StringUtils;
|
||||
import com.gh.common.util.TeaHelper;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.LoginActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.SuggestionActivity;
|
||||
import com.gh.gamecenter.eventbus.EBShowDialog;
|
||||
import com.gh.gamecenter.suggest.SuggestType;
|
||||
import com.lightgame.BaseAppCompatActivity;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -39,6 +33,8 @@ import org.json.JSONObject;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import butterknife.ButterKnife;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
|
||||
@ -47,14 +43,13 @@ import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
/**
|
||||
* 只提供基础的服务(EventBus/ButterKnife/Share/GlobalDialog/Permissions)
|
||||
* <p>
|
||||
* 需要通道工具栏的页面请继承{@link ToolBarActivity}
|
||||
* 需要工具栏的页面请继承{@link ToolBarActivity}
|
||||
*/
|
||||
|
||||
public abstract class BaseActivity extends BaseAppCompatActivity implements EasyPermissions.PermissionCallbacks {
|
||||
|
||||
// global dialog key
|
||||
public final static String DOWNLOAD_HIJACK = "hijack";
|
||||
public final static String DOWNLOAD_NOT_FOUND = "notfound";
|
||||
public final static String LOGIN_EXCEPTION = "loginException";
|
||||
public final static String PLUGGABLE = "plugin";
|
||||
|
||||
@ -138,9 +133,9 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
shareSummary,
|
||||
shareType);
|
||||
if (shareType == ShareUtils.ShareType.game || shareType == ShareUtils.ShareType.plugin) {
|
||||
DataUtils.onEvent(this, "内容分享", shareTitle + shareSummary);
|
||||
MtaHelper.onEvent("内容分享", shareTitle + shareSummary);
|
||||
} else {
|
||||
DataUtils.onEvent(this, "内容分享", shareTitle);
|
||||
MtaHelper.onEvent("内容分享", shareTitle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,7 +144,7 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
|
||||
&& this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
if (DOWNLOAD_HIJACK.equals(showDialog.getType())) {
|
||||
DialogUtils.showQqSessionDialog(this, "2586716223");// 建议用户联系客服
|
||||
DialogUtils.showQqSessionDialog(this);// 建议用户联系客服
|
||||
} else if (PLUGGABLE.equals(showDialog.getType())) {
|
||||
DialogUtils.showPluginDialog(this, () -> {
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
@ -176,25 +171,17 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (DOWNLOAD_NOT_FOUND.equals(showDialog.getType())) {
|
||||
DialogUtils.showAlertDialog(this, "下载失败", "下载链接已失效,建议提交反馈"
|
||||
, "立即反馈", "取消"
|
||||
, () -> SuggestionActivity.startSuggestionActivity(this,
|
||||
SuggestType.gameQuestion, null,
|
||||
(showDialog.getPath() + ",问题反馈:下载链接失效")), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
TeaHelper.onPause(this);
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
TeaHelper.onResume(this);
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ import android.view.View
|
||||
import android.webkit.JavascriptInterface
|
||||
import butterknife.OnClick
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.view.RichEditor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
@ -68,7 +69,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
val game = data?.getParcelableExtra<GameEntity>(GameEntity::class.java.simpleName)
|
||||
if (game != null) insertData = EditorInsertEntity.transform(game)
|
||||
}
|
||||
INSERT_VIDEO_CODE -> {
|
||||
VideoActivity.INSERT_VIDEO_CODE -> {
|
||||
val video = data?.getParcelableExtra<MyVideoEntity>(MyVideoEntity::class.java.simpleName)
|
||||
if (video != null) mRichEditor.insertCustomVideo(video)
|
||||
return
|
||||
@ -126,19 +127,30 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
R.id.editor_font_bold -> {
|
||||
mEditorFontBold.isChecked = !mEditorFontBold.isChecked
|
||||
mRichEditor.setBold()
|
||||
if (mEditorFontBold.isChecked) {
|
||||
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-加粗")
|
||||
}
|
||||
}
|
||||
R.id.editor_font_italic -> {
|
||||
mEditorFontItalic.isChecked = !mEditorFontItalic.isChecked
|
||||
mRichEditor.setItalic()
|
||||
if (mEditorFontItalic.isChecked) {
|
||||
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-斜体")
|
||||
}
|
||||
}
|
||||
R.id.editor_font_strikethrough -> {
|
||||
mEditorFontStrikeThrough.isChecked = !mEditorFontStrikeThrough.isChecked
|
||||
mRichEditor.setStrikeThrough()
|
||||
|
||||
if (mEditorFontStrikeThrough.isChecked) {
|
||||
MtaHelper.onEvent(mtaEventName(), "文字样式", "文字样式-删除线")
|
||||
}
|
||||
}
|
||||
R.id.editor_paragraph_h1 -> {
|
||||
if (mEditorParagraphH1.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-1级标题")
|
||||
mRichEditor.setHeading(1)
|
||||
}
|
||||
mEditorParagraphH1.isChecked = !mEditorParagraphH1.isChecked
|
||||
@ -147,6 +159,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
if (mEditorParagraphH2.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-2级标题")
|
||||
mRichEditor.setHeading(2)
|
||||
}
|
||||
mEditorParagraphH2.isChecked = !mEditorParagraphH2.isChecked
|
||||
@ -155,6 +168,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
if (mEditorParagraphH3.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-3级标题")
|
||||
mRichEditor.setHeading(3)
|
||||
}
|
||||
mEditorParagraphH3.isChecked = !mEditorParagraphH3.isChecked
|
||||
@ -163,6 +177,7 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
if (mEditorParagraphH4.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-4级标题")
|
||||
mRichEditor.setHeading(4)
|
||||
}
|
||||
mEditorParagraphH4.isChecked = !mEditorParagraphH4.isChecked
|
||||
@ -171,21 +186,26 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
if (mEditorParagraphQuote.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
MtaHelper.onEvent(mtaEventName(), "段落样式", "段落样式-引用")
|
||||
mRichEditor.setBlockquote()
|
||||
}
|
||||
mEditorParagraphQuote.isChecked = !mEditorParagraphQuote.isChecked
|
||||
}
|
||||
R.id.editor_link_answer -> {
|
||||
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-回答")
|
||||
startActivityForResult(InsertAnswerWrapperActivity.getIntent(this), INSERT_ANSWER_CODE)
|
||||
}
|
||||
R.id.editor_link_article -> {
|
||||
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-文章")
|
||||
startActivityForResult(InsertArticleWrapperActivity.getIntent(this), INSERT_ARTICLE_CODE)
|
||||
}
|
||||
R.id.editor_link_game -> {
|
||||
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-游戏")
|
||||
startActivityForResult(GameActivity.getIntent(this, "插入游戏"), INSERT_GAME_CODE)
|
||||
}
|
||||
R.id.editor_link_video -> {
|
||||
startActivityForResult(VideoActivity.getIntent(this), INSERT_VIDEO_CODE)
|
||||
MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-视频")
|
||||
startActivityForResult(VideoActivity.getIntent(this), VideoActivity.INSERT_VIDEO_CODE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,6 +251,8 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun mtaEventName(): String
|
||||
|
||||
companion object {
|
||||
const val ELEMENT_NAME_BOLD = " b "
|
||||
const val ELEMENT_NAME_ITALIC = " i "
|
||||
@ -244,6 +266,5 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
|
||||
const val INSERT_ANSWER_CODE = 411
|
||||
const val INSERT_ARTICLE_CODE = 412
|
||||
const val INSERT_GAME_CODE = 413
|
||||
const val INSERT_VIDEO_CODE = 414
|
||||
}
|
||||
}
|
||||
@ -140,8 +140,9 @@ class GHUmengNotificationService : UmengMessageService() {
|
||||
|
||||
notificationManager.notify(getNotificationTag(context), NOTIFICATION_ID, notification)
|
||||
} else {
|
||||
if (UserManager.getInstance().isLoggedIn
|
||||
&& HALO_MESSAGE_DIALOG == pushData.body?.custom) {
|
||||
if (UserManager.getInstance().isLoggedIn &&
|
||||
HALO_MESSAGE_DIALOG == pushData.body?.custom &&
|
||||
MessageUnreadRepository.unreadLiveData.value != null) {
|
||||
// 回答了问题或者关注了问题的消息
|
||||
val msg = gson.fromJson(message, PushMessageEntity::class.java)
|
||||
val data = msg?.extra?.data
|
||||
|
||||
@ -5,6 +5,7 @@ import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
@ -193,10 +194,20 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
|
||||
private void updateDownloadCountHint(List<GameUpdateEntity> updateList) {
|
||||
if (mDownloadCountHint == null) return;
|
||||
|
||||
int count = DownloadManager.getInstance(getApplicationContext()).getDownloadOrUpdateCount(updateList);
|
||||
if (count != 0) {
|
||||
String count = DownloadManager.getInstance(getApplicationContext()).getDownloadOrUpdateCount(updateList);
|
||||
if (count != null) {
|
||||
mDownloadCountHint.setVisibility(View.VISIBLE);
|
||||
mDownloadCountHint.setText(String.valueOf(count));
|
||||
mDownloadCountHint.setText(count);
|
||||
|
||||
ViewGroup.LayoutParams params = mDownloadCountHint.getLayoutParams();
|
||||
if (TextUtils.isEmpty(count)) {
|
||||
params.width = DisplayUtils.dip2px(6);
|
||||
params.height = DisplayUtils.dip2px(6);
|
||||
} else {
|
||||
params.width = DisplayUtils.dip2px(12);
|
||||
params.height = DisplayUtils.dip2px(12);
|
||||
}
|
||||
mDownloadCountHint.setLayoutParams(params);
|
||||
} else {
|
||||
mDownloadCountHint.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@ -9,14 +9,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
import com.gh.base.OnListClickListener;
|
||||
import com.gh.base.OnRequestCallBackListener;
|
||||
import com.gh.common.constant.Constants;
|
||||
@ -33,6 +25,12 @@ import org.greenrobot.eventbus.ThreadMode;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
@ -185,7 +183,11 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
Utils.toast(getContext(), msg);
|
||||
try {
|
||||
Utils.toast(getContext(), msg);
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void toastLong(@StringRes int msg) {
|
||||
|
||||
@ -14,16 +14,16 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Checkable;
|
||||
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* ViewPager 配合ViewGroup Checkable实现双切换<br/>
|
||||
@ -78,7 +78,18 @@ public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_View
|
||||
public void onPageSelected(int index) {
|
||||
onPageChanged(index);
|
||||
try {
|
||||
// 补充Viewpager Fragment的生命周期
|
||||
// 补充Viewpager Fragment的生命周期, 先调用旧选中 fragment 的 onPause 再当前的 onResume
|
||||
if (mFragmentsList.size() > mLastPosition) {
|
||||
Fragment fragment = mFragmentsList.get(mLastPosition);
|
||||
fragment.onPause();
|
||||
|
||||
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
|
||||
List<Fragment> fragments = childFragmentManager.getFragments();
|
||||
for (Fragment childFragment : fragments) {
|
||||
childFragment.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
if (mFragmentsList.size() > index) {
|
||||
Fragment fragment = mFragmentsList.get(index);
|
||||
fragment.onResume();
|
||||
@ -89,17 +100,6 @@ public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_View
|
||||
childFragment.onResume();
|
||||
}
|
||||
}
|
||||
|
||||
if (mFragmentsList.size() > mLastPosition) {
|
||||
Fragment fragment = mFragmentsList.get(mLastPosition);
|
||||
fragment.onPause();
|
||||
|
||||
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
|
||||
List<Fragment> fragments = childFragmentManager.getFragments();
|
||||
for (Fragment childFragment : fragments) {
|
||||
childFragment.onPause();
|
||||
}
|
||||
}
|
||||
mLastPosition = index;
|
||||
} catch (Exception ignore) {
|
||||
|
||||
|
||||
163
app/src/main/java/com/gh/base/fragment/BaseLazyFragment.kt
Normal file
163
app/src/main/java/com/gh/base/fragment/BaseLazyFragment.kt
Normal file
@ -0,0 +1,163 @@
|
||||
package com.gh.base.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.normal.NormalFragment
|
||||
|
||||
/**
|
||||
* 懒加载(支持多层嵌套)
|
||||
*/
|
||||
abstract class BaseLazyFragment : NormalFragment() {
|
||||
|
||||
private var mIsFirstVisible = true
|
||||
|
||||
private var isViewCreated = false
|
||||
|
||||
private var isSupportVisible = false
|
||||
|
||||
/**
|
||||
* 用于分发可见时间的时候父获取 fragment 是否隐藏
|
||||
*
|
||||
* @return true fragment 不可见, false 父 fragment 可见
|
||||
*/
|
||||
private val isParentInvisible: Boolean
|
||||
get() {
|
||||
val parentFragment = parentFragment
|
||||
return if (parentFragment is BaseLazyFragment) {
|
||||
val fragment = parentFragment as BaseLazyFragment?
|
||||
!fragment!!.isSupportVisible
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
||||
super.setUserVisibleHint(isVisibleToUser)
|
||||
// 对于默认 tab 和 间隔 checked tab 需要等到 isViewCreated = true 后才可以通过此通知用户可见
|
||||
// 这种情况下第一次可见不是在这里通知 因为 isViewCreated = false 成立,等从别的界面回到这里后会使用 onFragmentResume 通知可见
|
||||
// 对于非默认 tab mIsFirstVisible = true 会一直保持到选择则这个 tab 的时候,因为在 onActivityCreated 会返回 false
|
||||
if (isViewCreated) {
|
||||
if (isVisibleToUser && !isSupportVisible) {
|
||||
dispatchUserVisibleHint(true)
|
||||
} else if (!isVisibleToUser && isSupportVisible) {
|
||||
dispatchUserVisibleHint(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
isViewCreated = true
|
||||
// !isHidden() 默认为 true 在调用 hide show 的时候可以使用
|
||||
if (!isHidden && userVisibleHint) {
|
||||
dispatchUserVisibleHint(true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onHiddenChanged(hidden: Boolean) {
|
||||
super.onHiddenChanged(hidden)
|
||||
|
||||
if (hidden) {
|
||||
dispatchUserVisibleHint(false)
|
||||
} else {
|
||||
dispatchUserVisibleHint(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (!mIsFirstVisible) {
|
||||
if (!isHidden && !isSupportVisible && userVisibleHint) {
|
||||
dispatchUserVisibleHint(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
// 当前 Fragment 包含子 Fragment 的时候 dispatchUserVisibleHint 内部本身就会通知子 Fragment 不可见
|
||||
// 子 fragment 走到这里的时候自身又会调用一遍 ?
|
||||
if (isSupportVisible && userVisibleHint) {
|
||||
dispatchUserVisibleHint(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 统一处理 显示隐藏
|
||||
*
|
||||
* @param visible
|
||||
*/
|
||||
private fun dispatchUserVisibleHint(visible: Boolean) {
|
||||
//当前 Fragment 是 child 时候 作为缓存 Fragment 的子 fragment getUserVisibleHint = true
|
||||
//但当父 fragment 不可见所以 currentVisibleState = false 直接 return 掉
|
||||
// 这里限制则可以限制多层嵌套的时候子 Fragment 的分发
|
||||
if (visible && isParentInvisible) return
|
||||
|
||||
//此处是对子 Fragment 不可见的限制,因为 子 Fragment 先于父 Fragment回调本方法 currentVisibleState 置位 false
|
||||
// 当父 dispatchChildVisibleState 的时候第二次回调本方法 visible = false 所以此处 visible 将直接返回
|
||||
if (isSupportVisible == visible) {
|
||||
return
|
||||
}
|
||||
|
||||
isSupportVisible = visible
|
||||
|
||||
if (visible) {
|
||||
if (mIsFirstVisible) {
|
||||
mIsFirstVisible = false
|
||||
onFragmentFirstVisible()
|
||||
}
|
||||
onFragmentResume()
|
||||
dispatchChildVisibleState(true)
|
||||
} else {
|
||||
dispatchChildVisibleState(false)
|
||||
onFragmentPause()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前 Fragment 是 child 时候 作为缓存 Fragment 的子 fragment 的唯一或者嵌套 VP 的第一 fragment 时 getUserVisibleHint = true
|
||||
* 但是由于父 Fragment 还未进入可见状态所以自身也是不可见的, 这个方法可以存在是因为庆幸的是 父 fragment 的生命周期回调总是先于子 Fragment
|
||||
* 所以在父 fragment 设置完成当前不可见状态后,需要通知子 Fragment 我不可见,你也不可见,
|
||||
*
|
||||
*
|
||||
* 因为 dispatchUserVisibleHint 中判断了 isParentInvisible 所以当 子 fragment 走到了 onActivityCreated 的时候直接 return 掉了
|
||||
*
|
||||
*
|
||||
* 当真正的外部 Fragment 可见的时候,走 setVisibleHint (VP 中)或者 onActivityCreated (hide show) 的时候
|
||||
* 从对应的生命周期入口调用 dispatchChildVisibleState 通知子 Fragment 可见状态
|
||||
*
|
||||
* @param visible
|
||||
*/
|
||||
private fun dispatchChildVisibleState(visible: Boolean) {
|
||||
val childFragmentManager = childFragmentManager
|
||||
val fragments = childFragmentManager.fragments
|
||||
if (!fragments.isEmpty()) {
|
||||
for (child in fragments) {
|
||||
if (child is BaseLazyFragment && !child.isHidden() && child.getUserVisibleHint()) {
|
||||
child.dispatchUserVisibleHint(visible)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open fun onFragmentFirstVisible() {
|
||||
//ULog.e("对用户第一次可见")
|
||||
}
|
||||
|
||||
open fun onFragmentResume() {
|
||||
//ULog.e("对用户可见")
|
||||
}
|
||||
|
||||
open fun onFragmentPause() {
|
||||
//ULog.e("对用户不可见")
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
isViewCreated = false
|
||||
mIsFirstVisible = true
|
||||
}
|
||||
|
||||
}
|
||||
@ -49,7 +49,7 @@ class DefaultJsApi(var context: Context) {
|
||||
|
||||
@JavascriptInterface
|
||||
fun getUserToken(msg: Any): String {
|
||||
return UserManager.getInstance().loginTokenEntity.accessToken.value
|
||||
return if (UserManager.getInstance().isLoggedIn) UserManager.getInstance().loginTokenEntity.accessToken.value else ""
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
|
||||
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.EntranceUtils
|
||||
@ -12,7 +13,9 @@ import com.gh.gamecenter.LibaoDetailActivity
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
object DefaultWebViewUrlHandler {
|
||||
@ -107,10 +110,24 @@ object DefaultWebViewUrlHandler {
|
||||
entrance, "文章链接")
|
||||
}
|
||||
}
|
||||
EntranceUtils.HOST_UPLOAD_VIDEO -> {
|
||||
val titleParameter = uri.getQueryParameter("title")
|
||||
val title = if (titleParameter.isNullOrEmpty()) "" else "#$titleParameter#"
|
||||
val categoryId = uri.getQueryParameter("category_id") ?: ""
|
||||
val link = uri.getQueryParameter("link") ?: ""
|
||||
val linkEntity = VideoLinkEntity(title, categoryId, link)
|
||||
if (!CheckLoginUtils.isLogin()) {
|
||||
HaloApp.put(EntranceUtils.HOST_UPLOAD_VIDEO, linkEntity)
|
||||
}
|
||||
CheckLoginUtils.checkLogin(context, EntranceUtils.ENTRANCE_BROWSER) {
|
||||
DirectUtils.directToVideoManager(context, linkEntity, EntranceUtils.ENTRANCE_BROWSER, "")
|
||||
}
|
||||
}
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
return true
|
||||
}
|
||||
if ("http" != uri.scheme && "https" != uri.scheme) return true
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -9,15 +9,25 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.PackageHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.SuggestionActivity;
|
||||
import com.gh.gamecenter.entity.NewsEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class Config {
|
||||
|
||||
public static final String API_HOST = BuildConfig.API_HOST;
|
||||
@ -169,6 +179,9 @@ public class Config {
|
||||
getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply();
|
||||
mSettingsEntity = settingsEntity;
|
||||
|
||||
// 更新 FIX_ARTICLE_KEY 状态
|
||||
mSettingsEntity.showArticleEntrance();
|
||||
|
||||
// 加载完设置后刷新下
|
||||
PackageHelper.initList();
|
||||
}
|
||||
@ -232,4 +245,29 @@ public class Config {
|
||||
editor.putBoolean(Config.FIX_PLUGIN_KEY, true);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static void getGhzsSettings() {
|
||||
String channel = HaloApp.getInstance().getChannel();
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
|
||||
.getApi().getSettings(PackageUtils.getVersionName(), channel)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<SettingsEntity>() {
|
||||
@Override
|
||||
public void onResponse(SettingsEntity response) {
|
||||
Config.setSettings(response);
|
||||
|
||||
// 意见反馈
|
||||
SharedPreferences.Editor edit = getPreferences().edit();
|
||||
edit.putString(SuggestionActivity.SUGGESTION_HINT_TYPE,
|
||||
GsonUtils.toJson(response.getSuggestion()));
|
||||
edit.apply();
|
||||
|
||||
if (!getPreferences().getBoolean(Config.FIX_DOWNLOAD_KEY, false) && Config.isShow()) {
|
||||
getPreferences().edit().putBoolean(Config.FIX_DOWNLOAD_KEY, true).apply();
|
||||
}
|
||||
EventBus.getDefault().post(new EBReuse("Refresh"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package com.gh.common.constant;
|
||||
|
||||
import com.gh.common.util.PackageUtils;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final int SEND_NEWS_FEEDBACK = 0x126;
|
||||
@ -24,16 +26,30 @@ public class Constants {
|
||||
public static final String GAME_DETAIL_COME_IN = "game_detail_come_in"; // 从游戏详情进入
|
||||
|
||||
public static final String XPOSED_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
|
||||
|
||||
|
||||
public static final String EB_QUIT_LOGIN = "quit_login";
|
||||
|
||||
// 最近显示的弹窗信息
|
||||
public static final String SP_LAST_OPENING_ID = "last_opening_dialog_id";
|
||||
public static final String SP_LAST_OPENING_TIME = "last_opening_dialog_time";
|
||||
|
||||
public static final String SP_SHOWED_NOTIFICATION_HINT = "show_notification_hint";
|
||||
//标记安装的游戏为已玩过弹窗,最多取消2次
|
||||
public static final String SP_MARK_INSTALLED_GAME = "mark_installed_game";
|
||||
//引导设置 “通知管理” 引导弹窗
|
||||
public static final String SP_SHOWED_NOTIFICATION_LOGIN = "show_notification_login_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_QUESTION = "show_notification_question_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_ANSWER = "show_notification_answer_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_ARTICLE = "show_notification_article_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_VIDEO = "show_notification_video_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_RATING = "show_notification_rating_hint";
|
||||
// 新版本 也要触发一次“通知管理” 引导弹窗
|
||||
public static final String SP_SHOWED_NOTIFICATION_NEW_VERSION = "show_notification_new_version";
|
||||
// 今天是否已经触发了 “通知管理” 引导弹窗
|
||||
public static final String SP_IS_SHOWED_NOTIFICATION_TODAY = "show_is_notification_today";
|
||||
// 标记安装的游戏为已玩过弹窗,最多取消2次 (https://gitlab.ghzs.com/pm/halo-app-issues/issues/722 调整为版本相关) (不是常量了也放这里好像有点奇怪)
|
||||
public static final String SP_MARK_INSTALLED_GAME = "mark_installed_game" + PackageUtils.getVersionName();
|
||||
//视频详情滑动引导
|
||||
public static final String SP_SHOW_SLIDE_GUIDE = "show_slide_guide";
|
||||
//视频详情点击引导
|
||||
public static final String SP_SHOW_CLICK_GUIDE = "show_click_guide";
|
||||
|
||||
//手机号码匹配规则
|
||||
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
|
||||
@ -66,10 +82,15 @@ public class Constants {
|
||||
public static final int SEARCH_CD = 5 * 60 * 1000;
|
||||
//评论 cd间隔
|
||||
public static final int COMMENT_CD = 60 * 1000;
|
||||
//我的光环功能分组 cd间隔
|
||||
public static final int ADDONS_CD = 10 * 60 * 1000;
|
||||
|
||||
public static final String[] REPORT_LIST = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息", "违法有害信息", "其它"};
|
||||
|
||||
public static final String ENTRANCE_UNKNOWN = "(unknown)";
|
||||
|
||||
public static final String DEFAULT_TEXT_WRAPPER = "###";
|
||||
|
||||
// 触发了安装事件的标记
|
||||
public static final String MARK_ALREADY_TRIGGERED_INSTALLATION = "triggered_installation";
|
||||
}
|
||||
|
||||
@ -13,12 +13,6 @@ import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.BindingAdapter;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.OnViewClickListener;
|
||||
import com.gh.common.constant.Config;
|
||||
@ -34,6 +28,8 @@ import com.gh.common.util.DownloadDialogHelper;
|
||||
import com.gh.common.util.GameUtils;
|
||||
import com.gh.common.util.GameViewUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.NewsUtils;
|
||||
import com.gh.common.util.NumberUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
@ -46,11 +42,13 @@ import com.gh.common.view.DrawableView;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.baselist.LoadStatus;
|
||||
import com.gh.gamecenter.databinding.KaifuAddItemBinding;
|
||||
import com.gh.gamecenter.databinding.KaifuDetailItemRowBinding;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.entity.ServerCalendarEntity;
|
||||
import com.gh.gamecenter.entity.TagStyleEntity;
|
||||
@ -67,6 +65,12 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.BindingAdapter;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
/**
|
||||
* Created by khy on 12/02/18.
|
||||
*/
|
||||
@ -381,16 +385,17 @@ public class BindingAdapters {
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(progressBar.getContext()).getDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
|
||||
if (downloadEntity != null) {
|
||||
PackageUtils.launchSetup(v.getContext(), downloadEntity.getPath());
|
||||
PackageUtils.launchSetup(v.getContext(), downloadEntity);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RESERVABLE:
|
||||
CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> {
|
||||
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(progressBar.getContext(), () -> {
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
|
||||
gameEntity,
|
||||
() -> updateReservation(progressBar, gameEntity));
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(gameEntity, () -> {
|
||||
LogUtils.logReservation(gameEntity, traceEvent);
|
||||
updateReservation(progressBar, gameEntity);
|
||||
});
|
||||
dialogFragment.show(((AppCompatActivity) progressBar.getContext()).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
});
|
||||
@ -410,6 +415,12 @@ public class BindingAdapters {
|
||||
});
|
||||
}
|
||||
break;
|
||||
case H5_GAME:
|
||||
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
|
||||
LinkEntity linkEntity = gameEntity.getH5Link();
|
||||
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), "play".equals(linkEntity.getType())));
|
||||
progressBar.getContext().startActivity(i);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@ -427,13 +438,24 @@ public class BindingAdapters {
|
||||
|
||||
// 显示下载按钮状态
|
||||
if (gameEntity.getApk().isEmpty() || gameEntity.getDownloadOffStatus() != null) {
|
||||
LinkEntity h5LinkEntity = gameEntity.getH5Link();
|
||||
String offStatus = gameEntity.getDownloadOffStatus();
|
||||
if (offStatus != null && "dialog".equals(offStatus)) {
|
||||
progressBar.setText("查看");
|
||||
if (h5LinkEntity != null) {
|
||||
if ("play".equals(h5LinkEntity.getType())) {
|
||||
progressBar.setText("开始玩");
|
||||
} else {
|
||||
progressBar.setText("查看");
|
||||
}
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.H5_GAME);
|
||||
} else {
|
||||
progressBar.setText("暂无");
|
||||
if (offStatus != null && "dialog".equals(offStatus)) {
|
||||
progressBar.setText("查看");
|
||||
} else {
|
||||
progressBar.setText("暂无");
|
||||
}
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
|
||||
} else {
|
||||
String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity, PluginLocation.only_game);
|
||||
switch (status) {
|
||||
@ -524,9 +546,10 @@ public class BindingAdapters {
|
||||
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity.getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(progressBar.getContext(), gameEntity.getName(), apkEntity.getPlatform(), entrance, "下载开始", method);
|
||||
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, ExposureUtils.DownloadType.DOWNLOAD);
|
||||
|
||||
|
||||
ExposureUtils.DownloadType downloadType = ExposureUtils.getDownloadType(apkEntity, method);
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, downloadType);
|
||||
|
||||
DownloadManager.createDownload(progressBar.getContext(),
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.gh.common.exposure.meta.Meta
|
||||
import com.gh.common.exposure.meta.MetaUtil
|
||||
import com.gh.common.exposure.time.TimeUtil
|
||||
@ -24,7 +24,8 @@ data class ExposureEvent(
|
||||
@PrimaryKey
|
||||
val id: String = UUID.randomUUID().toString()) : Parcelable {
|
||||
companion object {
|
||||
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>?, event: ExposureType): ExposureEvent {
|
||||
@JvmStatic
|
||||
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>? = null, event: ExposureType = ExposureType.EXPOSURE): ExposureEvent {
|
||||
return ExposureEvent(
|
||||
payload = ExposureEntity(gameId = gameEntity?.id,
|
||||
gameName = gameEntity?.name,
|
||||
@ -34,7 +35,7 @@ data class ExposureEvent(
|
||||
downloadCompleteType = gameEntity?.downloadCompleteType),
|
||||
source = source,
|
||||
eTrace = eTrace,
|
||||
event = event)
|
||||
event = event).apply { gameEntity?.exposureEvent = this }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,10 +31,10 @@ object ExposureManager {
|
||||
private val loghubHelper = LoghubHelper.getInstance()
|
||||
|
||||
// exposureCache 用来过滤掉具有相同 id 的曝光事件,避免重复发送事件
|
||||
private val exposureCache = FixedSizeLinkedHashSet<String>(100)
|
||||
private val exposureSet = hashSetOf<ExposureEvent>()
|
||||
private val exposureDao by lazy { ExposureDatabase.buildDatabase(HaloApp.getInstance().application).logHubEventDao() }
|
||||
private val exposureExecutor = Executors.newSingleThreadExecutor()
|
||||
private val exposureCache = FixedSizeLinkedHashSet<String>(300)
|
||||
private val exposureDao by lazy { ExposureDatabase.buildDatabase(HaloApp.getInstance().application).logHubEventDao() }
|
||||
|
||||
@JvmStatic
|
||||
fun init() {
|
||||
@ -48,7 +48,7 @@ object ExposureManager {
|
||||
}
|
||||
|
||||
fixedRateTimer(name = "ExposureManager-Store-Checker", initialDelay = 500, period = STORE_FORCE_UPLOAD_PERIOD) {
|
||||
commitSavedExposureEvent(true)
|
||||
commitSavedExposureEvents(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,17 +57,19 @@ object ExposureManager {
|
||||
*/
|
||||
fun log(event: ExposureEvent) {
|
||||
exposureExecutor.execute {
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
|
||||
try {
|
||||
try {
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
|
||||
|
||||
exposureSet.add(event)
|
||||
exposureDao.insert(event)
|
||||
exposureCache.add(event.id)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
|
||||
} else {
|
||||
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 (${event.id} - ${event.payload.gameName})")
|
||||
}
|
||||
} else {
|
||||
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 (${event.id} - ${event.payload.gameName})")
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,24 +80,27 @@ object ExposureManager {
|
||||
fun log(eventList: List<ExposureEvent>) {
|
||||
exposureExecutor.execute {
|
||||
for (event in eventList) {
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
|
||||
try {
|
||||
try {
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
// Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception.
|
||||
exposureSet.add(event)
|
||||
exposureDao.insert(event)
|
||||
exposureCache.add(event.id)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} else {
|
||||
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 (${event.id} - ${event.payload.gameName})")
|
||||
}
|
||||
} else {
|
||||
Utils.log("Exposure", "遇到重复曝光事件,自动过滤 (${event.id} - ${event.payload.gameName})")
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
commitSavedExposureEvent()
|
||||
commitSavedExposureEvents()
|
||||
}
|
||||
}
|
||||
|
||||
fun commitSavedExposureEvent(forced: Boolean = false) {
|
||||
/**
|
||||
* @param forced Ignore all restrictions.
|
||||
*/
|
||||
fun commitSavedExposureEvents(forced: Boolean = false) {
|
||||
exposureExecutor.execute {
|
||||
if (exposureSet.size < STORE_SIZE && !forced || exposureSet.size == 0) return@execute
|
||||
|
||||
|
||||
@ -6,4 +6,4 @@ import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@Keep
|
||||
@Parcelize
|
||||
data class ExposureSource(var k: String, var v: String): Parcelable
|
||||
data class ExposureSource(var k: String, var v: String = ""): Parcelable
|
||||
@ -1,7 +1,10 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.gamecenter.entity.ApkEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
import java.util.*
|
||||
|
||||
object ExposureUtils {
|
||||
@ -36,7 +39,31 @@ object ExposureUtils {
|
||||
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
|
||||
event = ExposureType.DOWNLOAD_COMPLETE)
|
||||
ExposureManager.log(exposureEvent)
|
||||
ExposureManager.commitSavedExposureEvent(forced = true)
|
||||
ExposureManager.commitSavedExposureEvents(forced = true)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getDownloadType(apkEntity: ApkEntity, method: String) : DownloadType {
|
||||
return if ("更新" == method) {
|
||||
if (PackageUtils.isSignature(HaloApp.getInstance().application, apkEntity.packageName)) {
|
||||
DownloadType.PLUGIN_UPDATE
|
||||
} else {
|
||||
DownloadType.UPDATE
|
||||
}
|
||||
} else if ("插件化" == method) {
|
||||
DownloadType.PLUGIN_DOWNLOAD
|
||||
} else {
|
||||
DownloadType.DOWNLOAD
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getUpdateType(apkEntity: ApkEntity) : DownloadType {
|
||||
return if (PackageUtils.isSignature(HaloApp.getInstance().application, apkEntity.packageName)) {
|
||||
DownloadType.PLUGIN_UPDATE
|
||||
} else {
|
||||
DownloadType.UPDATE
|
||||
}
|
||||
}
|
||||
|
||||
enum class DownloadType {
|
||||
|
||||
@ -17,6 +17,7 @@ data class Meta(
|
||||
val network: String? = "",
|
||||
val os: String? = "",
|
||||
val gid: String? = "",
|
||||
val oaid: String? = "",
|
||||
val channel: String? = "",
|
||||
val appVersion: String? = "",
|
||||
val userId: String? = "",
|
||||
|
||||
@ -35,6 +35,7 @@ object MetaUtil {
|
||||
network = getNetwork(),
|
||||
os = getOS(),
|
||||
gid = HaloApp.getInstance().gid,
|
||||
oaid = HaloApp.getInstance().oaid,
|
||||
channel = getChannel(),
|
||||
appVersion = BuildConfig.VERSION_NAME,
|
||||
userId = UserManager.getInstance().userId,
|
||||
|
||||
@ -7,17 +7,15 @@ import androidx.room.TypeConverters
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.gh.gamecenter.entity.HistoryGameEntity
|
||||
import com.gh.gamecenter.entity.MyVideoEntity
|
||||
import com.gh.gamecenter.entity.NewsEntity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.ArticleEntity
|
||||
import com.gh.gamecenter.room.converter.*
|
||||
import com.gh.gamecenter.room.dao.AnswerHistoryDao
|
||||
import com.gh.gamecenter.room.dao.ArticleHistoryDao
|
||||
import com.gh.gamecenter.room.dao.GameDao
|
||||
import com.gh.gamecenter.room.dao.NewsHistoryDao
|
||||
import com.gh.gamecenter.room.dao.*
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class], version = 4, exportSchema = false)
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 5, exportSchema = false)
|
||||
@TypeConverters(CountConverter::class,
|
||||
CommunityConverter::class,
|
||||
TimeConverter::class,
|
||||
@ -33,6 +31,7 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
abstract fun articleDao(): ArticleHistoryDao
|
||||
abstract fun newsDao(): NewsHistoryDao
|
||||
abstract fun gameDao(): GameDao
|
||||
abstract fun videoHistoryDao(): VideoHistoryDao
|
||||
|
||||
companion object {
|
||||
|
||||
@ -49,10 +48,17 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_4_5: Migration = object : Migration(4, 5) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE MyVideoEntity(id TEXT NOT NULL PRIMARY KEY,poster TEXT NOT NULL DEFAULT '',url TEXT NOT NULL DEFAULT '',vote INTEGER NOT NULL DEFAULT 0,length INTEGER NOT NULL DEFAULT 0,time INTEGER NOT NULL DEFAULT 0,videoStreamRecord INTEGER NOT NULL DEFAULT 0,status TEXT NOT NULL DEFAULT '')")
|
||||
}
|
||||
}
|
||||
|
||||
val instance by lazy {
|
||||
Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE")
|
||||
.addMigrations(MIGRATION_2_3)
|
||||
.addMigrations(MIGRATION_3_4)
|
||||
.addMigrations(MIGRATION_4_5)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,16 +2,12 @@ package com.gh.common.im
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.core.view.ViewCompat
|
||||
import android.util.AttributeSet
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.KeyCharacterMap
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.ViewConfiguration
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.view.ViewCompat
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.gamecenter.R
|
||||
import kotlinx.android.synthetic.main.view_im_hint.view.*
|
||||
|
||||
@ -32,7 +28,7 @@ class ImHintView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
|
||||
val lp = ivContainer.layoutParams as RelativeLayout.LayoutParams
|
||||
|
||||
lp.setMargins(0, 0, dp2px(30f), dp2px(106f) + retrieveNavigationHeight())
|
||||
lp.setMargins(0, 0, dp2px(30f), dp2px(106f) + DisplayUtils.retrieveNavigationHeight(context))
|
||||
}
|
||||
|
||||
fun showDot(show: Boolean) {
|
||||
@ -46,39 +42,4 @@ class ImHintView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
private fun dp2px(dp: Float): Int {
|
||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.applicationContext.resources.displayMetrics).toInt()
|
||||
}
|
||||
|
||||
private fun hasSoftKeys(): Boolean {
|
||||
if (context !is Activity) return false
|
||||
|
||||
val hasSoftwareKeys: Boolean
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
val d = (context as Activity).windowManager.defaultDisplay
|
||||
|
||||
val realDisplayMetrics = DisplayMetrics()
|
||||
d.getRealMetrics(realDisplayMetrics)
|
||||
|
||||
val realHeight = realDisplayMetrics.heightPixels
|
||||
val realWidth = realDisplayMetrics.widthPixels
|
||||
|
||||
val displayMetrics = DisplayMetrics()
|
||||
d.getMetrics(displayMetrics)
|
||||
|
||||
val displayHeight = displayMetrics.heightPixels
|
||||
val displayWidth = displayMetrics.widthPixels
|
||||
|
||||
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0
|
||||
} else {
|
||||
val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
|
||||
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
|
||||
hasSoftwareKeys = !hasMenuKey && !hasBackKey
|
||||
}
|
||||
return hasSoftwareKeys
|
||||
}
|
||||
|
||||
private fun retrieveNavigationHeight(): Int {
|
||||
val resources = context.resources
|
||||
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
|
||||
return if (resourceId > 0 && hasSoftKeys()) resources.getDimensionPixelSize(resourceId) else 0
|
||||
}
|
||||
}
|
||||
@ -7,9 +7,9 @@ import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.HelpAndFeedbackActivity
|
||||
import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.MessageActivity
|
||||
import com.gh.gamecenter.SuggestSelectActivity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.m7.imkfsdk.KfStartHelper
|
||||
@ -69,12 +69,12 @@ object ImManager {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun startChatActivity(activity: Activity) {
|
||||
fun startChatActivity(activity: Activity, inputContent: String? = "", requestCode: Int? = null) {
|
||||
if (!UserManager.getInstance().userId.isNullOrEmpty()) {
|
||||
try {
|
||||
SPUtils.setBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId, false)
|
||||
shouldShowFloatingWindowDot = false
|
||||
val chatHelper = KfStartHelper(activity, UserManager.getInstance().userInfoEntity.icon)
|
||||
val chatHelper = KfStartHelper(activity, UserManager.getInstance().userInfoEntity.icon, inputContent, requestCode)
|
||||
chatHelper.initSdkChat(
|
||||
ImReceiver.UNIQUE_BROADCAST_ACTION,
|
||||
IM_KEY,
|
||||
@ -152,7 +152,7 @@ object ImManager {
|
||||
private fun isActivityValid(activity: Activity): Boolean {
|
||||
return when (activity) {
|
||||
is MainActivity -> true
|
||||
is SuggestSelectActivity -> true
|
||||
is HelpAndFeedbackActivity -> true
|
||||
is MessageActivity -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
21
app/src/main/java/com/gh/common/loghub/LoghubDatabase.kt
Normal file
21
app/src/main/java/com/gh/common/loghub/LoghubDatabase.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
|
||||
@Database(entities = [LoghubEvent::class], version = 1, exportSchema = false)
|
||||
abstract class LoghubDatabase : RoomDatabase() {
|
||||
companion object {
|
||||
private const val DATABASE = "gh_loghub_database"
|
||||
|
||||
fun buildDatabase(context: Context): LoghubDatabase {
|
||||
return Room.databaseBuilder(context, LoghubDatabase::class.java, DATABASE)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun logHubEventDao(): LoghubEventDao
|
||||
}
|
||||
17
app/src/main/java/com/gh/common/loghub/LoghubEvent.kt
Normal file
17
app/src/main/java/com/gh/common/loghub/LoghubEvent.kt
Normal file
@ -0,0 +1,17 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import java.util.*
|
||||
|
||||
@Keep
|
||||
@Parcelize
|
||||
@Entity(tableName = "loghubEvent")
|
||||
data class LoghubEvent(@PrimaryKey
|
||||
val id: String = UUID.randomUUID().toString(),
|
||||
var time: String,
|
||||
var content: String,
|
||||
var logStore: String) : Parcelable
|
||||
18
app/src/main/java/com/gh/common/loghub/LoghubEventDao.kt
Normal file
18
app/src/main/java/com/gh/common/loghub/LoghubEventDao.kt
Normal file
@ -0,0 +1,18 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import androidx.room.*
|
||||
|
||||
@Dao
|
||||
interface LoghubEventDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertMany(eventList: List<LoghubEvent>)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(event: LoghubEvent)
|
||||
|
||||
@Query("SELECT * FROM LoghubEvent")
|
||||
fun getAll(): List<LoghubEvent>
|
||||
|
||||
@Delete
|
||||
fun deleteMany(eventList: List<LoghubEvent>)
|
||||
}
|
||||
88
app/src/main/java/com/gh/common/loghub/LoghubUtils.kt
Normal file
88
app/src/main/java/com/gh/common/loghub/LoghubUtils.kt
Normal file
@ -0,0 +1,88 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import android.app.Application
|
||||
import com.aliyun.sls.android.sdk.model.Log
|
||||
import com.aliyun.sls.android.sdk.model.LogGroup
|
||||
import com.gh.loghub.LoghubHelper
|
||||
import org.json.JSONObject
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
object LoghubUtils {
|
||||
|
||||
private const val STORE_SIZE = 100
|
||||
private const val STORE_FORCE_UPLOAD_INTERVAL = 120 * 1000L
|
||||
|
||||
private lateinit var mApplication: Application
|
||||
|
||||
private val loghubEventSet = hashSetOf<LoghubEvent>()
|
||||
private val loghubEventExecutor by lazy { Executors.newSingleThreadExecutor() }
|
||||
private val loghubEventDao by lazy { LoghubDatabase.buildDatabase(mApplication).logHubEventDao() }
|
||||
|
||||
@JvmStatic
|
||||
fun init(application: Application) {
|
||||
mApplication = application
|
||||
|
||||
loghubEventExecutor.execute {
|
||||
val eventList = loghubEventDao.getAll()
|
||||
loghubEventSet.addAll(eventList)
|
||||
}
|
||||
|
||||
fixedRateTimer(name = "Loghub-Event-Checker", initialDelay = 1000, period = STORE_FORCE_UPLOAD_INTERVAL) {
|
||||
commitSavedLoghubEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun log(logJson: JSONObject, logStore: String, forcedUpload: Boolean) {
|
||||
loghubEventExecutor.execute {
|
||||
try {
|
||||
val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = logJson.toString(), logStore = logStore)
|
||||
loghubEventSet.add(event)
|
||||
loghubEventDao.insert(event)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
if (forcedUpload || loghubEventSet.size >= STORE_SIZE) {
|
||||
commitSavedLoghubEvents()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun uploadLogGroup(logGroup: LogGroup, logStore: String) {
|
||||
LoghubHelper.getInstance().uploadLogGroup(logGroup, logStore)
|
||||
}
|
||||
|
||||
private fun commitSavedLoghubEvents() {
|
||||
loghubEventExecutor.execute {
|
||||
if (loghubEventSet.isEmpty()) return@execute
|
||||
|
||||
val exposureList = loghubEventSet.toList()
|
||||
|
||||
createLogGroupAndUpload()
|
||||
loghubEventSet.removeAll(exposureList)
|
||||
loghubEventDao.deleteMany(exposureList)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLogGroupAndUpload() {
|
||||
val logGroupHashMap = hashMapOf<String, LogGroup>()
|
||||
|
||||
for (event in loghubEventSet) {
|
||||
if (!logGroupHashMap.containsKey(event.logStore)) {
|
||||
logGroupHashMap[event.logStore] = LogGroup("sls android", "no ip")
|
||||
}
|
||||
|
||||
val log = Log()
|
||||
log.PutContent("current time ", event.time)
|
||||
log.PutContent("content", event.content)
|
||||
logGroupHashMap[event.logStore]?.PutLog(log)
|
||||
}
|
||||
|
||||
for ((logStore, logGroup) in logGroupHashMap) {
|
||||
uploadLogGroup(logGroup, logStore)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,18 +1,19 @@
|
||||
package com.gh.common.notifier
|
||||
|
||||
import android.animation.*
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.graphics.Path
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import android.util.AttributeSet
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.*
|
||||
import android.view.Gravity
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.ViewCompat
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.common.util.doOnEnd
|
||||
import com.gh.common.util.doOnStart
|
||||
@ -74,7 +75,7 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
|
||||
verticalAnimationOffset = dp2px(100F)
|
||||
|
||||
navigationHeight = retrieveNavigationHeight()
|
||||
navigationHeight = DisplayUtils.retrieveNavigationHeight(context)
|
||||
|
||||
rightToLeftPath = Path()
|
||||
leftToRightPath = Path()
|
||||
@ -290,41 +291,6 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.applicationContext.resources.displayMetrics).toInt()
|
||||
}
|
||||
|
||||
private fun hasSoftKeys(): Boolean {
|
||||
if (context !is Activity) return false
|
||||
|
||||
val hasSoftwareKeys: Boolean
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
val d = (context as Activity).windowManager.defaultDisplay
|
||||
|
||||
val realDisplayMetrics = DisplayMetrics()
|
||||
d.getRealMetrics(realDisplayMetrics)
|
||||
|
||||
val realHeight = realDisplayMetrics.heightPixels
|
||||
val realWidth = realDisplayMetrics.widthPixels
|
||||
|
||||
val displayMetrics = DisplayMetrics()
|
||||
d.getMetrics(displayMetrics)
|
||||
|
||||
val displayHeight = displayMetrics.heightPixels
|
||||
val displayWidth = displayMetrics.widthPixels
|
||||
|
||||
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0
|
||||
} else {
|
||||
val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
|
||||
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
|
||||
hasSoftwareKeys = !hasMenuKey && !hasBackKey
|
||||
}
|
||||
return hasSoftwareKeys
|
||||
}
|
||||
|
||||
private fun retrieveNavigationHeight(): Int {
|
||||
val resources = context.resources
|
||||
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
|
||||
return if (resourceId > 0 && hasSoftKeys()) resources.getDimensionPixelSize(resourceId) else 0
|
||||
}
|
||||
|
||||
interface OnShowNotificationListener {
|
||||
fun onShow()
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
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.LoginActivity;
|
||||
@ -19,8 +19,12 @@ public class CheckLoginUtils {
|
||||
if (listener != null) Utils.toast(context, "需要登录");
|
||||
LogUtils.login("dialog", null, entrance);
|
||||
LogUtils.login("activity", null, entrance);
|
||||
Intent intent = LoginActivity.getIntent(context, entrance);
|
||||
context.startActivity(intent);
|
||||
|
||||
// 有可能App未启动
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
bundle.putString(EntranceUtils.KEY_TO, LoginActivity.class.getName());
|
||||
EntranceUtils.jumpActivity(context, bundle);
|
||||
} else {
|
||||
if (listener != null) {
|
||||
listener.onLogin();
|
||||
|
||||
@ -9,6 +9,7 @@ import com.gh.common.view.DownloadProgressBar;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.DetailViewHolder;
|
||||
import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
@ -47,12 +48,24 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
|
||||
if (viewHolder.gameEntity.getApk().isEmpty() || viewHolder.gameEntity.getDownloadOffStatus() != null) {
|
||||
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "查看详情" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE_WITH_HINT);
|
||||
LinkEntity h5LinkEntity = viewHolder.gameEntity.getH5Link();
|
||||
|
||||
if (h5LinkEntity != null) {
|
||||
if ("play".equals(h5LinkEntity.getType())) {
|
||||
String defaultString = String.format("开始玩" + "《%s》", viewHolder.gameEntity.getName());
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(h5LinkEntity.getText()) ? defaultString : h5LinkEntity.getText());
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(h5LinkEntity.getText()) ? "查看" : h5LinkEntity.getText());
|
||||
}
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.H5_GAME);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "暂无下载" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "查看详情" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE_WITH_HINT);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "暂无下载" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String status = GameUtils.getDownloadBtnText(viewHolder.context, viewHolder.gameEntity, PluginLocation.only_game);
|
||||
|
||||
@ -5,7 +5,10 @@ import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
@ -17,26 +20,41 @@ import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchy;
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.TrackableDialog;
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.common.view.FixLinearLayoutManager;
|
||||
import com.gh.gamecenter.AboutActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.adapter.viewholder.PrivacyPolicyItemViewHolder;
|
||||
import com.gh.gamecenter.databinding.PrivacyItemBinding;
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
|
||||
import com.gh.gamecenter.entity.TrackableEntity;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.halo.assistant.fragment.SettingsFragment;
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter;
|
||||
import com.lightgame.utils.AppManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class DialogUtils {
|
||||
|
||||
public static Dialog showWaitDialog(Context context, String msg) {
|
||||
@ -144,29 +162,33 @@ public class DialogUtils {
|
||||
}
|
||||
|
||||
// 网络劫持时 打开QQ客户端,创建临时会话
|
||||
public static void showQqSessionDialog(final Context context, final String qq) {
|
||||
public static void showQqSessionDialog(final Context context) {
|
||||
String qq = "";
|
||||
if (Config.getSettings() != null && Config.getSettings().getSupport() != null) {
|
||||
qq = Config.getSettings().getSupport().getQq();
|
||||
}
|
||||
String finalQq = qq;
|
||||
showWarningDialog(context, "警告", "您当前网络环境异常,下载地址可能被运营商恶意替换(网络劫持)" +
|
||||
",如多次下载失败,请联系客服获取正确的下载地址(客服QQ:" + qq + ")"
|
||||
, "取消", "前往QQ", () -> DirectUtils.directToQqConversation(context, qq), null);
|
||||
, "取消", "前往QQ", () -> DirectUtils.directToQqConversation(context, finalQq), null);
|
||||
}
|
||||
|
||||
public static void checkDownload(Context context, String size, CheckDownloadCallBack callBack) {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
|
||||
if (!NetworkUtils.isNetworkConnected(context)) {
|
||||
showNoConnectionDownloadDialog(context, null,
|
||||
() -> callBack.onResponse(true));
|
||||
} else if (NetworkUtils.isWifiConnected(context) || filter4GorSize(context, size)) {
|
||||
} else if (NetworkUtils.isWifiConnected(context)
|
||||
|| filter4GorSize(context, size)) {
|
||||
callBack.onResponse(false);
|
||||
} else if (!preferences.getBoolean(SettingsFragment.getTrafficDownloadHintKey(), true)) {
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> Utils.toast(context, "当前使用移动网络下载,请注意流量消耗"), 500);
|
||||
callBack.onResponse(false);
|
||||
} else {
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "出现弹窗提示");
|
||||
showDownloadDialog(context,
|
||||
() -> {
|
||||
callBack.onResponse(false);
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "立即下载");
|
||||
},
|
||||
() -> {
|
||||
callBack.onResponse(true);
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "连上WiFi后自动下载");
|
||||
});
|
||||
() -> callBack.onResponse(false),
|
||||
() -> callBack.onResponse(true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +200,8 @@ public class DialogUtils {
|
||||
String mb = size.toUpperCase().replaceAll("MB", "").trim();
|
||||
Float i = Float.valueOf(mb);
|
||||
if (NetworkUtils.isWifiOr4GConnected(context) && i <= 50) {
|
||||
Utils.toast(context, "当前使用移动流量下载");
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> Utils.toast(context, "当前使用移动网络下载,请注意流量消耗"),500);
|
||||
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -206,14 +229,54 @@ public class DialogUtils {
|
||||
}
|
||||
|
||||
public static void showDownloadDialog(Context context, ConfirmListener listener, CancelListener cancelListener) {
|
||||
showWarningDialog(context, "下载提示", "当前正在使用移动网络,立即下载会消耗手机流量", "连上WiFi后自动下载", "立即下载", listener, cancelListener);
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_download_traffic, null);
|
||||
View allowOnce = contentView.findViewById(R.id.allow_once);
|
||||
View allowAlways = contentView.findViewById(R.id.allow_always);
|
||||
View wifiAuto = contentView.findViewById(R.id.wifi_auto);
|
||||
|
||||
Context finalContext = context;
|
||||
allowOnce.setOnClickListener(v -> {
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
Utils.toast(HaloApp.getInstance().getApplication(), "已使用移动网络下载,请注意流量消耗");
|
||||
}, 500);
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "本次允许");
|
||||
});
|
||||
wifiAuto.setOnClickListener(v -> {
|
||||
cancelListener.onCancel();
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "连上WiFi后自动下载");
|
||||
});
|
||||
allowAlways.setOnClickListener(v -> {
|
||||
PreferenceManager
|
||||
.getDefaultSharedPreferences(finalContext)
|
||||
.edit()
|
||||
.putBoolean(SettingsFragment.getTrafficDownloadHintKey(), false)
|
||||
.apply();
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
// 显示了弹窗以后,即便下面这个 toast 放在 listener.onConfirm 后调用也是显示 listener.onConfirm 里的 toast
|
||||
// 喷了,延时包治疑难杂症
|
||||
Utils.toast(HaloApp.getInstance().getApplication(), "已使用移动网络下载,请注意流量消耗");
|
||||
}, 500);
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "总是允许");
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showResumeDownloadDialog(Context context, ConfirmListener listener, CancelListener cancelListener) {
|
||||
showWarningDialog(context, "下载提示", "当前正在使用移动网络,继续下载会消耗手机流量", "连上WiFi后自动下载", "继续下载", listener, cancelListener);
|
||||
}
|
||||
|
||||
|
||||
public static void showDownloadDialog(Context context, ConfirmListener listener) {
|
||||
showWarningDialog(context, "下载提示", "您当前使用的网络为2G/3G/4G,开始下载将会消耗移动流量,确定下载?", listener);
|
||||
}
|
||||
@ -224,10 +287,30 @@ public class DialogUtils {
|
||||
}
|
||||
|
||||
public static void showPluginDialog(Context context, final ConfirmListener listener) {
|
||||
Spanned spanned = Html.fromHtml("您将进行插件化安装以实现插件功能,此过程将"
|
||||
+ "<font color=\"#ff0000\">卸载</font>" + "当前使用的版本并"
|
||||
+ "<font color=\"#ff0000\">安装插件版本</font>");
|
||||
showWarningDialog(context, "插件化安装", spanned, listener);
|
||||
context = checkDialogContext(context);
|
||||
|
||||
MtaHelper.onEvent("插件化", "插件化安装弹窗", "出现弹窗提示");
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_plugin, null);
|
||||
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
negativeTv.setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("插件化", "插件化安装弹窗", "取消");
|
||||
});
|
||||
positiveTv.setOnClickListener(view -> {
|
||||
if (listener != null) {
|
||||
listener.onConfirm();
|
||||
}
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("插件化", "插件化安装弹窗", "确认并开始");
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -786,33 +869,71 @@ public class DialogUtils {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static void showPrivacyPolicyDialog(Context context, String title, String content, EmptyCallback callback) {
|
||||
public static void showPrivacyPolicyDialog(Context context,
|
||||
@NonNull PrivacyPolicyEntity entity,
|
||||
EmptyCallback callback) {
|
||||
|
||||
final Context activityContext = checkDialogContext(context);
|
||||
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
AtomicBoolean isCanceledByClickOutsideOfDialog = new AtomicBoolean(true);
|
||||
|
||||
String privacyPolicyContent;
|
||||
String privacyPolicyTitle = (TextUtils.isEmpty(title)) ? "个人信息保护指引" : title;
|
||||
if (TextUtils.isEmpty(content)) {
|
||||
privacyPolicyContent = "光环助手致力于为每位用户提供更安全的互联网环境,我们将依据相关法律法规和技术规范来收集和使用你的个人信息。" +
|
||||
"<br/>1.为帮助你浏览内容、互动交流、注册认证等,我们需要获取一些必要的信息,以实现完整的功能;" +
|
||||
"<br/>2.日常使用中,我们可能需要开启 IMEI号码、IMSI号码、定位、相册 等信息的读取权限;" +
|
||||
"<br/>3.以上信息的读取权限均不会默认开启,只有在运行相关功能或服务时才会明确提示授权,光环助手不会在未经你同意的情况下收集相关信息。";
|
||||
} else {
|
||||
privacyPolicyContent = content;
|
||||
final Dialog dialog = new Dialog(activityContext, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
|
||||
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_privacy_policy, null);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.getDecorView().setPadding(0, 0, 0, 0);
|
||||
window.setBackgroundDrawableResource(android.R.color.transparent);
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.horizontalMargin = 0;
|
||||
params.width = context.getResources().getDisplayMetrics().widthPixels;
|
||||
params.height = context.getResources().getDisplayMetrics().heightPixels;
|
||||
window.setAttributes(params);
|
||||
}
|
||||
|
||||
final Dialog dialog = new Dialog(activityContext, R.style.GhAlertDialog);
|
||||
|
||||
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
|
||||
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_privacy_policy, null);
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
TextView skipTv = contentView.findViewById(R.id.dialog_skip);
|
||||
TextView title = contentView.findViewById(R.id.title);
|
||||
TextView bottomContent = contentView.findViewById(R.id.bottom_content);
|
||||
TextView topContent = contentView.findViewById(R.id.top_content);
|
||||
TextView allowButton = contentView.findViewById(R.id.allow_button);
|
||||
TextView linkContent = contentView.findViewById(R.id.link_content);
|
||||
RecyclerView permissions = contentView.findViewById(R.id.permissions_content);
|
||||
|
||||
SpannableStringBuilder skipText = new SpannableStringBuilder("你可以查看完整版的 隐私政策");
|
||||
permissions.setLayoutManager(new FixLinearLayoutManager(context));
|
||||
permissions.setAdapter(new BaseRecyclerAdapter(context) {
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = mLayoutInflater.inflate(R.layout.privacy_item, parent, false);
|
||||
return new PrivacyPolicyItemViewHolder(PrivacyItemBinding.bind(view));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
if (holder instanceof PrivacyPolicyItemViewHolder) {
|
||||
PrivacyPolicyItemViewHolder viewHolder = (PrivacyPolicyItemViewHolder) holder;
|
||||
PrivacyItemBinding binding = viewHolder.getBinding();
|
||||
binding.setData(entity.getPermissions().get(position));
|
||||
GenericDraweeHierarchy hierarchy = binding.icon.getHierarchy();
|
||||
if (hierarchy != null) {
|
||||
if (position == 0) {
|
||||
hierarchy.setPlaceholderImage(R.drawable.permission_storage);
|
||||
} else {
|
||||
hierarchy.setPlaceholderImage(R.drawable.permission_phone_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return entity.getPermissions().size();
|
||||
}
|
||||
});
|
||||
|
||||
SpannableStringBuilder skipText = new SpannableStringBuilder("查看完整版的隐私政策和用户协议");
|
||||
skipText.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
@ -827,16 +948,31 @@ public class DialogUtils {
|
||||
Intent intent = WebActivity.getPrivacyPolicyIntent(activityContext);
|
||||
activityContext.startActivity(intent);
|
||||
}
|
||||
}, skipText.length() - 9, skipText.length() - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
skipText.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setColor(ContextCompat.getColor(activityContext, R.color.text_1383EB));
|
||||
ds.setUnderlineText(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(@NonNull View widget) {
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击用户协议");
|
||||
activityContext.startActivity(WebActivity.getWebIntent(activityContext));
|
||||
}
|
||||
}, skipText.length() - 4, skipText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
title.setText(entity.getTitle());
|
||||
linkContent.setText(skipText);
|
||||
linkContent.setMovementMethod(new LinkMovementMethod());
|
||||
allowButton.setText("我知道了");
|
||||
topContent.setText(entity.getTopContent());
|
||||
bottomContent.setText(entity.getBottomContent());
|
||||
|
||||
skipTv.setText(skipText);
|
||||
skipTv.setMovementMethod(new LinkMovementMethod());
|
||||
contentTv.setText(Html.fromHtml(privacyPolicyContent));
|
||||
titleTv.setText(privacyPolicyTitle);
|
||||
positiveTv.setText("我知道了");
|
||||
|
||||
positiveTv.setOnClickListener(view -> {
|
||||
allowButton.setOnClickListener(view -> {
|
||||
dialog.dismiss();
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "点击我知道了");
|
||||
});
|
||||
@ -844,13 +980,13 @@ 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);
|
||||
@ -861,8 +997,6 @@ public class DialogUtils {
|
||||
|
||||
MtaHelper.onEvent("隐私政策弹窗", "隐私政策弹窗", "出现弹窗");
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
try {
|
||||
dialog.show();
|
||||
} catch (Exception ignored) {
|
||||
@ -908,6 +1042,59 @@ public class DialogUtils {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static Dialog showTrackableDialog(Context context,
|
||||
String title,
|
||||
CharSequence message,
|
||||
String positive,
|
||||
String negative,
|
||||
final ConfirmListener cmListener,
|
||||
final CancelListener clListener,
|
||||
TrackableEntity trackableEntity) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final TrackableDialog dialog = new TrackableDialog(context,
|
||||
R.style.GhAlertDialog,
|
||||
trackableEntity.getEvent(),
|
||||
trackableEntity.getKey(),
|
||||
trackableEntity.getCancelValue(),
|
||||
trackableEntity.getKeyBackValue(),
|
||||
trackableEntity.getLogShowEvent());
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_alert, null);
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
if (message.toString().contains("红包奖励")) {//将红包奖励四个字标红
|
||||
String str = message.toString().substring(0, message.toString().indexOf("红包奖励")) + "<font color='#FF0000'>红包奖励</font>";
|
||||
contentTv.setText(Html.fromHtml(str));
|
||||
} else {
|
||||
contentTv.setText(message);
|
||||
}
|
||||
titleTv.setText(title);
|
||||
negativeTv.setText(negative);
|
||||
positiveTv.setText(positive);
|
||||
|
||||
negativeTv.setOnClickListener(view -> {
|
||||
if (clListener != null) {
|
||||
clListener.onCancel();
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
positiveTv.setOnClickListener(view -> {
|
||||
if (cmListener != null) {
|
||||
cmListener.onConfirm();
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static Dialog fixWebViewKeyboardNotWorking(Activity activity) {
|
||||
final Dialog dialog = new Dialog(activity, R.style.TransparentDialog);
|
||||
View view = new View(activity);
|
||||
@ -923,6 +1110,46 @@ public class DialogUtils {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static Dialog showUsageStatsDialog(Context context, final ConfirmListener cmListener, final CancelListener clListener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_usage_stats, null);
|
||||
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
negativeTv.setOnClickListener(view -> {
|
||||
if (clListener != null) {
|
||||
clListener.onCancel();
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
positiveTv.setOnClickListener(view -> {
|
||||
if (cmListener != null) {
|
||||
cmListener.onConfirm();
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.setOnDismissListener(dialog1 -> {
|
||||
if (clListener != null) {
|
||||
clListener.onCancel();
|
||||
}
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context may be is application context
|
||||
* @return activity context
|
||||
|
||||
@ -9,6 +9,8 @@ import android.text.TextUtils
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.exposure.ExposureEvent
|
||||
import com.gh.common.util.EntranceUtils.*
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.amway.AmwayActivity
|
||||
@ -19,6 +21,7 @@ import com.gh.gamecenter.eventbus.EBReuse
|
||||
import com.gh.gamecenter.eventbus.EBSkip
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment
|
||||
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.mygame.PlayedGameActivity
|
||||
import com.gh.gamecenter.personalhome.UserHomeActivity
|
||||
@ -34,6 +37,9 @@ import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.gh.gamecenter.suggest.SuggestType
|
||||
import com.gh.gamecenter.tag.TagsActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.gh.gamecenter.video.game.GameVideoActivity
|
||||
import com.gh.gamecenter.video.videomanager.VideoManagerActivity
|
||||
import com.lightgame.utils.Util_System_ClipboardManager
|
||||
import com.lightgame.utils.Utils
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
@ -49,27 +55,27 @@ object DirectUtils {
|
||||
@JvmStatic
|
||||
fun directToSpecificPage(context: Context, type: String, link: String, text: String? = "", entrance: String? = null, path: String? = null) {
|
||||
when (type) {
|
||||
EntranceUtils.HOST_ARTICLE -> directToArticle(context, id = link, entrance = entrance)
|
||||
HOST_ARTICLE -> directToArticle(context, id = link, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_GAME -> directToGameDetail(context, id = link, entrance = entrance)
|
||||
HOST_GAME -> directToGameDetail(context, id = link, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_GAME_DOWNLOAD -> directToGameDetail(context, id = link, entrance = entrance, autoDownload = true)
|
||||
HOST_GAME_DOWNLOAD -> directToGameDetail(context, id = link, entrance = entrance, autoDownload = true)
|
||||
|
||||
EntranceUtils.HOST_COLUMN -> directToSubject(context, id = link, subjectName = text, entrance = entrance)
|
||||
HOST_COLUMN -> directToSubject(context, id = link, subjectName = text, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_QUESTION -> directToQuestionDetail(context, id = link, entrance = entrance, path = path)
|
||||
HOST_QUESTION -> directToQuestionDetail(context, id = link, entrance = entrance, path = path)
|
||||
|
||||
EntranceUtils.HOST_ANSWER -> directToAnswerDetail(context, id = link, entrance = entrance, path = path)
|
||||
HOST_ANSWER -> directToAnswerDetail(context, id = link, entrance = entrance, path = path)
|
||||
|
||||
EntranceUtils.HOST_WEB -> directToWebView(context, url = link, entrance = entrance)
|
||||
HOST_WEB -> directToWebView(context, url = link, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_DOWNLOAD -> directToDownloadManagerAndStartDownload(context, gameId = link, packageName = text, entrance = entrance)
|
||||
HOST_DOWNLOAD -> directToDownloadManagerAndStartDownload(context, gameId = link, packageName = text, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_UPDATE -> directToDownloadManagerAndStartUpdate(context, gameId = link, packageName = text, entrance = entrance)
|
||||
HOST_UPDATE -> directToDownloadManagerAndStartUpdate(context, gameId = link, packageName = text, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_LIBAO -> directToGiftDetail(context, giftId = link, entrance = entrance)
|
||||
HOST_LIBAO -> directToGiftDetail(context, giftId = link, entrance = entrance)
|
||||
|
||||
EntranceUtils.HOST_COMMUNITY -> directToCommunity(context, CommunityEntity(link, text!!))
|
||||
HOST_COMMUNITY -> directToCommunity(context, CommunityEntity(link, text!!))
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,37 +84,80 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String) {
|
||||
directToLinkPage(context, linkEntity, entrance, path, null)
|
||||
}
|
||||
|
||||
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String, exposureEvent: ExposureEvent? = null) {
|
||||
directToLinkPage(context, linkEntity, entrance, path, exposureEvent, null)
|
||||
}
|
||||
|
||||
// 用于判断是否已经对接相关类型
|
||||
var directLinkTypes = arrayOf(
|
||||
"article", "news",
|
||||
"game",
|
||||
"column",
|
||||
"question",
|
||||
"answer",
|
||||
"community",
|
||||
"community_article",
|
||||
"community_column",
|
||||
"community_special_column",
|
||||
"web", "inurl",
|
||||
"qq", "QQ",
|
||||
"qqqun",
|
||||
"tag",
|
||||
"all_community_article",
|
||||
"category",
|
||||
"block",
|
||||
"column_collection",
|
||||
"server",
|
||||
"top_game_comment",
|
||||
"wechat_bind",
|
||||
"video")
|
||||
|
||||
fun directToLinkPage(context: Context,
|
||||
linkEntity: LinkEntity,
|
||||
entrance: String,
|
||||
path: String,
|
||||
exposureEvent: ExposureEvent? = null,
|
||||
unknownCallback: (() -> Unit)?) {
|
||||
when (linkEntity.type) {
|
||||
"article", "news" -> {
|
||||
"article", "news", "文章" -> {
|
||||
NewsUtils.statNewsViews(context, linkEntity.link) // 统计阅读量
|
||||
context.startActivity(NewsDetailActivity.getIntentById(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path)))
|
||||
}
|
||||
|
||||
"game" -> GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
"game", "游戏" -> {
|
||||
if (exposureEvent != null) {
|
||||
GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path), exposureEvent)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
}
|
||||
}
|
||||
|
||||
"column" -> SubjectActivity.startSubjectActivity(context, linkEntity.link, linkEntity.text, false, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
"column", "游戏专题" -> SubjectActivity.startSubjectActivity(context, linkEntity.link, linkEntity.text, false, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
|
||||
"question" -> context.startActivity(QuestionsDetailActivity.getIntent(context, linkEntity.link, entrance, path))
|
||||
"question", "社区问题" -> context.startActivity(QuestionsDetailActivity.getIntent(context, linkEntity.link, entrance, path))
|
||||
|
||||
"answer" -> context.startActivity(AnswerDetailActivity.getIntent(context, linkEntity.link, entrance, path))
|
||||
"answer", "社区回答" -> context.startActivity(AnswerDetailActivity.getIntent(context, linkEntity.link, entrance, path))
|
||||
|
||||
"community" -> directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
|
||||
"community", "问答社区" -> directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
|
||||
|
||||
"community_article" -> context.startActivity(ArticleDetailActivity.getIntent(context, linkEntity.community!!, linkEntity.link!!, entrance, path))
|
||||
"community_article", "社区文章" -> context.startActivity(ArticleDetailActivity.getIntent(context, linkEntity.community!!, linkEntity.link!!, entrance, path))
|
||||
|
||||
"community_column" -> directToCommunityColumn(context, linkEntity.community, linkEntity.link!!, entrance, path)
|
||||
"community_column", "社区专题" -> directToCommunityColumn(context, linkEntity.community, linkEntity.link!!, entrance, path)
|
||||
|
||||
"community_special_column" -> context.startActivity(AskColumnDetailActivity.getIntentByColumnId(context, linkEntity.link, linkEntity.community!!, entrance, path))
|
||||
|
||||
"web", "inurl" -> directToWebView(context, url = linkEntity.link!!, entrance = BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
"web", "inurl", "web链接" -> directToWebView(context, url = linkEntity.link!!, entrance = BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
|
||||
"qq" -> directToQqConversation(context, linkEntity.link)
|
||||
"qq", "QQ" -> directToQqConversation(context, linkEntity.link)
|
||||
|
||||
"outurl" -> directToExternalBrowser(context, linkEntity.link!!)
|
||||
|
||||
"qqqun" -> directToQqGroup(context, linkEntity.link!!)
|
||||
"qqqun", "QQ群" -> directToQqGroup(context, linkEntity.link!!)
|
||||
|
||||
"tag" -> context.startActivity(TagsActivity.getIntent(context, linkEntity.text!!, entrance, path))
|
||||
"tag" -> context.startActivity(TagsActivity.getIntent(context, linkEntity.text!!, linkEntity.title, entrance, path))
|
||||
|
||||
"all_community_article" -> {
|
||||
context.startActivity(SimpleArticleListActivity.getIntent(
|
||||
@ -118,11 +167,11 @@ object DirectUtils {
|
||||
path))
|
||||
}
|
||||
|
||||
"category" -> {
|
||||
"category", "分类" -> {
|
||||
context.startActivity(CategoryDirectoryActivity.getIntent(context, linkEntity.link!!, linkEntity.text!!))
|
||||
}
|
||||
|
||||
"block" -> {
|
||||
"block", "版块" -> {
|
||||
context.startActivity(BlockActivity.getIntent(context, SubjectRecommendEntity(
|
||||
link = linkEntity.link,
|
||||
text = linkEntity.text,
|
||||
@ -130,7 +179,7 @@ object DirectUtils {
|
||||
display = linkEntity.display ?: Display())))
|
||||
}
|
||||
|
||||
"column_collection" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
|
||||
"column_collection", "专题合集" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
|
||||
|
||||
"server" -> {
|
||||
context.startActivity(GameServersActivity.getIntent(context, entrance, path))
|
||||
@ -140,7 +189,21 @@ object DirectUtils {
|
||||
|
||||
"wechat_bind" -> context.startActivity(WebActivity.getBindWechatIntent(context))
|
||||
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
"video", "video_stream" -> directToVideoDetail(context,
|
||||
videoId = linkEntity.link!!,
|
||||
fromLocation = VideoDetailContainerViewModel.Location.VIDEO_CHOICENESS.value,
|
||||
entrance = entrance,
|
||||
path = path)
|
||||
|
||||
"game_video" -> directToGameVideo(context, linkEntity.link ?: "", entrance, path)
|
||||
|
||||
else -> {
|
||||
if (unknownCallback != null) {
|
||||
unknownCallback.invoke()
|
||||
} else {
|
||||
DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,6 +255,21 @@ object DirectUtils {
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转视频流-游戏介绍进入
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameDetailVideoStreaming(context: Context, id: String, entrance: String? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameVideoActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
bundle.putBoolean(KEY_OPEN_VIDEO_STREAMING, true)
|
||||
bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_DESC)
|
||||
// GameDetailActivity.startGameDetailToVideoStreaming(context, id, entrance)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
// 跳转至用户玩过的游戏
|
||||
fun directToPlayedGame(context: Context, userId: String, entrance: String = "", path: String = "") {
|
||||
context.startActivity(PlayedGameActivity.getIntent(context, userId, entrance, path))
|
||||
@ -309,16 +387,16 @@ object DirectUtils {
|
||||
context.startActivity(browserIntent)
|
||||
}
|
||||
|
||||
// 跳转 QQ
|
||||
// 跳转 QQ,qqNumber 为空选择默认客服 QQ
|
||||
@JvmStatic
|
||||
fun directToQqConversation(context: Context, qqNumber: String? = null) {
|
||||
var qq = qqNumber
|
||||
|
||||
if (TextUtils.isEmpty(qq)) {
|
||||
qq = "2586716223"
|
||||
qq = Config.getSettings()?.support?.qq ?: "3509629529"
|
||||
}
|
||||
if (ShareUtils.isQQClientAvailable(context)) {
|
||||
// 安装了 QQ 直接调用QQ,打开手机QQ进行会话 默认 QQ 号:2586716223
|
||||
// 安装了 QQ 直接调用QQ,打开手机QQ进行会话 默认 QQ 号:3509629529
|
||||
val chatType: String
|
||||
if (qq!!.startsWith("400") || qq.startsWith("800")) {
|
||||
chatType = "crm"
|
||||
@ -380,6 +458,21 @@ object DirectUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToCommunity(context: Context) {
|
||||
if (MainActivity::class.java.name != RunningUtils.getTopActivity(context)) {
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
// 这里换个线程操作是为了做一点延时
|
||||
AppExecutor.ioExecutor.execute {
|
||||
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_ASK))
|
||||
EventBus.getDefault().post(EBReuse(CommunityFragment.EB_RETRY_PAGE))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToCommunityArticle(context: Context, articleId: String?, communityId: String?, entrance: String?, path: String?) {
|
||||
val bundle = Bundle()
|
||||
@ -409,15 +502,17 @@ object DirectUtils {
|
||||
* @param fromLocation 可见 [VideoDetailContainerViewModel.Location]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, entrance: String? = null, path: String? = "") {
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null, path: String? = "", referer: String = "") {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, VideoDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_ID, videoId)
|
||||
bundle.putString(KEY_GAMEID, gameId)
|
||||
bundle.putString(KEY_LOCATION, fromLocation)
|
||||
bundle.putBoolean(KEY_SHOW_COMMENT, showComment)
|
||||
bundle.putString(KEY_REFERER, referer)
|
||||
jumpActivity(context, bundle)
|
||||
} else {
|
||||
DialogUtils.showLowSystemVersionDialog(context)
|
||||
@ -445,4 +540,31 @@ object DirectUtils {
|
||||
fun directToBadgeWall(context: Context, userId: String?, name: String?, icon: String?) {
|
||||
context.startActivity(WebActivity.getBadgeCenterIntent(context, userId, name, icon))
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至上传视频
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToVideoManager(context: Context, linkEntity: VideoLinkEntity, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putParcelable(VideoLinkEntity::class.java.simpleName, linkEntity)
|
||||
bundle.putString(KEY_TO, VideoManagerActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转视频合集
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameVideo(context: Context, gameId: String, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_TO, GameVideoActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
bundle.putString(KEY_GAMEID, gameId)
|
||||
// context.startActivity(GameVideoActivity.getIntent(context, gameId, entrance, path))
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,18 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Display;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
@ -17,7 +24,7 @@ import java.lang.reflect.Method;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class DisplayUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 根据手机的分辨率从 dip(像素) 的单位 转成为 px
|
||||
*/
|
||||
@ -25,7 +32,7 @@ public class DisplayUtils {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据手机的分辨率从 px(像素) 的单位 转成为 dip
|
||||
*/
|
||||
@ -33,19 +40,19 @@ public class DisplayUtils {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (pxValue / scale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据手机的分辨率从 dip(像素) 的单位 转成为 px
|
||||
*/
|
||||
public static int dip2px(float dpValue) {
|
||||
final float scale = HaloApp.getInstance()
|
||||
.getApplication()
|
||||
.getResources()
|
||||
.getDisplayMetrics().density;
|
||||
.getApplication()
|
||||
.getResources()
|
||||
.getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 将px值转换为sp值,保证文字大小不变
|
||||
*
|
||||
@ -57,7 +64,7 @@ public class DisplayUtils {
|
||||
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
|
||||
return (int) (pxValue / fontScale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将sp值转换为px值,保证文字大小不变
|
||||
*
|
||||
@ -69,7 +76,7 @@ public class DisplayUtils {
|
||||
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
|
||||
return (int) (spValue * fontScale + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取状态栏的高度
|
||||
*
|
||||
@ -79,7 +86,7 @@ public class DisplayUtils {
|
||||
public static int getStatusBarHeight(Resources resources) {
|
||||
return getInternalDimensionSize(resources, "status_bar_height");
|
||||
}
|
||||
|
||||
|
||||
public static int getInternalDimensionSize(Resources res, String key) {
|
||||
int result = 0;
|
||||
int resourceId = res.getIdentifier(key, "dimen", "android");
|
||||
@ -88,7 +95,7 @@ public class DisplayUtils {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static void transparentStatusBar(Activity activity) {
|
||||
//make full transparent statusBar
|
||||
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
|
||||
@ -96,15 +103,15 @@ public class DisplayUtils {
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
setWindowFlag(activity, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false);
|
||||
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void transparentStatusAndNavigation(Activity activity) {
|
||||
//make full transparent statusBar
|
||||
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
|
||||
@ -112,8 +119,8 @@ public class DisplayUtils {
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
setWindowFlag(activity, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, false);
|
||||
@ -121,7 +128,7 @@ public class DisplayUtils {
|
||||
activity.getWindow().setNavigationBarColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void setWindowFlag(Activity activity, final int bits, boolean on) {
|
||||
Window win = activity.getWindow();
|
||||
WindowManager.LayoutParams winParams = win.getAttributes();
|
||||
@ -132,14 +139,12 @@ public class DisplayUtils {
|
||||
}
|
||||
win.setAttributes(winParams);
|
||||
}
|
||||
|
||||
public static void setLightStatusBar(Activity activity, boolean lightStatusBar) {
|
||||
boolean isMIUI = setMIUIStatusBarStyle(activity, lightStatusBar);
|
||||
|
||||
if (!isMIUI) {
|
||||
|
||||
public static void setLightStatusBar(Activity activity, boolean lightStatusBar, boolean isKeepLowVersionMiui) {
|
||||
if (!isMiuiOs()) {
|
||||
Window window = activity.getWindow();
|
||||
View decor = window.getDecorView();
|
||||
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (lightStatusBar) {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
@ -149,46 +154,116 @@ public class DisplayUtils {
|
||||
} else {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
} else {
|
||||
setMIUIStatusBarStyle(activity, lightStatusBar, isKeepLowVersionMiui);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean setMIUIStatusBarStyle(Activity activity, boolean lightStatusBar) {
|
||||
boolean result = false;
|
||||
Window window = activity.getWindow();
|
||||
if (window != null) {
|
||||
Class clazz = window.getClass();
|
||||
try {
|
||||
int darkModeFlag = 0;
|
||||
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
extraFlagField.invoke(window, lightStatusBar ? darkModeFlag : 0, darkModeFlag);//状态栏透明且黑色字体
|
||||
result = true;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && lightStatusBar) {
|
||||
//开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void setStatusBarColor(Activity activity, int color, boolean lightStatusBar) {
|
||||
public static void setLightStatusBar(Activity activity, boolean lightStatusBar) {
|
||||
setLightStatusBar(activity, lightStatusBar, true);
|
||||
}
|
||||
|
||||
private static void setMIUIStatusBarStyle(Activity activity, boolean lightStatusBar, boolean isKeepLowVersionMiui) {
|
||||
Window window = activity.getWindow();
|
||||
if (window != null) {
|
||||
|
||||
View decor = window.getDecorView();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (lightStatusBar) {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
} else {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
} else {
|
||||
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
|
||||
if (isKeepLowVersionMiui) {
|
||||
Class clazz = window.getClass();
|
||||
try {
|
||||
int darkModeFlag = 0;
|
||||
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
extraFlagField.invoke(window, lightStatusBar ? darkModeFlag : 0, darkModeFlag);//状态栏透明且黑色字体
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && lightStatusBar) {
|
||||
//开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
|
||||
activity.getWindow()
|
||||
.getDecorView()
|
||||
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void setStatusBarColor(Activity activity, int color, boolean lightStatusBar) {
|
||||
Window window = activity.getWindow();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.setStatusBarColor(ContextCompat.getColor(activity,color));
|
||||
window.setStatusBarColor(ContextCompat.getColor(activity, color));
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
|
||||
setLightStatusBar(activity,lightStatusBar);
|
||||
setLightStatusBar(activity, lightStatusBar);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static boolean isMiuiOs() {
|
||||
String property = getSystemProperty("ro.miui.ui.version.name", "");
|
||||
return !TextUtils.isEmpty(property);
|
||||
}
|
||||
|
||||
private static String getSystemProperty(String key, String defaultValue) {
|
||||
try {
|
||||
@SuppressLint("PrivateApi") Class<?> clz = Class.forName("android.os.SystemProperties");
|
||||
Method method = clz.getMethod("get", String.class, String.class);
|
||||
return (String) method.invoke(clz, key, defaultValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static int retrieveNavigationHeight(Context context) {
|
||||
Resources resources = context.getResources();
|
||||
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||
return (resourceId > 0 && hasSoftKeys(context)) ? resources.getDimensionPixelSize(resourceId) : 0;
|
||||
}
|
||||
|
||||
public static boolean hasSoftKeys(Context context) {
|
||||
if (!(context instanceof Activity)) return false;
|
||||
|
||||
boolean hasSoftwareKeys;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
Display d = ((Activity) context).getWindowManager().getDefaultDisplay();
|
||||
|
||||
DisplayMetrics realDisplayMetrics = new DisplayMetrics();
|
||||
d.getRealMetrics(realDisplayMetrics);
|
||||
|
||||
int realHeight = realDisplayMetrics.heightPixels;
|
||||
int realWidth = realDisplayMetrics.widthPixels;
|
||||
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
d.getMetrics(displayMetrics);
|
||||
|
||||
int displayHeight = displayMetrics.heightPixels;
|
||||
int displayWidth = displayMetrics.widthPixels;
|
||||
|
||||
hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0;
|
||||
} else {
|
||||
boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
|
||||
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
|
||||
hasSoftwareKeys = !hasMenuKey && !hasBackKey;
|
||||
}
|
||||
return hasSoftwareKeys;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,18 +1,13 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.ReserveDialogFragment;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
@ -22,9 +17,11 @@ import com.gh.common.view.DownloadDialog;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadConfig;
|
||||
@ -35,6 +32,12 @@ import com.lightgame.utils.Utils;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class DownloadItemUtils {
|
||||
|
||||
// 更新下载进度条
|
||||
@ -167,22 +170,34 @@ public class DownloadItemUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gameEntity.getApk().isEmpty() || gameEntity.getDownloadOffStatus() != null) {
|
||||
if (gameEntity.getApk().isEmpty()
|
||||
|| gameEntity.getDownloadOffStatus() != null) {
|
||||
LinkEntity h5LinkEntity = gameEntity.getH5Link();
|
||||
String offStatus = gameEntity.getDownloadOffStatus();
|
||||
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
|
||||
String offStatus = gameEntity.getDownloadOffStatus();
|
||||
if ("dialog".equals(offStatus)) {
|
||||
holder.gameDownloadBtn.setText("查看");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.white));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
|
||||
if (h5LinkEntity != null) {
|
||||
if ("play".equals(h5LinkEntity.getType())) {
|
||||
holder.gameDownloadBtn.setText("开始玩");
|
||||
} else {
|
||||
holder.gameDownloadBtn.setText("查看");
|
||||
}
|
||||
holder.gameDownloadBtn.setClickable(true);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setText("暂无");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.button_gray));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.news_detail_comment);
|
||||
if ("dialog".equals(offStatus)) {
|
||||
holder.gameDownloadBtn.setText("查看");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.white));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setText("暂无");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.button_gray));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.news_detail_comment);
|
||||
}
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
}
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
updateNormalItem(context, holder, gameEntity, isShowPlatform, pluginLocation);
|
||||
} else {
|
||||
@ -374,7 +389,10 @@ public class DownloadItemUtils {
|
||||
PermissionHelper.checkReadPhoneStatePermissionBeforeAction(context, () -> {
|
||||
ReserveDialogFragment dialogFragment = ReserveDialogFragment.getInstance(
|
||||
gameEntity,
|
||||
() -> adapter.notifyItemChanged(position)
|
||||
() -> {
|
||||
LogUtils.logReservation(gameEntity, traceEvent);
|
||||
adapter.notifyItemChanged(position);
|
||||
}
|
||||
);
|
||||
dialogFragment.show(((AppCompatActivity) context).getSupportFragmentManager(), "reserve");
|
||||
});
|
||||
@ -402,8 +420,14 @@ public class DownloadItemUtils {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
|
||||
if (gameEntity.getApk().size() == 0 && gameEntity.getH5Link() != null) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
|
||||
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), "play".equals(gameEntity.getH5Link().getType()));
|
||||
context.startActivity(i);
|
||||
});
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
EmptyCallback clickRunnable = () -> {
|
||||
if (clickCallback != null) {
|
||||
@ -512,8 +536,6 @@ public class DownloadItemUtils {
|
||||
downloadBtn.setText(R.string.downloading);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
|
||||
|
||||
// DownloadManager.getInstance(context).putStatus(gameEntity.getApk().get(0).getUrl(), "downloading");
|
||||
} else {
|
||||
Utils.toast(context, msg);
|
||||
}
|
||||
@ -534,8 +556,6 @@ public class DownloadItemUtils {
|
||||
downloadBtn.setText(R.string.downloading);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
|
||||
|
||||
// DownloadManager.getInstance(context).putStatus(gameEntity.getApk().get(0).getUrl(), "downloading");
|
||||
} else {
|
||||
Utils.toast(context, msg);
|
||||
}
|
||||
@ -556,16 +576,20 @@ public class DownloadItemUtils {
|
||||
}
|
||||
adapter.notifyItemChanged(position);
|
||||
} else {
|
||||
PackageUtils.launchSetup(context, path);
|
||||
PackageUtils.launchSetup(context, downloadEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//更新
|
||||
private static void update(Context context, GameEntity gameEntity, String entrance, String location,
|
||||
boolean isSubscribe, @Nullable ExposureEvent traceEvent) {
|
||||
DataUtils.onGameUpdateEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), "下载开始");
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, gameEntity.getApk().get(0).getPlatform(), traceEvent, ExposureUtils.DownloadType.UPDATE);
|
||||
private static void update(Context context, GameEntity gameEntity, String entrance, String location, boolean isSubscribe, @Nullable ExposureEvent traceEvent) {
|
||||
ApkEntity apkEntity = gameEntity.getApk().get(0);
|
||||
|
||||
ExposureUtils.DownloadType downloadType = ExposureUtils.getUpdateType(apkEntity);
|
||||
DataUtils.onGameUpdateEvent(context, gameEntity.getName(), apkEntity.getPlatform(), "下载开始");
|
||||
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity
|
||||
.getPlatform(), traceEvent, downloadType);
|
||||
DownloadManager.createDownload(context, gameEntity, "更新", entrance, location, isSubscribe, downloadExposureEvent);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,161 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
|
||||
object DownloadNotificationHelper {
|
||||
|
||||
private const val DOWNLOAD_GROUP_KEY = "download_group_key"
|
||||
private const val DOWNLOAD_CHANNEL_ID = "download"
|
||||
private const val DOWNLOAD_NOTIFICATION_FOLD_ID = 889
|
||||
private const val DOWNLOAD_NOTIFICATION_ID = 888
|
||||
private const val PROGRESS_MAX = 100
|
||||
|
||||
const val ACTION_INSTALL = "com.gh.gamecenter.INSTALL"
|
||||
const val ACTION_DOWNLOAD = "com.gh.gamecenter.DOWNLOAD"
|
||||
|
||||
private val mNotifyMap: MutableMap<String, Long> = mutableMapOf()
|
||||
|
||||
private fun getNotificationManager(): NotificationManager {
|
||||
return HaloApp.getInstance().application.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Synchronized
|
||||
fun addOrUpdateDownloadNotification(entity: DownloadEntity) {
|
||||
var requireUpdateNotificationGroupDelay = false
|
||||
val notificationManager = getNotificationManager()
|
||||
val downloadNotificationId = (entity.gameId + entity.packageName).hashCode()
|
||||
|
||||
val intent = Intent()
|
||||
if (entity.status == DownloadStatus.done) {
|
||||
intent.putExtra(EntranceUtils.KEY_DATA, entity.toJson())
|
||||
intent.putExtra(EntranceUtils.KEY_PATH, entity.path)
|
||||
intent.action = ACTION_INSTALL
|
||||
} else {
|
||||
intent.action = ACTION_DOWNLOAD
|
||||
}
|
||||
val pendingIntent = PendingIntent.getBroadcast(HaloApp.getInstance().application,
|
||||
downloadNotificationId,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// importance == IMPORTANCE_DEFAULT 时每次更新都会触发震动
|
||||
val channel = NotificationChannel(DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
val whenTime = 1000 * 60 * (System.currentTimeMillis() / 1000 / 60)
|
||||
val builder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
|
||||
.setContentTitle(entity.name)
|
||||
.setSmallIcon(R.mipmap.logo)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setGroup(DOWNLOAD_GROUP_KEY)
|
||||
.setWhen(whenTime)
|
||||
.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
|
||||
|
||||
when (entity.status) {
|
||||
DownloadStatus.downloading -> builder.setContentText(String.format("%s(剩%s)",
|
||||
SpeedUtils.getSpeed(entity.speed),
|
||||
SpeedUtils.getRemainTime(entity.size, entity.progress, entity.speed * 1024)))
|
||||
DownloadStatus.done -> builder.setContentText("下载完成,点击立即安装")
|
||||
DownloadStatus.waiting -> builder.setContentText("等待中")
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.neterror -> builder.setContentText("已暂停,连接WiFi自动下载")
|
||||
else -> builder.setContentText("暂停中")
|
||||
}
|
||||
|
||||
when {
|
||||
entity.status == DownloadStatus.done -> {
|
||||
builder.setSortKey("A")
|
||||
builder.setOngoing(true) // 垃圾华为 sortKey 不起效 priority 也不起效,要将下载完成任务的通知置顶只能设置为 ongoing,喷了
|
||||
}
|
||||
entity.status == DownloadStatus.downloading -> builder.setSortKey("B")
|
||||
else -> builder.setSortKey("C")
|
||||
}
|
||||
|
||||
val notification = builder.build()
|
||||
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
|
||||
|
||||
if (entity.status == DownloadStatus.delete
|
||||
|| entity.status == DownloadStatus.cancel
|
||||
|| entity.status == DownloadStatus.hijack
|
||||
|| entity.status == DownloadStatus.notfound
|
||||
|| entity.status == DownloadStatus.overflow
|
||||
|| (entity.status == DownloadStatus.done // 触发安装事件以后也 cancel 掉通知
|
||||
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty())) {
|
||||
requireUpdateNotificationGroupDelay = true
|
||||
notificationManager.cancel(entity.path, DOWNLOAD_NOTIFICATION_ID)
|
||||
} else {
|
||||
if (entity.status != DownloadStatus.downloading) {
|
||||
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
|
||||
} else {
|
||||
val time = mNotifyMap[entity.path]
|
||||
val curTime = System.currentTimeMillis()
|
||||
if (time == null || curTime - time > 2000) {
|
||||
mNotifyMap[entity.path] = curTime
|
||||
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (requireUpdateNotificationGroupDelay) {
|
||||
// 虽然运行到这里时 notification 已经被 cancel 了,但在下面的 notificationManager.getActiveNotifications 里它有可能还是 active 状态,
|
||||
// 这里延时 100 ms 避免出现所有的任务都取消了以后依旧有一条 notification group 常驻
|
||||
AppExecutor.uiExecutor.executeWithDelay(Runnable { updateNotificationGroup() }, 100)
|
||||
} else {
|
||||
updateNotificationGroup()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateNotificationGroup() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val notificationManager = getNotificationManager()
|
||||
val activeNotifications = notificationManager.activeNotifications
|
||||
var downloadNotificationSize = 0
|
||||
var downloadGroupNotificationSize = 0
|
||||
for (activeNotification in activeNotifications) {
|
||||
if (activeNotification.id == DOWNLOAD_NOTIFICATION_ID) {
|
||||
downloadNotificationSize++
|
||||
}
|
||||
if (activeNotification.id == DOWNLOAD_NOTIFICATION_FOLD_ID) {
|
||||
downloadGroupNotificationSize++
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadNotificationSize == 0 && downloadGroupNotificationSize != 0) {
|
||||
// 删除组可能会把组内所有通知一并删除
|
||||
notificationManager.cancel(DOWNLOAD_NOTIFICATION_FOLD_ID)
|
||||
} else if (downloadNotificationSize != 0 && downloadGroupNotificationSize == 0) {
|
||||
val groupBuilder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
|
||||
.setSmallIcon(R.mipmap.logo)
|
||||
.setGroup(DOWNLOAD_GROUP_KEY)
|
||||
.setGroupSummary(true)
|
||||
.setStyle(NotificationCompat.BigTextStyle().bigText("下载任务"))
|
||||
val groupNotification = groupBuilder.build()
|
||||
groupNotification.flags = groupNotification.flags or Notification.FLAG_NO_CLEAR
|
||||
notificationManager.notify(DOWNLOAD_NOTIFICATION_FOLD_ID, groupNotification)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun initDownloadNotification(downloadTasks: MutableList<DownloadEntity>) {
|
||||
for (downloadTask in downloadTasks) {
|
||||
addOrUpdateDownloadNotification(downloadTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,12 @@ 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_UPLOAD_VIDEO = "upload_video";//上传视频
|
||||
public static final String HOST_VIDEO_SINGLE = "video_single";//指定视频-不能划动
|
||||
public static final String HOST_VIDEO_MORE = "video_more";//指定视频-能划动
|
||||
public static final String HOST_VIDEO_STREAMING_HOME = "video_streaming_home";//视频流-首页
|
||||
public static final String HOST_VIDEO_STREAMING_DESC = "video_streaming_desc";//视频流-游戏介绍进入
|
||||
public static final String HOST_VIDEO_COLLECTION = "video_collection";//视频合集
|
||||
public static final String HOST_VIDEO = "video";
|
||||
public static final String HOST_COMMUNITY_ARTICLE = "community_article";
|
||||
public static final String HOST_COMMUNITY_COLUMN = "community_column";
|
||||
@ -32,6 +38,7 @@ public class EntranceUtils {
|
||||
public static final String HOST_COLUMN = "column";
|
||||
public static final String HOST_WEB = "web";
|
||||
public static final String HOST_QQ = "qq";
|
||||
public static final String HOST_QQ_GROUP = "qqgroup";
|
||||
public static final String HOST_DOWNLOAD = "download";
|
||||
public static final String HOST_UPDATE = "update";
|
||||
public static final String HOST_LIBAO = "libao";
|
||||
@ -48,6 +55,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_NAME = "name";
|
||||
public static final String KEY_POSITION = "position";
|
||||
public static final String KEY_ENTRANCE = "entrance";
|
||||
public static final String KEY_ENTRANCE_LINK = "entrance_link";
|
||||
public static final String KEY_TARGET = "target";
|
||||
public static final String ENTRANCE_BROWSER = "(浏览器)";
|
||||
public static final String ENTRANCE_WELCOME = "(启动弹窗)";
|
||||
@ -125,6 +133,13 @@ public class EntranceUtils {
|
||||
public static final String KEY_AMWAY = "amway";
|
||||
public static final String KEY_COLLECTION_ID = "collectionId";
|
||||
public static final String KEY_NAVIGATION_TITLE = "navigationTitle";
|
||||
public static final String KEY_IMAGE_CROP_RATIO = "imageCropRatio";
|
||||
public static final String KEY_OPEN_VIDEO_STREAMING = "openVideoStreaming";
|
||||
public static final String KEY_REFERER = "referer";
|
||||
public static final String KEY_UUID = "uuid";
|
||||
public static final String KEY_IS_HOME_VIDEO = "isHomeVideo";
|
||||
public static final String KEY_IS_HOME = "isHome";
|
||||
public static final String KEY_WEB_SHARE = "webShare";
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.ErrorEntity
|
||||
@ -110,9 +111,10 @@ object ErrorHelper {
|
||||
403016 -> Utils.toast(context, "标签内容可能包含敏感信息,请修改后再提交")
|
||||
403018 -> Utils.toast(context, R.string.comment_failed_unable)
|
||||
403070 -> Utils.toast(context, "请勿重复提交~")
|
||||
403073 -> Utils.toast(context, "标题可能包含敏感词,请修改后再提交")
|
||||
403073 -> Utils.toast(context, "标题违规,请重新编辑")
|
||||
403074 -> Utils.toast(context, "该微信号(${errorEntity.data?.nickname})已绑定")
|
||||
403078 -> Utils.toast(context, "已点赞")
|
||||
403072 -> Utils.toast(context, R.string.comment_failed_userblocked)
|
||||
|
||||
403020 -> if (showHighPriorityHint) {
|
||||
DialogUtils.showAlertDialog(context,
|
||||
@ -143,7 +145,7 @@ object ErrorHelper {
|
||||
val dialogContext = DialogUtils.checkDialogContext(context)
|
||||
DialogUtils.showAlertDialog(dialogContext,
|
||||
"提示",
|
||||
"你因违反《光环助手评论规则》,已被禁言,如有疑问$bannedType,请联系客服(QQ:3467475980)",
|
||||
"你因违反《光环助手评论规则》,已被禁言$bannedType,如有疑问,请联系客服(QQ:${Config.getSettings()?.support?.qq})",
|
||||
"去看看", "关闭", {
|
||||
dialogContext.startActivity(WebActivity.getCommentRulesIntent(dialogContext))
|
||||
}, null)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.animation.Animator
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.text.Editable
|
||||
@ -18,6 +19,7 @@ import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.*
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.constant.Constants
|
||||
@ -26,9 +28,13 @@ import com.gh.gamecenter.R
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import java.net.URI
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
@ -223,6 +229,11 @@ fun String.fromHtml(): Spanned {
|
||||
return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||
}
|
||||
|
||||
// 将双引号换成单引号避免 JSON 解析异常 ( escape 后会有其它异常,暂时先替换成单引号了)
|
||||
fun String.eliminateDoubleQuote(): String {
|
||||
return this.replace("\"", "'")
|
||||
}
|
||||
|
||||
// 去掉文章/答案的插入内容
|
||||
fun String.removeInsertedContent(): String {
|
||||
val textRegex = "(?s)<div class=\"gh-internal-content content-right\".*?</div>"
|
||||
@ -262,6 +273,16 @@ fun Map<String, String>.createRequestBody(): RequestBody {
|
||||
return RequestBody.create(MediaType.parse("application/json"), json)
|
||||
}
|
||||
|
||||
fun Map<String, Any>.createRequestBodyAny(): RequestBody {
|
||||
val json = GsonUtils.toJson(this)
|
||||
return RequestBody.create(MediaType.parse("application/json"), json)
|
||||
}
|
||||
|
||||
fun Any.toRequestBody(): RequestBody {
|
||||
val json = GsonUtils.toJson(this)
|
||||
return RequestBody.create(MediaType.parse("application/json"), json)
|
||||
}
|
||||
|
||||
// 对在浏览器(WebView)显示的路径进行转码
|
||||
fun String.decodeURI(): String {
|
||||
return URI(null, null, this, null).rawPath
|
||||
@ -285,8 +306,9 @@ fun Float.px2dip(): Int {
|
||||
|
||||
/**
|
||||
* PopupWindow 自动适配方向
|
||||
* 弹出与锚点右对齐
|
||||
*/
|
||||
fun PopupWindow.showAutoOrientation(anchorView: View, distanceY: Int = 0) {
|
||||
fun PopupWindow.showAutoOrientation(anchorView: View, distanceY: Int = 0, distanceX: Int = 0) {
|
||||
val windowPos = IntArray(2)
|
||||
val anchorLoc = IntArray(2)
|
||||
// 获取锚点View在屏幕上的左上角坐标位置
|
||||
@ -294,21 +316,18 @@ fun PopupWindow.showAutoOrientation(anchorView: View, distanceY: Int = 0) {
|
||||
val anchorHeight = anchorView.height + distanceY
|
||||
// 获取屏幕的高宽
|
||||
val screenHeight = anchorView.context.resources.displayMetrics.heightPixels
|
||||
val screenWidth = anchorView.context.resources.displayMetrics.widthPixels
|
||||
// 测量contentView
|
||||
contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
|
||||
// 计算contentView的高宽
|
||||
val windowHeight = contentView.measuredHeight
|
||||
val windowWidth = contentView.measuredWidth
|
||||
|
||||
// 判断需要向上弹出还是向下弹出显示
|
||||
val isNeedShowUp = screenHeight - anchorLoc[1] - anchorHeight < windowHeight
|
||||
if (isNeedShowUp) {
|
||||
windowPos[0] = screenWidth - windowWidth
|
||||
windowPos[1] = anchorLoc[1] - windowHeight
|
||||
} else {
|
||||
windowPos[0] = screenWidth - windowWidth
|
||||
windowPos[1] = anchorLoc[1] + anchorHeight
|
||||
}
|
||||
windowPos[1] = if (isNeedShowUp) {
|
||||
anchorLoc[1] - windowHeight
|
||||
} else anchorLoc[1] + anchorHeight
|
||||
windowPos[0] = anchorLoc[0] - windowWidth + anchorView.width - distanceX
|
||||
|
||||
animationStyle = R.style.popwindow_option_anim_style
|
||||
showAtLocation(anchorView, Gravity.TOP or Gravity.START, windowPos[0], windowPos[1])
|
||||
@ -431,4 +450,76 @@ inline fun testChannelOnly(f: () -> Unit) {
|
||||
if (HaloApp.getInstance().channel == Config.DEFAULT_CHANNEL) {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 倒计时,单位s
|
||||
*/
|
||||
inline fun countDownTimer(
|
||||
millisUntilFinish: Long,
|
||||
crossinline block: (finish: Boolean, millisUntilFinished: Long) -> Unit
|
||||
): Disposable {
|
||||
var subscribe: Disposable? = null
|
||||
subscribe = Observable.interval(0, 1000, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
if (it < millisUntilFinish) {
|
||||
block.invoke(false, millisUntilFinish - it)
|
||||
} else {
|
||||
block.invoke(true, 0)
|
||||
if (subscribe != null && !subscribe!!.isDisposed) {
|
||||
subscribe?.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
return subscribe
|
||||
}
|
||||
|
||||
/**
|
||||
* 正计时
|
||||
* @start 起始时间
|
||||
*/
|
||||
inline fun countUpTimer(
|
||||
start: Long,
|
||||
period: Long = 1000,
|
||||
crossinline block: (millisUntilFinished: Long) -> Unit
|
||||
): Disposable {
|
||||
var startTime = start
|
||||
return Observable.interval(0, period, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
startTime += period
|
||||
block.invoke(startTime)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计时器(注意不需要的时候要取消订阅)
|
||||
*/
|
||||
inline fun rxTimer(interval: Long, crossinline block: (times: Long) -> Unit): Disposable {
|
||||
return Observable.interval(0, interval, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
block.invoke(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun LottieAnimationView.doOnAnimationEnd(action: () -> Unit) {
|
||||
this.addAnimatorListener(object : Animator.AnimatorListener {
|
||||
override fun onAnimationRepeat(animation: Animator?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
action.invoke()
|
||||
}
|
||||
|
||||
override fun onAnimationCancel(animation: Animator?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onAnimationStart(animation: Animator?) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -2,10 +2,11 @@ package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -148,6 +149,7 @@ public class GameUtils {
|
||||
gameUpdateEntity.setBrief(gameEntity.getBrief());
|
||||
gameUpdateEntity.setPlugin(apkEntity.getPlugin());
|
||||
gameUpdateEntity.setDownload(gameEntity.getDownload());
|
||||
gameUpdateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
return gameUpdateEntity;
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@ package com.gh.common.util;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
@ -22,6 +21,8 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
/**
|
||||
* @author 温冠超
|
||||
* @email 294299195@qq.com
|
||||
@ -53,6 +54,28 @@ public class GameViewUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setLabelList(Context context, LinearLayout labelLayout, String tagType, List<TagStyleEntity> tagStyle) {
|
||||
labelLayout.removeAllViews();
|
||||
if (tagStyle == null || tagStyle.isEmpty()) {
|
||||
labelLayout.addView(getGameTagView(context, "官方版", 0, tagType, null));
|
||||
} else {
|
||||
for (int i = 0; i < tagStyle.size() - 1; i++) {
|
||||
View view;
|
||||
if (i == tagStyle.size() - 1) {
|
||||
view = getGameTagView(context, tagStyle.get(i).getName(), 0, tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
|
||||
} else {
|
||||
view = getGameTagView(context, tagStyle.get(i).getName(), DisplayUtils.dip2px(context, 8), tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
|
||||
}
|
||||
if (view != null) {
|
||||
labelLayout.addView(view);
|
||||
}
|
||||
if (labelLayout.getChildCount() == 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static TextView getGameTagView(Context context, String tagStr, int rightMargin, String tagType, TagStyleEntity tagEntity) {
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
|
||||
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
|
||||
@ -15,7 +15,7 @@ class GhMatisseVideoFilter : Filter() {
|
||||
override fun filter(context: Context, item: Item): IncapableCause? {
|
||||
if (!needFiltering(context, item)) return null
|
||||
if (item.mimeType != MimeType.MP4.toString()) {
|
||||
return IncapableCause(IncapableCause.TOAST, "请把视频格式转换为Mp4后再上传")
|
||||
return IncapableCause(IncapableCause.TOAST, "请把视频格式转换为MP4后再上传")
|
||||
}
|
||||
|
||||
if (item.size > 500 * 1024 * 1024) {
|
||||
|
||||
38
app/src/main/java/com/gh/common/util/HomeBottomBarHelper.kt
Normal file
38
app/src/main/java/com/gh/common/util/HomeBottomBarHelper.kt
Normal file
@ -0,0 +1,38 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.gh.gamecenter.entity.Display
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
object HomeBottomBarHelper {
|
||||
private const val GAME_BAR_KEY = "game_bar_key"
|
||||
|
||||
@JvmStatic
|
||||
fun getDefaultGameBarData(): SubjectRecommendEntity {
|
||||
try {
|
||||
val json = SPUtils.getString(GAME_BAR_KEY)
|
||||
if (json.isNotEmpty()) {
|
||||
return GsonUtils.fromJson(json, SubjectRecommendEntity::class.java)
|
||||
}
|
||||
} catch (ignore: Exception) {
|
||||
|
||||
}
|
||||
val animationCode = HaloApp.getInstance().application.assets
|
||||
.open("lottie/tab_game.json")
|
||||
.bufferedReader().use { it.readText() }
|
||||
return SubjectRecommendEntity(link = "5de21b5d75e6fa054f784882",
|
||||
type = "block",
|
||||
text = "游戏库",
|
||||
name = "游戏库",
|
||||
iconSelect = "https://resource.ghzs.com/image/game/library/entrance/5e183202913fbd002c75f247.png",
|
||||
iconUnselect = "https://resource.ghzs.com/image/game/library/entrance/5e1831fd913fbd003024641e.png",
|
||||
animationCode = animationCode,
|
||||
default = false,
|
||||
display = Display())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun updateDefaultGameBarData(data: SubjectRecommendEntity) {
|
||||
SPUtils.setString(GAME_BAR_KEY, data.toJson())
|
||||
}
|
||||
}
|
||||
@ -259,7 +259,8 @@ object ImageUtils {
|
||||
}
|
||||
|
||||
// Wifi/4G:x2 traffic:x1
|
||||
private fun getTransformLimitUrl(url: String?, width: Int?, context: Context?): String? {
|
||||
@JvmStatic
|
||||
fun getTransformLimitUrl(url: String?, width: Int?, context: Context?): String? {
|
||||
var transformUrl: String? = url
|
||||
if (width != null && width > 0) {
|
||||
val transformUrlX2 = addLimitWidth(url, width * 2)
|
||||
|
||||
@ -6,24 +6,102 @@ import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureSource;
|
||||
import com.gh.common.exposure.meta.Meta;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.common.loghub.LoghubUtils;
|
||||
import com.gh.download.DownloadDataHelper;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.CommunityEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.SpecialColumn;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.qa.entity.Questions;
|
||||
import com.gh.loghub.LogHubUtils;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Created by khy on 2/01/18.
|
||||
*/
|
||||
public class LogUtils {
|
||||
|
||||
|
||||
public static void logVideoStreamingUpload(String action, String entrance, String entranceDetail, String videoId) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
|
||||
try {
|
||||
object.put("event", "UPLOAD_VIDEO_STEAMING");
|
||||
object.put("action", action);
|
||||
payloadObject.put("entrance", entrance);
|
||||
payloadObject.put("entrance_detail", entranceDetail);
|
||||
payloadObject.put("video_id", videoId);
|
||||
object.put("payload", payloadObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploadVideoStreaming(object);
|
||||
}
|
||||
|
||||
public static void uploadDownloadEvent(DownloadEntity downloadEntity) {
|
||||
Context context = HaloApp.getInstance().getApplication();
|
||||
Meta meta = MetaUtil.INSTANCE.getMeta();
|
||||
JSONObject object = new JSONObject();
|
||||
|
||||
try {
|
||||
object.put("event", DownloadDataHelper.getDownloadStatusAlias(downloadEntity));
|
||||
object.put("msg", downloadEntity.getError());
|
||||
object.put("status", downloadEntity.getStatus().getStatus());
|
||||
|
||||
// payload
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
payloadObject.put("game_id", downloadEntity.getGameId());
|
||||
payloadObject.put("gameName", downloadEntity.getName());
|
||||
payloadObject.put("platform", downloadEntity.getPlatform());
|
||||
payloadObject.put("package", downloadEntity.getPackageName());
|
||||
payloadObject.put("filename", downloadEntity.getPath().substring(downloadEntity.getPath().lastIndexOf("/") + 1));
|
||||
payloadObject.put("total_size", (downloadEntity.getSize() / 1024 / 1024));
|
||||
payloadObject.put("completed_size", (downloadEntity.getProgress() / 1024 / 1024));
|
||||
|
||||
object.put("payload", payloadObject);
|
||||
|
||||
// meta
|
||||
JSONObject metaObject = new JSONObject();
|
||||
metaObject.put("android_id", meta.getAndroid_id());
|
||||
metaObject.put("android_sdk", meta.getAndroid_sdk());
|
||||
metaObject.put("android_version", meta.getAndroid_version());
|
||||
metaObject.put("appVersion", meta.getAppVersion());
|
||||
metaObject.put("channel", meta.getChannel());
|
||||
metaObject.put("gid", meta.getGid());
|
||||
metaObject.put("imei", meta.getImei());
|
||||
metaObject.put("mac", meta.getMac());
|
||||
metaObject.put("manufacturer", meta.getManufacturer());
|
||||
metaObject.put("model", meta.getModel());
|
||||
metaObject.put("network", DeviceUtils.getNetwork(context));
|
||||
metaObject.put("os", meta.getOs());
|
||||
metaObject.put("userId", meta.getUserId());
|
||||
|
||||
object.put("meta", metaObject);
|
||||
object.put("timestamp", System.currentTimeMillis() / 1000);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->" + object.toString());
|
||||
}
|
||||
LoghubUtils.log(object, "download_debug", false);
|
||||
}
|
||||
|
||||
public static void uploadCommunityArticle(String tracers, String articleId, String articleTitle, int readTime, CommunityEntity community, SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -48,10 +126,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
|
||||
public static void uploadDevice(LunchType launchType) {
|
||||
JSONObject object = new JSONObject();
|
||||
Application application = HaloApp.getInstance().getApplication();
|
||||
@ -63,10 +141,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object, true);
|
||||
}
|
||||
|
||||
|
||||
public static void uploadAnswerReadTime(String tracers, int readTime, String answerId, Questions questions, String communityId, String CommunityName, SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -92,10 +170,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
|
||||
public static void uploadQuestionReadTime(String tracers, int readTime, Questions questions, String communityId, String communityName, SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -120,13 +198,13 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
|
||||
public static void uploadSearch(String searchKey) {
|
||||
if (TextUtils.isEmpty(searchKey)) return;
|
||||
|
||||
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("community_id", UserManager.getInstance().getCommunity().getId());
|
||||
@ -136,11 +214,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void communityRefresh(int dataCount, boolean manualRefresh) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -152,10 +229,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
|
||||
public static void login(String loginStep, String loginType, String entrance) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -166,10 +243,10 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object, true);
|
||||
}
|
||||
|
||||
|
||||
public static void qaAccess(String access, CommunityEntity communityEntity) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -180,15 +257,42 @@ public class LogUtils {
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
upload(object);
|
||||
|
||||
uploadToCommunity(object);
|
||||
}
|
||||
|
||||
public static void logReservation(GameEntity gameEntity, @Nullable ExposureEvent event) {
|
||||
JSONObject object = new JSONObject();
|
||||
List<ExposureSource> exposureSourceList;
|
||||
|
||||
if (event == null) {
|
||||
exposureSourceList = new ArrayList<>();
|
||||
exposureSourceList.add(new ExposureSource("其它", ""));
|
||||
} else {
|
||||
exposureSourceList = event.getSource();
|
||||
}
|
||||
|
||||
try {
|
||||
object.put("source", GsonUtils.toJson(exposureSourceList));
|
||||
object.put("game_name", gameEntity.getName());
|
||||
object.put("game_id", gameEntity.getId());
|
||||
object.put("game_platform", gameEntity.getPlatform());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
uploadToReservation(object);
|
||||
}
|
||||
|
||||
private static void upload(JSONObject object) {
|
||||
private static void uploadToCommunity(JSONObject object) {
|
||||
uploadToCommunity(object, false);
|
||||
}
|
||||
|
||||
private static void uploadToCommunity(JSONObject object, boolean forcedUpload) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->" + object.toString());
|
||||
}
|
||||
|
||||
|
||||
Context context = HaloApp.getInstance().getApplication();
|
||||
try {
|
||||
object.put("version", PackageUtils.getVersionName());
|
||||
@ -200,13 +304,119 @@ public class LogUtils {
|
||||
object.put("device_system", android.os.Build.VERSION.RELEASE);
|
||||
object.put("device_model", android.os.Build.MODEL);
|
||||
object.put("imei", Util_System_Phone_State.getImei(HaloApp.getInstance()
|
||||
.getApplication()));
|
||||
.getApplication()));
|
||||
object.put("G_ID", UserManager.getInstance().getDeviceId());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
// 暂时除了曝光外的数据都是扔到 community 这个库的,要是不是这个这个库的话这里要改一下
|
||||
LogHubUtils.uploadLog(DeviceUtils.getIPAddress(context), object, "community");
|
||||
LoghubUtils.log(object, "community", forcedUpload);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传数据到“预约”的 logStore
|
||||
*/
|
||||
private static void uploadToReservation(JSONObject object) {
|
||||
Context context = HaloApp.getInstance().getApplication();
|
||||
try {
|
||||
object.put("version", PackageUtils.getVersionName());
|
||||
object.put("channel", HaloApp.getInstance().getChannel());
|
||||
object.put("android_id", Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID));
|
||||
object.put("time", Utils.getTime(context));
|
||||
object.put("network", DeviceUtils.getNetwork(context));
|
||||
object.put("user_id", UserManager.getInstance().getUserId());
|
||||
object.put("device_system", android.os.Build.VERSION.RELEASE);
|
||||
object.put("device_model", android.os.Build.MODEL);
|
||||
object.put("imei", Util_System_Phone_State.getImei(HaloApp.getInstance()
|
||||
.getApplication()));
|
||||
object.put("G_ID", UserManager.getInstance().getDeviceId());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
LoghubUtils.log(object, "appointment", false);
|
||||
}
|
||||
|
||||
private static void uploadVideoStreaming(JSONObject object) {
|
||||
Meta meta = MetaUtil.INSTANCE.getMeta();
|
||||
JSONObject metaObject = new JSONObject();
|
||||
try {
|
||||
metaObject.put("android_id", meta.getAndroid_id());
|
||||
metaObject.put("android_sdk", meta.getAndroid_sdk());
|
||||
metaObject.put("android_version", meta.getAndroid_version());
|
||||
metaObject.put("appVersion", meta.getAppVersion());
|
||||
metaObject.put("channel", meta.getChannel());
|
||||
metaObject.put("gid", meta.getGid());
|
||||
metaObject.put("imei", meta.getImei());
|
||||
metaObject.put("mac", meta.getMac());
|
||||
metaObject.put("manufacturer", meta.getManufacturer());
|
||||
metaObject.put("model", meta.getModel());
|
||||
metaObject.put("network", meta.getNetwork());
|
||||
metaObject.put("os", meta.getOs());
|
||||
metaObject.put("userId", meta.getUserId());
|
||||
|
||||
object.put("meta", metaObject);
|
||||
object.put("timestamp", System.currentTimeMillis() / 1000);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->" + object.toString());
|
||||
}
|
||||
|
||||
LoghubUtils.log(object, "video_streaming", false);
|
||||
}
|
||||
|
||||
public static void uploadVideoStreamingEnter(String entrance, String entranceDetail, String videoId, String streamingId) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
|
||||
try {
|
||||
object.put("event", "ENTERING_VIDEO_STEAMING");
|
||||
payloadObject.put("entrance", entrance);
|
||||
if (!TextUtils.isEmpty(entranceDetail)) {
|
||||
payloadObject.put("entrance_detail", entranceDetail);
|
||||
}
|
||||
payloadObject.put("video_id", videoId);
|
||||
payloadObject.put("streaming_id", streamingId);
|
||||
object.put("payload", payloadObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploadVideoStreaming(object);
|
||||
}
|
||||
|
||||
public static void uploadVideoStreamingPlaying(String action, String msg, String entrance, String entranceDetail, String videoId, String streamingId, double videoSize, int videoTotalTime, int progress, String videoPlayStatus) {
|
||||
JSONObject object = new JSONObject();
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
|
||||
try {
|
||||
object.put("event", "VIDEO_PLAYING");
|
||||
object.put("action", action);
|
||||
if (!TextUtils.isEmpty(msg)) {
|
||||
object.put("msg", msg);
|
||||
}
|
||||
|
||||
payloadObject.put("entrance", entrance);
|
||||
if (!TextUtils.isEmpty(entranceDetail)) {
|
||||
payloadObject.put("entrance_detail", entranceDetail);
|
||||
}
|
||||
payloadObject.put("video_id", videoId);
|
||||
payloadObject.put("streaming_id", streamingId);
|
||||
if (videoSize > 0) {
|
||||
payloadObject.put("video_size", videoSize);
|
||||
}
|
||||
if (videoTotalTime > 0) {
|
||||
payloadObject.put("video_total_time", videoTotalTime);
|
||||
}
|
||||
payloadObject.put("progress", progress);
|
||||
payloadObject.put("video_play_status", videoPlayStatus);
|
||||
|
||||
object.put("payload", payloadObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
uploadVideoStreaming(object);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,6 +264,12 @@ public class LoginUtils {
|
||||
case 400212:
|
||||
Utils.toast(context, "请输入正确的手机号");
|
||||
break;
|
||||
case 400010:
|
||||
Utils.toast(context, "身份证无效,请重新输入");
|
||||
break;
|
||||
case 400011:
|
||||
Utils.toast(context, "请输入正确的身份信息");
|
||||
break;
|
||||
default:
|
||||
Utils.toast(context, code + "");
|
||||
break;
|
||||
|
||||
@ -1,22 +1,122 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.dialog.NotificationHintDialogFragment
|
||||
import com.gh.gamecenter.entity.NotificationHint
|
||||
import com.gh.gamecenter.entity.NotificationUgc
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.AppManager
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
object NotificationHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun showNotificationHintDialog(ugc: NotificationUgc) {
|
||||
val showedNewVersion = SPUtils.getInt(Constants.SP_SHOWED_NOTIFICATION_NEW_VERSION, 0)
|
||||
val currentVersion = PackageUtils.getVersionCode()
|
||||
// 版本升级后重置数据
|
||||
if (currentVersion > showedNewVersion) {
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, false)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, false)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, false)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, false)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, false)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, false)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, "")
|
||||
|
||||
SPUtils.setInt(Constants.SP_SHOWED_NOTIFICATION_NEW_VERSION, currentVersion)
|
||||
}
|
||||
|
||||
|
||||
val isShowedToday = SPUtils.getString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, "")
|
||||
// 每天最多只需提示一次
|
||||
if (isShowedToday == TimeUtils.getToday()) return
|
||||
|
||||
val isShowedLogin = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, false)
|
||||
val isShowedQuestion = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, false)
|
||||
val isShowedAnswer = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, false)
|
||||
val isShowedArticle = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, false)
|
||||
val isShowedVideo = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, false)
|
||||
val isShowedRating = SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, false)
|
||||
|
||||
if (isShowedLogin && isShowedQuestion && isShowedAnswer && isShowedArticle && isShowedVideo && isShowedRating) return
|
||||
|
||||
when (ugc) {
|
||||
NotificationUgc.LOGIN -> {
|
||||
if (!isShowedLogin) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN, true)
|
||||
// 设置今天的时间,表示今天已经触发过了
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
NotificationUgc.QUESTION -> {
|
||||
if (!isShowedQuestion) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_QUESTION, true)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
NotificationUgc.ANSWER -> {
|
||||
if (!isShowedAnswer) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ANSWER, true)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
NotificationUgc.ARTICLE -> {
|
||||
if (!isShowedArticle) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_ARTICLE, true)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
NotificationUgc.VIDEO -> {
|
||||
if (!isShowedVideo) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_VIDEO, true)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
NotificationUgc.RATING -> {
|
||||
if (!isShowedRating) {
|
||||
show(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_RATING, true)
|
||||
SPUtils.setString(Constants.SP_IS_SHOWED_NOTIFICATION_TODAY, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun show(activity: AppCompatActivity?) {
|
||||
if (activity == null) return
|
||||
RetrofitManager.getInstance(activity).api.bootPopup
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<NotificationHint>() {
|
||||
override fun onSuccess(data: NotificationHint) {
|
||||
try {
|
||||
showEnableNotificationDialogIfItsDisabled(activity, data)
|
||||
} catch (ignore: Exception) {
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showEnableNotificationDialogIfItsDisabled(activity: AppCompatActivity, notificationHint: NotificationHint) {
|
||||
if (notificationIsEnable()) {
|
||||
Utils.log("notification is enable")
|
||||
} else {
|
||||
NotificationHintDialogFragment.getInstance(notificationHint).show(activity.supportFragmentManager, "notification")
|
||||
SPUtils.setBoolean(Constants.SP_SHOWED_NOTIFICATION_HINT, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,4 +16,13 @@ object NumberUtils {
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun transSimpleUsageTime(second: Long): String {
|
||||
val totalMinute = second / 60
|
||||
if (totalMinute < 60) return ((if (totalMinute == 0L) 1 else totalMinute).toString() + "分钟")
|
||||
val hour = Math.round((totalMinute / 60).toFloat())
|
||||
val minute = Math.round((totalMinute - hour * 60).toFloat())
|
||||
return hour.toString() + "小时" + if (minute == 0) "" else minute.toString() + "分钟"
|
||||
}
|
||||
}
|
||||
@ -13,14 +13,14 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import com.g00fy2.versioncompare.Version;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@ -35,6 +35,8 @@ import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
public class PackageUtils {
|
||||
|
||||
public static final String publicKey = "OpenSSLRSAPublicKey{modulus=a8c4bb5748fec8d5c35db1a7a182d41ba4721a91131a417330af79ef4ddb43f9fa0ff4907b0a613bfe152de0ed8fc1b2e6f94a908aa98a5f7adc1ce814ba7ec919d75d9910bdfd8649b4789da6a90ffb61f0d23ac4f828a78fcd0d6f6120c1c43c1f87f7498a89eb40ca8e32dfc2f9d5c10d612b95192870223674e241e53305abf320d7eed76ded398778576e4db7b17b3bc6a792f13de5e43a6a5fae4276c73e6990ce97f68dff0ec16fc9594f175c8d49cd0d7877340d9de60942ca0efc737e50b6c295dfe0713e4532b4e810e1ea11b702b4a27753e41559cbceb247e7f044ec4e3ab2e8bccd8b9fd71286e63307550bcde86deee95adb8133076269135b,publicExponent=10001}";
|
||||
@ -73,6 +75,7 @@ public class PackageUtils {
|
||||
updateEntity.setTag(gameEntity.getTag());
|
||||
updateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
updateEntity.setDownload(gameEntity.getDownload());
|
||||
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
updateList.add(updateEntity);
|
||||
}
|
||||
}
|
||||
@ -108,6 +111,7 @@ public class PackageUtils {
|
||||
updateEntity.setBrief(gameEntity.getBrief());
|
||||
updateEntity.setTag(gameEntity.getTag());
|
||||
updateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
updateList.add(updateEntity);
|
||||
}
|
||||
}
|
||||
@ -188,11 +192,18 @@ public class PackageUtils {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 启动安装应用程序
|
||||
*/
|
||||
public static void launchSetup(final Context context, final String path) {
|
||||
public static void launchSetup(final Context context, DownloadEntity downloadEntity) {
|
||||
// 取消状态栏下载完成的通知,若存在
|
||||
downloadEntity.getMeta().put(Constants.MARK_ALREADY_TRIGGERED_INSTALLATION, "YES");
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity);
|
||||
launchSetup(context, downloadEntity.getPath());
|
||||
}
|
||||
|
||||
private static void launchSetup(final Context context, final String path) {
|
||||
try {
|
||||
if (isCanLaunchSetup(context, path)) {
|
||||
context.startActivity(PackageUtils.getInstallIntent(context, path));
|
||||
@ -237,6 +248,10 @@ public class PackageUtils {
|
||||
* 根据路径,获取安装游戏的意图
|
||||
*/
|
||||
public static Intent getInstallIntent(Context context, String path) {
|
||||
return getInstallIntent(context, path, false);
|
||||
}
|
||||
|
||||
public static Intent getInstallIntent(Context context, String path, boolean isInAppUpdate) {
|
||||
Uri uri = Uri.fromFile(new File(path));
|
||||
Intent installIntent = new Intent(Intent.ACTION_VIEW);
|
||||
if ("smartisan".equals(Build.MANUFACTURER)) {
|
||||
@ -249,6 +264,10 @@ public class PackageUtils {
|
||||
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
|
||||
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
} else {
|
||||
if (isInAppUpdate) {
|
||||
// 应用内更新不加 FLAG_ACTIVITY_NEW_TASK 在模拟器上会出现安装完成后安装界面也一并消失的类似闪退的表现
|
||||
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
|
||||
}
|
||||
InstallUtils.getInstance(context).addInstall(getPackageNameByPath(context, path));
|
||||
|
||||
@ -4,6 +4,8 @@ import android.util.Patterns;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import kotlin.text.Regex;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 17/05/2017
|
||||
@ -32,6 +34,25 @@ public class PatternUtils {
|
||||
Matcher matcher = Patterns.PHONE.matcher(phone);
|
||||
return matcher.matches();
|
||||
}
|
||||
/**
|
||||
* 判断字符串中是否有连续2个以上的空格 忽略 \t \r \n
|
||||
*/
|
||||
public static boolean isHasSpace(String text) {
|
||||
String pattern = "[\\s|\\t|\\r|\\n]{2,}";
|
||||
Regex regex = new Regex(pattern);
|
||||
return regex.find(text, 0) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换字符串中连续2个以上的空格为一个空格 忽略 \t \r \n
|
||||
*/
|
||||
public static String replaceSpace(String text) {
|
||||
String pattern = "[\\s|\\t|\\r|\\n]{2,}";
|
||||
String newText = text;
|
||||
if (isHasSpace(text)) {
|
||||
newText = text.replaceAll(pattern, " ");
|
||||
}
|
||||
return newText;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -52,6 +52,7 @@ import java.util.List;
|
||||
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
|
||||
import static com.gh.common.util.LoginHelper.WEIBO_SCOPE;
|
||||
|
||||
@ -148,6 +149,79 @@ public class ShareUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void showShareWindowsCancelCallback(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareType shareType, Function0 function) {
|
||||
if (activity.isFinishing()) return;
|
||||
this.mActivity = new WeakReference<>(activity);
|
||||
this.shareIcon = icon;
|
||||
this.shareUrl = url;
|
||||
this.mSummary = shareSummary;
|
||||
this.mTitle = shareTitle;
|
||||
this.mShareType = shareType;
|
||||
|
||||
View contentView = View.inflate(activity, R.layout.share_popup_layout, null);
|
||||
contentView.setFocusable(true);
|
||||
contentView.setFocusableInTouchMode(true);
|
||||
RecyclerView shareRecyclerView = contentView.findViewById(R.id.share_rv);
|
||||
|
||||
shareRecyclerView.setPadding(DisplayUtils.dip2px(mContext, 20), DisplayUtils.dip2px(mContext, 10), DisplayUtils.dip2px(mContext, 20), 0);
|
||||
|
||||
//RecyclerView禁止滑动
|
||||
GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, 4) {
|
||||
@Override
|
||||
public boolean canScrollVertically() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
shareRecyclerView.setLayoutManager(gridLayoutManager);
|
||||
ShareRecyclerViewAdapter shareRecyclerViewAdapter = new ShareRecyclerViewAdapter();
|
||||
shareRecyclerView.setAdapter(shareRecyclerViewAdapter);
|
||||
shareRecyclerViewAdapter.setOnItemClickListener(position -> {
|
||||
if ("取消".equals(arrLabel[position])) {
|
||||
function.invoke();
|
||||
}
|
||||
});
|
||||
|
||||
if (mShareType == ShareType.shareGh) {
|
||||
RelativeLayout layout = (RelativeLayout) view;
|
||||
layout.addView(contentView);
|
||||
arrLabel[6] = "邮件";
|
||||
arrLogo[6] = R.drawable.share_email_logo;
|
||||
arrLabel[7] = "复制链接";
|
||||
arrLogo[7] = R.drawable.share_copyfont_logo;
|
||||
return;
|
||||
} else {
|
||||
arrLabel[6] = "复制链接";
|
||||
arrLogo[6] = R.drawable.share_copyfont_logo;
|
||||
arrLabel[7] = "取消";
|
||||
arrLogo[7] = R.drawable.share_cancel_logo;
|
||||
}
|
||||
|
||||
popupWindow = new PopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT
|
||||
, LinearLayout.LayoutParams.MATCH_PARENT, true);
|
||||
popupWindow.setAnimationStyle(R.style.mypopwindow_anim_style);
|
||||
//解决PopupWindow无法覆盖状态栏
|
||||
popupWindow.setClippingEnabled(false);
|
||||
try {
|
||||
popupWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
contentView.setOnClickListener(v -> popupWindow.dismiss());
|
||||
|
||||
contentView.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK
|
||||
&& event.getRepeatCount() == 0
|
||||
&& popupWindow != null
|
||||
&& popupWindow.isShowing()) {
|
||||
function.invoke();
|
||||
popupWindow.dismiss();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void showShareWindows(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareType shareType) {
|
||||
if (activity.isFinishing()) return;
|
||||
@ -298,7 +372,7 @@ public class ShareUtils {
|
||||
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);
|
||||
@ -520,37 +594,56 @@ public class ShareUtils {
|
||||
|
||||
private class ShareRecyclerViewAdapter extends RecyclerView.Adapter<ShareRecyclerViewAdapter.ViewHolder> {
|
||||
|
||||
private OnItemClickListener listener;
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(mContext).inflate(R.layout.share_popup_item, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(OnItemClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final ViewHolder holder, int position) {
|
||||
holder.shareLogo.setImageResource(arrLogo[position]);
|
||||
holder.shareLabel.setText(arrLabel[position]);
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (mShareType == ShareUtils.ShareType.shareGh) {
|
||||
MtaHelper.onEvent("我的光环_新", "分享光环", arrLabel[position]);
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onItemClick(holder.getAdapterPosition());
|
||||
}
|
||||
switch (holder.getPosition()) {
|
||||
case 0:
|
||||
MtaHelper.onEvent("内容分享", "微信好友", mTitle);
|
||||
wechatShare();
|
||||
break;
|
||||
case 1:
|
||||
MtaHelper.onEvent("内容分享", "微信朋友圈", mTitle);
|
||||
wechatMomentsShare();
|
||||
break;
|
||||
case 2:
|
||||
MtaHelper.onEvent("内容分享", "QQ好友", mTitle);
|
||||
qqShare();
|
||||
break;
|
||||
case 3:
|
||||
MtaHelper.onEvent("内容分享", "QQ空间", mTitle);
|
||||
qZoneShare();
|
||||
break;
|
||||
case 4:
|
||||
MtaHelper.onEvent("内容分享", "新浪微博", mTitle);
|
||||
sinaWeiboShare();
|
||||
break;
|
||||
case 5:
|
||||
MtaHelper.onEvent("内容分享", "短信", mTitle);
|
||||
shortMessageShare();
|
||||
break;
|
||||
case 6:
|
||||
MtaHelper.onEvent("内容分享", "复制链接", mTitle);
|
||||
if (mShareType == ShareType.askInvite) {
|
||||
copyLink(mTitle + " - 光环助手" + shareUrl);
|
||||
} else if (mShareType == ShareType.askNormal) {
|
||||
@ -597,4 +690,8 @@ public class ShareUtils {
|
||||
}
|
||||
}
|
||||
|
||||
interface OnItemClickListener {
|
||||
void onItemClick(int position);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
42
app/src/main/java/com/gh/common/util/SimpleImageLoader.java
Normal file
42
app/src/main/java/com/gh/common/util/SimpleImageLoader.java
Normal file
@ -0,0 +1,42 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import com.github.piasy.biv.loader.ImageLoader;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class SimpleImageLoader implements ImageLoader.Callback {
|
||||
@Override
|
||||
public void onCacheHit(int imageType, File image) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCacheMiss(int imageType, File image) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(int progress) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(File image) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(Exception error) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -83,6 +83,16 @@ object SPUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setStringSet(key: String, values: Set<String>) {
|
||||
sp.edit().putStringSet(key, values).apply()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getStringSet(key: String): Set<String> {
|
||||
return sp.getStringSet(key, HashSet())?: HashSet()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun remove(key: String) {
|
||||
val editor = sp.edit()
|
||||
|
||||
@ -1,36 +1,39 @@
|
||||
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
|
||||
import com.bytedance.applog.AppLog
|
||||
import com.bytedance.applog.GameReportHelper
|
||||
import com.bytedance.applog.InitConfig
|
||||
import com.bytedance.applog.util.UriConfig
|
||||
import com.gh.common.exposure.meta.MetaUtil
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
/**
|
||||
* 今日头条的激活统计 SDK https://gitlab.ghzs.com/pm/halo-app-issues/issues/567
|
||||
*
|
||||
* 更新 SDK https://gitlab.ghzs.com/pm/halo-app-issues/issues/743
|
||||
*/
|
||||
object TeaHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun init(context: Context, channel: String) {
|
||||
TeaAgent.init(TeaConfigBuilder.create(context)
|
||||
.setAppName("guanghuan1")
|
||||
.setChannel(channel)
|
||||
.setAid(163824)
|
||||
.createTeaConfig()
|
||||
)
|
||||
val config = InitConfig("163824", channel)
|
||||
config.setUriConfig(UriConfig.DEFAULT)
|
||||
config.appName = "guanghuan1"
|
||||
config.setEnablePlay(true)
|
||||
AppLog.setEnableLog(false)
|
||||
AppLog.init(context, config)
|
||||
|
||||
EventUtils.setRegister("mobile", true)
|
||||
EventUtils.setPurchase(null, null, null, 0, null, null, true, 1)
|
||||
}
|
||||
AppLog.setOaidObserver {
|
||||
HaloApp.getInstance().oaid = it.id
|
||||
Utils.log("oaid is $it.id")
|
||||
MetaUtil.refreshMeta()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onResume(context: Context) {
|
||||
TeaAgent.onResume(context)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onPause(context: Context) {
|
||||
TeaAgent.onPause(context)
|
||||
// gameReportHelper ?!
|
||||
GameReportHelper.onEventRegister("wechat", true)
|
||||
GameReportHelper.onEventPurchase("gift", "flower", "008", 1, "wechat", "¥", true, 1)
|
||||
}
|
||||
|
||||
}
|
||||
@ -62,6 +62,34 @@ object TextHelper {
|
||||
}
|
||||
}
|
||||
|
||||
//限制最大长度(空格不算入字数判断)-Toast弹窗提示
|
||||
@JvmStatic
|
||||
fun getFilterIgnoreBlank(maxLength: Int, msg: String): InputFilter {
|
||||
return InputFilter { source, start, end, dest, dstart, dend ->
|
||||
val newMaxLength = maxLength + getBlankCount(source.toString()) + getBlankCount(dest.toString())
|
||||
val keep = newMaxLength - (dest.length - (dend - dstart))
|
||||
if (keep < end - start) {
|
||||
ToastUtils.showToast(msg)
|
||||
}
|
||||
when {
|
||||
keep <= 0 -> ""
|
||||
keep >= end - start -> null
|
||||
else -> source.subSequence(start, start + keep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBlankCount(text: String): Int {
|
||||
var blankCount = 0
|
||||
val toCharArray = text.toCharArray()
|
||||
toCharArray.forEach {
|
||||
if (it == ' ') {
|
||||
blankCount++
|
||||
}
|
||||
}
|
||||
return blankCount
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun highlightTextThatIsWrappedInsideWrapperByDefault(textView: TextView, text: String) {
|
||||
textView.text = getHighlightedSpannableStringThatIsWrappedInsideWrapper(textView.context, text, "###", R.color.theme, object : SimpleCallback<String> {
|
||||
@ -156,7 +184,6 @@ object TextHelper {
|
||||
* [amwayStyle] 是否为安利墙列表样式,安利墙列表样式与其它地方略有不同
|
||||
*/
|
||||
fun getCommentLabelSpannableStringBuilder(comment: CharSequence,
|
||||
lineFeed: String = "\n",
|
||||
amwayStyle: Boolean = false,
|
||||
tagStrokeColor: String = "#FFDAA2",
|
||||
tagTextColor: String = "#FF9B06"): SpannableStringBuilder {
|
||||
@ -166,13 +193,14 @@ object TextHelper {
|
||||
splits.forEachIndexed { index, s ->
|
||||
if (index != 0) {
|
||||
val item = "<tag>$s"
|
||||
val pattern = Pattern.compile("<tag>(\\S+)</tag>(\\S+)")
|
||||
val pattern = Pattern.compile("<tag>(\\S+)</tag>([\\S,\n]+)")
|
||||
val matcher = pattern.matcher(item)
|
||||
if (matcher.find()) {
|
||||
val label = matcher.group(1)
|
||||
val content = matcher.group(2)
|
||||
// val content = matcher.group(2) //不知为什么这里正则不能匹配颜文字,所以就用字符串裁剪。。。
|
||||
var content = item.substring(item.indexOf("</tag>") + 6)
|
||||
if (index == splits.size - 1) content += " "
|
||||
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(
|
||||
@ -181,9 +209,12 @@ object TextHelper {
|
||||
count + newLabel.length - 1,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
count += newLabel.length
|
||||
contents.append(newContent)
|
||||
count += newContent.length
|
||||
contents.append(content)
|
||||
count += content.length
|
||||
}
|
||||
} else {
|
||||
contents.append(s)
|
||||
count += s.length
|
||||
}
|
||||
}
|
||||
return contents
|
||||
|
||||
22
app/src/main/java/com/gh/common/util/TimeUtils.kt
Normal file
22
app/src/main/java/com/gh/common/util/TimeUtils.kt
Normal file
@ -0,0 +1,22 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
object TimeUtils {
|
||||
|
||||
/**
|
||||
* 获取今天日期
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getToday(): String {
|
||||
var date = Date()
|
||||
val calendar = GregorianCalendar()
|
||||
calendar.time = date
|
||||
//把日期往后增加一天.整数往后推,负数往前移动
|
||||
calendar.add(GregorianCalendar.DATE, 0)
|
||||
date = calendar.time
|
||||
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
|
||||
return formatter.format(date)
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,5 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import androidx.collection.ArrayMap;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.constant.Constants;
|
||||
@ -10,6 +8,8 @@ import com.halo.assistant.HaloApp;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import androidx.collection.ArrayMap;
|
||||
|
||||
public class TimestampUtils {
|
||||
|
||||
// 基准时间
|
||||
@ -29,6 +29,7 @@ public class TimestampUtils {
|
||||
intervalMap.put(".*columns.*", 10);
|
||||
intervalMap.put(".*games.*", 15);
|
||||
intervalMap.put(".*articles.*", 20);
|
||||
intervalMap.put(".*halo_addons.*", 10);
|
||||
}
|
||||
|
||||
private static void initCDMap() {
|
||||
@ -37,6 +38,7 @@ public class TimestampUtils {
|
||||
cdMap.put(".*columns.*", Constants.GAME_CD);
|
||||
cdMap.put(".*games.*", Constants.GAME_CD);
|
||||
cdMap.put(".*articles.*", Constants.NEWS_CD);
|
||||
cdMap.put(".*halo_addons.*", Constants.ADDONS_CD);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -18,6 +18,7 @@ import okhttp3.MultipartBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.net.URLEncoder
|
||||
import java.util.*
|
||||
|
||||
|
||||
@ -185,14 +186,14 @@ object UploadImageUtils {
|
||||
* 上传图片,每成功一个就回调
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun uploadImageListOneByOne(type: UploadType, imgs: List<String>, compressGif: Boolean, listener: OnUploadImageListCountListener):Disposable?{
|
||||
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 file = File(img)
|
||||
val requestBody = FileRequestBody(file, object : RetrofitCallback<ResponseBody>() {
|
||||
override fun onProgress(total: Long, progress: Long) {
|
||||
|
||||
@ -274,7 +275,7 @@ object UploadImageUtils {
|
||||
if (options.outMimeType.contains("gif") && !file.name.toLowerCase().contains(".gif".toLowerCase())) {
|
||||
return System.currentTimeMillis().toString() + ".gif"
|
||||
}
|
||||
return file.name
|
||||
return URLEncoder.encode(file.name, "utf-8")
|
||||
}
|
||||
|
||||
interface OnUploadImageListener {
|
||||
@ -288,8 +289,9 @@ object UploadImageUtils {
|
||||
fun onError() // 全部上传失败时回调
|
||||
fun onProgress(total: Long, progress: Long)
|
||||
}
|
||||
interface OnUploadImageListCountListener{
|
||||
fun onSuccess(map:Map<String, String>)//上传成功一个回调
|
||||
|
||||
interface OnUploadImageListCountListener {
|
||||
fun onSuccess(map: Map<String, String>)//上传成功一个回调
|
||||
fun onFinish()//全部上传成功回调
|
||||
fun onError() // 全部上传失败时回调
|
||||
}
|
||||
|
||||
269
app/src/main/java/com/gh/common/util/UsageStatsHelper.kt
Normal file
269
app/src/main/java/com/gh/common/util/UsageStatsHelper.kt
Normal file
@ -0,0 +1,269 @@
|
||||
@file:Suppress("DEPRECATED_IDENTITY_EQUALS")
|
||||
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Activity
|
||||
import android.app.AppOpsManager
|
||||
import android.app.AppOpsManager.MODE_ALLOWED
|
||||
import android.app.AppOpsManager.OPSTR_GET_USAGE_STATS
|
||||
import android.app.usage.UsageEvents
|
||||
import android.app.usage.UsageStatsManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Process
|
||||
import android.preference.PreferenceManager
|
||||
import android.provider.Settings
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.gh.common.util.UsageStatsHelper.getDataByUsageEvents
|
||||
import com.gh.common.util.UsageStatsHelper.getDataByUsageStats
|
||||
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 io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 参考资料: https://developer.android.com/reference/android/app/usage/UsageStatsManager
|
||||
*
|
||||
* queryUsageStats 无法准确获取设定时间内的使用情况,所以以下统计有两个策略(但依然无法解决queryUsageStats初始取值问题)
|
||||
*
|
||||
* [getDataByUsageStats]:用于获取时间跨度较大的数据(至少跨度一天)
|
||||
* [getDataByUsageEvents]:用于获取时间跨度较小的数据(只用于获取当天数据)
|
||||
*
|
||||
* 详情可见:https://stackoverflow.com/questions/36238481/android-usagestatsmanager-not-returning-correct-daily-results
|
||||
*
|
||||
*/
|
||||
object UsageStatsHelper {
|
||||
|
||||
const val USAGE_STATUS_REQUEST_CODE = 233
|
||||
const val USAGE_STATUS_SP_KEY = "usage_status_sp_key"
|
||||
|
||||
private val mApi = RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
private val mPreference = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().application)
|
||||
|
||||
/**
|
||||
* 一般用于获取时间跨度较大的数据
|
||||
*
|
||||
* 当天数据获取是有问题的
|
||||
* 例如: 设置起始时间为上午10点,当时返回的数据还是包括更前的数据(例如9点)
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
private fun getDataByUsageStats(lastPostTime: Long): JSONArray? {
|
||||
val usageStatsManager = HaloApp
|
||||
.getInstance().application
|
||||
.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
|
||||
|
||||
val usageStatsMap = usageStatsManager.queryAndAggregateUsageStats(
|
||||
lastPostTime,
|
||||
System.currentTimeMillis()) ?: return null
|
||||
|
||||
val postBody = JSONArray()
|
||||
for (entry in usageStatsMap) {
|
||||
if (entry.value.totalTimeInForeground != 0L) {
|
||||
val jsonObject = JSONObject()
|
||||
jsonObject.put("package", entry.key)
|
||||
jsonObject.put("duration", (entry.value.totalTimeInForeground / 1000))
|
||||
postBody.put(jsonObject)
|
||||
|
||||
debugOnly {
|
||||
Utils.log("UsageStats post log==>" + entry.key + ":" + (entry.value.totalTimeInForeground / 1000))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return postBody
|
||||
}
|
||||
|
||||
/**
|
||||
* 一般用于获取时间跨度较小的数据
|
||||
* 在此功能只用来获取当天数据(queryEvents 获取的数据只保留几天内的数据)
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
private fun getDataByUsageEvents(startTime: Long): JSONArray? {
|
||||
|
||||
val mUsageStatsManager = HaloApp
|
||||
.getInstance()
|
||||
.application
|
||||
.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
|
||||
|
||||
val usageEvents = mUsageStatsManager.queryEvents(startTime, System.currentTimeMillis())
|
||||
val allEvents = ArrayList<UsageEvents.Event>()
|
||||
var currentEvent: UsageEvents.Event
|
||||
|
||||
|
||||
|
||||
while (usageEvents.hasNextEvent()) {
|
||||
currentEvent = UsageEvents.Event()
|
||||
usageEvents.getNextEvent(currentEvent)
|
||||
if (currentEvent.eventType == UsageEvents.Event.MOVE_TO_FOREGROUND
|
||||
|| currentEvent.eventType == UsageEvents.Event.MOVE_TO_BACKGROUND) {
|
||||
allEvents.add(currentEvent)
|
||||
}
|
||||
}
|
||||
|
||||
val pakAndTime = HashMap<String, Long>()
|
||||
for (i in 0 until allEvents.size - 1) {
|
||||
val curEvent = allEvents[i]
|
||||
val nextEvent = allEvents[i + 1]
|
||||
|
||||
if (curEvent.eventType == UsageEvents.Event.MOVE_TO_FOREGROUND
|
||||
&& nextEvent.eventType == UsageEvents.Event.MOVE_TO_BACKGROUND
|
||||
&& curEvent.className == nextEvent.className) {
|
||||
val diff = nextEvent.timeStamp - curEvent.timeStamp
|
||||
|
||||
if (pakAndTime[curEvent.packageName] == null) {
|
||||
pakAndTime[curEvent.packageName] = diff
|
||||
} else {
|
||||
pakAndTime[curEvent.packageName] = pakAndTime[curEvent.packageName]!! + diff
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val postBody = JSONArray()
|
||||
for (pkg in pakAndTime.keys) {
|
||||
val totalTime = pakAndTime[pkg] ?: return null
|
||||
val jsonObject = JSONObject()
|
||||
jsonObject.put("package", pkg)
|
||||
jsonObject.put("duration", (totalTime / 1000))
|
||||
postBody.put(jsonObject)
|
||||
Utils.log("UsageStats getDataByUsageEvents->" + pkg + " :" + (totalTime / 1000))
|
||||
}
|
||||
|
||||
return postBody
|
||||
}
|
||||
|
||||
/**
|
||||
* 第一次统计默认起始时间
|
||||
*/
|
||||
private fun getDefaultBeginTime(): Long {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.add(Calendar.YEAR, -5)
|
||||
return calendar.timeInMillis
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
private fun postUsageStats(beginTime: Long) {
|
||||
debugOnly {
|
||||
Utils.log("UsageStats->beginTime:$beginTime endTime:" + System.currentTimeMillis())
|
||||
}
|
||||
|
||||
val postBody = if (isSameDay(beginTime, System.currentTimeMillis())) {
|
||||
getDataByUsageEvents(beginTime)
|
||||
} else {
|
||||
getDataByUsageStats(beginTime)
|
||||
}
|
||||
|
||||
if (postBody == null || postBody.length() == 0) {
|
||||
debugOnly {
|
||||
Utils.log("UsageStats: 没有可上传的数据")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), postBody.toString())
|
||||
mApi.postUsageStatus(body, UserManager.getInstance().userId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
debugOnly {
|
||||
Utils.log("UsageStats: 数据上传成功")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
fun checkForPermission(): Boolean {
|
||||
val appOps = HaloApp
|
||||
.getInstance().application
|
||||
.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
|
||||
val mode = appOps.checkOpNoThrow(
|
||||
OPSTR_GET_USAGE_STATS,
|
||||
Process.myUid(),
|
||||
HaloApp.getInstance().application.packageName)
|
||||
|
||||
return mode == MODE_ALLOWED
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@SuppressLint("CheckResult")
|
||||
fun checkAndPostUsageStats() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
debugOnly {
|
||||
Utils.log("UsageStats checkAndPostUsageStats Android 版本小于22")
|
||||
}
|
||||
return
|
||||
}
|
||||
if (!checkForPermission()) {
|
||||
debugOnly {
|
||||
Utils.log("UsageStats checkAndPostUsageStats 没有授予权限")
|
||||
}
|
||||
return
|
||||
}
|
||||
if (!mPreference.getBoolean(USAGE_STATUS_SP_KEY, true)) {
|
||||
debugOnly {
|
||||
Utils.log("UsageStats checkAndPostUsageStats 有权限,但用户在设置关闭统计")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
mApi.getUsageStatusUpdateTime(HaloApp.getInstance().gid)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
val body = JSONObject(data.string())
|
||||
val lastPostTime = body.getLong("update_time") * 1000
|
||||
|
||||
val beginTime = if (lastPostTime == 0L) {
|
||||
getDefaultBeginTime()
|
||||
} else {
|
||||
lastPostTime
|
||||
}
|
||||
postUsageStats(beginTime)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun isSameDay(timeA: Long, timeB: Long): Boolean {
|
||||
if (timeA == timeB) {
|
||||
return true
|
||||
}
|
||||
|
||||
val calendarB = Calendar.getInstance()
|
||||
calendarB.time = Date(timeB)
|
||||
|
||||
val calendarA = Calendar.getInstance()
|
||||
calendarA.time = Date(timeA)
|
||||
|
||||
return (calendarB.get(Calendar.YEAR) === calendarA.get(Calendar.YEAR)
|
||||
&& calendarB.get(Calendar.MONTH) === calendarA.get(Calendar.MONTH)
|
||||
&& calendarB.get(Calendar.DATE) === calendarA.get(Calendar.DATE))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun skipToUsageStats(context: Context, requestCode: Int = -1) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (context is Activity && requestCode != -1) {
|
||||
context.startActivityForResult(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS), requestCode)
|
||||
} else {
|
||||
context.startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS))
|
||||
}
|
||||
} else {
|
||||
Utils.toast(context, "当前设备不支持查看应用使用情况")
|
||||
}
|
||||
}
|
||||
}
|
||||
154
app/src/main/java/com/gh/common/view/ClearEditTextNormal.java
Normal file
154
app/src/main/java/com/gh/common/view/ClearEditTextNormal.java
Normal file
@ -0,0 +1,154 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnFocusChangeListener;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.CycleInterpolator;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
|
||||
public class ClearEditTextNormal extends androidx.appcompat.widget.AppCompatEditText implements OnFocusChangeListener, TextWatcher {
|
||||
/**
|
||||
* 删除按钮的引用
|
||||
*/
|
||||
private Drawable mClearDrawable;
|
||||
/**
|
||||
* 控件是否有焦点
|
||||
*/
|
||||
private boolean hasFoucs;
|
||||
|
||||
public ClearEditTextNormal(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ClearEditTextNormal(Context context, AttributeSet attrs) {
|
||||
//这里构造方法也很重要,不加这个很多属性不能再XML里面定义
|
||||
this(context, attrs, android.R.attr.editTextStyle);
|
||||
}
|
||||
|
||||
public ClearEditTextNormal(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void init() {
|
||||
//获取EditText的DrawableRight,假如没有设置我们就使用默认的图片
|
||||
mClearDrawable = getCompoundDrawables()[2];
|
||||
if (mClearDrawable == null) {
|
||||
// throw new NullPointerException("You can add drawableRight attribute in XML");
|
||||
mClearDrawable = getResources().getDrawable(R.drawable.icon_close);
|
||||
}
|
||||
|
||||
mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
|
||||
//默认设置隐藏图标
|
||||
setClearIconVisible(false);
|
||||
//设置焦点改变的监听
|
||||
setOnFocusChangeListener(this);
|
||||
//设置输入框里面内容发生改变的监听
|
||||
addTextChangedListener(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件
|
||||
* 当我们按下的位置 在 EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 和
|
||||
* EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标,竖直方向就没有考虑
|
||||
*/
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
if (getCompoundDrawables()[2] != null) {
|
||||
|
||||
boolean touchable = event.getX() > (getWidth() - getTotalPaddingRight())
|
||||
&& (event.getX() < ((getWidth() - getPaddingRight())));
|
||||
|
||||
if (touchable) {
|
||||
this.setText("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置清除图标的显示与隐藏
|
||||
*/
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
this.hasFoucs = hasFocus;
|
||||
if (hasFocus) {
|
||||
setClearIconVisible(getText().length() > 0);
|
||||
} else {
|
||||
setClearIconVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去
|
||||
*
|
||||
* @param visible
|
||||
*/
|
||||
public void setClearIconVisible(boolean visible) {
|
||||
Drawable right = visible ? mClearDrawable : null;
|
||||
setCompoundDrawables(getCompoundDrawables()[0],
|
||||
getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 当输入框里面内容发生变化的时候回调的方法
|
||||
*/
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int count,
|
||||
int after) {
|
||||
if (hasFoucs) {
|
||||
setClearIconVisible(s.length() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count,
|
||||
int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置晃动动画
|
||||
*/
|
||||
public void setShakeAnimation() {
|
||||
this.setAnimation(shakeAnimation(5));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 晃动动画
|
||||
*
|
||||
* @param counts 1秒钟晃动多少下
|
||||
* @return
|
||||
*/
|
||||
public static Animation shakeAnimation(int counts) {
|
||||
Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
|
||||
translateAnimation.setInterpolator(new CycleInterpolator(counts));
|
||||
translateAnimation.setDuration(1000);
|
||||
return translateAnimation;
|
||||
}
|
||||
|
||||
}
|
||||
@ -30,6 +30,8 @@ public class CropImageBorderView extends View {
|
||||
|
||||
private Paint mPaint, mPaintRect;
|
||||
|
||||
private float mRatio = 1; // 宽高比
|
||||
|
||||
public CropImageBorderView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@ -64,7 +66,8 @@ public class CropImageBorderView extends View {
|
||||
// 计算矩形区域的宽度
|
||||
mWidth = getWidth() - 2 * mHorizontalPadding;
|
||||
// 计算距离屏幕垂直边界 的边距
|
||||
mVerticalPadding = (getHeight() - mWidth) / 2;
|
||||
|
||||
mVerticalPadding = (getHeight() - (int) (mWidth * mRatio)) / 2;
|
||||
|
||||
// 绘制左边
|
||||
canvas.drawRect(0, 0, mHorizontalPadding, getHeight()
|
||||
@ -81,13 +84,12 @@ public class CropImageBorderView extends View {
|
||||
|
||||
// 绘制边框
|
||||
canvas.drawRect(mHorizontalPadding, mVerticalPadding,
|
||||
mHorizontalPadding + mWidth, mVerticalPadding + mWidth, mPaint);
|
||||
mHorizontalPadding + mWidth, getHeight() - mVerticalPadding, mPaint);
|
||||
|
||||
}
|
||||
|
||||
public void setHorizontalPadding(int mHorizontalPadding) {
|
||||
public void setHorizontalPadding(int mHorizontalPadding, float ratio) {
|
||||
this.mHorizontalPadding = mHorizontalPadding;
|
||||
|
||||
this.mRatio = ratio;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -8,8 +8,6 @@ import android.util.TypedValue;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@ -21,6 +19,8 @@ public class CropImageCustom extends RelativeLayout {
|
||||
|
||||
private int mHorizontalPadding = 20;
|
||||
|
||||
private float mRatio = 1F; // 裁剪比例
|
||||
|
||||
public CropImageCustom(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
@ -38,17 +38,15 @@ public class CropImageCustom extends RelativeLayout {
|
||||
mHorizontalPadding = (int) TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding, getResources()
|
||||
.getDisplayMetrics());
|
||||
mZoomImageView.setHorizontalPadding(mHorizontalPadding);
|
||||
mClipImageView.setHorizontalPadding(mHorizontalPadding);
|
||||
|
||||
mZoomImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
|
||||
mClipImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对外公布设置边距的方法,单位为dp
|
||||
*
|
||||
* @param mHorizontalPadding
|
||||
*/
|
||||
public void setHorizontalPadding(int mHorizontalPadding) {
|
||||
this.mHorizontalPadding = mHorizontalPadding;
|
||||
public void setCropRatio(float ratio) {
|
||||
this.mRatio = ratio;
|
||||
mZoomImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
|
||||
mClipImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,6 +58,7 @@ public class CropImageCustom extends RelativeLayout {
|
||||
return mZoomImageView.clip();
|
||||
}
|
||||
|
||||
// 用户头像压缩规则
|
||||
public boolean savePicture(String path) {
|
||||
float limitSize = 900;
|
||||
int quality = 90;
|
||||
|
||||
@ -6,7 +6,6 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.GestureDetector.SimpleOnGestureListener;
|
||||
@ -17,6 +16,8 @@ import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class CropImageZoomView extends AppCompatImageView implements
|
||||
OnScaleGestureListener, OnTouchListener,
|
||||
@ -60,6 +61,10 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
*/
|
||||
private int mVerticalPadding;// ——屏幕顶部离截图区的高度
|
||||
|
||||
private float mRatio = 1; // 宽高比
|
||||
|
||||
private int mWidth;
|
||||
|
||||
public CropImageZoomView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@ -290,8 +295,10 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
Drawable d = getDrawable();
|
||||
if (d == null)
|
||||
return;
|
||||
|
||||
mWidth = getWidth() - 2 * mHorizontalPadding;
|
||||
// 垂直方向的边距
|
||||
mVerticalPadding = (getHeight() - (getWidth() - 2 * mHorizontalPadding)) / 2;
|
||||
mVerticalPadding = (getHeight() - (int) (mWidth * mRatio)) / 2;
|
||||
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
@ -339,13 +346,16 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
draw(canvas);
|
||||
return Bitmap.createBitmap(bitmap, mHorizontalPadding,
|
||||
mVerticalPadding, getWidth() - 2 * mHorizontalPadding,
|
||||
getWidth() - 2 * mHorizontalPadding);
|
||||
return Bitmap.createBitmap(bitmap,
|
||||
mHorizontalPadding,
|
||||
mVerticalPadding,
|
||||
mWidth,
|
||||
(getHeight() - mVerticalPadding * 2));
|
||||
}
|
||||
|
||||
public void setHorizontalPadding(int mHorizontalPadding) {
|
||||
public void setHorizontalPadding(int mHorizontalPadding, float ratio) {
|
||||
this.mHorizontalPadding = mHorizontalPadding;
|
||||
this.mRatio = ratio;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -15,12 +15,12 @@ import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class DownloadProgressBar extends ProgressBar {
|
||||
public static final int MAX_LENGTH = 1000;
|
||||
public static final int DOWNLOAD_NORMAL_STYLE = 0;
|
||||
@ -39,7 +39,8 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
DOWNLOADING_NORMAL,
|
||||
DOWNLOADING_PLUGIN,
|
||||
RESERVABLE,
|
||||
RESERVED
|
||||
RESERVED,
|
||||
H5_GAME
|
||||
}
|
||||
|
||||
private PorterDuffXfermode mDuffXFerMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
|
||||
@ -165,6 +166,7 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
case NORMAL:
|
||||
case NONE_WITH_HINT:
|
||||
case INSTALL_NORMAL:
|
||||
case H5_GAME:
|
||||
switch (mDownloadStyle) {
|
||||
case DOWNLOAD_RECT_STYLE:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_download_normal_rect_style));
|
||||
|
||||
@ -0,0 +1,142 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
||||
|
||||
public class GridSpacingItemColorDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
private int dividerWidth;
|
||||
private int dividerHeight;
|
||||
private int dividerWidthTop;
|
||||
private int dividerWidthBot;
|
||||
private Paint dividerPaint;
|
||||
|
||||
/**
|
||||
* @param dividerDp 分割块宽高,单位:dp
|
||||
* @param dividerColor 分割块颜色
|
||||
*/
|
||||
public GridSpacingItemColorDecoration(Context context, int dividerDp, @ColorRes int dividerColor) {
|
||||
this(context, dividerDp, dividerDp, dividerColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dividerWidthDp 分割块宽,单位:dp
|
||||
* @param dividerHeightDp 分割块高,单位:dp
|
||||
* @param dividerColor 分割块颜色
|
||||
*/
|
||||
public GridSpacingItemColorDecoration(Context context, int dividerWidthDp, int dividerHeightDp, @ColorRes int dividerColor) {
|
||||
this.dividerPaint = new Paint();
|
||||
this.dividerPaint.setColor(ContextCompat.getColor(context, dividerColor));
|
||||
|
||||
this.dividerWidth = dip2px(context, dividerWidthDp);
|
||||
this.dividerHeight = dip2px(context, dividerHeightDp);
|
||||
this.dividerWidthTop = dividerHeight / 2;
|
||||
this.dividerWidthBot = dividerHeight - dividerWidthTop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
||||
drawHorizontal(c, parent);
|
||||
drawVertical(c, parent);
|
||||
}
|
||||
|
||||
private void drawHorizontal(Canvas c, RecyclerView parent) {
|
||||
int childCount = parent.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
if (!isLastRaw(parent, i, getSpanCount(parent), childCount)) {//最后一行不设置颜色
|
||||
final View child = parent.getChildAt(i);
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
|
||||
.getLayoutParams();
|
||||
final int left = child.getLeft() - params.leftMargin;
|
||||
final int right = !isLastColum(parent, i, getSpanCount(parent)) ? child.getRight() + params.rightMargin
|
||||
+ dividerWidth : child.getRight() + params.rightMargin;
|
||||
final int top = child.getBottom() + params.bottomMargin;
|
||||
final int bottom = top + dividerHeight;
|
||||
c.drawRect(left, top, right, bottom, dividerPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawVertical(Canvas c, RecyclerView parent) {
|
||||
final int childCount = parent.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
if (!isLastColum(parent, i, getSpanCount(parent)) && i != childCount - 1) {//最后一列和最后个item后面不设置颜色
|
||||
final View child = parent.getChildAt(i);
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
|
||||
.getLayoutParams();
|
||||
final int top = child.getTop() - params.topMargin;
|
||||
final int bottom = child.getBottom() + params.bottomMargin;
|
||||
final int left = child.getRight() + params.rightMargin;
|
||||
final int right = left + dividerWidth;
|
||||
c.drawRect(left, top, right, bottom, dividerPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View child, RecyclerView parent, RecyclerView.State state) {
|
||||
super.getItemOffsets(outRect, child, parent, state);
|
||||
int spanCount = getSpanCount(parent);
|
||||
int pos = parent.getChildAdapterPosition(child);
|
||||
int childCount = parent.getAdapter().getItemCount();
|
||||
int column = (pos) % spanCount;// 计算这个child 处于第几列
|
||||
|
||||
outRect.top = isFirstRaw(parent, pos, spanCount) ? 0 : dividerWidthTop;
|
||||
outRect.bottom = isLastRaw(parent, pos, spanCount, childCount) ? 0 : dividerWidthBot;
|
||||
|
||||
outRect.left = (column * dividerWidth / spanCount);
|
||||
outRect.right = dividerWidth - (column + 1) * dividerWidth / spanCount;
|
||||
|
||||
}
|
||||
|
||||
private boolean isLastColum(RecyclerView parent, int pos, int spanCount) {
|
||||
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
|
||||
return layoutManager instanceof GridLayoutManager && (pos + 1) % spanCount == 0;
|
||||
}
|
||||
|
||||
private boolean isFirstRaw(RecyclerView parent, int pos, int spanCount) {
|
||||
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
|
||||
return layoutManager instanceof GridLayoutManager && pos < spanCount;
|
||||
}
|
||||
|
||||
private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
|
||||
int childCount) {
|
||||
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
|
||||
if (layoutManager instanceof GridLayoutManager) {
|
||||
int rawChildCount = childCount - childCount % spanCount;
|
||||
if (rawChildCount == childCount) {
|
||||
return pos >= rawChildCount - spanCount;
|
||||
}
|
||||
return pos >= rawChildCount;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int getSpanCount(RecyclerView parent) {
|
||||
// 列数
|
||||
int spanCount = -1;
|
||||
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
|
||||
if (layoutManager instanceof GridLayoutManager) {
|
||||
|
||||
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
|
||||
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
|
||||
spanCount = ((StaggeredGridLayoutManager) layoutManager)
|
||||
.getSpanCount();
|
||||
}
|
||||
return spanCount;
|
||||
}
|
||||
|
||||
private int dip2px(Context context, float dpValue) {
|
||||
float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
}
|
||||
82
app/src/main/java/com/gh/common/view/LongPressView.java
Normal file
82
app/src/main/java/com/gh/common/view/LongPressView.java
Normal file
@ -0,0 +1,82 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class LongPressView extends View {
|
||||
private int mLastMotionX, mLastMotionY;
|
||||
// 是否移动了
|
||||
private boolean isMoved;
|
||||
// 是否释放了
|
||||
private boolean isReleased;
|
||||
// 计数器,防止多次点击导致最后一次形成longpress的时间变短
|
||||
private int mCounter;
|
||||
// 长按的runnable
|
||||
private Runnable mLongPressRunnable;
|
||||
// 移动的阈值
|
||||
private static final int TOUCH_SLOP = 60;
|
||||
private int longPressTimeout = ViewConfiguration.getLongPressTimeout();
|
||||
|
||||
public LongPressView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LongPressView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public LongPressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
if (attrs != null) {
|
||||
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LongPressViewStyle);
|
||||
longPressTimeout = ta.getInteger(R.styleable.LongPressViewStyle_timeout, longPressTimeout);
|
||||
ta.recycle();
|
||||
}
|
||||
mLongPressRunnable = () -> {
|
||||
mCounter--;
|
||||
if (mCounter > 0 || isReleased || isMoved)
|
||||
return;
|
||||
performLongClick();// 回调长按事件
|
||||
};
|
||||
}
|
||||
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
int x = (int) event.getX();
|
||||
int y = (int) event.getY();
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mLastMotionX = x;
|
||||
mLastMotionY = y;
|
||||
mCounter++;
|
||||
isReleased = false;
|
||||
isMoved = false;
|
||||
postDelayed(mLongPressRunnable, longPressTimeout);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (isMoved)
|
||||
break;
|
||||
if (Math.abs(mLastMotionX - x) > TOUCH_SLOP
|
||||
|| Math.abs(mLastMotionY - y) > TOUCH_SLOP) {
|
||||
isMoved = true;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
isReleased = true;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,8 @@
|
||||
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)
|
||||
@ -13,13 +11,18 @@ class MaterializedFrameLayout @JvmOverloads constructor(context: 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)
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
setOnApplyWindowInsetsListener { _, insets ->
|
||||
val childCount = childCount
|
||||
for (index in 0 until childCount) {
|
||||
getChildAt(index).dispatchApplyWindowInsets(insets)
|
||||
}
|
||||
insets
|
||||
}
|
||||
}
|
||||
return insets
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,10 +1,8 @@
|
||||
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)
|
||||
@ -13,13 +11,18 @@ class MaterializedRelativeLayout @JvmOverloads constructor(context: Context, att
|
||||
/**
|
||||
* 将 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)
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
setOnApplyWindowInsetsListener { _, insets ->
|
||||
val childCount = childCount
|
||||
for (index in 0 until childCount) {
|
||||
getChildAt(index).dispatchApplyWindowInsets(insets)
|
||||
}
|
||||
insets
|
||||
}
|
||||
}
|
||||
return insets
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,14 +1,10 @@
|
||||
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
|
||||
import com.gh.common.util.DisplayUtils
|
||||
|
||||
/**
|
||||
* 导航栏占位 View
|
||||
@ -18,44 +14,8 @@ class NavigationBarView @JvmOverloads constructor(context: Context?, attrs: Attr
|
||||
val height = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
0
|
||||
} else {
|
||||
retrieveNavigationHeight()
|
||||
DisplayUtils.retrieveNavigationHeight(context)
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
82
app/src/main/java/com/gh/common/view/ReserveDialog.kt
Normal file
82
app/src/main/java/com/gh/common/view/ReserveDialog.kt
Normal file
@ -0,0 +1,82 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.util.fromHtml
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DialogReserveBinding
|
||||
import com.gh.gamecenter.databinding.DialogReserveItemBinding
|
||||
import com.gh.gamecenter.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.mygame.MyGameActivity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class ReserveDialog : BaseDialogFragment() {
|
||||
|
||||
private lateinit var mReserveList: List<SimpleGameEntity>
|
||||
private var mDismissListener: (() -> Unit)? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val binding: DialogReserveBinding = DataBindingUtil.inflate(inflater, R.layout.dialog_reserve, container, false)
|
||||
binding.title.text = resources.getString(R.string.dialog_reserve_title, mReserveList.size).fromHtml()
|
||||
binding.more.visibility = if (mReserveList.size > 4) {
|
||||
View.VISIBLE
|
||||
} else View.GONE
|
||||
binding.more.setOnClickListener {
|
||||
val intent = MyGameActivity.getIntentWithConfig(requireContext(), 2)
|
||||
startActivity(intent)
|
||||
dismiss()
|
||||
}
|
||||
binding.recyclerView.layoutManager = if (mReserveList.size > 4) {
|
||||
GridLayoutManager(context, 4)
|
||||
} else {
|
||||
FixLinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
|
||||
}
|
||||
binding.recyclerView.adapter = object : BaseRecyclerAdapter<ReserveDialogItemViewHolder>(context) {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ReserveDialogItemViewHolder {
|
||||
val inflate = mLayoutInflater.inflate(R.layout.dialog_reserve_item, parent, false)
|
||||
return ReserveDialogItemViewHolder(DialogReserveItemBinding.bind(inflate))
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (mReserveList.size > 4) 4 else mReserveList.size
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ReserveDialogItemViewHolder, position: Int) {
|
||||
val entity = mReserveList[position]
|
||||
holder.binding.game = entity
|
||||
holder.itemView.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(mContext, entity.id, "(预约弹窗)")
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
|
||||
fun setOnDismissListener(dismissListener: () -> Unit) {
|
||||
mDismissListener = dismissListener
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mDismissListener?.invoke()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(reserveList: List<SimpleGameEntity>) = ReserveDialog().apply { mReserveList = reserveList }
|
||||
}
|
||||
}
|
||||
|
||||
class ReserveDialogItemViewHolder(val binding: DialogReserveItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
@ -56,6 +56,9 @@ public class RichEditor extends WebView {
|
||||
public static String IMAGE_FLAG_DEFAULT = ",default";
|
||||
public static String IMAGE_FLAG_THUMBNAIL = ",thumbnail";
|
||||
|
||||
private boolean mContentOwner;
|
||||
private boolean mInputEnabled;
|
||||
|
||||
private int mDefaultImageWidth;
|
||||
private int mThumbnailImageWidth;
|
||||
|
||||
@ -227,7 +230,7 @@ public class RichEditor extends WebView {
|
||||
// getSettings().setBlockNetworkImage(true); // 先不加载网络图片,因为后面有资源替换操作防止流量无故丢失
|
||||
|
||||
try {
|
||||
exec("javascript:RE.setHtml('" + URLEncoder.encode(contents, "UTF-8") + "');");
|
||||
exec("javascript:RE.setHtmlByVideoStatus('" + URLEncoder.encode(contents, "UTF-8") + "');");
|
||||
|
||||
if (isLoadTbImage) {
|
||||
if (!NetworkUtils.isWifiOr4GConnected(getContext())) {
|
||||
@ -259,8 +262,8 @@ public class RichEditor extends WebView {
|
||||
// 转译
|
||||
String brief = entity.getBrief();
|
||||
String title = entity.getTitle();
|
||||
brief = TextUtils.isEmpty(brief) ? "" : brief.replaceAll("[\\x00-\\x1F\\x7F]", "");
|
||||
title = TextUtils.isEmpty(title) ? "" : title.replaceAll("[\\x00-\\x1F\\x7F]", "");
|
||||
brief = TextUtils.isEmpty(brief) ? "" : brief.replaceAll("[\\x00-\\x1F\\x7F]", "").replace("\\", "");
|
||||
title = TextUtils.isEmpty(title) ? "" : title.replaceAll("[\\x00-\\x1F\\x7F]", "").replace("\\", "");
|
||||
|
||||
entity.setBrief(TextUtils.htmlEncode(brief));
|
||||
entity.setTitle(TextUtils.htmlEncode(title));
|
||||
@ -273,15 +276,16 @@ public class RichEditor extends WebView {
|
||||
JSONObject object = new JSONObject();
|
||||
object.put("poster", entity.getPoster());
|
||||
object.put("url", entity.getUrl());
|
||||
object.put("duration", formatDuration(entity.getLength()));
|
||||
object.put("duration", formatVideoDuration(entity.getLength()));
|
||||
object.put("id", entity.getId());
|
||||
object.put("status", entity.getStatus());
|
||||
exec("javascript:RE.insertCustomVideo('" + object.toString() + "');");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private String formatDuration(long seconds) {
|
||||
public static String formatVideoDuration(long seconds) {
|
||||
long absSeconds = Math.abs(seconds);
|
||||
@SuppressLint("DefaultLocale") String positive = String.format(
|
||||
"%02d:%02d",
|
||||
@ -415,6 +419,7 @@ public class RichEditor extends WebView {
|
||||
}
|
||||
|
||||
public void setInputEnabled(Boolean inputEnabled) {
|
||||
mInputEnabled = inputEnabled;
|
||||
exec("javascript:RE.setInputEnabled(" + inputEnabled + ")");
|
||||
}
|
||||
|
||||
@ -574,6 +579,9 @@ public class RichEditor extends WebView {
|
||||
}
|
||||
}
|
||||
|
||||
public void setContentOwner(boolean contentOwner) {
|
||||
this.mContentOwner = contentOwner;
|
||||
}
|
||||
|
||||
public interface WebChromeClientListener {
|
||||
void onPageFinished(WebView view, String url);
|
||||
@ -583,9 +591,29 @@ public class RichEditor extends WebView {
|
||||
|
||||
class NativeCallBack {
|
||||
|
||||
/**
|
||||
* true:测试接口
|
||||
* false:正式接口
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public boolean isNativeBuildDebug() {
|
||||
return "internal".equals(BuildConfig.FLAVOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 只在插入HTML之后才有效
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public boolean isContentOwner() {
|
||||
return mContentOwner;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前页面是不是编辑状态
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public boolean isInputEnabled() {
|
||||
return mInputEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,11 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.TimeElapsedHelper
|
||||
import com.gh.common.constant.Constants.SP_LAST_OPENING_ID
|
||||
@ -30,6 +30,8 @@ class WelcomeDialog : BaseDialogFragment() {
|
||||
|
||||
lateinit var binding: DialogWelcomeBinding
|
||||
|
||||
private var mDismissListener: (() -> Unit)? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
mTimeHelper = TimeElapsedHelper(this)
|
||||
@ -93,6 +95,10 @@ class WelcomeDialog : BaseDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
fun setOnDismissListener(dismissListener: () -> Unit) {
|
||||
mDismissListener = dismissListener
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
val type = if (mDismissByClickImage) {
|
||||
"点击图片"
|
||||
@ -108,6 +114,8 @@ class WelcomeDialog : BaseDialogFragment() {
|
||||
putString(SP_LAST_OPENING_ID, mWelcomeEntity?.id)
|
||||
putLong(SP_LAST_OPENING_TIME, mWelcomeEntity?.time!!)
|
||||
}
|
||||
|
||||
mDismissListener?.invoke()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
|
||||
@ -1,296 +0,0 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ScaleGestureDetector;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
|
||||
/**
|
||||
* Created by khy on 2016/10/26.
|
||||
*/
|
||||
public class ZoomSimpleDraweeView extends SimpleDraweeView {
|
||||
private final float[] matrixValues = new float[9];
|
||||
private ScaleGestureDetector mScaleDetector;
|
||||
private GestureDetector mGestureDetector;
|
||||
private float mCurrentScale = 1f;
|
||||
private Matrix mCurrentMatrix;
|
||||
private setOnSingleClickListener mClickListener;
|
||||
private setOnLongClickListener mLongClickListener;
|
||||
private float imgagePro = -1; // 图片宽高比
|
||||
|
||||
public ZoomSimpleDraweeView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mCurrentMatrix = new Matrix();
|
||||
|
||||
ScaleGestureDetector.OnScaleGestureListener scaleListener = new ScaleGestureDetector
|
||||
.SimpleOnScaleGestureListener() {
|
||||
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
float scaleFactor = detector.getScaleFactor();
|
||||
if (mCurrentScale < 4f || detector.getScaleFactor() < 1f) {
|
||||
mCurrentScale *= scaleFactor;
|
||||
mCurrentMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
|
||||
invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||
super.onScaleEnd(detector);
|
||||
|
||||
if (mCurrentScale < 1f) {
|
||||
reset();
|
||||
}
|
||||
checkBorder();
|
||||
}
|
||||
|
||||
};
|
||||
mScaleDetector = new ScaleGestureDetector(getContext(), scaleListener);
|
||||
|
||||
GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {
|
||||
@Override
|
||||
public boolean onSingleTapUp(MotionEvent e) {
|
||||
|
||||
return super.onSingleTapUp(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLongPress(MotionEvent e) {
|
||||
super.onLongPress(e);
|
||||
if (mLongClickListener != null) {
|
||||
mLongClickListener.onLongClick();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
||||
if (mCurrentScale > 1f) {
|
||||
mCurrentMatrix.postTranslate(-distanceX, -distanceY);
|
||||
invalidate();
|
||||
checkBorder();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap(MotionEvent e) {
|
||||
final float x = e.getX();
|
||||
final float y = e.getY();
|
||||
float scaleSize; //扩大或缩小的倍数
|
||||
|
||||
if (mCurrentScale > 1.5f) { //缩小时直接回到原画大小
|
||||
scaleSize = 0.5f;
|
||||
ZoomSimpleDraweeView.this.post(new AutoScaleRunnable(mCurrentScale * scaleSize, getWidth() / 2f, getHeight() / 2f, false));
|
||||
} else {
|
||||
scaleSize = 2.0f;
|
||||
ZoomSimpleDraweeView.this.post(new AutoScaleRunnable(mCurrentScale * scaleSize, x, y, true));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
||||
if (mClickListener != null) {
|
||||
mClickListener.onClick();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
mGestureDetector = new GestureDetector(getContext(), gestureListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置图片
|
||||
*/
|
||||
public void reset() {
|
||||
mCurrentMatrix.reset();
|
||||
mCurrentScale = 1f;
|
||||
invalidate();
|
||||
EventBus.getDefault().post(new EBReuse("isStopMove"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查图片边界是否移到view以内
|
||||
* 目的是让图片边缘不要移动到view里面
|
||||
*/
|
||||
private void checkBorder() {
|
||||
RectF rectF = getDisplayRect(mCurrentMatrix);
|
||||
boolean reset = false;
|
||||
float dx = 0;
|
||||
float dy = 0;
|
||||
|
||||
|
||||
if (rectF.left > 0) {
|
||||
dx = getLeft() - rectF.left;
|
||||
reset = true;
|
||||
}
|
||||
if (rectF.top > 0) {
|
||||
dy = getTop() - rectF.top;
|
||||
reset = true;
|
||||
}
|
||||
if (rectF.right < getRight()) {
|
||||
dx = getRight() - rectF.right;
|
||||
reset = true;
|
||||
}
|
||||
if (rectF.bottom < getHeight()) {
|
||||
dy = getHeight() - rectF.bottom;
|
||||
reset = true;
|
||||
}
|
||||
if (reset) {
|
||||
mCurrentMatrix.postTranslate(dx, dy);
|
||||
invalidate();
|
||||
}
|
||||
if (dy == 0 && reset || mCurrentScale == 1f) {
|
||||
EventBus.getDefault().post(new EBReuse("isStopMove"));
|
||||
} else {
|
||||
EventBus.getDefault().post(new EBReuse("isStartove"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that maps the supplied Matrix to the current Drawable
|
||||
*
|
||||
* @param matrix - Matrix to map Drawable against
|
||||
* @return RectF - Displayed Rectangle
|
||||
*/
|
||||
private RectF getDisplayRect(Matrix matrix) {
|
||||
// int bottom;
|
||||
// if (imgagePro != -1){
|
||||
// bottom = (int) (getRight()*imgagePro);
|
||||
// } else {
|
||||
// bottom = getBottom();
|
||||
// }
|
||||
RectF rectF = new RectF(getLeft(), getTop(), getRight(), getBottom());
|
||||
matrix.mapRect(rectF);
|
||||
return rectF;
|
||||
}
|
||||
|
||||
public ZoomSimpleDraweeView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public ZoomSimpleDraweeView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageURI(Uri uri) {
|
||||
reset();
|
||||
super.setImageURI(uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
int saveCount = canvas.save();
|
||||
canvas.concat(mCurrentMatrix);
|
||||
super.onDraw(canvas);
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
mScaleDetector.onTouchEvent(event);
|
||||
if (!mScaleDetector.isInProgress()) {
|
||||
mGestureDetector.onTouchEvent(event);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public final float getScale() {
|
||||
mCurrentMatrix.getValues(matrixValues);
|
||||
return matrixValues[Matrix.MSCALE_X];
|
||||
}
|
||||
|
||||
//图片宽高比例
|
||||
public void setImagePro(float imgPro) {
|
||||
this.imgagePro = imgPro;
|
||||
}
|
||||
|
||||
public void setOnSingleClickListener(setOnSingleClickListener listener) {
|
||||
mClickListener = listener;
|
||||
}
|
||||
|
||||
public void setOnLongClickListener(setOnLongClickListener listener) {
|
||||
mLongClickListener = listener;
|
||||
}
|
||||
|
||||
public interface setOnLongClickListener {
|
||||
void onLongClick();
|
||||
}
|
||||
|
||||
public interface setOnSingleClickListener {
|
||||
void onClick();
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动缩放的任务
|
||||
*/
|
||||
private class AutoScaleRunnable implements Runnable {
|
||||
static final float BIGGER = 1.07f;
|
||||
static final float SMALLER = 0.96f;
|
||||
private float mTargetScale;
|
||||
private boolean isExp;
|
||||
|
||||
/**
|
||||
* 缩放的中心
|
||||
*/
|
||||
private float x;
|
||||
private float y;
|
||||
|
||||
/**
|
||||
* @param isExp :判断是否是放大
|
||||
*/
|
||||
public AutoScaleRunnable(float targetScale, float x, float y, boolean isExp) {
|
||||
this.mTargetScale = targetScale;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.isExp = isExp;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (isExp) { //放大
|
||||
mCurrentMatrix.postScale(BIGGER, BIGGER, x, y);
|
||||
invalidate();
|
||||
if (mCurrentScale < mTargetScale && mCurrentScale <= 4) {
|
||||
ZoomSimpleDraweeView.this.postDelayed(this, 10);
|
||||
mCurrentScale = mCurrentScale * BIGGER;
|
||||
} else {
|
||||
checkBorder();
|
||||
mCurrentScale = getScale();
|
||||
}
|
||||
} else {//缩小
|
||||
mCurrentMatrix.postScale(SMALLER, SMALLER, x, y);
|
||||
invalidate();
|
||||
checkBorder();
|
||||
if (getScale() > 1.01) {
|
||||
ZoomSimpleDraweeView.this.postDelayed(this, 1);
|
||||
mCurrentScale = mCurrentScale * SMALLER;
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,8 +12,6 @@ import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.TintTypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
@ -22,6 +20,9 @@ import android.widget.RatingBar;
|
||||
import com.gh.common.view.materialratingbar.internal.DrawableCompat;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.TintTypedArray;
|
||||
|
||||
|
||||
// AppCompatRatingBar will add undesired measuring behavior.
|
||||
@SuppressLint("AppCompatCustomView")
|
||||
@ -154,6 +155,12 @@ public class MaterialRatingBar extends RatingBar {
|
||||
@Nullable
|
||||
@Override
|
||||
public ColorStateList getProgressTintList() {
|
||||
// Samsung Android 10 might call this in super class constructor.
|
||||
// Base on this PR: https://github.com/zhanghai/MaterialRatingBar/pull/62
|
||||
if (mProgressTintInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
logRatingBarTintWarning();
|
||||
return getSupportProgressTintList();
|
||||
}
|
||||
@ -301,9 +308,6 @@ public class MaterialRatingBar extends RatingBar {
|
||||
}
|
||||
|
||||
private void logRatingBarTintWarning() {
|
||||
if (getContext().getApplicationInfo().minSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
return;
|
||||
}
|
||||
Log.w(TAG, "Non-support version of tint method called, this is error-prone and will crash" +
|
||||
" below Lollipop if you are calling it as a method of RatingBar instead of" +
|
||||
" MaterialRatingBar");
|
||||
|
||||
@ -37,41 +37,42 @@ public class PagerLayoutManager extends LinearLayoutManager {
|
||||
* 初始化操作
|
||||
*/
|
||||
private void init() {
|
||||
switch (mOrientation){
|
||||
switch (mOrientation) {
|
||||
case HORIZONTAL:
|
||||
mPagerSnapHelper = new ScrollPageHelper(Gravity.START,false);
|
||||
mPagerSnapHelper = new ScrollPageHelper(Gravity.START, false);
|
||||
break;
|
||||
case VERTICAL:
|
||||
mPagerSnapHelper = new ScrollPageHelper(Gravity.TOP,false);
|
||||
mPagerSnapHelper = new ScrollPageHelper(Gravity.TOP, false);
|
||||
break;
|
||||
default:
|
||||
mPagerSnapHelper = new ScrollPageHelper(Gravity.TOP,false);
|
||||
mPagerSnapHelper = new ScrollPageHelper(Gravity.TOP, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* attach到window窗口时,该方法必须调用
|
||||
* @param recyclerView recyclerView
|
||||
*
|
||||
* @param recyclerView recyclerView
|
||||
*/
|
||||
@Override
|
||||
public void onAttachedToWindow(RecyclerView recyclerView){
|
||||
public void onAttachedToWindow(RecyclerView recyclerView) {
|
||||
if (recyclerView == null) {
|
||||
throw new IllegalArgumentException("The attach RecycleView must not null!!");
|
||||
}
|
||||
super.onAttachedToWindow(recyclerView);
|
||||
this.mRecyclerView = recyclerView;
|
||||
if (mPagerSnapHelper==null){
|
||||
if (mPagerSnapHelper == null) {
|
||||
init();
|
||||
}
|
||||
try {
|
||||
//attachToRecyclerView源码上的方法可能会抛出IllegalStateException异常,这里手动捕获一下
|
||||
RecyclerView.OnFlingListener onFlingListener = mRecyclerView.getOnFlingListener();
|
||||
//源码中判断了,如果onFlingListener已经存在的话,再次设置就直接抛出异常,那么这里可以判断一下
|
||||
if (onFlingListener==null){
|
||||
if (onFlingListener == null) {
|
||||
mPagerSnapHelper.attachToRecyclerView(mRecyclerView);
|
||||
}
|
||||
} catch (IllegalStateException e){
|
||||
} catch (IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
mRecyclerView.addOnChildAttachStateChangeListener(mChildAttachStateChangeListener);
|
||||
@ -79,13 +80,14 @@ public class PagerLayoutManager extends LinearLayoutManager {
|
||||
|
||||
/**
|
||||
* 销毁的时候调用该方法,需要移除监听事件
|
||||
* @param view view
|
||||
* @param recycler recycler
|
||||
*
|
||||
* @param view view
|
||||
* @param recycler recycler
|
||||
*/
|
||||
@Override
|
||||
public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) {
|
||||
super.onDetachedFromWindow(view, recycler);
|
||||
if (mRecyclerView!=null){
|
||||
if (mRecyclerView != null) {
|
||||
mRecyclerView.removeOnChildAttachStateChangeListener(mChildAttachStateChangeListener);
|
||||
}
|
||||
}
|
||||
@ -100,7 +102,8 @@ public class PagerLayoutManager extends LinearLayoutManager {
|
||||
* 缓慢拖拽-> SCROLL_STATE_DRAGGING
|
||||
* 快速滚动-> SCROLL_STATE_SETTLING
|
||||
* 空闲状态-> SCROLL_STATE_IDLE
|
||||
* @param state 状态
|
||||
*
|
||||
* @param state 状态
|
||||
*/
|
||||
@Override
|
||||
public void onScrollStateChanged(int state) {
|
||||
@ -134,13 +137,15 @@ public class PagerLayoutManager extends LinearLayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
double speedRatio = 0.8;
|
||||
|
||||
/**
|
||||
* 监听竖直方向的相对偏移量
|
||||
* @param dy y轴滚动值
|
||||
* @param recycler recycler
|
||||
* @param state state滚动状态
|
||||
* @return int值
|
||||
*
|
||||
* @param dy y轴滚动值
|
||||
* @param recycler recycler
|
||||
* @param state state滚动状态
|
||||
* @return int值
|
||||
*/
|
||||
@Override
|
||||
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
|
||||
@ -155,10 +160,11 @@ public class PagerLayoutManager extends LinearLayoutManager {
|
||||
|
||||
/**
|
||||
* 监听水平方向的相对偏移量
|
||||
* @param dx x轴滚动值
|
||||
* @param recycler recycler
|
||||
* @param state state滚动状态
|
||||
* @return int值
|
||||
*
|
||||
* @param dx x轴滚动值
|
||||
* @param recycler recycler
|
||||
* @param state state滚动状态
|
||||
* @return int值
|
||||
*/
|
||||
@Override
|
||||
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler,
|
||||
@ -172,9 +178,10 @@ public class PagerLayoutManager extends LinearLayoutManager {
|
||||
|
||||
/**
|
||||
* 设置监听
|
||||
* @param listener listener
|
||||
*
|
||||
* @param listener listener
|
||||
*/
|
||||
public void setOnViewPagerListener(OnPagerListener listener){
|
||||
public void setOnViewPagerListener(OnPagerListener listener) {
|
||||
this.mOnViewPagerListener = listener;
|
||||
}
|
||||
|
||||
@ -197,13 +204,13 @@ public class PagerLayoutManager extends LinearLayoutManager {
|
||||
*/
|
||||
@Override
|
||||
public void onChildViewDetachedFromWindow(@NonNull View view) {
|
||||
if (mDrift >= 0){
|
||||
if (mDrift >= 0) {
|
||||
if (mOnViewPagerListener != null) {
|
||||
mOnViewPagerListener.onPageRelease(true , getPosition(view));
|
||||
mOnViewPagerListener.onPageRelease(true, getPosition(view));
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
if (mOnViewPagerListener != null) {
|
||||
mOnViewPagerListener.onPageRelease(false , getPosition(view));
|
||||
mOnViewPagerListener.onPageRelease(false, getPosition(view));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
56
app/src/main/java/com/gh/download/DownloadDataHelper.kt
Normal file
56
app/src/main/java/com/gh/download/DownloadDataHelper.kt
Normal file
@ -0,0 +1,56 @@
|
||||
package com.gh.download
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
|
||||
object DownloadDataHelper {
|
||||
const val DOWNLOAD_RESUME_WAY = "download_resume_way"
|
||||
const val DOWNLOAD_RESUME_MANUAL = "manual"
|
||||
const val DOWNLOAD_RESUME_AUTO = "auto"
|
||||
|
||||
const val DOWNLOAD_CANCEL_WAY = "download_cancel_way"
|
||||
const val DOWNLOAD_CANCEL_MANUAL = "manual"
|
||||
const val DOWNLOAD_CANCEL_AUTO = "auto"
|
||||
|
||||
@JvmStatic
|
||||
fun getDownloadStatusAlias(downloadEntity: DownloadEntity): String {
|
||||
val status = downloadEntity.status
|
||||
return if (status == DownloadStatus.add) {
|
||||
"开始下载"
|
||||
} else if (status == DownloadStatus.pause) {
|
||||
"暂停下载"
|
||||
} else if (status == DownloadStatus.resume) {
|
||||
if (downloadEntity.meta[DOWNLOAD_RESUME_WAY] == DOWNLOAD_RESUME_AUTO) {
|
||||
"自动恢复下载"
|
||||
} else {
|
||||
"继续下载"
|
||||
}
|
||||
} else if (status == DownloadStatus.waiting) {
|
||||
"暂停下载-等待中"
|
||||
} else if (status == DownloadStatus.subscribe || status == DownloadStatus.neterror || status == DownloadStatus.timeout) {
|
||||
"暂停下载-连上WiFi自动下载"
|
||||
} else if (status == DownloadStatus.done) {
|
||||
val pm = HaloApp.getInstance().application.applicationContext.packageManager
|
||||
val packageInfo = pm.getPackageArchiveInfo(downloadEntity.path, PackageManager.GET_ACTIVITIES)
|
||||
if (packageInfo == null) {
|
||||
"解析包错误"
|
||||
} else {
|
||||
"下载完成"
|
||||
}
|
||||
} else if (status == DownloadStatus.delete || status == DownloadStatus.cancel) {
|
||||
if (downloadEntity.meta[DOWNLOAD_CANCEL_WAY] == DOWNLOAD_CANCEL_AUTO) {
|
||||
"自动删除任务"
|
||||
} else {
|
||||
"删除任务"
|
||||
}
|
||||
} else if (status == DownloadStatus.overflow) {
|
||||
"解析包错误-下载过程中"
|
||||
} else if (status == DownloadStatus.hijack || status == DownloadStatus.notfound) {
|
||||
"下载失败"
|
||||
} else {
|
||||
"未知状态"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,21 +10,25 @@ import android.os.Message;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.util.AppDebugConfig;
|
||||
import com.gh.common.util.DataCollectionUtils;
|
||||
import com.gh.common.util.DeviceUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.GdtHelper;
|
||||
import com.gh.common.util.MD5Utils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository;
|
||||
import com.google.gson.Gson;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
@ -46,7 +50,9 @@ import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@ -58,6 +64,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
private static DownloadManager mInstance;
|
||||
private static Gson gson = new Gson();
|
||||
private static final String HINT_MARK = "hint_mark";
|
||||
|
||||
private Context mContext;
|
||||
private Handler mHandler;
|
||||
@ -71,6 +78,8 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
private DownloadDao mDownloadDao;
|
||||
|
||||
private Set<String> mUpdateMarks;
|
||||
|
||||
@Override
|
||||
public void onTaskCancelled(DownloadEntity entity) {
|
||||
EBDownloadStatus status = new EBDownloadStatus("delete", entity.getName(),
|
||||
@ -78,8 +87,6 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
status.setPluggable(entity.isPluggable());
|
||||
EventBus.getDefault().post(status);
|
||||
|
||||
DownloadNotification.showDownloadingNotification(mContext);
|
||||
|
||||
DownloadManager.getInstance(mContext).putStatus(entity.getUrl(), DownloadStatus.delete);
|
||||
|
||||
downloadingMap.remove(entity.getUrl());
|
||||
@ -87,11 +94,9 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
@Override
|
||||
public void onTaskAdded(DownloadEntity entity) {
|
||||
EventBus.getDefault().post(new EBDownloadStatus("download",entity.getName(),
|
||||
EventBus.getDefault().post(new EBDownloadStatus("download", entity.getName(),
|
||||
entity.getPlatform(), entity.getUrl(), entity.getPackageName(), entity.getGameId()));
|
||||
|
||||
DownloadNotification.showDownloadingNotification(mContext);
|
||||
|
||||
downloadingMap.put(entity.getUrl(), entity);
|
||||
|
||||
DownloadWorkManager.addWorker();
|
||||
@ -103,7 +108,6 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
if (entity.getStatus() == DownloadStatus.overflow) {
|
||||
MtaHelper.onEventWithBasicDeviceInfo("下载无法完成", "游戏", entity.getName());
|
||||
} else {
|
||||
DownloadNotification.showDownloadingNotification(mContext);
|
||||
downloadingMap.remove(entity.getUrl());
|
||||
}
|
||||
}
|
||||
@ -115,8 +119,6 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
@Override
|
||||
public void onTaskDone(DownloadEntity entity) {
|
||||
DownloadNotification.showDownloadingNotification(mContext);
|
||||
DownloadNotification.showDownloadDoneNotification(mContext, entity);
|
||||
downloadingMap.remove(entity.getUrl());
|
||||
|
||||
if (downloadingMap.isEmpty()) {
|
||||
@ -133,6 +135,8 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
mContext = context.getApplicationContext();
|
||||
mDownloadDao = DownloadDao.getInstance(mContext);
|
||||
|
||||
mUpdateMarks = SPUtils.getStringSet(HINT_MARK);
|
||||
|
||||
//TODO unregister this
|
||||
DownloadStatusManager.getInstance().registerTaskStatusListener(this);
|
||||
|
||||
@ -153,9 +157,12 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
String url = (String) msg.obj;
|
||||
switch (msg.what) {
|
||||
case DownloadConfig.CONTINUE_DOWNLOAD_TASK:
|
||||
case DownloadConfig.CONTINUE_DOWNLOAD_AUTO_TASK:
|
||||
if (lastTimeMap.get(url) != null && System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) {
|
||||
DownloadEntity downloadEntity = getDownloadEntityByUrl(url);
|
||||
if (downloadEntity != null) add(downloadEntity);
|
||||
if (downloadEntity != null) {
|
||||
resume(downloadEntity, msg.what == DownloadConfig.CONTINUE_DOWNLOAD_AUTO_TASK);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DownloadConfig.PAUSE_DOWNLOAD_TASK:
|
||||
@ -305,6 +312,42 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "add");
|
||||
}
|
||||
|
||||
/**
|
||||
* 继续下载任务
|
||||
*
|
||||
* @param downloadEntity
|
||||
* @param automatic 是否是自动下载
|
||||
*/
|
||||
public void resume(DownloadEntity downloadEntity, boolean automatic) {
|
||||
if (downloadEntity != null) {
|
||||
String url = downloadEntity.getUrl();
|
||||
checkDownloadEntryRecordValidate(url);
|
||||
if (isFileCompleted(url)) {
|
||||
downloadEntity.setStatus(DownloadStatus.done);
|
||||
DataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
} else if (!isTaskDownloading(url)) {
|
||||
DownloadEntity daoEntity = mDownloadDao.get(downloadEntity.getUrl());
|
||||
if (automatic) {
|
||||
if (daoEntity != null) {
|
||||
daoEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_RESUME_WAY, DownloadDataHelper.DOWNLOAD_RESUME_AUTO);
|
||||
mDownloadDao.newOrUpdate(daoEntity);
|
||||
}
|
||||
downloadEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_RESUME_WAY, DownloadDataHelper.DOWNLOAD_RESUME_AUTO);
|
||||
} else {
|
||||
if (daoEntity != null) {
|
||||
daoEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_RESUME_WAY, DownloadDataHelper.DOWNLOAD_RESUME_MANUAL);
|
||||
mDownloadDao.newOrUpdate(daoEntity);
|
||||
}
|
||||
downloadEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_RESUME_WAY, DownloadDataHelper.DOWNLOAD_RESUME_MANUAL);
|
||||
}
|
||||
startDownloadService(downloadEntity, DownloadStatus.resume);
|
||||
}
|
||||
put(url, System.currentTimeMillis());
|
||||
putStatus(url, DownloadStatus.downloading);
|
||||
}
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "resume");
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个下载任务(WiFi时自动下载)
|
||||
*
|
||||
@ -478,10 +521,16 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
* @param url
|
||||
*/
|
||||
public void cancel(String url) {
|
||||
cancel(url, true);
|
||||
cancel(url, true, false);
|
||||
}
|
||||
|
||||
public void cancel(String url, boolean isDeleteFile) {
|
||||
/**
|
||||
* 根据url取消下载,并删除已下载的文件
|
||||
*
|
||||
* @param url
|
||||
* @param automatic 是否是安装完自动删除
|
||||
*/
|
||||
public void cancel(String url, boolean isDeleteFile, boolean automatic) {
|
||||
DownloadEntity entry = mDownloadDao.get(url);
|
||||
if (entry != null) {
|
||||
if (isDeleteFile) {
|
||||
@ -491,6 +540,11 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "cancel==>file and record were deleted!");
|
||||
}
|
||||
if (entry != null) {
|
||||
if (automatic) {
|
||||
entry.getMeta().put(DownloadDataHelper.DOWNLOAD_CANCEL_WAY, DownloadDataHelper.DOWNLOAD_CANCEL_AUTO);
|
||||
} else {
|
||||
entry.getMeta().put(DownloadDataHelper.DOWNLOAD_CANCEL_WAY, DownloadDataHelper.DOWNLOAD_CANCEL_MANUAL);
|
||||
}
|
||||
entry.setStatus(DownloadStatus.cancel);
|
||||
startDownloadService(entry, DownloadStatus.cancel);
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "cancel");
|
||||
@ -502,7 +556,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
*/
|
||||
public void cancelAll() {
|
||||
for (DownloadEntity entry : DataChanger.INSTANCE.getDownloadEntries().values()) {
|
||||
cancel(entry.getUrl(), true);
|
||||
cancel(entry.getUrl(), true, false);
|
||||
}
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "cancel all");
|
||||
}
|
||||
@ -567,9 +621,8 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
}
|
||||
}
|
||||
|
||||
// 开启下载服务
|
||||
startDownloadServiceInBackground();
|
||||
DownloadNotification.showDownloadingNotification(mContext);
|
||||
// 开启下载服务, Fuck me, 即便是在启动页调用的方法,依然有可能触发 `unable is in background`
|
||||
startDownloadService();
|
||||
}
|
||||
|
||||
public void addObserver(DataWatcher dataWatcher) {
|
||||
@ -582,11 +635,30 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
DataChanger.INSTANCE.deleteObserver(dataWatcher);
|
||||
}
|
||||
|
||||
public void startDownloadServiceInBackground() {
|
||||
mContext.startService(new Intent(mContext, DownloadService.class));
|
||||
private void startDownloadService() {
|
||||
Intent serviceIntent = new Intent(mContext, DownloadService.class);
|
||||
// 当满足系统版本大于 8.0 、应用在后台运行时以前台服务开启
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||
&& !HaloApp.getInstance().isRunningForeground) {
|
||||
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
|
||||
mContext.startForegroundService(serviceIntent);
|
||||
} else {
|
||||
mContext.startService(serviceIntent);
|
||||
}
|
||||
}
|
||||
|
||||
public void startDownloadService(DownloadEntity downloadEntity, DownloadStatus status) {
|
||||
private void startDownloadService(DownloadEntity downloadEntity, DownloadStatus status) {
|
||||
// 在启动服务时添加该条下载的网络状态
|
||||
if (status == DownloadStatus.add || status == DownloadStatus.resume) {
|
||||
String network = DeviceUtils.getNetwork(mContext);
|
||||
DownloadEntity daoEntity = mDownloadDao.get(downloadEntity.getUrl());
|
||||
if (daoEntity != null) {
|
||||
daoEntity.getMeta().put(DownloadEntity.NETWORK_STATUS_KEY, network);
|
||||
mDownloadDao.newOrUpdate(daoEntity);
|
||||
}
|
||||
downloadEntity.getMeta().put(DownloadEntity.NETWORK_STATUS_KEY, network);
|
||||
}
|
||||
|
||||
Intent serviceIntent = getIntent(downloadEntity, status);
|
||||
// 当满足系统版本大于 8.0 、应用在后台运行时以前台服务开启
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||
@ -598,6 +670,14 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
}
|
||||
}
|
||||
|
||||
public void disableDownloadSpeedLimit() {
|
||||
// DownloadSpeedController.disableSpeedLimit();
|
||||
}
|
||||
|
||||
public void updateSpeedLimitationReleaseDelay(int delay) {
|
||||
// DownloadSpeedController.updateLimitationReleaseDelay(delay);
|
||||
}
|
||||
|
||||
public void checkRetryDownload() {
|
||||
if (!NetworkUtils.isWifiConnected(mContext)) return;
|
||||
|
||||
@ -607,7 +687,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
DownloadStatus.subscribe.equals(downloadEntity.getStatus())) {
|
||||
DownloadManager.getInstance(mContext).put(downloadEntity.getUrl(), System.currentTimeMillis());
|
||||
Message msg = Message.obtain();
|
||||
msg.what = DownloadConfig.CONTINUE_DOWNLOAD_TASK;
|
||||
msg.what = DownloadConfig.CONTINUE_DOWNLOAD_AUTO_TASK;
|
||||
msg.obj = downloadEntity.getUrl();
|
||||
DownloadManager.getInstance(mContext).sendMessageDelayed(msg, 1000);
|
||||
}
|
||||
@ -615,19 +695,104 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
}
|
||||
}
|
||||
|
||||
public int getDownloadOrUpdateCount(List<GameUpdateEntity> updateList) {
|
||||
int downloadSize = getAll().size();
|
||||
if (downloadSize != 0) {
|
||||
return downloadSize;
|
||||
}
|
||||
/**
|
||||
* @param updateList 更新/插件化数据
|
||||
* @return null: 不显示小红点
|
||||
*/
|
||||
@Nullable
|
||||
public String getDownloadOrUpdateCount(List<GameUpdateEntity> updateList) {
|
||||
boolean showRedPoint = false;
|
||||
int downloadingSize = 0;
|
||||
|
||||
int updateSize = 0;
|
||||
if (updateList != null) {
|
||||
for (GameUpdateEntity updateEntity : updateList) {
|
||||
if (updateEntity.isShowPlugin(PluginLocation.only_index)) updateSize++;
|
||||
for (DownloadEntity downloadEntity : getAll()) {
|
||||
if (DownloadStatus.done.equals(downloadEntity.getStatus())) {
|
||||
String mark = downloadEntity.getMeta().get(HINT_MARK);
|
||||
if (TextUtils.isEmpty(mark)) showRedPoint = true;
|
||||
} else {
|
||||
downloadingSize++;
|
||||
}
|
||||
}
|
||||
return updateSize;
|
||||
|
||||
if (downloadingSize != 0) return String.valueOf(downloadingSize);
|
||||
|
||||
if (showRedPoint) return "";
|
||||
|
||||
if (updateList != null) {
|
||||
for (GameUpdateEntity updateEntity : updateList) {
|
||||
if (updateEntity.isShowPlugin(PluginLocation.only_index)
|
||||
&& !mUpdateMarks.contains(updateEntity.getId() + updateEntity.getPackageName())) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记下载已完成的任务为已读 (用于下载管理页入口的 toolbar 红点显示)
|
||||
*/
|
||||
public void markDownloadedTaskAsRead() {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
boolean markHasChanged = false;
|
||||
|
||||
List<DownloadEntity> all = getAll();
|
||||
for (DownloadEntity downloadEntity : all) {
|
||||
DownloadStatus status = downloadEntity.getStatus();
|
||||
if (status == DownloadStatus.done) {
|
||||
String mark = downloadEntity.getMeta().get(HINT_MARK);
|
||||
if (TextUtils.isEmpty(mark)) {
|
||||
downloadEntity.getMeta().put(HINT_MARK, HINT_MARK);
|
||||
mDownloadDao.newOrUpdate(downloadEntity);
|
||||
if (!markHasChanged) markHasChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (markHasChanged) {
|
||||
EventBus.getDefault().post(new EBDownloadStatus("download", "", "", "", "", ""));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记可用更新为已读 (用于下载管理页入口的 toolbar 红点显示)
|
||||
*/
|
||||
public void markUpdatableTaskAsRead() {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
boolean markHasChanged = false;
|
||||
|
||||
ArrayList<GameUpdateEntity> updates = PackageRepository.INSTANCE.getGameUpdate();
|
||||
for (GameUpdateEntity update : updates) {
|
||||
String mark = update.getId() + update.getPackageName();
|
||||
if (!mUpdateMarks.contains(mark)) {
|
||||
mUpdateMarks.add(mark);
|
||||
if (!markHasChanged) markHasChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (markHasChanged) {
|
||||
saveUpdateMarkToStorage();
|
||||
EventBus.getDefault().post(new EBDownloadStatus("download", "", "", "", "", ""));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将可用更新标记为已读的事件
|
||||
*/
|
||||
public void saveUpdateMarkToStorage() {
|
||||
ArrayList<GameUpdateEntity> updates = PackageRepository.INSTANCE.getGameUpdate();
|
||||
if (updates.size() == mUpdateMarks.size()) {
|
||||
SPUtils.setStringSet(HINT_MARK, mUpdateMarks);
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> marks = new HashSet<>();
|
||||
for (GameUpdateEntity update : updates) {
|
||||
String mark = update.getId() + update.getPackageName();
|
||||
marks.add(mark);
|
||||
}
|
||||
SPUtils.setStringSet(HINT_MARK, marks);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,146 +0,0 @@
|
||||
package com.gh.download;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.gh.common.util.AppDebugConfig;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 26/06/2017
|
||||
* @Time 6:01 PM
|
||||
*/
|
||||
|
||||
public class DownloadNotification {
|
||||
|
||||
public static final String ACTION_INSTALL = "com.gh.gamecenter.INSTALL";
|
||||
public static final String ACTION_DOWNLOAD = "com.gh.gamecenter.DOWNLOAD";
|
||||
public static final int ICON = R.mipmap.logo;
|
||||
public static final int NOTIFY_ID = 0x123;
|
||||
public static final int WAIT_NOTIFY_ID = 0x124;
|
||||
private static final String CHANNEL_ID = "Halo_Download";
|
||||
|
||||
private static NotificationManager getNotificationManager(Context context) {
|
||||
return (NotificationManager) context.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
|
||||
//TODO 下载重构
|
||||
public static void showDownloadDoneNotification(Context context, DownloadEntity downloadEntity) {
|
||||
final NotificationManager manager = getNotificationManager(context);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
|
||||
manager.createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(EntranceUtils.KEY_PATH, downloadEntity.getPath());
|
||||
intent.setAction(ACTION_INSTALL);
|
||||
final int requestCode = downloadEntity.getPackageName().hashCode();
|
||||
final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
String text;
|
||||
String title;
|
||||
if (downloadEntity.isPluggable()) {
|
||||
title = "下载完成,点击继续插件化";
|
||||
text = downloadEntity.getName() + " - "
|
||||
+ PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
|
||||
} else {
|
||||
if (downloadEntity.isPlugin()) {
|
||||
text = downloadEntity.getName()
|
||||
+ " - " + PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
|
||||
} else {
|
||||
text = downloadEntity.getName();
|
||||
}
|
||||
title = "下载完成,点击立即安装";
|
||||
}
|
||||
|
||||
final Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setSmallIcon(R.mipmap.logo)
|
||||
.setTicker(title)
|
||||
.setContentTitle(text)
|
||||
.setContentText(title)
|
||||
.setContentIntent(pendingIntent).build();
|
||||
// notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音
|
||||
notification.flags |= Notification.FLAG_AUTO_CANCEL; // // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。
|
||||
manager.notify(requestCode, notification);
|
||||
}
|
||||
|
||||
public static void showDownloadingNotification(Context context) {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(DownloadNotification.class, context);
|
||||
}
|
||||
int downloadingSize = 0;
|
||||
final List<DownloadEntity> list = DownloadManager.getInstance(context).getAll();
|
||||
if (list == null) return;
|
||||
for (DownloadEntity entity : list) {
|
||||
if (entity.getStatus().equals(DownloadStatus.downloading)
|
||||
|| entity.getStatus().equals(DownloadStatus.waiting)
|
||||
|| entity.getStatus().equals(DownloadStatus.pause)
|
||||
|| entity.getStatus().equals(DownloadStatus.timeout)
|
||||
|| entity.getStatus().equals(DownloadStatus.neterror)) {
|
||||
downloadingSize++;
|
||||
}
|
||||
}
|
||||
NotificationManager nManager = getNotificationManager(context);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
|
||||
nManager.createNotificationChannel(channel);
|
||||
}
|
||||
if (downloadingSize == 0) {
|
||||
nManager.cancel(NOTIFY_ID);
|
||||
} else {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_DOWNLOAD);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, NOTIFY_ID,
|
||||
intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setSmallIcon(ICON)
|
||||
.setTicker("点击查看")
|
||||
.setContentTitle("正在下载" + downloadingSize + "个游戏")
|
||||
.setContentText("点击查看")
|
||||
.setContentIntent(pendingIntent).build();
|
||||
// notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音
|
||||
notification.flags |= Notification.FLAG_NO_CLEAR; // 通知无法手动清除
|
||||
nManager.notify(NOTIFY_ID, notification);
|
||||
}
|
||||
}
|
||||
|
||||
public static void showWaitingNotification(Context context) {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(DownloadNotification.class, context);
|
||||
}
|
||||
|
||||
NotificationManager nManager = getNotificationManager(context);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
|
||||
nManager.createNotificationChannel(channel);
|
||||
}
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_DOWNLOAD);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, NOTIFY_ID,
|
||||
intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setSmallIcon(ICON)
|
||||
.setTicker("连接WiFi后自动恢复下载")
|
||||
.setContentTitle("下载已暂停")
|
||||
.setContentText("连接WiFi后自动恢复下载")
|
||||
.setContentIntent(pendingIntent).build();
|
||||
notification.flags = Notification.FLAG_AUTO_CANCEL;
|
||||
if (nManager != null) nManager.notify(WAIT_NOTIFY_ID, notification);
|
||||
}
|
||||
|
||||
}
|
||||
41
app/src/main/java/com/gh/download/cache/CacheInfo.java
vendored
Normal file
41
app/src/main/java/com/gh/download/cache/CacheInfo.java
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
package com.gh.download.cache;
|
||||
|
||||
public class CacheInfo {
|
||||
public static final long TOTAL_ERROR = -1;//获取进度失败
|
||||
private String url;
|
||||
private long total;
|
||||
private long progress;
|
||||
private String fileName;
|
||||
|
||||
public CacheInfo(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public long getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(long total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public long getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public void setProgress(long progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
}
|
||||
236
app/src/main/java/com/gh/download/cache/CacheManager.java
vendored
Normal file
236
app/src/main/java/com/gh/download/cache/CacheManager.java
vendored
Normal file
@ -0,0 +1,236 @@
|
||||
package com.gh.download.cache;
|
||||
|
||||
import com.danikula.videocache.file.FileNameGenerator;
|
||||
import com.danikula.videocache.file.Md5FileNameGenerator;
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.shuyu.gsyvideoplayer.utils.StorageUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.ObservableEmitter;
|
||||
import io.reactivex.ObservableOnSubscribe;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class CacheManager {
|
||||
private static final AtomicReference<CacheManager> INSTANCE = new AtomicReference<>();
|
||||
private volatile HashMap<String, Call> downCalls;
|
||||
private OkHttpClient mClient;
|
||||
private File cacheDirectory = StorageUtils.getIndividualCacheDirectory(HaloApp.getInstance().getApplication());
|
||||
private FileNameGenerator generator = new Md5FileNameGenerator();
|
||||
private final String TEMP_POSTFIX = ".download";
|
||||
// private final int preLength = 5 * 1024 * 1024;//预加载大小
|
||||
|
||||
|
||||
public static CacheManager getInstance() {
|
||||
for (; ; ) {
|
||||
CacheManager current = INSTANCE.get();
|
||||
if (current != null) {
|
||||
return current;
|
||||
}
|
||||
current = new CacheManager();
|
||||
if (INSTANCE.compareAndSet(null, current)) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CacheManager() {
|
||||
downCalls = new HashMap<>();
|
||||
mClient = new OkHttpClient.Builder().build();
|
||||
}
|
||||
|
||||
private synchronized HashMap<String, Call> getDownCalls() {
|
||||
return downCalls;
|
||||
}
|
||||
|
||||
public void download(String url, CacheObserver cacheObserver) {
|
||||
//当前url已下载完成则不再下载
|
||||
for (File file : getAllFile()) {
|
||||
if (file.getName().equals(generator.generate(url))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Observable.just(url)
|
||||
.filter(s -> !getDownCalls().containsKey(s))//call的map已经有了,就证明正在下载,则这次不下载
|
||||
.flatMap(s -> Observable.just(createDownInfo(s)))
|
||||
.map(this::getRealFileName)
|
||||
.flatMap(cacheInfo -> Observable.create(new DownloadSubscribe(cacheInfo)))
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(cacheObserver);
|
||||
|
||||
}
|
||||
|
||||
public void cancel(String url) {
|
||||
Call call = getDownCalls().get(url);
|
||||
if (call != null) {
|
||||
call.cancel();
|
||||
}
|
||||
getDownCalls().remove(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建DownInfo
|
||||
*
|
||||
* @param url 请求网址
|
||||
* @return DownInfo
|
||||
*/
|
||||
private CacheInfo createDownInfo(String url) {
|
||||
CacheInfo cacheInfo = new CacheInfo(url);
|
||||
long contentLength = getContentLength(url);//获得文件大小
|
||||
cacheInfo.setTotal(contentLength);
|
||||
String fileName = generator.generate(url) + TEMP_POSTFIX;
|
||||
cacheInfo.setFileName(fileName);
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
private CacheInfo getRealFileName(CacheInfo cacheInfo) {
|
||||
String fileName = cacheInfo.getFileName();
|
||||
long downloadLength = 0;
|
||||
if (!cacheDirectory.exists()) {
|
||||
cacheDirectory.mkdir();
|
||||
}
|
||||
File file = new File(cacheDirectory, fileName);
|
||||
if (file.exists()) {
|
||||
//找到了文件,代表已经下载过,则获取其长度
|
||||
downloadLength = file.length();
|
||||
}
|
||||
//设置改变过的文件名/大小
|
||||
cacheInfo.setProgress(downloadLength);
|
||||
cacheInfo.setFileName(file.getName());
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
|
||||
private class DownloadSubscribe implements ObservableOnSubscribe<CacheInfo> {
|
||||
private CacheInfo cacheInfo;
|
||||
|
||||
public DownloadSubscribe(CacheInfo cacheInfo) {
|
||||
this.cacheInfo = cacheInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(ObservableEmitter<CacheInfo> e) throws Exception {
|
||||
String url = cacheInfo.getUrl();
|
||||
final long[] downloadLength = {cacheInfo.getProgress()};//已经下载好的长度
|
||||
long contentLength = cacheInfo.getTotal();//文件的总长度
|
||||
// if (downloadLength[0] >= preLength) {
|
||||
if (downloadLength[0] >= contentLength) {
|
||||
e.onComplete();
|
||||
return;
|
||||
}
|
||||
e.onNext(cacheInfo);
|
||||
Request request = new Request.Builder()
|
||||
// .addHeader("RANGE", "bytes=" + downloadLength[0] + "-" + (contentLength > preLength ? preLength : contentLength))
|
||||
.addHeader("RANGE", "bytes=" + downloadLength[0] + "-" + contentLength)
|
||||
.url(url)
|
||||
.build();
|
||||
Call call = mClient.newCall(request);
|
||||
getDownCalls().put(url, call);
|
||||
call.enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
File file = new File(cacheDirectory, cacheInfo.getFileName());
|
||||
InputStream is = null;
|
||||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
is = response.body().byteStream();
|
||||
fileOutputStream = new FileOutputStream(file, true);
|
||||
byte[] buffer = new byte[2048];
|
||||
int len;
|
||||
while (downCalls.get(url) != null && !call.isCanceled() && (len = is.read(buffer)) != -1) {
|
||||
fileOutputStream.write(buffer, 0, len);
|
||||
downloadLength[0] += len;
|
||||
cacheInfo.setProgress(downloadLength[0]);
|
||||
e.onNext(cacheInfo);
|
||||
}
|
||||
fileOutputStream.flush();
|
||||
getDownCalls().remove(url);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
if (fileOutputStream != null) {
|
||||
fileOutputStream.close();
|
||||
}
|
||||
}
|
||||
if (file.length() == contentLength) {
|
||||
file.renameTo(new File(file.getPath().substring(0, file.getPath().lastIndexOf(TEMP_POSTFIX))));
|
||||
}
|
||||
e.onComplete();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载长度
|
||||
*
|
||||
* @param downloadUrl
|
||||
* @return
|
||||
*/
|
||||
public long getContentLength(String downloadUrl) {
|
||||
long contentLength = CacheInfo.TOTAL_ERROR;
|
||||
Request request = new Request.Builder()
|
||||
.url(downloadUrl)
|
||||
.build();
|
||||
Response response = null;
|
||||
try {
|
||||
response = mClient.newCall(request).execute();
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
long length = response.body().contentLength();
|
||||
contentLength = length == 0 ? CacheInfo.TOTAL_ERROR : length;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
public void removeAllCall() {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
for (Map.Entry<String, Call> entry : getDownCalls().entrySet()) {
|
||||
entry.getValue().cancel();
|
||||
}
|
||||
AppExecutor.getUiExecutor().execute(() -> getDownCalls().clear());
|
||||
});
|
||||
}
|
||||
|
||||
private List<File> getAllFile() {
|
||||
if (cacheDirectory.exists()) {
|
||||
File[] files = cacheDirectory.listFiles();
|
||||
return Arrays.asList(files);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
||||
35
app/src/main/java/com/gh/download/cache/CacheObserver.java
vendored
Normal file
35
app/src/main/java/com/gh/download/cache/CacheObserver.java
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package com.gh.download.cache;
|
||||
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
|
||||
public abstract class CacheObserver implements Observer<CacheInfo> {
|
||||
protected Disposable d;//可以用于取消注册的监听者
|
||||
protected CacheInfo cacheInfo;
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(CacheInfo cacheInfo) {
|
||||
this.cacheInfo = cacheInfo;
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log(cacheInfo.getProgress() + "-" + cacheInfo.getTotal());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.game.GameFragment
|
||||
|
||||
@ -20,6 +21,8 @@ class BlockActivity : NormalActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
|
||||
DownloadManager.getInstance(this).updateSpeedLimitationReleaseDelay(10)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
|
||||
@ -2,74 +2,40 @@ package com.gh.gamecenter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.gh.base.ToolBarActivity;
|
||||
import com.gh.base.fragment.WaitingDialogFragment;
|
||||
import com.gh.common.util.BitmapUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.UploadImageUtils;
|
||||
import com.gh.common.view.CropImageCustom;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.ObservableOnSubscribe;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import retrofit2.HttpException;
|
||||
|
||||
public class CropImageActivity extends ToolBarActivity {
|
||||
|
||||
@BindView(R.id.cropimage_custom)
|
||||
CropImageCustom mCropimageCustom;
|
||||
public CropImageCustom mCropImageCustom;
|
||||
|
||||
public static final String RESULT_CLIP_PATH = "result_clip_path";
|
||||
|
||||
private SoftReference<Bitmap> reference;
|
||||
|
||||
private SharedPreferences sp;
|
||||
|
||||
@Override
|
||||
protected void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case 0:
|
||||
toast("上传成功");
|
||||
break;
|
||||
case 1:
|
||||
toast("上传失败");
|
||||
break;
|
||||
case 2:
|
||||
toast("修改太频繁,请稍后再试");
|
||||
break;
|
||||
case 3:
|
||||
toast("图片违规");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getIntent(Context context, String picturePath, String entrance) {
|
||||
public static Intent getIntent(Context context, String picturePath, float cropRatio, String entrance) {
|
||||
Intent intent = new Intent(context, CropImageActivity.class);
|
||||
intent.putExtra(EntranceUtils.KEY_PATH, picturePath);
|
||||
intent.putExtra(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
intent.putExtra(EntranceUtils.KEY_IMAGE_CROP_RATIO, cropRatio);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@ -84,108 +50,28 @@ public class CropImageActivity extends ToolBarActivity {
|
||||
setNavigationTitle(getString(R.string.title_crop_image));
|
||||
setToolbarMenu(R.menu.menu_positive);
|
||||
|
||||
sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
float ratio = getIntent().getFloatExtra(EntranceUtils.KEY_IMAGE_CROP_RATIO, 1F);
|
||||
mCropImageCustom.setCropRatio(ratio);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.layout_menu_positive) {
|
||||
final WaitingDialogFragment postDialog = WaitingDialogFragment.newInstance(getString(R.string.post_img));
|
||||
postDialog.show(getSupportFragmentManager(), null);
|
||||
final String path = getCacheDir() + File.separator + System.currentTimeMillis() + ".jpg";
|
||||
Observable.create((ObservableOnSubscribe<String>) emitter -> {
|
||||
boolean isSuccess = mCropimageCustom.savePicture(path);
|
||||
if (isSuccess) {
|
||||
UploadImageUtils.INSTANCE.uploadImage(UploadImageUtils.UploadType.icon, path, new UploadImageUtils.OnUploadImageListener() {
|
||||
@Override
|
||||
public void onSuccess(@NotNull String imageUrl) {
|
||||
emitter.onNext(imageUrl);
|
||||
emitter.onComplete();
|
||||
}
|
||||
Intent data = new Intent();
|
||||
Bitmap clip = mCropImageCustom.clip();
|
||||
String clipPath = getCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".jpg";
|
||||
try {
|
||||
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(clipPath)));
|
||||
clip.compress(Bitmap.CompressFormat.WEBP, 100, bos);
|
||||
bos.flush();
|
||||
bos.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@Nullable Throwable e) {
|
||||
if (e != null) {
|
||||
emitter.onError(e);
|
||||
} else {
|
||||
emitter.onError(new IllegalStateException("upload image error"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(long total, long progress) {
|
||||
int percent = (int) (100 * (progress / (float) total));
|
||||
if (percent >= 100) percent = 99;
|
||||
if (postDialog != null) {
|
||||
postDialog.uploadWaitingHint("图片上传中 " + percent + "%");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}).subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new Response<String>() {
|
||||
@Override
|
||||
public void onResponse(String url) {
|
||||
try {
|
||||
if (postDialog != null) postDialog.dismissAllowingStateLoss();
|
||||
mBaseHandler.sendEmptyMessage(0);
|
||||
|
||||
String iconCount = sp.getString("updateIconCount", null);
|
||||
|
||||
long l = System.currentTimeMillis();
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.CHINA);
|
||||
String time = format.format(new Date(l));
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("time", time);
|
||||
|
||||
if (TextUtils.isEmpty(iconCount)) {
|
||||
jsonObject.put("count", 1);
|
||||
} else {
|
||||
JSONObject json = new JSONObject(iconCount);
|
||||
String lastTime = json.getString("time");
|
||||
if (lastTime.equals(time)) {
|
||||
jsonObject.put("count", json.getInt("count") + 1);
|
||||
} else {
|
||||
jsonObject.put("count", 1);
|
||||
}
|
||||
}
|
||||
|
||||
sp.edit().putString("updateIconCount", jsonObject.toString()).apply();
|
||||
|
||||
Intent data = new Intent();
|
||||
data.putExtra(EntranceUtils.KEY_URL, url);
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(HttpException e) {
|
||||
if (postDialog != null) postDialog.dismissAllowingStateLoss();
|
||||
try {
|
||||
if (e != null && e.code() == HttpURLConnection.HTTP_FORBIDDEN && e.response().errorBody() != null) {
|
||||
JSONObject object = new JSONObject(e.response().errorBody().string());
|
||||
String detail = object.getString("detail");
|
||||
if ("too frequent".equals(detail)) {
|
||||
mBaseHandler.sendEmptyMessage(2);
|
||||
} else if ("INVALID PICTURE".equals(detail)) {
|
||||
mBaseHandler.sendEmptyMessage(3);
|
||||
} else {
|
||||
mBaseHandler.sendEmptyMessage(1);
|
||||
}
|
||||
} else {
|
||||
mBaseHandler.sendEmptyMessage(1);
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
mBaseHandler.sendEmptyMessage(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
data.putExtra(RESULT_CLIP_PATH, clipPath);
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
}
|
||||
return super.onMenuItemClick(item);
|
||||
}
|
||||
@ -202,7 +88,7 @@ public class CropImageActivity extends ToolBarActivity {
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if (hasFocus && (reference == null || reference.get() == null)) {
|
||||
ImageView imageView = mCropimageCustom.getCropImageZoomView();
|
||||
ImageView imageView = mCropImageCustom.getCropImageZoomView();
|
||||
Bitmap bitmap = BitmapUtils.getBitmapByFile(getIntent().getStringExtra(EntranceUtils.KEY_PATH),
|
||||
imageView.getWidth(), imageView.getHeight());
|
||||
if (bitmap != null) {
|
||||
|
||||
@ -6,6 +6,7 @@ import android.os.Bundle;
|
||||
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.download.DownloadFragment;
|
||||
|
||||
/**
|
||||
@ -48,4 +49,11 @@ public class DownloadManagerActivity extends NormalActivity {
|
||||
bundle.putString(EntranceUtils.KEY_PACKAGENAME, packageName);
|
||||
return getTargetIntent(context, DownloadManagerActivity.class, DownloadFragment.class, bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
DownloadManager.getInstance(this).disableDownloadSpeedLimit();
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,7 @@ import com.gh.common.exposure.ExposureType;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment;
|
||||
import com.halo.assistant.HaloApp;
|
||||
@ -19,28 +20,30 @@ import com.halo.assistant.HaloApp;
|
||||
import static com.gh.common.constant.Constants.GAME_DETAIL_COME_IN;
|
||||
|
||||
/**
|
||||
* TODO 合并构建 intent 的重复代码
|
||||
* Created by khy on 2017/3/24.
|
||||
* 游戏详情适配器
|
||||
*/
|
||||
public class GameDetailActivity extends NormalActivity {
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
|
||||
DownloadManager.getInstance(this).updateSpeedLimitationReleaseDelay(10);
|
||||
DisplayUtils.transparentStatusBar(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Intent provideNormalIntent() {
|
||||
return getTargetIntent(this, GameDetailActivity.class, GameDetailFragment.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_game_detail;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 启动游戏详情页面
|
||||
*/
|
||||
@ -66,51 +69,88 @@ public class GameDetailActivity extends NormalActivity {
|
||||
* 启动游戏详情页面 with 曝光事件
|
||||
*/
|
||||
public static void startGameDetailActivity(Context context, GameEntity gameEntity, String entrance, ExposureEvent traceEvent) {
|
||||
startGameDetailActivity(context, gameEntity, entrance, -1, traceEvent);
|
||||
}
|
||||
|
||||
public static void startGameDetailActivity(Context context, GameEntity gameEntity, String entrance, int defaultTab, ExposureEvent traceEvent) {
|
||||
DataUtils.onMtaEvent(context, "详情页面", "游戏详情", gameEntity != null ? gameEntity.getName() : "");
|
||||
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
// TODO TraceEvent 为空时不该调用此方法才对
|
||||
if (BuildConfig.DEBUG) {
|
||||
if (traceEvent == null) {
|
||||
throw new IllegalArgumentException("没有曝光的 TraceEvent 不要调用这个方法");
|
||||
}
|
||||
}
|
||||
|
||||
if (traceEvent != null) {
|
||||
ExposureEvent clickEvent = ExposureEvent.Companion.createEvent(gameEntity, traceEvent.getSource(), ExposureTraceUtils.INSTANCE
|
||||
.appendTrace(traceEvent), ExposureType.CLICK);
|
||||
ExposureManager.INSTANCE.log(clickEvent);
|
||||
bundle.putParcelable(EntranceUtils.KEY_TRACE_EVENT, clickEvent);
|
||||
}
|
||||
|
||||
if (gameEntity != null
|
||||
&& traceEvent != null
|
||||
&& gameEntity.getId() != null
|
||||
&& !gameEntity.getId().equals(traceEvent.getPayload().getGameId())) {
|
||||
&& traceEvent != null
|
||||
&& gameEntity.getId() != null
|
||||
&& !gameEntity.getId().equals(traceEvent.getPayload().getGameId())) {
|
||||
// 当游戏 ID 跟曝光 traceEvent 的游戏ID 不一样的时候更新 traceEvent 的游戏ID
|
||||
ExposureEvent forNewPayload = ExposureEvent.Companion.createEvent(gameEntity,
|
||||
traceEvent.getSource(),
|
||||
ExposureTraceUtils.INSTANCE.appendTrace(traceEvent),
|
||||
ExposureType.EXPOSURE);
|
||||
traceEvent.getSource(),
|
||||
ExposureTraceUtils.INSTANCE.appendTrace(traceEvent),
|
||||
ExposureType.EXPOSURE);
|
||||
traceEvent.setPayload(forNewPayload.getPayload());
|
||||
}
|
||||
|
||||
ExposureEvent clickEvent = ExposureEvent.Companion.createEvent(gameEntity, traceEvent.getSource(), ExposureTraceUtils.INSTANCE.appendTrace(traceEvent), ExposureType.CLICK);
|
||||
ExposureManager.INSTANCE.log(clickEvent);
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
if (defaultTab != -1) {
|
||||
bundle.putInt(EntranceUtils.KEY_TARGET, defaultTab);
|
||||
}
|
||||
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
bundle.putParcelable(GameEntity.TAG, gameEntity);
|
||||
bundle.putParcelable(EntranceUtils.KEY_TRACE_EVENT, clickEvent);
|
||||
context.startActivity(getTargetIntent(context, GameDetailActivity.class, GameDetailFragment.class, bundle));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 启动游戏详情页面 with 曝光事件
|
||||
*/
|
||||
public static void startGameDetailActivity(Context context, String gameId, String entrance, ExposureEvent traceEvent) {
|
||||
|
||||
startGameDetailActivity(context, gameId, entrance, -1, traceEvent);
|
||||
}
|
||||
|
||||
public static void startGameDetailActivity(Context context, String gameId, String entrance, int defaultTab, ExposureEvent traceEvent) {
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
// TODO TraceEvent 为空时不该调用此方法才对
|
||||
if (BuildConfig.DEBUG) {
|
||||
if (traceEvent == null) {
|
||||
throw new IllegalArgumentException("没有曝光的 TraceEvent 不要调用这个方法");
|
||||
}
|
||||
}
|
||||
|
||||
if (traceEvent != null) {
|
||||
ExposureEvent clickEvent = ExposureEvent.Companion.createEvent(new GameEntity(gameId), traceEvent.getSource(), ExposureTraceUtils.INSTANCE.appendTrace(traceEvent), ExposureType.CLICK);
|
||||
ExposureManager.INSTANCE.log(clickEvent);
|
||||
bundle.putParcelable(EntranceUtils.KEY_TRACE_EVENT, clickEvent);
|
||||
}
|
||||
|
||||
if (traceEvent != null
|
||||
&& !gameId.equals(traceEvent.getPayload().getGameId())) {
|
||||
&& !gameId.equals(traceEvent.getPayload().getGameId())) {
|
||||
// 当游戏 ID 跟曝光 traceEvent 的游戏ID 不一样的时候更新 traceEvent 的游戏ID
|
||||
ExposureEvent forNewPayload = ExposureEvent.Companion.createEvent(new GameEntity(gameId),
|
||||
traceEvent.getSource(),
|
||||
ExposureTraceUtils.INSTANCE.appendTrace(traceEvent),
|
||||
ExposureType.EXPOSURE);
|
||||
traceEvent.getSource(),
|
||||
ExposureTraceUtils.INSTANCE.appendTrace(traceEvent),
|
||||
ExposureType.EXPOSURE);
|
||||
traceEvent.setPayload(forNewPayload.getPayload());
|
||||
}
|
||||
|
||||
ExposureEvent clickEvent = ExposureEvent.Companion.createEvent(new GameEntity(gameId), traceEvent.getSource(), ExposureTraceUtils.INSTANCE.appendTrace(traceEvent), ExposureType.CLICK);
|
||||
ExposureManager.INSTANCE.log(clickEvent);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
if (defaultTab != -1) {
|
||||
bundle.putInt(EntranceUtils.KEY_TARGET, defaultTab);
|
||||
}
|
||||
|
||||
bundle.putString(EntranceUtils.KEY_GAMEID, gameId);
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
bundle.putParcelable(EntranceUtils.KEY_TRACE_EVENT, clickEvent);
|
||||
context.startActivity(getTargetIntent(context, GameDetailActivity.class, GameDetailFragment.class, bundle));
|
||||
}
|
||||
|
||||
@ -147,6 +187,18 @@ public class GameDetailActivity extends NormalActivity {
|
||||
context.startActivity(getTargetIntent(context, GameDetailActivity.class, GameDetailFragment.class, bundle));
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动游戏详情页面并定位到 介绍tab,并打开视频流
|
||||
*/
|
||||
public static void startGameDetailToVideoStreaming(Context context, String gameId, String entrance) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_GAMEID, gameId);
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
bundle.putBoolean(EntranceUtils.KEY_OPEN_VIDEO_STREAMING, true);
|
||||
bundle.putInt(EntranceUtils.KEY_TARGET, GameDetailFragment.INDEX_DESC);
|
||||
context.startActivity(getTargetIntent(context, GameDetailActivity.class, GameDetailFragment.class, bundle));
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果存在多个游戏平台则打开
|
||||
*/
|
||||
@ -173,7 +225,7 @@ public class GameDetailActivity extends NormalActivity {
|
||||
super.onDestroy();
|
||||
HaloApp.remove(GAME_DETAIL_COME_IN);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getActivityNameInChinese() {
|
||||
return "游戏详情";
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
package com.gh.gamecenter
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.gh.base.BaseActivity_TabLayout
|
||||
import com.gh.gamecenter.help.HelpContainerFragment
|
||||
import com.gh.gamecenter.suggest.SuggestSelectFragment
|
||||
import com.lightgame.utils.Util_System_Keyboard
|
||||
|
||||
class HelpAndFeedbackActivity : BaseActivity_TabLayout() {
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.activity_help_and_feedback
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == SuggestSelectFragment.SUGGEST_TYPE_REQUEST
|
||||
&& resultCode == SuggestSelectFragment.SUGGEST_TYPE_REQUEST) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun initFragmentList(fragments: MutableList<Fragment>) {
|
||||
fragments.add(HelpContainerFragment())
|
||||
fragments.add(SuggestSelectFragment())
|
||||
}
|
||||
|
||||
override fun initTabTitleList(tabTitleList: MutableList<String>) {
|
||||
tabTitleList.add("使用帮助")
|
||||
tabTitleList.add("意见反馈")
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setNavigationTitle("帮助与反馈")
|
||||
mTabIndicatorView.setIndicatorWidth(88)
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
super.onPageSelected(position)
|
||||
if (position == SUGGESTION_ITEM) {
|
||||
Util_System_Keyboard.hideSoftKeyboard(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurrentItem(position: Int) {
|
||||
mViewPager.currentItem = position
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val HELP_ITEM = 0
|
||||
const val SUGGESTION_ITEM = 1
|
||||
|
||||
@JvmStatic
|
||||
fun getIntent(context: Context): Intent {
|
||||
return Intent(context, HelpAndFeedbackActivity::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,9 @@ package com.gh.gamecenter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
@ -14,10 +16,23 @@ import com.gh.gamecenter.fragment.LoginFragment;
|
||||
|
||||
public class LoginActivity extends NormalActivity {
|
||||
|
||||
@Override
|
||||
protected Intent provideNormalIntent() {
|
||||
return getTargetIntent(this, LoginActivity.class, LoginFragment.class);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getIntent(Context context, String entrance) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
return getTargetIntent(context, LoginActivity.class, LoginFragment.class, bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mTitleTv.setText("登录光环助手");
|
||||
mTitleTv.setTextSize(18);
|
||||
mTitleTv.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,8 +48,8 @@ import com.gh.common.util.DeviceTokenUtils;
|
||||
import com.gh.common.util.DeviceUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.DownloadNotificationHelper;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.LunchType;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
@ -59,17 +59,19 @@ import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.PushHelper;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.common.util.StringUtils;
|
||||
import com.gh.common.util.ThirdPartyPackageHelper;
|
||||
import com.gh.common.util.UrlFilterUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.DownloadNotification;
|
||||
import com.gh.gamecenter.download.DownloadFragment;
|
||||
import com.gh.gamecenter.entity.CommunityEntity;
|
||||
import com.gh.gamecenter.entity.GameDigestEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.InnerMetaInfoEntity;
|
||||
import com.gh.gamecenter.entity.NotificationHint;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.entity.NotificationUgc;
|
||||
import com.gh.gamecenter.entity.SimpleGameEntity;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.eventbus.EBNetworkState;
|
||||
import com.gh.gamecenter.eventbus.EBPackage;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
@ -87,10 +89,12 @@ import com.gh.gamecenter.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.retrofit.EmptyResponse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.gamecenter.suggest.SuggestSelectFragment;
|
||||
import com.gh.gamecenter.suggest.SuggestType;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.halo.assistant.fragment.SettingsFragment;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.download.DataWatcher;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
@ -98,15 +102,18 @@ import com.lightgame.download.DownloadStatus;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.AppManager;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.shuyu.gsyvideoplayer.utils.StorageUtils;
|
||||
import com.tencent.bugly.beta.tinker.TinkerManager;
|
||||
import com.tencent.bugly.crashreport.CrashReport;
|
||||
|
||||
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.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@ -119,6 +126,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
@ -128,7 +136,13 @@ import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.ENTRANCE_BROWSER;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_QQ;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_QQ_GROUP;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_WEB;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_DATA;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_TO;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_TYPE;
|
||||
import static com.gh.gamecenter.fragment.MainWrapperFragment.INDEX_PERSONAL;
|
||||
import static com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG;
|
||||
import static com.gh.gamecenter.personal.PersonalFragment.LOGOUT_TAG;
|
||||
@ -138,6 +152,7 @@ public class MainActivity extends BaseActivity {
|
||||
public final static String EB_SKIP_MAIN = "MainActivity";
|
||||
public final static String SHOULD_INIT_IM = "should_init_im";
|
||||
public final static String SWITCH_TO_COMMUNITY = "switch_to_community";
|
||||
public final static String SWITCH_TO_VIDEO = "switch_to_video";
|
||||
|
||||
private final static String IS_SKIPPED = "is_skipped";
|
||||
|
||||
@ -151,12 +166,19 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
private boolean isSkipped = false;
|
||||
public static boolean isNewFirstLaunch;
|
||||
public String uuid = UUID.randomUUID().toString();
|
||||
|
||||
private Handler handler = new Handler();
|
||||
|
||||
// todo 全局监听可能不应该放这里, MainActivity 销毁后此处无法工作
|
||||
// 黄壮华 添加观察者 修改2015/8/15
|
||||
private DataWatcher dataWatcher = new DataWatcher() {
|
||||
@Override
|
||||
public void onDataChanged(DownloadEntity downloadEntity) {
|
||||
if (downloadEntity.getStatus() != DownloadStatus.downloading) {
|
||||
LogUtils.uploadDownloadEvent(downloadEntity);
|
||||
}
|
||||
|
||||
if (DownloadStatus.hijack.equals(downloadEntity.getStatus())) {
|
||||
// 链接被劫持
|
||||
processHijack(downloadEntity);
|
||||
@ -171,16 +193,22 @@ public class MainActivity extends BaseActivity {
|
||||
DownloadManager.getInstance(getApplicationContext()).cancel(downloadEntity.getUrl());
|
||||
toast("该链接已失效!请联系管理员。");
|
||||
|
||||
EventBus.getDefault().post(new EBShowDialog(DOWNLOAD_NOT_FOUND, downloadEntity.getName()));
|
||||
MtaHelper.onEventWithBasicDeviceInfo("下载失败弹窗",
|
||||
"游戏", downloadEntity.getName(),
|
||||
"平台", downloadEntity.getPlatform());
|
||||
|
||||
DialogUtils.showAlertDialog(AppManager.getInstance().currentActivity()
|
||||
, "下载失败"
|
||||
, "下载链接已失效,建议提交反馈"
|
||||
, "立即反馈", "取消"
|
||||
, () -> SuggestionActivity.startSuggestionActivity(AppManager.getInstance().currentActivity(),
|
||||
SuggestType.gameQuestion, "notfound",
|
||||
StringUtils.buildString(downloadEntity.getName(), ",问题反馈:下载链接失效"),
|
||||
new SimpleGameEntity(downloadEntity.getGameId(), downloadEntity.getName(), "")), null);
|
||||
return;
|
||||
} else if (DownloadStatus.neterror.equals(downloadEntity.getStatus())
|
||||
|| DownloadStatus.timeout.equals(downloadEntity.getStatus())) {
|
||||
|
||||
DownloadNotification.showWaitingNotification(MainActivity.this); // 系统通知
|
||||
|
||||
toast("网络不稳定,下载任务已暂停");
|
||||
DataLogUtils.uploadNeterrorLog(MainActivity.this, downloadEntity);
|
||||
|
||||
@ -191,7 +219,7 @@ public class MainActivity extends BaseActivity {
|
||||
if (DownloadStatus.done.equals(downloadEntity.getStatus())) {
|
||||
if (downloadEntity.getName().contains(getString(R.string.app_name))) {
|
||||
DataUtils.onEvent(MainActivity.this, "软件更新", "下载完成");
|
||||
startActivity(PackageUtils.getInstallIntent(MainActivity.this, downloadEntity.getPath()));
|
||||
startActivity(PackageUtils.getInstallIntent(MainActivity.this, downloadEntity.getPath(), true));
|
||||
DataLogUtils.uploadUpgradeLog(MainActivity.this, "install"); //上传更新安装数据
|
||||
} else {
|
||||
statDoneEvent(downloadEntity);
|
||||
@ -212,12 +240,13 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
if (!downloadEntity.isPluggable()) {
|
||||
// 是否是自动安装
|
||||
if (mSp.getBoolean("autoinstall", true)) {
|
||||
if (mSp.getBoolean(SettingsFragment.AUTO_INSTALL_SP_KEY, true)) {
|
||||
if (FileUtils.isEmptyFile(downloadEntity.getPath())) {
|
||||
toast(R.string.install_failure_hint);
|
||||
DownloadManager.getInstance(MainActivity.this).cancel(downloadEntity.getUrl());
|
||||
} else {
|
||||
if (PackageUtils.isCanLaunchSetup(getApplicationContext(), downloadEntity.getPath())) {
|
||||
downloadEntity.getMeta().put(Constants.MARK_ALREADY_TRIGGERED_INSTALLATION, "YES");
|
||||
startActivity(PackageUtils.getInstallIntent(MainActivity.this, downloadEntity.getPath()));
|
||||
} else {
|
||||
// 弹出卸载提示框
|
||||
@ -244,13 +273,19 @@ public class MainActivity extends BaseActivity {
|
||||
"游戏", downloadEntity.getName() + ":" + PlatformUtils.getInstance(getApplicationContext()).getPlatformName(downloadEntity.getPlatform()));
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadEntity.getStatus() == DownloadStatus.done) {
|
||||
EventBus.getDefault().post(new EBDownloadStatus("done", "", "", "", "", ""));
|
||||
}
|
||||
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setStatusBarColor(Color.WHITE);
|
||||
setStatusBarColor(Color.TRANSPARENT);
|
||||
|
||||
mSp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
@ -328,6 +363,9 @@ public class MainActivity extends BaseActivity {
|
||||
if (getIntent().getBooleanExtra(SWITCH_TO_COMMUNITY, false)) {
|
||||
handler.postDelayed(this::switchToCommunityTabAndRefresh, 800);
|
||||
}
|
||||
if (getIntent().getBooleanExtra(SWITCH_TO_VIDEO, false)) {
|
||||
handler.postDelayed(() -> mMainWrapperFragment.setCurrentItem(2), 800);
|
||||
}
|
||||
|
||||
// 跳转至其它页面
|
||||
if (getIntent() != null && getIntent().getExtras() != null && !isSkipped) {
|
||||
@ -343,18 +381,42 @@ public class MainActivity extends BaseActivity {
|
||||
// 上传数据
|
||||
DataCollectionManager.getInstance(getApplicationContext()).upload();
|
||||
// 获取默认配置
|
||||
getGhzsSettings();
|
||||
Config.getGhzsSettings();
|
||||
// 检查助手更新
|
||||
UpdateManager.getInstance(this).checkUpdate(true, null);
|
||||
// 初始化PlatformUtils
|
||||
PlatformUtils.getInstance(getApplicationContext());
|
||||
});
|
||||
|
||||
|
||||
//启动app删除视频缓存文件
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
File cacheFileDirectory = StorageUtils.getIndividualCacheDirectory(this);
|
||||
if (cacheFileDirectory.exists() && cacheFileDirectory.isDirectory()) {
|
||||
for (File file : cacheFileDirectory.listFiles()) {
|
||||
FileUtils.deleteFile(file.getPath());
|
||||
}
|
||||
}
|
||||
//创建nomedia文件
|
||||
File noMediaFile = new File(cacheFileDirectory.getParent(), ".nomedia");
|
||||
|
||||
if (!cacheFileDirectory.exists()) {
|
||||
cacheFileDirectory.mkdirs();
|
||||
}
|
||||
try {
|
||||
if (!noMediaFile.exists()) {
|
||||
noMediaFile.createNewFile();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == 100 && resultCode == SuggestSelectActivity.SUGGEST_TYPE_REQUEST) {
|
||||
if (requestCode == 100 && resultCode == SuggestSelectFragment.SUGGEST_TYPE_REQUEST) {
|
||||
showKefuReportDialog();
|
||||
}
|
||||
}
|
||||
@ -365,7 +427,7 @@ public class MainActivity extends BaseActivity {
|
||||
DialogUtils.showWarningDialog(MainActivity.this, "反馈成功", Html.fromHtml(str.substring(0, str.indexOf("红包奖励")) + "<font color='#FF0000'>红包奖励</font>"), "暂不", "联系客服",
|
||||
() -> {
|
||||
if (ShareUtils.isQQClientAvailable(this)) {
|
||||
DirectUtils.directToQqConversation(this, "3467475980");
|
||||
DirectUtils.directToQqConversation(this, null);
|
||||
} else {
|
||||
toast("本机未安装QQ应用");
|
||||
}
|
||||
@ -375,7 +437,8 @@ public class MainActivity extends BaseActivity {
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
DownloadManager.getInstance(this).removeObserver(dataWatcher);
|
||||
// 退出后,同样需要更新通知栏进度
|
||||
// DownloadManager.getInstance(this).removeObserver(dataWatcher);
|
||||
|
||||
handler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
@ -413,6 +476,24 @@ public class MainActivity extends BaseActivity {
|
||||
skipIntent.putExtras(bundle);
|
||||
startActivity(skipIntent);
|
||||
}
|
||||
} else {
|
||||
// 使用光环进行二次跳转的页面会经过这里
|
||||
switch (to) {
|
||||
case HOST_QQ:
|
||||
DirectUtils.directToQqConversation(this, bundle.getString(KEY_DATA));
|
||||
break;
|
||||
case HOST_QQ_GROUP:
|
||||
DirectUtils.directToQqGroup(this, bundle.getString(KEY_DATA));
|
||||
break;
|
||||
case HOST_WEB:
|
||||
String url = bundle.getString(KEY_DATA) == null ? "" : bundle.getString(KEY_DATA);
|
||||
if ("internal".equals(bundle.getString(KEY_TYPE))) {
|
||||
DirectUtils.directToWebView(this, url, ENTRANCE_BROWSER);
|
||||
} else {
|
||||
DirectUtils.directToExternalBrowser(this, url);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -421,10 +502,13 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
private void checkNotificationPermission() {
|
||||
// 仅登录后再启动光环时请求一次权限
|
||||
if (!SPUtils.getBoolean(Constants.HAS_REQUESTED_NOTIFICATION_PERMISSIONS)
|
||||
/*if (!SPUtils.getBoolean(Constants.HAS_REQUESTED_NOTIFICATION_PERMISSIONS)
|
||||
&& UserManager.getInstance().isLoggedIn()) {
|
||||
SPUtils.setBoolean(Constants.HAS_REQUESTED_NOTIFICATION_PERMISSIONS, true);
|
||||
showNotificationHintDialog();
|
||||
}*/
|
||||
if (UserManager.getInstance().isLoggedIn()) {
|
||||
NotificationHelper.showNotificationHintDialog(NotificationUgc.LOGIN);
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,6 +539,9 @@ public class MainActivity extends BaseActivity {
|
||||
kv1.put("光环助手版本", BuildConfig.VERSION_NAME);
|
||||
if (downloadEntity.isUpdate()) {
|
||||
type = ExposureUtils.DownloadType.UPDATE;
|
||||
if (downloadEntity.isPlugin()) {
|
||||
type = ExposureUtils.DownloadType.PLUGIN_UPDATE;
|
||||
}
|
||||
DataUtils.onEvent(MainActivity.this, "游戏更新", downloadEntity.getName(), kv1);
|
||||
} else {
|
||||
type = ExposureUtils.DownloadType.DOWNLOAD;
|
||||
@ -507,7 +594,7 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 && !mMainWrapperFragment.onHandleBackPressed()) {
|
||||
DownloadEntity downloadEntity = null;
|
||||
for (DownloadEntity entity : DownloadManager.getInstance(getApplicationContext()).getAll()) {
|
||||
if (entity.getStatus().equals(DownloadStatus.done)) {
|
||||
@ -532,12 +619,12 @@ public class MainActivity extends BaseActivity {
|
||||
} else {
|
||||
msg = "《" + downloadEntity.getName() + "》已下载完但还未安装,是否立即安装?";
|
||||
}
|
||||
final String path = downloadEntity.getPath();
|
||||
DownloadEntity finalDownloadEntity = downloadEntity;
|
||||
DialogUtils.showWarningDialog(this,
|
||||
"提示", msg,
|
||||
"直接退出",
|
||||
"立即安装",
|
||||
() -> handler.postDelayed(() -> PackageUtils.launchSetup(MainActivity.this, path), 200),
|
||||
() -> handler.postDelayed(() -> PackageUtils.launchSetup(MainActivity.this, finalDownloadEntity), 200),
|
||||
this::finish);
|
||||
return true;
|
||||
}
|
||||
@ -553,6 +640,11 @@ public class MainActivity extends BaseActivity {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean handleBackPressed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
// 上传数据
|
||||
@ -582,6 +674,9 @@ public class MainActivity extends BaseActivity {
|
||||
if (getIntent().getBooleanExtra(SWITCH_TO_COMMUNITY, false)) {
|
||||
switchToCommunityTabAndRefresh();
|
||||
}
|
||||
if (getIntent().getBooleanExtra(SWITCH_TO_VIDEO, false)) {
|
||||
mMainWrapperFragment.setCurrentItem(2);
|
||||
}
|
||||
}
|
||||
|
||||
private void switchToCommunityTabAndRefresh() {
|
||||
@ -591,32 +686,6 @@ public class MainActivity extends BaseActivity {
|
||||
EventBus.getDefault().post(new EBReuse(CommunityFragment.EB_RETRY_PAGE));
|
||||
}
|
||||
|
||||
private void getGhzsSettings() {
|
||||
String channel = HaloApp.getInstance().getChannel();
|
||||
RetrofitManager.getInstance(this)
|
||||
.getApi().getSettings(PackageUtils.getVersionName(), channel)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<SettingsEntity>() {
|
||||
@Override
|
||||
public void onResponse(SettingsEntity response) {
|
||||
Config.setSettings(response);
|
||||
|
||||
// 意见反馈
|
||||
SharedPreferences.Editor edit = mSp.edit();
|
||||
edit.putString(SuggestionActivity.SUGGESTION_HINT_TYPE,
|
||||
GsonUtils.toJson(response.getSuggestion()));
|
||||
edit.apply();
|
||||
|
||||
if (!mSp.getBoolean(Config.FIX_DOWNLOAD_KEY, false) && Config.isShow()) {
|
||||
mSp.edit().putBoolean(Config.FIX_DOWNLOAD_KEY, true).apply();
|
||||
}
|
||||
|
||||
EventBus.getDefault().post(new EBReuse("Refresh"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void checkRetryDownload() {
|
||||
DownloadManager.getInstance(this).checkRetryDownload();
|
||||
}
|
||||
@ -711,7 +780,7 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void showNotificationHintDialog() {
|
||||
if (!SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_HINT)) {
|
||||
if (!SPUtils.getBoolean(Constants.SP_SHOWED_NOTIFICATION_LOGIN)) {
|
||||
RetrofitManager.getInstance(this).getApi().getBootPopup()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -801,7 +870,7 @@ public class MainActivity extends BaseActivity {
|
||||
if (busNetworkState.isNetworkConnected()) {
|
||||
checkRetryDownload();
|
||||
if (Config.getSettings() == null) {
|
||||
getGhzsSettings();
|
||||
Config.getGhzsSettings();
|
||||
}
|
||||
|
||||
mPackageViewModel.checkData();
|
||||
@ -850,11 +919,11 @@ public class MainActivity extends BaseActivity {
|
||||
ThirdPartyPackageHelper.saveGameId(mDownloadEntity.getPackageName(), mDownloadEntity.getGameId());
|
||||
}
|
||||
DownloadManager.getInstance(getApplicationContext()).cancel(
|
||||
mDownloadEntity.getUrl(), false); // 默认不删除安装包 mSp.getBoolean("autodelete", true)
|
||||
mDownloadEntity.getUrl(), false, true); // 默认不删除安装包 mSp.getBoolean("autodelete", true)
|
||||
}
|
||||
|
||||
|
||||
if (mSp.getBoolean("concerngame", true)) { //设置页面控制是否安装后自动关注
|
||||
if (mSp.getBoolean(SettingsFragment.CONCERN_GAME_SP_KEY, true)) { //设置页面控制是否安装后自动关注
|
||||
// 安装后关注游戏
|
||||
DownloadEntity finalDownloadEntity = mDownloadEntity;
|
||||
RetrofitManager.getInstance(this).getApi().getGameDigestByPackageName(UrlFilterUtils.getFilterQuery("package", packageName))
|
||||
@ -901,6 +970,7 @@ public class MainActivity extends BaseActivity {
|
||||
DataCollectionUtils.uploadInorunstall(this, busFour.getType(), busFour.getPackageName());
|
||||
}
|
||||
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
@SuppressLint("CheckResult")
|
||||
private void postNewlyInstalledApp(String gameId, String packageName) {
|
||||
|
||||
@ -920,11 +990,20 @@ public class MainActivity extends BaseActivity {
|
||||
.subscribe(new EmptyResponse<>());
|
||||
|
||||
if (!TextUtils.isEmpty(gameId) && UserManager.getInstance().isLoggedIn()) {
|
||||
RetrofitManager.getInstance(MainActivity.this).getApi()
|
||||
.postPlayedGame(UserManager.getInstance().getUserId(), gameId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new EmptyResponse<>());
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
try {
|
||||
jsonObject.put("game_id", gameId);
|
||||
jsonObject.put("package", packageName);
|
||||
RequestBody rBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString());
|
||||
|
||||
RetrofitManager.getInstance(MainActivity.this).getApi()
|
||||
.postPlayedGame(UserManager.getInstance().getUserId(), rBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new EmptyResponse<>());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -55,6 +55,7 @@ import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.newsdetail.NewsDetailAdapter;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.halo.assistant.fragment.SettingsFragment;
|
||||
import com.lightgame.download.DataWatcher;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -297,7 +298,7 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
|
||||
}
|
||||
|
||||
sp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
fontsize = sp.getInt("fontsize", 1);
|
||||
fontsize = sp.getInt(SettingsFragment.FONT_SIZE_SP_KEY, 1);
|
||||
if (fontsize == 0) {
|
||||
fontsize = 1;
|
||||
}
|
||||
@ -542,14 +543,14 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
|
||||
if ((R11 - R12) > scrollSize && fontsize > 1) {
|
||||
fontsize--;
|
||||
adapter.setFontSize(fontsize);
|
||||
sp.edit().putInt("fontsize", fontsize).apply();
|
||||
sp.edit().putInt(SettingsFragment.FONT_SIZE_SP_KEY, fontsize).apply();
|
||||
String fontSizeText = getFontSize(fontsize);
|
||||
Utils.toast(this, fontSizeText);
|
||||
}
|
||||
if ((R11 - R12) < -scrollSize && fontsize < 4) {
|
||||
fontsize++;
|
||||
adapter.setFontSize(fontsize);
|
||||
sp.edit().putInt("fontsize", fontsize).apply();
|
||||
sp.edit().putInt(SettingsFragment.FONT_SIZE_SP_KEY, fontsize).apply();
|
||||
String fontSizeText = getFontSize(fontsize);
|
||||
Utils.toast(this, fontSizeText);
|
||||
}
|
||||
|
||||
@ -10,15 +10,15 @@ import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.gh.base.ToolBarActivity;
|
||||
import com.gh.common.util.MessageShareUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.QRCodeUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.tencent.tauth.Tencent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
@ -72,6 +72,7 @@ public class ShareGhActivity extends ToolBarActivity {
|
||||
|
||||
@OnClick(R.id.gh_address_tv)
|
||||
public void copyAddress() {
|
||||
MtaHelper.onEvent("我的光环_新", "分享光环", "复制官网");
|
||||
ClipboardManager cmb = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cmb.setText(getString(R.string.gh_website_url_100));
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user