Compare commits
353 Commits
v3.7.6
...
v4.0.0-bug
| Author | SHA1 | Date | |
|---|---|---|---|
| 0dcf86ce1c | |||
| 961d4ebb5c | |||
| 54b947504c | |||
| ee7f102d34 | |||
| 135b55f6f9 | |||
| 17782a500f | |||
| 64a64960ac | |||
| d4be850e68 | |||
| 414064699a | |||
| 99878606d5 | |||
| e1cfccfcc0 | |||
| 4c2a46875d | |||
| 6ce64892e4 | |||
| 92e1c55913 | |||
| b0a4aa66f6 | |||
| aad92e529e | |||
| 6e03e75110 | |||
| cc53a1f3d6 | |||
| 25cd086298 | |||
| b27ecab969 | |||
| db1c0d954f | |||
| 03d20aed61 | |||
| c2fb1a58db | |||
| 55998c3c4d | |||
| 1ef8fa5deb | |||
| d0a2868e5a | |||
| 49c2366a89 | |||
| cb7d985195 | |||
| bead0bded1 | |||
| cc92d5f639 | |||
| 84c281122e | |||
| bb4a35a6a9 | |||
| 71ae36fbf0 | |||
| 04864e059c | |||
| 7a47184af3 | |||
| 48e2831e96 | |||
| c1caa23b10 | |||
| 443cc6007d | |||
| 7d99923960 | |||
| 7342d0706f | |||
| c15c194feb | |||
| 3b6a5b5a20 | |||
| f9028ea8a5 | |||
| 8cd06a80ba | |||
| 6c80266abb | |||
| ca3c1fa8c2 | |||
| 2b7deaef2c | |||
| 42f1898bd1 | |||
| 0bdff3eac7 | |||
| a00f6660a1 | |||
| 67d1ad497f | |||
| f1bbf4e9fc | |||
| 00ff5e6a94 | |||
| 7f77a8fd63 | |||
| 7c1267148b | |||
| 2dbb7b67cb | |||
| c41db52b05 | |||
| 72f3a262ca | |||
| 2fbe6a4937 | |||
| c6fb63afe6 | |||
| 2e05320ddf | |||
| a3f86ab604 | |||
| 5d2efda925 | |||
| 4a30ac04b7 | |||
| 1097068393 | |||
| df88502c3d | |||
| b8df485a7e | |||
| a8a66a7b1e | |||
| a1548faeda | |||
| 34f452be6e | |||
| bef04854e3 | |||
| 757782e43b | |||
| 8a69f565a3 | |||
| be20d1fec6 | |||
| 7a71e457ef | |||
| 3af9fa0a10 | |||
| ff8b3efde9 | |||
| 161f63a664 | |||
| 3206e04639 | |||
| f1dea0f200 | |||
| d94a83a7c3 | |||
| 6bbc7104d9 | |||
| a2180196ee | |||
| a6dc4c7891 | |||
| fa7355c5c6 | |||
| 0140c10f15 | |||
| 796da0e673 | |||
| 743f78096a | |||
| 52d726b6f3 | |||
| bed4450900 | |||
| c2ab369d0c | |||
| 32a7f37b6a | |||
| b299199579 | |||
| 7091ea179d | |||
| dceb582bb1 | |||
| 6e2e9f7dcf | |||
| c27025269e | |||
| cf1411b412 | |||
| b167f5bb8b | |||
| 87d0fd9edb | |||
| b59a169e10 | |||
| 941e3985b0 | |||
| 127fb76c19 | |||
| 5f3028f795 | |||
| b596f04dba | |||
| 0bb96ecf12 | |||
| 60f21f6113 | |||
| 051000e4a8 | |||
| 14e8020147 | |||
| a99b1499a2 | |||
| 6a1c01556b | |||
| c41327640b | |||
| 7df5834ebc | |||
| ebafc2f98f | |||
| 92c9d81171 | |||
| 7d34a3972d | |||
| 90f1254c6c | |||
| 8b71d68749 | |||
| 17c0cf52b6 | |||
| 045be4ff09 | |||
| af7948fcb5 | |||
| e1c12d5007 | |||
| 8676b20fbb | |||
| 54db9fb910 | |||
| 0eaee1ae63 | |||
| e141dfb6b5 | |||
| b14b8c9f66 | |||
| b4b589f307 | |||
| 7a74bc0d04 | |||
| b826c0a9ad | |||
| a197b59200 | |||
| c25503d7f8 | |||
| 2c0449dcf6 | |||
| 59655daa3b | |||
| 1c36d7b923 | |||
| a51175620c | |||
| 7b95c265df | |||
| a11bb9c210 | |||
| 72227a5591 | |||
| f9f2eb4c05 | |||
| e9c57df5fb | |||
| 158c47d94b | |||
| 7616435098 | |||
| 69443ff457 | |||
| 6a257c0a9f | |||
| eddd56e53a | |||
| de6648867b | |||
| 567a6ceda5 | |||
| 59330bcd7e | |||
| 36803f24bc | |||
| 46458e2667 | |||
| d0aa6e1fe5 | |||
| 9bef919123 | |||
| 88a0603d50 | |||
| 106dbb3d8d | |||
| 4214d924a4 | |||
| c3b40f9264 | |||
| 69f00626a2 | |||
| c485b1f7f8 | |||
| 7186c73a64 | |||
| 88f9f65fb6 | |||
| 714573ec6b | |||
| a979445ffc | |||
| 3cf38eb3fc | |||
| 94ceca35bf | |||
| 2bd4eb2004 | |||
| 355e71e620 | |||
| 7d9520d97b | |||
| ce0957cea7 | |||
| c93169fe97 | |||
| 485dd96e93 | |||
| 9b0f0892ff | |||
| 9a04f3ae38 | |||
| 968d668afa | |||
| 85d19ed2bd | |||
| 28e490f8d4 | |||
| 298ae7f657 | |||
| d50f29b3dc | |||
| f167eff21c | |||
| 69d4f00807 | |||
| 904dc4fe2e | |||
| c870cc683d | |||
| deb29fd2e4 | |||
| 19f1bc947a | |||
| 60d1b47c66 | |||
| d67b845dfd | |||
| 6f1c7c7ded | |||
| 46e9118d73 | |||
| 8aa1557b7a | |||
| 6058c3f8c1 | |||
| d409e6f2a9 | |||
| a4d272c556 | |||
| 911d7c04ec | |||
| afc379d449 | |||
| 18feca49e2 | |||
| 792b19d40d | |||
| 108d05edea | |||
| d8882da17b | |||
| f120dfda15 | |||
| dd60ed7abd | |||
| d0b478c743 | |||
| defe69ba18 | |||
| 32d748efae | |||
| f194dc9bf6 | |||
| 075fbd77b2 | |||
| edb3e3713a | |||
| c70648e038 | |||
| 966f4ee57d | |||
| f90ced4c31 | |||
| 6bda4d80bf | |||
| 3ecb6b30c9 | |||
| 3c337b618c | |||
| 40a90bbcfa | |||
| e54b124252 | |||
| 18923efe23 | |||
| 5c5ad63cc6 | |||
| d5fd444ae5 | |||
| 4a22f70e30 | |||
| 9805bd4caa | |||
| 0690f13bea | |||
| da8faea4c8 | |||
| ff927bab09 | |||
| e3e5def3b6 | |||
| ba246585ad | |||
| f242a6a3bc | |||
| 0c89e76b39 | |||
| 1fa82e72f1 | |||
| b4e6b04e47 | |||
| 002f824f5c | |||
| 1aaf7f8de1 | |||
| 82ba19842c | |||
| 32ed1bf622 | |||
| 0d4838c536 | |||
| 11527b46f9 | |||
| 20c1957b59 | |||
| ed2630e016 | |||
| 8cc2ac2cad | |||
| 37745ca548 | |||
| 29edcdca4b | |||
| 92669d6974 | |||
| 351a64f592 | |||
| a29e56543b | |||
| 6db3e8c671 | |||
| 20c4d24698 | |||
| 114e185bcb | |||
| a293bff964 | |||
| 98b4d9f95d | |||
| 8489e87586 | |||
| 6f7ee2179d | |||
| ea6b442a48 | |||
| 12d26edd76 | |||
| 27053eecd7 | |||
| 151d5b9c1f | |||
| d35c558658 | |||
| baa4dc7a23 | |||
| 9b565c32d1 | |||
| 243dd26d73 | |||
| 263234fecb | |||
| 0ba598ee67 | |||
| 29430b9967 | |||
| 2038b16dce | |||
| 9ea793397b | |||
| 6061938129 | |||
| 62277aa525 | |||
| 1c118b06c9 | |||
| a41c315e36 | |||
| 40576e0012 | |||
| a582db52f4 | |||
| cb2656ad85 | |||
| da1c686d42 | |||
| b613fe2ba0 | |||
| 83e29b1cf3 | |||
| 5bbd23bf33 | |||
| 9f69b83b51 | |||
| 4f77781e24 | |||
| b23d589a29 | |||
| 7f16a69301 | |||
| 006da73737 | |||
| 3f998cdf75 | |||
| 3e94cd9d8c | |||
| 5922f92caf | |||
| f5f5909fde | |||
| 7e67357887 | |||
| d5750c6cb8 | |||
| b2983d5c96 | |||
| 5a19e46d26 | |||
| 8456a5a1d6 | |||
| b9329a092e | |||
| 6ecad9eebd | |||
| f32dd9efee | |||
| 48cbaf03b7 | |||
| 7f23cda97a | |||
| 49c1809aa2 | |||
| 173aa82134 | |||
| c57e8b2c76 | |||
| bb741013d4 | |||
| 5b014a5a1d | |||
| a85548ac33 | |||
| 77e689fec4 | |||
| fe942dcf73 | |||
| da3b700403 | |||
| fcd46cb2ea | |||
| e918b19e2e | |||
| afb8badc74 | |||
| 4e22a5c7bb | |||
| b5d2e02606 | |||
| 28afb4f14c | |||
| 165659a664 | |||
| 7b3d910b10 | |||
| 1e4a85719a | |||
| 4269cb37d2 | |||
| b7ce3e8c20 | |||
| 15a0240808 | |||
| 0aa68ea04b | |||
| 2d9b69fd1e | |||
| 48d6023e0d | |||
| 0612582a46 | |||
| a3d0d91dd7 | |||
| 982e8f67bf | |||
| 0bb871bff2 | |||
| 0eb43d6552 | |||
| b4f29f4856 | |||
| 4fd68565d2 | |||
| 8241551438 | |||
| d7bb45f287 | |||
| dbb3078300 | |||
| a7d141efcc | |||
| 31c404021c | |||
| 631cec2fc6 | |||
| be6eab0cae | |||
| 71ee8bfd29 | |||
| 66c9c02dc6 | |||
| 7880ee4aef | |||
| 6274d1f778 | |||
| 5e98813f92 | |||
| 1a30800fb4 | |||
| 454e6933f4 | |||
| e3072071b7 | |||
| 83a88326f0 | |||
| 27109a810f | |||
| 3d5bd424c5 | |||
| c7cd56e7be | |||
| 860769c44a | |||
| a83761b88d | |||
| a79fc9c0b1 | |||
| 877bd63d9d | |||
| bb9d0582c4 | |||
| df7e89e7e4 | |||
| a12593ea51 | |||
| 5ca0af4285 | |||
| 89e72a0fea | |||
| fc25ad7ddb | |||
| 6b656cf446 |
@ -122,7 +122,6 @@ android {
|
||||
dimension "nonsense"
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "COMMENT_HOST", "\"${COMMENT_HOST}\""
|
||||
buildConfigField "String", "DATA_HOST", "\"${DATA_HOST}\""
|
||||
|
||||
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
|
||||
@ -140,7 +139,6 @@ android {
|
||||
|
||||
buildConfigField "String", "API_HOST", "\"${DEV_API_HOST}\""
|
||||
buildConfigField "String", "COMMENT_HOST", "\"${DEV_COMMENT_HOST}\""
|
||||
buildConfigField "String", "DATA_HOST", "\"${DEV_DATA_HOST}\""
|
||||
|
||||
buildConfigField "String", "UMENG_APPKEY", "\"${DEBUG_UMENG_APPKEY}\""
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${DEBUG_UMENG_MESSAGE_SECRET}\""
|
||||
@ -273,8 +271,6 @@ dependencies {
|
||||
exclude module: "gsyvideoplayer-androidvideocache"
|
||||
})
|
||||
implementation "com.shuyu:GSYVideoPlayer-exo2:$gsyVideo"
|
||||
// implementation "com.shuyu:gsyVideoPlayer-armv7a:$gsyVideo"
|
||||
// implementation "com.shuyu:gsyVideoPlayer-x86:$gsyVideo"
|
||||
|
||||
implementation "com.github.wendux:DSBridge-Android:$dsBridge"
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@ import android.app.Application;
|
||||
|
||||
import com.facebook.stetho.Stetho;
|
||||
import com.facebook.stetho.okhttp3.StethoInterceptor;
|
||||
import com.gu.toolargetool.TooLargeTool;
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
@ -30,7 +29,9 @@ public class Injection {
|
||||
|
||||
// init stetho
|
||||
Stetho.initializeWithDefaults(application);
|
||||
TooLargeTool.startLogging(application);
|
||||
|
||||
// 监控Bundle大小,预防溢出(需要调试的时候再开启吧!)
|
||||
// TooLargeTool.startLogging(application);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -115,6 +115,10 @@
|
||||
android:name="com.gh.gamecenter.ShellActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.history.HistoryApkListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.NewsDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -458,8 +462,8 @@
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.HelpAndFeedbackActivity"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:screenOrientation="portrait" />
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.help.HelpDetailActivity"
|
||||
@ -480,6 +484,14 @@
|
||||
android:name=".gamedetail.myrating.MyRatingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.QaActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!-- 使用小米/华为推送弹窗功能提高推送成功率-->
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.PushProxyActivity"
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@ -93,8 +95,8 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EventBus.getDefault().register(this);
|
||||
ButterKnife.bind(this);
|
||||
if (useEventBus()) EventBus.getDefault().register(this);
|
||||
if (useButterKnife()) ButterKnife.bind(this);
|
||||
mEntrance = getIntent().getStringExtra(KEY_ENTRANCE);
|
||||
if (TextUtils.isEmpty(mEntrance)) {
|
||||
mEntrance = Constants.ENTRANCE_UNKNOWN;
|
||||
@ -107,7 +109,7 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
if (useEventBus()) EventBus.getDefault().unregister(this);
|
||||
mBaseHandler.removeCallbacksAndMessages(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
@ -187,13 +189,12 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 可凭借此回调确定当前 activity 已经执行了 finish() 处于 isFinishing 状态
|
||||
* 可在后续进行
|
||||
* 此回调可用于确认当前 activity 已经执行了 finish() 方法并处于 isFinishing 状态
|
||||
*/
|
||||
protected void onFinish() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -246,4 +247,22 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
return StringUtils.buildString(entrance, "+(", path, ")");
|
||||
}
|
||||
|
||||
protected boolean useEventBus() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean useButterKnife() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
Resources resources = super.getResources();
|
||||
if (resources.getConfiguration().fontScale != 1.0f) {
|
||||
Configuration configuration = resources.getConfiguration();
|
||||
configuration.fontScale = 1.0f;
|
||||
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.gh.base.adapter.FragmentAdapter;
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout;
|
||||
import com.gh.common.view.TabIndicatorView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
@ -45,7 +46,7 @@ public abstract class BaseActivity_TabLayout extends ToolBarActivity implements
|
||||
protected abstract void initTabTitleList(List<String> tabTitleList);
|
||||
|
||||
protected int provideIndicatorWidth() {
|
||||
return 65;
|
||||
return 20;
|
||||
}
|
||||
|
||||
protected View provideTabView(int position, String tabTitle) {
|
||||
@ -89,11 +90,14 @@ public abstract class BaseActivity_TabLayout extends ToolBarActivity implements
|
||||
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
|
||||
TabLayout.Tab tab = mTabLayout.getTabAt(i);
|
||||
if (tab == null) continue;
|
||||
View tabView = provideTabView(i, tab.getText() != null ? tab.getText().toString() : "");
|
||||
if (tabView == null) continue;
|
||||
String tabTitle = tab.getText() != null ? tab.getText().toString() : "";
|
||||
View tabView = provideTabView(i, tabTitle);
|
||||
if (tabView == null)
|
||||
tabView = BaseFragment_TabLayout.createDefaultTabCustomView(tabTitle);
|
||||
tab.setCustomView(tabView);
|
||||
}
|
||||
|
||||
BaseFragment_TabLayout.initTabStyle(mTabLayout, mCheckedIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -145,7 +145,10 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
} else {
|
||||
mCachedView = View.inflate(getContext(), getLayoutId(), null);
|
||||
}
|
||||
ButterKnife.bind(this, mCachedView);
|
||||
|
||||
if (useButterKnife()) {
|
||||
ButterKnife.bind(this, mCachedView);
|
||||
}
|
||||
|
||||
initView(mCachedView);
|
||||
|
||||
@ -309,4 +312,8 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
protected boolean addSyncPageObserver() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean useButterKnife() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,28 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CheckedTextView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.base.adapter.FragmentAdapter;
|
||||
import com.gh.common.view.TabIndicatorView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.normal.NormalFragment;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.lightgame.view.NoScrollableViewPager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -46,7 +56,7 @@ public abstract class BaseFragment_TabLayout extends NormalFragment implements V
|
||||
protected abstract void initTabTitleList(List<String> tabTitleList);
|
||||
|
||||
protected int provideIndicatorWidth() {
|
||||
return 65;
|
||||
return 20;
|
||||
}
|
||||
|
||||
protected View provideTabView(int position, String tabTitle) {
|
||||
@ -94,11 +104,71 @@ public abstract class BaseFragment_TabLayout extends NormalFragment implements V
|
||||
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
|
||||
TabLayout.Tab tab = mTabLayout.getTabAt(i);
|
||||
if (tab == null) continue;
|
||||
View tabView = provideTabView(i, tab.getText() != null ? tab.getText().toString() : "");
|
||||
if (tabView == null) continue;
|
||||
String tabTitle = tab.getText() != null ? tab.getText().toString() : "";
|
||||
View tabView = provideTabView(i, tabTitle);
|
||||
if (tabView == null) tabView = createDefaultTabCustomView(tabTitle);
|
||||
tab.setCustomView(tabView);
|
||||
}
|
||||
|
||||
initTabStyle(mTabLayout, mCheckedIndex);
|
||||
}
|
||||
|
||||
public static void initTabStyle(TabLayout tabLayout, int currentItem) {
|
||||
// 默认选择addOnTabSelectedListener不会回调
|
||||
int tabCount = tabLayout.getTabCount();
|
||||
if (tabCount > 0) {
|
||||
TabLayout.Tab tab = tabLayout.getTabAt(currentItem);
|
||||
if (tab != null) updateTabStyle(tab, true);
|
||||
}
|
||||
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
updateTabStyle(tab, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
updateTabStyle(tab, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
updateTabStyle(tab, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void updateTabStyle(TabLayout.Tab tab, boolean isChecked) {
|
||||
View tabView = tab.getCustomView();
|
||||
if (tabView == null) {
|
||||
Utils.log("TabLayout->Tab样式不是通用样式,请检查");
|
||||
return;
|
||||
}
|
||||
|
||||
TextView tabTitle;
|
||||
if (tabView instanceof TextView) {
|
||||
tabTitle = (TextView) tabView;
|
||||
} else {
|
||||
tabTitle = tabView.findViewById(R.id.tab_title);
|
||||
}
|
||||
|
||||
if (tabTitle == null) {
|
||||
Utils.log("TabLayout->Tab样式不是通用样式,请检查");
|
||||
return;
|
||||
}
|
||||
tabTitle.setTypeface(isChecked ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
|
||||
}
|
||||
|
||||
// 如果不设置View的话,无法动态设置字体样式
|
||||
@NonNull
|
||||
public static View createDefaultTabCustomView(String title) {
|
||||
View view = LayoutInflater.from(HaloApp.getInstance().getApplication().getBaseContext()).inflate(R.layout.tab_item, null);
|
||||
View tabTitle = view.findViewById(R.id.tab_title);
|
||||
if (tabTitle instanceof CheckedTextView) {
|
||||
((CheckedTextView) tabTitle).setText(title);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.base.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.normal.NormalFragment
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
/**
|
||||
* 懒加载(支持多层嵌套)
|
||||
@ -104,7 +105,7 @@ abstract class BaseLazyFragment : NormalFragment() {
|
||||
isSupportVisible = visible
|
||||
|
||||
if (visible) {
|
||||
if (mIsFirstVisible) {
|
||||
if (mIsFirstVisible && view != null) {
|
||||
mIsFirstVisible = false
|
||||
onFragmentFirstVisible()
|
||||
}
|
||||
|
||||
152
app/src/main/java/com/gh/base/fragment/BaseLazyTabFragment.kt
Normal file
152
app/src/main/java/com/gh/base/fragment/BaseLazyTabFragment.kt
Normal file
@ -0,0 +1,152 @@
|
||||
package com.gh.base.fragment
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.CheckedTextView
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import butterknife.BindView
|
||||
import com.gh.base.adapter.FragmentAdapter
|
||||
import com.gh.common.view.TabIndicatorView
|
||||
import com.gh.gamecenter.R
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import com.lightgame.view.NoScrollableViewPager
|
||||
|
||||
abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeListener {
|
||||
|
||||
@BindView(R.id.fragment_tab_layout)
|
||||
lateinit var mTabLayout: TabLayout
|
||||
@BindView(R.id.fragment_view_pager)
|
||||
lateinit var mViewPager: NoScrollableViewPager
|
||||
@BindView(R.id.fragment_tab_indicator)
|
||||
lateinit var mTabIndicatorView: TabIndicatorView
|
||||
|
||||
var mFragmentsList: MutableList<Fragment> = arrayListOf()
|
||||
|
||||
var mTabTitleList: MutableList<String> = arrayListOf()
|
||||
|
||||
var mCheckedIndex = 0
|
||||
|
||||
abstract fun initFragmentList(fragments: MutableList<Fragment>)
|
||||
|
||||
abstract fun initTabTitleList(tabTitleList: MutableList<String>)
|
||||
|
||||
protected open fun provideIndicatorWidth(): Int {
|
||||
return 20
|
||||
}
|
||||
|
||||
protected open fun provideTabView(position: Int, tabTitle: String?): View? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.fragment_tablayout_viewpager
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
val fragments = childFragmentManager.fragments
|
||||
if (fragments != null) {
|
||||
for (fragment in fragments) {
|
||||
fragment.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (arguments != null) mCheckedIndex = requireArguments().getInt(PAGE_INDEX, 0)
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
super.onFragmentFirstVisible()
|
||||
|
||||
initFragmentList(mFragmentsList)
|
||||
initTabTitleList(mTabTitleList)
|
||||
|
||||
mViewPager.offscreenPageLimit = mFragmentsList.size
|
||||
mViewPager.addOnPageChangeListener(this)
|
||||
mViewPager.adapter = FragmentAdapter(childFragmentManager, mFragmentsList, mTabTitleList)
|
||||
mViewPager.currentItem = mCheckedIndex
|
||||
mTabLayout.setupWithViewPager(mViewPager)
|
||||
mTabIndicatorView.setupWithTabLayout(mTabLayout)
|
||||
mTabIndicatorView.setupWithViewPager(mViewPager)
|
||||
mTabIndicatorView.setIndicatorWidth(provideIndicatorWidth())
|
||||
for (i in 0 until mTabLayout.tabCount) {
|
||||
val tab = mTabLayout.getTabAt(i) ?: continue
|
||||
val tabTitle = if (tab.text != null) tab.text.toString() else ""
|
||||
var tabView = provideTabView(i, tabTitle)
|
||||
if (tabView == null) tabView = createDefaultTabCustomView(tabTitle)
|
||||
tab.customView = tabView
|
||||
}
|
||||
initTabStyle(mTabLayout, mCheckedIndex)
|
||||
}
|
||||
|
||||
open fun initTabStyle(tabLayout: TabLayout?, currentItem: Int) { // 默认选择addOnTabSelectedListener不会回调
|
||||
val tabCount = tabLayout!!.tabCount
|
||||
if (tabCount > 0) {
|
||||
val tab = tabLayout.getTabAt(currentItem)
|
||||
if (tab != null) updateTabStyle(tab, true)
|
||||
}
|
||||
tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, true)
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, false)
|
||||
}
|
||||
|
||||
override fun onTabReselected(tab: TabLayout.Tab) {
|
||||
updateTabStyle(tab, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
open fun updateTabStyle(tab: TabLayout.Tab, isChecked: Boolean) {
|
||||
val tabView = tab.customView
|
||||
if (tabView == null) {
|
||||
Utils.log("TabLayout->Tab样式不是通用样式,请检查")
|
||||
return
|
||||
}
|
||||
val tabTitle: TextView?
|
||||
tabTitle = if (tabView is TextView) {
|
||||
tabView
|
||||
} else {
|
||||
tabView.findViewById(R.id.tab_title)
|
||||
}
|
||||
if (tabTitle == null) {
|
||||
Utils.log("TabLayout->Tab样式不是通用样式,请检查")
|
||||
return
|
||||
}
|
||||
tabTitle.typeface = if (isChecked) Typeface.DEFAULT_BOLD else Typeface.DEFAULT
|
||||
}
|
||||
|
||||
// 如果不设置View的话,无法动态设置字体样式
|
||||
open fun createDefaultTabCustomView(title: String?): View {
|
||||
val view = LayoutInflater.from(HaloApp.getInstance().application.baseContext).inflate(R.layout.tab_item, null)
|
||||
val tabTitle = view.findViewById<View>(R.id.tab_title)
|
||||
if (tabTitle is CheckedTextView) {
|
||||
tabTitle.text = title
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
|
||||
override fun onPageSelected(position: Int) {}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
|
||||
companion object {
|
||||
const val PAGE_INDEX = "PAGE_INDEX"
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,8 @@ import android.os.Looper
|
||||
import com.gh.common.AppExecutor.ioExecutor
|
||||
import com.gh.common.AppExecutor.lightWeightIoExecutor
|
||||
import com.gh.common.AppExecutor.uiExecutor
|
||||
import java.util.concurrent.*
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
/**
|
||||
* APP 线程池管理类
|
||||
@ -18,11 +19,11 @@ import java.util.concurrent.*
|
||||
object AppExecutor {
|
||||
|
||||
@JvmStatic
|
||||
var uiExecutor = MainThreadExecutor()
|
||||
val uiExecutor by lazy { MainThreadExecutor() }
|
||||
@JvmStatic
|
||||
var lightWeightIoExecutor = Executors.newSingleThreadExecutor()
|
||||
val lightWeightIoExecutor by lazy { Executors.newSingleThreadExecutor() }
|
||||
@JvmStatic
|
||||
var ioExecutor = Executors.newCachedThreadPool()
|
||||
val ioExecutor = Executors.newCachedThreadPool() // 用 by lazy 可能影响初始化速度
|
||||
|
||||
class MainThreadExecutor : Executor {
|
||||
private val mainThreadHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
@ -8,7 +8,6 @@ import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.common.util.EntranceUtils.ENTRANCE_BROWSER
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.LibaoDetailActivity
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
@ -18,7 +17,6 @@ import com.gh.gamecenter.entity.VideoLinkEntity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.lightgame.utils.Utils
|
||||
import com.moor.imkf.requesturl.RequestUrl.type
|
||||
|
||||
object DefaultWebViewUrlHandler {
|
||||
|
||||
@ -46,7 +44,7 @@ object DefaultWebViewUrlHandler {
|
||||
|
||||
"qq" -> try {
|
||||
DirectUtils.directToQqConversation(context, id)
|
||||
} catch (e: Exception) {
|
||||
} catch (e: Throwable) {
|
||||
Utils.toast(context, "请检查是否已经安装手机QQ")
|
||||
e.printStackTrace()
|
||||
}
|
||||
@ -81,10 +79,18 @@ object DefaultWebViewUrlHandler {
|
||||
"community" -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = id
|
||||
community.name = uri.getQueryParameter("name")
|
||||
community.name = uri.getQueryParameter("name") ?: ""
|
||||
DirectUtils.directToCommunity(context, community)
|
||||
}
|
||||
|
||||
"community_column" -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = uri.getQueryParameter("community_id") ?: ""
|
||||
community.name = uri.getQueryParameter("community_name") ?: ""
|
||||
val columnId = uri.getQueryParameter("column_id") ?: ""
|
||||
DirectUtils.directToCommunityColumn(context, community, columnId, entrance, "文章链接")
|
||||
}
|
||||
|
||||
"answer" -> DirectUtils.directToAnswerDetail(context, id, entrance, "文章链接")
|
||||
|
||||
"communities" -> {
|
||||
|
||||
@ -8,6 +8,7 @@ import com.gh.common.exposure.meta.MetaUtil
|
||||
import com.gh.common.util.edit
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.entity.AliasEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -35,33 +36,34 @@ object PushManager {
|
||||
|
||||
@JvmStatic
|
||||
fun init(channel: String) {
|
||||
//初始化友盟推送
|
||||
UMConfigure.init(mApplication,
|
||||
Config.UMENG_APPKEY, channel,
|
||||
UMConfigure.DEVICE_TYPE_PHONE,
|
||||
Config.UMENG_MESSAGE_SECRET)
|
||||
tryWithDefaultCatch {
|
||||
//初始化友盟推送
|
||||
UMConfigure.init(mApplication,
|
||||
Config.UMENG_APPKEY, channel,
|
||||
UMConfigure.DEVICE_TYPE_PHONE,
|
||||
Config.UMENG_MESSAGE_SECRET)
|
||||
|
||||
// 注册小米、华为和魅族通道
|
||||
MiPushRegistar.register(mApplication, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
|
||||
HuaWeiRegister.register(mApplication)
|
||||
MeizuRegister.register(mApplication, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
|
||||
// 注册小米、华为和魅族通道
|
||||
MiPushRegistar.register(mApplication, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
|
||||
HuaWeiRegister.register(mApplication)
|
||||
MeizuRegister.register(mApplication, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
|
||||
|
||||
//友盟推送
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
pushAgent.onAppStart() // 开启App统计
|
||||
//友盟推送
|
||||
val pushAgent = PushAgent.getInstance(mApplication)
|
||||
|
||||
//注册推送服务,每次调用register方法都会回调该接口
|
||||
registerDevice()
|
||||
//注册推送服务,每次调用register方法都会回调该接口
|
||||
runOnIoThread { registerDevice() }
|
||||
|
||||
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(mApplication).getString(SP_PUSH_ALIAS, "")
|
||||
mPreviousAlias = aliasInSp?.toObject()
|
||||
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(mApplication).getString(SP_PUSH_ALIAS, "")
|
||||
mPreviousAlias = aliasInSp?.toObject()
|
||||
|
||||
if (mPreviousAlias == null) {
|
||||
getAndSetAlias()
|
||||
if (mPreviousAlias == null) {
|
||||
getAndSetAlias()
|
||||
}
|
||||
|
||||
// 完全自定义处理(透传)
|
||||
pushAgent.setPushIntentServiceClass(GHUmengNotificationService::class.java)
|
||||
}
|
||||
|
||||
// 完全自定义处理(透传)
|
||||
pushAgent.setPushIntentServiceClass(GHUmengNotificationService::class.java)
|
||||
}
|
||||
|
||||
private fun registerDevice() {
|
||||
|
||||
@ -6,6 +6,7 @@ import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
/**
|
||||
@ -113,7 +114,7 @@ class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) {
|
||||
}
|
||||
|
||||
object TimeElapsedThreadHolder {
|
||||
val threadService = Executors.newSingleThreadExecutor()
|
||||
val threadService: ExecutorService by lazy { Executors.newSingleThreadExecutor() }
|
||||
}
|
||||
|
||||
interface TimeoutCallback {
|
||||
|
||||
@ -5,6 +5,8 @@ import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.PackageHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
@ -23,7 +25,6 @@ import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
@ -31,7 +32,6 @@ public class Config {
|
||||
|
||||
public static final String API_HOST = BuildConfig.API_HOST;
|
||||
public static final String COMMENT_HOST = BuildConfig.COMMENT_HOST;
|
||||
public static final String DATA_HOST = BuildConfig.DATA_HOST;
|
||||
|
||||
/**
|
||||
* 需要配置的请使用{@link PreferenceManager#getDefaultSharedPreferences(Context)}
|
||||
@ -234,6 +234,10 @@ public class Config {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isGameDomeSwitchOpen() {
|
||||
return getSettings() != null && getSettings().getGameDomeSwitch().equals("on");
|
||||
}
|
||||
|
||||
public static void fixHideFunction() {
|
||||
SharedPreferences preferences = PreferenceManager.
|
||||
getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
|
||||
|
||||
@ -29,6 +29,8 @@ public class Constants {
|
||||
|
||||
public static final String EB_QUIT_LOGIN = "quit_login";
|
||||
|
||||
public static final String GAME_ID_DIVIDER = ":"; // 用于避免历史下载掺和到普通下载状态的 ID 修饰符
|
||||
|
||||
// 最近显示的弹窗信息
|
||||
public static final String SP_LAST_OPENING_ID = "last_opening_dialog_id";
|
||||
public static final String SP_LAST_OPENING_TIME = "last_opening_dialog_time";
|
||||
@ -64,6 +66,16 @@ public class Constants {
|
||||
public static final String SP_NON_WIFI_TIPS = "non_wifi_tips";
|
||||
//首页视频最新tab提示
|
||||
public static final String SP_HOME_NEW_VIDEO_TIPS = "home_new_video";
|
||||
//游戏设备弹窗提示
|
||||
public static final String SP_DEVICE_REMIND = "device_remind";
|
||||
//是否是第一次弹出游戏设备弹窗提示
|
||||
public static final String SP_FIRST_DEVICE_REMIND = "first_device_remind";
|
||||
//游戏设备弹窗不再提示
|
||||
public static final String SP_NO_REMIND_AGAIN = "no_remind_again";
|
||||
//游戏详情过滤标签数据
|
||||
public static final String SP_FILTER_TAGS= "filter_tags";
|
||||
//实名认证弹窗分类数据
|
||||
public static final String SP_AUTH_DIALOG= "auth_dialog";
|
||||
|
||||
//手机号码匹配规则
|
||||
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
|
||||
|
||||
@ -13,9 +13,16 @@ 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;
|
||||
import com.gh.common.dialog.CertificationDialog;
|
||||
import com.gh.common.dialog.ReserveDialogFragment;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
@ -36,10 +43,10 @@ import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PermissionHelper;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.common.view.DownloadDialog;
|
||||
import com.gh.common.view.DownloadProgressBar;
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
@ -65,12 +72,6 @@ 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.
|
||||
*/
|
||||
@ -198,6 +199,17 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("textColorFromString")
|
||||
public static void textColorFromString(TextView tv, String hexString) {
|
||||
if (TextUtils.isEmpty(hexString)) return;
|
||||
|
||||
try {
|
||||
tv.setTextColor(Color.parseColor(hexString));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("visibleGone")
|
||||
public static void showHide(View view, Boolean show) {
|
||||
if (show != null && show) {
|
||||
@ -207,6 +219,32 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("goneIf")
|
||||
public static void goneIf(View view, Boolean gone) {
|
||||
if (gone != null && gone) {
|
||||
view.setVisibility(View.GONE);
|
||||
} else {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lazy 的 paddingTop
|
||||
*/
|
||||
@BindingAdapter("lazyPaddingTop")
|
||||
public static void lazyPaddingTop(View view, int paddingTopInDp) {
|
||||
view.setPadding(view.getPaddingLeft(), DisplayUtils.dip2px(paddingTopInDp), view.getPaddingRight(), view.getPaddingBottom());
|
||||
}
|
||||
|
||||
@BindingAdapter("visibleInvisible")
|
||||
public static void visibleInvisible(View view, Boolean show) {
|
||||
if (show != null && show) {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
view.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("messageUnread")
|
||||
public static void setMessageUnread(TextView view, int unreadCount) {
|
||||
if (unreadCount < 100) {
|
||||
@ -358,17 +396,25 @@ public class BindingAdapters {
|
||||
case PLUGIN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
ApkEntity apk = gameEntity.getApk().get(0);
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
apk,
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(v.getContext(), gameEntity, apk,
|
||||
() -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
entrance, location + gameEntity.getName(), traceEvent);
|
||||
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
|
||||
DownloadDialog.showDownloadDialog(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
entrance,
|
||||
location + ":" + gameEntity.getName());
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
case LAUNCH_OR_OPEN:
|
||||
@ -376,8 +422,11 @@ public class BindingAdapters {
|
||||
DataUtils.onGameLaunchEvent(v.getContext(), gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), location);
|
||||
PackageUtils.launchApplicationByPackageName(v.getContext(), gameEntity.getApk().get(0).getPackageName());
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
entrance, location + gameEntity.getName(), traceEvent);
|
||||
DownloadDialog.showDownloadDialog(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
entrance,
|
||||
location + ":" + gameEntity.getName());
|
||||
}
|
||||
break;
|
||||
case INSTALL_PLUGIN:
|
||||
@ -455,7 +504,7 @@ public class BindingAdapters {
|
||||
}
|
||||
progressBar.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
String status = GameUtils.getDownloadBtnText(progressBar.getContext(), gameEntity, PluginLocation.only_game);
|
||||
switch (status) {
|
||||
@ -511,6 +560,23 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
/*private static void download(DownloadProgressBar progressBar, GameEntity gameEntity, ExposureEvent traceEvent, @Nullable String entrance, @Nullable String location, View v) {
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
ApkEntity apk = gameEntity.getApk().get(0);
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
apk,
|
||||
() -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
});
|
||||
} else {
|
||||
DownloadDialog.getInstance(v.getContext()).showPopupWindow(v, gameEntity,
|
||||
entrance, location + gameEntity.getName(), traceEvent);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
private static void updateReservation(DownloadProgressBar progressBar, GameEntity gameEntity) {
|
||||
// 显示预约
|
||||
@ -546,10 +612,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);
|
||||
|
||||
|
||||
ExposureUtils.DownloadType downloadType = ExposureUtils.getDownloadType(apkEntity, method);
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, downloadType);
|
||||
|
||||
|
||||
DownloadManager.createDownload(progressBar.getContext(),
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
@ -567,27 +633,9 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"gameLabelList", "subjectTag"})
|
||||
public static void setGameLabelList(LinearLayout layout, GameEntity gameEntity, String subjectTag) {
|
||||
if (gameEntity == null) return;
|
||||
if (gameEntity.getTest() != null) {
|
||||
layout.removeAllViews();
|
||||
View testView = LayoutInflater.from(layout.getContext()).inflate(R.layout.game_test_label, null);
|
||||
TextView testType = testView.findViewById(R.id.test_type);
|
||||
TextView testTime = testView.findViewById(R.id.test_time);
|
||||
testType.setText(gameEntity.getTest().getType());
|
||||
testType.setBackgroundColor(ContextCompat.getColor(layout.getContext(), R.color.tag_yellow));
|
||||
|
||||
if (gameEntity.getTest().getStart() == 0) {
|
||||
testTime.setVisibility(View.GONE);
|
||||
} else {
|
||||
testTime.setText(GameViewUtils.getGameTestDate(gameEntity.getTest().getStart()));
|
||||
}
|
||||
layout.addView(testView);
|
||||
} else {
|
||||
GameViewUtils.setLabelList(layout.getContext(), layout, gameEntity.getTag(), subjectTag, gameEntity.getTagStyle());
|
||||
}
|
||||
|
||||
@BindingAdapter("gameLabelList")
|
||||
public static void setGameLabelList(LinearLayout layout, List<TagStyleEntity> tagStyle) {
|
||||
GameViewUtils.setLabelList(layout.getContext(), layout, tagStyle);
|
||||
}
|
||||
|
||||
@BindingAdapter("isRefreshing")
|
||||
|
||||
@ -15,6 +15,7 @@ abstract class BaseTrackableDialogFragment : BaseDialogFragment() {
|
||||
|
||||
abstract fun getEvent(): String
|
||||
abstract fun getKey(): String
|
||||
open fun getValue(): String = ""
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
private val mIsCanceledByClickOutsideOfDialog = AtomicBoolean(true)
|
||||
@ -47,6 +48,9 @@ abstract class BaseTrackableDialogFragment : BaseDialogFragment() {
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), value)
|
||||
} else {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), value)
|
||||
if (getValue().isNotEmpty()) {
|
||||
MtaHelper.onEvent(getEvent(), value, getValue())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
196
app/src/main/java/com/gh/common/dialog/CertificationDialog.kt
Normal file
196
app/src/main/java/com/gh/common/dialog/CertificationDialog.kt
Normal file
@ -0,0 +1,196 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.CheckBox
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.common.avoidcallback.AvoidOnResultManager
|
||||
import com.gh.common.avoidcallback.Callback
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.GsonUtils
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.UserInfoEditActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.AuthDialogEntity
|
||||
import com.gh.gamecenter.entity.AuthDialogLevel
|
||||
import com.gh.gamecenter.entity.DeviceDialogEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.user.UserViewModel
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.fragment.user.UserInfoEditFragment
|
||||
import com.lightgame.utils.AppManager
|
||||
import com.tencent.bugly.beta.tinker.TinkerManager.getApplication
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.HttpException
|
||||
|
||||
class CertificationDialog(context: Context, private val authDialogEntity: AuthDialogEntity, val gameId: String, val listener: DialogUtils.ConfirmListener) :
|
||||
Dialog(context, R.style.GhAlertDialog) {
|
||||
|
||||
private lateinit var view: View
|
||||
private lateinit var detailedDesTv: TextView
|
||||
private lateinit var noRemindAgainCb: CheckBox
|
||||
private lateinit var actionLeftTv: TextView
|
||||
private lateinit var actionRightTv: TextView
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
view = LayoutInflater.from(context).inflate(R.layout.dialog_sertification, null)
|
||||
setContentView(view)
|
||||
detailedDesTv = view.findViewById(R.id.detailedDesTv)
|
||||
noRemindAgainCb = view.findViewById(R.id.noRemindAgainCb)
|
||||
actionLeftTv = view.findViewById(R.id.actionLeftTv)
|
||||
actionRightTv = view.findViewById(R.id.actionRightTv)
|
||||
|
||||
detailedDesTv.paint.flags = Paint.UNDERLINE_TEXT_FLAG
|
||||
detailedDesTv.paint.isAntiAlias = true
|
||||
|
||||
detailedDesTv.setOnClickListener {
|
||||
context.startActivity(WebActivity.getIntentByUrl(context, authDialogEntity.link))
|
||||
}
|
||||
|
||||
when (authDialogEntity.level) {
|
||||
AuthDialogLevel.MUST_PASS.value -> {
|
||||
actionLeftTv.text = "暂不下载"
|
||||
actionRightTv.text = "去实名认证"
|
||||
noRemindAgainCb.visibility = View.GONE
|
||||
actionLeftTv.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
actionRightTv.setOnClickListener {
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
gotoAuthPage()
|
||||
} else {
|
||||
gotoLoginPage()
|
||||
}
|
||||
}
|
||||
}
|
||||
AuthDialogLevel.ALWAYS_HINT.value -> {
|
||||
actionLeftTv.text = "去实名认证"
|
||||
actionRightTv.text = "继续下载"
|
||||
noRemindAgainCb.visibility = View.GONE
|
||||
actionLeftTv.setOnClickListener {
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
gotoAuthPage()
|
||||
} else {
|
||||
gotoLoginPage()
|
||||
}
|
||||
}
|
||||
actionRightTv.setOnClickListener {
|
||||
listener.onConfirm()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
AuthDialogLevel.OPTIONAL_HINT.value -> {
|
||||
actionLeftTv.text = "去实名认证"
|
||||
actionRightTv.text = "继续下载"
|
||||
noRemindAgainCb.visibility = View.VISIBLE
|
||||
actionLeftTv.setOnClickListener {
|
||||
if (noRemindAgainCb.isChecked) {
|
||||
SPUtils.setBoolean(gameId, true)
|
||||
}
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
gotoAuthPage()
|
||||
} else {
|
||||
gotoLoginPage()
|
||||
}
|
||||
}
|
||||
actionRightTv.setOnClickListener {
|
||||
if (noRemindAgainCb.isChecked) {
|
||||
SPUtils.getBoolean(gameId, true)
|
||||
}
|
||||
listener.onConfirm()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//跳转登录页面
|
||||
private fun gotoLoginPage() {
|
||||
CheckLoginUtils.checkLogin(AppManager.getInstance().currentActivity() as AppCompatActivity,
|
||||
null, true, "实名认证弹窗") {
|
||||
if (UserManager.getInstance().isAuth) {
|
||||
listener.onConfirm()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//跳转实名认证页面
|
||||
private fun gotoAuthPage() {
|
||||
AvoidOnResultManager.getInstance(AppManager.getInstance().currentActivity() as AppCompatActivity)
|
||||
.startForResult(UserInfoEditActivity.getIntent(context, UserViewModel.TYPE_ID_CARD), object : Callback {
|
||||
override fun onActivityResult(resultCode: Int, data: Intent?) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val isAuthSuccess = data.getBooleanExtra(UserInfoEditFragment.AUTH_SUCCESS, false)
|
||||
if (isAuthSuccess) {
|
||||
listener.onConfirm()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun showCertificationDialog(context: Context, game: GameEntity, listener: DialogUtils.ConfirmListener) {
|
||||
//1.先判断是否登录 是执行2 否执行3
|
||||
//2.判断是否实名认证 是终止 否执行3
|
||||
//3.判断是否需要弹出认证弹窗接口
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
if (UserManager.getInstance().isAuth) {//已实名认证
|
||||
listener.onConfirm()
|
||||
} else {
|
||||
authDialog(context, game, listener)
|
||||
}
|
||||
} else {
|
||||
authDialog(context, game, listener)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun authDialog(context: Context, game: GameEntity, listener: DialogUtils.ConfirmListener) {
|
||||
var authDialog: AuthDialogEntity? = null
|
||||
if (game.authDialog != null) {
|
||||
authDialog = game.authDialog
|
||||
}
|
||||
if (authDialog == null) {
|
||||
val datas = SPUtils.getString(Constants.SP_AUTH_DIALOG)
|
||||
val type = object : TypeToken<List<AuthDialogEntity>>() {}.type
|
||||
val authDialogs = GsonUtils.gson.fromJson<List<AuthDialogEntity>>(datas, type)
|
||||
if (!authDialogs.isNullOrEmpty()) {
|
||||
authDialog = authDialogs.find { it.gameCategory == game.category }
|
||||
}
|
||||
}
|
||||
val isCloseAuthDialog = SPUtils.getBoolean(game.id, false)
|
||||
if (authDialog != null && (authDialog.level != AuthDialogLevel.OPTIONAL_HINT.value || !isCloseAuthDialog)) {
|
||||
val dialog = CertificationDialog(context, authDialog, game.id, listener)
|
||||
dialog.show()
|
||||
} else {
|
||||
listener.onConfirm()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
234
app/src/main/java/com/gh/common/dialog/DeviceRemindDialog.kt
Normal file
234
app/src/main/java/com/gh/common/dialog/DeviceRemindDialog.kt
Normal file
@ -0,0 +1,234 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Message
|
||||
import android.preference.PreferenceManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.DeviceDialogEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.fragment.SettingsFragment.AUTO_INSTALL_SP_KEY
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.android.synthetic.main.dialog_device_remind.view.*
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
* 设备提醒弹窗
|
||||
*/
|
||||
class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val gameEntity: GameEntity) : Dialog(context, R.style.GhAlertDialog) {
|
||||
private lateinit var view: View
|
||||
private var currentPage = 0
|
||||
private var mSlideLooperInterval = 3000L
|
||||
private lateinit var mLooperHandle: LooperHandle
|
||||
private lateinit var mAdapter: BannerAdapter
|
||||
private var mDatas: ArrayList<String> = ArrayList()
|
||||
private val mSlideLooperKey = 100
|
||||
private var disposable: Disposable? = null
|
||||
private val dataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
if (downloadEntity.status == DownloadStatus.done && downloadEntity.name == gameEntity.name) {
|
||||
val sp = PreferenceManager.getDefaultSharedPreferences(getContext())
|
||||
val autoInstall = sp.getBoolean(AUTO_INSTALL_SP_KEY, true)
|
||||
if (autoInstall) {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun showDeviceRemindDialog(context: Context, gameEntity: GameEntity) {
|
||||
val datas = SPUtils.getString(Constants.SP_DEVICE_REMIND)
|
||||
if (datas.isNotEmpty()) {
|
||||
val type = object : TypeToken<List<DeviceDialogEntity>>() {}.type
|
||||
val entitys = GsonUtils.gson.fromJson<List<DeviceDialogEntity>>(datas, type)
|
||||
//1.判断设备是否匹配
|
||||
val entity = entitys.find { it.manufacturer.toLowerCase().startsWith(Build.MANUFACTURER.toLowerCase()) }
|
||||
?: return
|
||||
//2.判断游戏不含剔除标签
|
||||
gameEntity.tagStyle.forEach {
|
||||
if (entity.excludeTags.contains(it.name)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
//3.不再弹出提示判断
|
||||
val isNoRemindAgain = SPUtils.getBoolean(Constants.SP_NO_REMIND_AGAIN, false)
|
||||
if (isNoRemindAgain) return
|
||||
|
||||
val dialog = DeviceRemindDialog(context, entity, gameEntity)
|
||||
dialog.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
view = LayoutInflater.from(context).inflate(R.layout.dialog_device_remind, null)
|
||||
setContentView(view)
|
||||
mDatas.addAll(entity.gallery)
|
||||
view.titleTv.text = entity.title
|
||||
view.contentTv.text = entity.content
|
||||
|
||||
view.bannerView.apply {
|
||||
orientation = ViewPager2.ORIENTATION_HORIZONTAL
|
||||
mAdapter = BannerAdapter()
|
||||
val recyclerView = getChildAt(0) as RecyclerView
|
||||
recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_NEVER
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
super.onPageSelected(position)
|
||||
currentPage = position
|
||||
slideIndicator(currentPage % mDatas.size)
|
||||
}
|
||||
})
|
||||
recyclerView.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
|
||||
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
|
||||
val isStop = e.action == MotionEvent.ACTION_DOWN || e.action == MotionEvent.ACTION_MOVE
|
||||
if (isStop) mAdapter.stopScroll() else mAdapter.startScroll()
|
||||
return false
|
||||
}
|
||||
})
|
||||
adapter = mAdapter
|
||||
mLooperHandle = LooperHandle(mAdapter)
|
||||
currentPage = (adapter as BannerAdapter).getActualFirstPositionInCenter()
|
||||
setCurrentItem(currentPage, false)
|
||||
if (mDatas.size > 1) {
|
||||
addIndicator()
|
||||
slideIndicator(currentPage % mDatas.size)
|
||||
autoPlay()
|
||||
}
|
||||
}
|
||||
val isFirst = SPUtils.getBoolean(Constants.SP_FIRST_DEVICE_REMIND, false)
|
||||
if (!isFirst) {
|
||||
view.cancelTv.isEnabled = false
|
||||
view.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_round_f5f5f5)
|
||||
disposable = countDownTimer(3) { finish, time ->
|
||||
if (finish) {
|
||||
view.cancelTv.isEnabled = true
|
||||
view.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_blue_oval)
|
||||
view.cancelTv.text = "我知道了"
|
||||
view.cancelTv.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
} else {
|
||||
view.cancelTv.text = "我知道了(${time}S)"
|
||||
}
|
||||
}
|
||||
|
||||
SPUtils.setBoolean(Constants.SP_FIRST_DEVICE_REMIND, true)
|
||||
} else {
|
||||
view.noRemindAgainCb.visibility = View.VISIBLE
|
||||
view.cancelTv.text = "我知道了"
|
||||
view.cancelTv.isEnabled = true
|
||||
view.cancelTv.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
view.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_blue_oval)
|
||||
}
|
||||
view.cancelTv.setOnClickListener {
|
||||
SPUtils.setBoolean(Constants.SP_NO_REMIND_AGAIN, view.noRemindAgainCb.isChecked)
|
||||
dismiss()
|
||||
}
|
||||
DownloadManager.getInstance(context).addObserver(dataWatcher)
|
||||
}
|
||||
|
||||
private fun addIndicator() {
|
||||
view.indicatorLl.removeAllViews()
|
||||
mDatas.forEach { _ ->
|
||||
val indicatorView = ImageView(context).apply {
|
||||
setImageResource(R.drawable.selector_device_remind_indicator)
|
||||
val params = LinearLayout.LayoutParams(DisplayUtils.dip2px(8F), LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
params.leftMargin = DisplayUtils.dip2px(1F)
|
||||
params.rightMargin = DisplayUtils.dip2px(1F)
|
||||
layoutParams = params
|
||||
}
|
||||
view.indicatorLl.addView(indicatorView)
|
||||
}
|
||||
}
|
||||
|
||||
private fun slideIndicator(position: Int) {
|
||||
for (i in 0 until view.indicatorLl.childCount) {
|
||||
val childAt = view.indicatorLl.getChildAt(i)
|
||||
childAt.isSelected = i == position
|
||||
}
|
||||
}
|
||||
|
||||
private fun autoPlay() {
|
||||
mAdapter.startScroll()
|
||||
}
|
||||
|
||||
inner class BannerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return object : RecyclerView.ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_ad_banner, parent, false)) {}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = if (mDatas.size == 1) mDatas.size else Int.MAX_VALUE
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val data = mDatas[position % mDatas.size]
|
||||
val view = holder.itemView as SimpleDraweeView
|
||||
ImageUtils.display(view, data)
|
||||
}
|
||||
|
||||
fun getActualFirstPositionInCenter(): Int {
|
||||
if (mDatas.size == 1) return 0
|
||||
var index = itemCount / 2
|
||||
if (index % mDatas.size != 0) {
|
||||
index -= (index % mDatas.size)
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
fun scrollToNextPage() {
|
||||
currentPage++
|
||||
view.bannerView.setCurrentItem(currentPage, true)
|
||||
}
|
||||
|
||||
fun startScroll() {
|
||||
mLooperHandle.removeMessages(mSlideLooperKey)
|
||||
mLooperHandle.sendEmptyMessageDelayed(mSlideLooperKey, mSlideLooperInterval)
|
||||
}
|
||||
|
||||
fun stopScroll() {
|
||||
mLooperHandle.removeMessages(mSlideLooperKey)
|
||||
}
|
||||
}
|
||||
|
||||
class LooperHandle(val mAdapter: BannerAdapter) : Handler() {
|
||||
private val mWeakReference: WeakReference<BannerAdapter> = WeakReference(mAdapter)
|
||||
override fun handleMessage(msg: Message?) {
|
||||
val adapter = mWeakReference.get()
|
||||
adapter?.scrollToNextPage()
|
||||
adapter?.startScroll()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
if (disposable != null && !disposable!!.isDisposed) {
|
||||
disposable!!.dispose()
|
||||
disposable = null
|
||||
}
|
||||
DownloadManager.getInstance(context).removeObserver(dataWatcher)
|
||||
}
|
||||
}
|
||||
@ -8,12 +8,13 @@ import com.gh.common.util.MtaHelper
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
open class TrackableDialog(context: Context,
|
||||
themeResId: Int,
|
||||
private var mEvent: String,
|
||||
private var mKey: String,
|
||||
private var mCancelValue: String? = null,
|
||||
private var mKeyBackValue: String? = null,
|
||||
private var mLogShowEvent: Boolean = true)
|
||||
themeResId: Int,
|
||||
private var mEvent: String,
|
||||
private var mKey: String,
|
||||
private var mValue: String? = null,
|
||||
private var mCancelValue: String? = null,
|
||||
private var mKeyBackValue: String? = null,
|
||||
private var mLogShowEvent: Boolean = true)
|
||||
: Dialog(context, themeResId) {
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
@ -25,6 +26,9 @@ open class TrackableDialog(context: Context,
|
||||
setOnCancelListener {
|
||||
if (mIsCanceledByClickOutsideOfDialog.get()) {
|
||||
MtaHelper.onEvent(mEvent, mKey, mCancelValue ?: "点击空白")
|
||||
if (!mValue.isNullOrEmpty()) {
|
||||
MtaHelper.onEvent(mEvent, "点击空白", mValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +36,9 @@ open class TrackableDialog(context: Context,
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
|
||||
mIsCanceledByClickOutsideOfDialog.set(false)
|
||||
MtaHelper.onEvent(mEvent, mKey, mKeyBackValue ?: "点击返回")
|
||||
if (mValue != null) {
|
||||
MtaHelper.onEvent(mEvent, "点击返回", mValue)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
@ -41,6 +48,9 @@ open class TrackableDialog(context: Context,
|
||||
super.show()
|
||||
if (mLogShowEvent) {
|
||||
MtaHelper.onEvent(mEvent, mKey, "出现弹窗")
|
||||
if (!mValue.isNullOrEmpty()) {
|
||||
MtaHelper.onEvent(mEvent, "出现弹窗", mValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -31,9 +31,9 @@ object ExposureManager {
|
||||
private val loghubHelper = LoghubHelper.getInstance()
|
||||
|
||||
// exposureCache 用来过滤掉具有相同 id 的曝光事件,避免重复发送事件
|
||||
private val exposureSet = hashSetOf<ExposureEvent>()
|
||||
private val exposureExecutor = Executors.newSingleThreadExecutor()
|
||||
private val exposureCache = FixedSizeLinkedHashSet<String>(300)
|
||||
private val exposureSet by lazy { hashSetOf<ExposureEvent>() }
|
||||
private val exposureExecutor by lazy { Executors.newSingleThreadExecutor() }
|
||||
private val exposureCache by lazy { FixedSizeLinkedHashSet<String>(300) }
|
||||
private val exposureDao by lazy { ExposureDatabase.buildDatabase(HaloApp.getInstance().application).logHubEventDao() }
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@ -15,7 +15,7 @@ object LoghubUtils {
|
||||
|
||||
private lateinit var mApplication: Application
|
||||
|
||||
private val loghubEventSet = hashSetOf<LoghubEvent>()
|
||||
private val loghubEventSet by lazy { hashSetOf<LoghubEvent>() }
|
||||
private val loghubEventExecutor by lazy { Executors.newSingleThreadExecutor() }
|
||||
private val loghubEventDao by lazy { LoghubDatabase.buildDatabase(mApplication).logHubEventDao() }
|
||||
|
||||
@ -75,8 +75,16 @@ object LoghubUtils {
|
||||
}
|
||||
|
||||
val log = Log()
|
||||
log.PutContent("current time ", event.time)
|
||||
log.PutContent("content", event.content)
|
||||
// 特殊处理,以下logStore不需要用content包裹数据
|
||||
if (event.logStore == "collection" || event.logStore == "common" || event.logStore == "halo-api-device-installed") {
|
||||
val contentJson = JSONObject(event.content)
|
||||
for (key in contentJson.keys()) {
|
||||
log.PutContent(key, contentJson.get(key).toString())
|
||||
}
|
||||
} else {
|
||||
log.PutContent("current time ", event.time)
|
||||
log.PutContent("content", event.content)
|
||||
}
|
||||
logGroupHashMap[event.logStore]?.PutLog(log)
|
||||
}
|
||||
|
||||
|
||||
@ -14,4 +14,7 @@ object SyncFieldConstants {
|
||||
const val ANSWER_COMMENT_COUNT = "ANSWER_COMMENT_COUNT"
|
||||
const val ARTICLE_COMMENT_COUNT = "ARTICLE_COMMENT_COUNT"
|
||||
|
||||
// 回答数量
|
||||
const val ANSWER_COUNT = "ANSWER_COUNT"
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@ import android.graphics.BitmapFactory
|
||||
import android.graphics.Matrix
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.entity.SettingsEntity
|
||||
import com.github.piasy.biv.metadata.ImageInfoExtractor
|
||||
import com.halo.assistant.HaloApp
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
@ -26,11 +27,16 @@ object CompressImageUtils {
|
||||
* 压缩图片并保存到目标文件
|
||||
* 该压缩方法是同步执行 请勿在主线程执行
|
||||
* 返回源文件的三种情况:小于特定值,图片类型为GIF,压缩失败
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* 关于压缩格式问题:
|
||||
* 1.图片详情对动态Webp/静态Webp的判断存在问题,导致部分静态Webp图片误判为动态Webp而直接委托Fresco处理,出现无法缩放问题
|
||||
* 2.为了解决上述问题,如果压缩是检测到是动态Webp时直接压缩为JPEG,这样就能解决图片详情无法缩放问题(todo 这样会导致动态Webp无法播放)
|
||||
*/
|
||||
@Throws(Exception::class)
|
||||
fun compressImageAndSaveToFile(imageFile: File, compressGif: Boolean): File {
|
||||
val imageType = ImageInfoExtractor.getImageType(imageFile)
|
||||
// 小于某一个设定的值时,直接返回原图
|
||||
if (imageFile.length() < getImageSetting().processLimitSize) {
|
||||
if (imageType != ImageInfoExtractor.TYPE_ANIMATED_WEBP && imageFile.length() < getImageSetting().processLimitSize) {
|
||||
return imageFile
|
||||
}
|
||||
|
||||
@ -49,7 +55,7 @@ object CompressImageUtils {
|
||||
} else if (options.outMimeType.contains("gif") && !compressGif) { // gif直接返回原图
|
||||
return imageFile
|
||||
} else {
|
||||
Bitmap.CompressFormat.WEBP
|
||||
Bitmap.CompressFormat.JPEG
|
||||
}
|
||||
|
||||
fileOutputStream = FileOutputStream(cacheDir)
|
||||
@ -165,6 +171,7 @@ object CompressImageUtils {
|
||||
enum class CompressType {
|
||||
// 0: 短边等比压缩至1280 H:长边 W:短边
|
||||
LIMIT_SHORT,
|
||||
|
||||
// 1: 取长边等比压缩至1280 H:短边 W: 长边
|
||||
LIMIT_LONG
|
||||
}
|
||||
@ -9,8 +9,6 @@ import com.gh.gamecenter.manager.DataCollectionManager;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -169,24 +167,4 @@ public class DataCollectionUtils {
|
||||
map.put("type", args[2]);
|
||||
DataCollectionManager.onEvent(context, "concern", map);
|
||||
}
|
||||
|
||||
//上传推荐位数据
|
||||
public static void uploadPosition(Context context, String... args) {
|
||||
if (args.length < 3) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("page", args[0]);
|
||||
map.put("location", args[1]);
|
||||
map.put("name", args[2]);
|
||||
DataCollectionManager.onEvent(context, "position", map);
|
||||
}
|
||||
|
||||
//上传应用列表
|
||||
public static void uploadAppList(Context context, JSONArray applist) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("applist", applist);
|
||||
DataCollectionManager.onEvent(context, "applist", map);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,8 +2,7 @@ package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.common.loghub.LoghubUtils;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
@ -14,12 +13,6 @@ import org.json.JSONObject;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/12/8.
|
||||
* 日志上传工具类
|
||||
@ -68,12 +61,7 @@ public class DataLogUtils {
|
||||
params.put("time", String.valueOf(Utils.getTime(context)));
|
||||
params.put("content", new JSONObject(map).toString());
|
||||
|
||||
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
|
||||
new JSONObject(params).toString());
|
||||
RetrofitManager.getInstance(context).getData().postLog(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>());
|
||||
LoghubUtils.log(new JSONObject(params), "common", true);
|
||||
}
|
||||
|
||||
// 网络错误
|
||||
|
||||
@ -13,6 +13,7 @@ import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
/**
|
||||
* Created by khy on 27/06/17.
|
||||
@ -22,6 +23,7 @@ import com.lightgame.download.DownloadEntity;
|
||||
public class DetailDownloadUtils {
|
||||
|
||||
public static void detailInitDownload(DetailViewHolder viewHolder, boolean isCheck) {
|
||||
String downloadAddWord = viewHolder.gameEntity.getDownloadAddWord();
|
||||
|
||||
if (viewHolder.gameEntity != null
|
||||
&& Config.isShowDownload(viewHolder.gameEntity.getId())
|
||||
@ -34,10 +36,11 @@ public class DetailDownloadUtils {
|
||||
|
||||
if (viewHolder.gameEntity.isReservable()) {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(viewHolder.gameEntity.getId())) {
|
||||
if (TextUtils.isEmpty(viewHolder.downloadAddWord)) {
|
||||
|
||||
if (TextUtils.isEmpty(downloadAddWord)) {
|
||||
viewHolder.mDownloadPb.setText(String.format("预约" + "《%s》", viewHolder.gameEntity.getName()));
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(String.format("预约" + "《%s》%s", viewHolder.gameEntity.getName(), viewHolder.downloadAddWord));
|
||||
viewHolder.mDownloadPb.setText(String.format("预约" + "《%s》%s", viewHolder.gameEntity.getName(), downloadAddWord));
|
||||
}
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.RESERVABLE);
|
||||
} else {
|
||||
@ -49,10 +52,10 @@ public class DetailDownloadUtils {
|
||||
|
||||
if (viewHolder.gameEntity.getApk().isEmpty() || viewHolder.gameEntity.getDownloadOffStatus() != null) {
|
||||
LinkEntity h5LinkEntity = viewHolder.gameEntity.getH5Link();
|
||||
|
||||
|
||||
if (h5LinkEntity != null) {
|
||||
if ("play".equals(h5LinkEntity.getType())) {
|
||||
String defaultString = String.format("开始玩" + "《%s》", viewHolder.gameEntity.getName());
|
||||
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());
|
||||
@ -60,35 +63,39 @@ public class DetailDownloadUtils {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.H5_GAME);
|
||||
} else {
|
||||
if ("dialog".equals(viewHolder.gameEntity.getDownloadOffStatus())) {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "查看详情" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "查看详情" : viewHolder.gameEntity.getDownloadOffText());
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE_WITH_HINT);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.downloadOffText) ? "暂无下载" : viewHolder.downloadOffText);
|
||||
viewHolder.mDownloadPb.setText(TextUtils.isEmpty(viewHolder.gameEntity.getDownloadOffText()) ? "暂无下载" : viewHolder.gameEntity.getDownloadOffText());
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (viewHolder.gameEntity.getApk().size() == 1) {
|
||||
String status = GameUtils.getDownloadBtnText(viewHolder.context, viewHolder.gameEntity, PluginLocation.only_game);
|
||||
switch (status) {
|
||||
case "插件化":
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.PLUGIN);
|
||||
break;
|
||||
case "打开":
|
||||
case "启动":
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.LAUNCH_OR_OPEN);
|
||||
break;
|
||||
default:
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NORMAL);
|
||||
break;
|
||||
if (viewHolder.context.getString(R.string.pluggable).equals(status)) {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.PLUGIN);
|
||||
} else if (viewHolder.context.getString(R.string.launch).equals(status)) {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.LAUNCH_OR_OPEN);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NORMAL);
|
||||
}
|
||||
|
||||
String downloadText;
|
||||
if (viewHolder.isNewsDetail) {
|
||||
viewHolder.mDownloadPb.setText(status);
|
||||
} else if (TextUtils.isEmpty(viewHolder.downloadAddWord)) {
|
||||
viewHolder.mDownloadPb.setText(String.format(status + "《%s》", viewHolder.gameEntity.getName()));
|
||||
downloadText = status;
|
||||
} else if (viewHolder.context.getString(R.string.pluggable).equals(status)) {
|
||||
downloadText = "升级" + (TextUtils.isEmpty(downloadAddWord) ? "" : "至" + downloadAddWord) + getDownloadSizeText(viewHolder);
|
||||
} else if (viewHolder.context.getString(R.string.launch).equals(status)) {
|
||||
downloadText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord);
|
||||
} else if (viewHolder.context.getString(R.string.attempt).equals(status)) {
|
||||
downloadText = status + getDownloadSizeText(viewHolder);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText(String.format(status + "《%s》%s", viewHolder.gameEntity.getName(), viewHolder.downloadAddWord));
|
||||
downloadText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : downloadAddWord) + getDownloadSizeText(viewHolder);
|
||||
}
|
||||
viewHolder.mDownloadPb.setText(downloadText);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setText("选择下载你的版本" + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord) + " >");
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NORMAL);
|
||||
}
|
||||
if (isCheck && viewHolder.gameEntity.getApk().size() == 1) {
|
||||
String url = viewHolder.gameEntity.getApk().get(0).getUrl();
|
||||
@ -100,6 +107,10 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static String getDownloadSizeText(DetailViewHolder viewHolder) {
|
||||
return String.format("(%s)", viewHolder.gameEntity.getApk().get(0).getSize());
|
||||
}
|
||||
|
||||
public static void detailInvalidate(DetailViewHolder viewHolder) {
|
||||
viewHolder.mDownloadPb.setProgress((int) (viewHolder.downloadEntity.getPercent() * 10));
|
||||
DownloadEntity downloadEntity = viewHolder.downloadEntity;
|
||||
@ -128,7 +139,7 @@ public class DetailDownloadUtils {
|
||||
case done:
|
||||
viewHolder.mDownloadPb.setText(R.string.install);
|
||||
if (downloadEntity.isPluggable()
|
||||
&& PackagesManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
|
||||
&& PackagesManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_PLUGIN);
|
||||
} else {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_NORMAL);
|
||||
@ -143,6 +154,4 @@ public class DetailDownloadUtils {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.CountDownTimer;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Html;
|
||||
@ -29,23 +30,24 @@ 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.common.view.LimitHeightLinearLayout;
|
||||
import com.gh.common.view.MaxHeightNestedScrollView;
|
||||
import com.gh.gamecenter.AboutActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.adapter.viewholder.PrivacyPolicyItemViewHolder;
|
||||
import com.gh.gamecenter.databinding.ImprintContentItemBinding;
|
||||
import com.gh.gamecenter.databinding.PrivacyItemBinding;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.entity.TrackableEntity;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.halo.assistant.fragment.SettingsFragment;
|
||||
@ -53,9 +55,17 @@ import com.lightgame.adapter.BaseRecyclerAdapter;
|
||||
import com.lightgame.utils.AppManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class DialogUtils {
|
||||
|
||||
public static Dialog showWaitDialog(Context context, String msg) {
|
||||
@ -1097,6 +1107,7 @@ public class DialogUtils {
|
||||
R.style.GhAlertDialog,
|
||||
trackableEntity.getEvent(),
|
||||
trackableEntity.getKey(),
|
||||
trackableEntity.getValue(),
|
||||
trackableEntity.getCancelValue(),
|
||||
trackableEntity.getKeyBackValue(),
|
||||
trackableEntity.getLogShowEvent());
|
||||
@ -1224,6 +1235,114 @@ public class DialogUtils {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showVersionNumberDialog(Context context, GameEntity gameEntity, @NonNull ConfirmListener listener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
if (!gameEntity.isShowVersionNumber()) {
|
||||
listener.onConfirm();
|
||||
} else {
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_version_number, null);
|
||||
|
||||
TextView contentTv = contentView.findViewById(R.id.contentTv);
|
||||
TextView cancelTv = contentView.findViewById(R.id.cancelTv);
|
||||
TextView continueTv = contentView.findViewById(R.id.continueTv);
|
||||
|
||||
contentTv.setText(gameEntity.getVersionNumberString());
|
||||
cancelTv.setOnClickListener(v -> dialog.dismiss());
|
||||
continueTv.setOnClickListener(v -> {
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
public static void showImprintDialog(Context context, GameEntity gameEntity, String titleName) {
|
||||
context = checkDialogContext(context);
|
||||
Dialog dialog = new Dialog(context, R.style.full_dialog);
|
||||
View inflate = LayoutInflater.from(context).inflate(R.layout.imprint_dialog, null);
|
||||
dialog.setContentView(inflate);
|
||||
dialog.show();
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
WindowManager.LayoutParams params;
|
||||
if (window != null) {
|
||||
params = window.getAttributes();
|
||||
params.width = (int) (context.getResources().getDisplayMetrics().widthPixels * 0.9);
|
||||
window.setAttributes(params);
|
||||
window.setBackgroundDrawableResource(R.drawable.full_dialog_background);
|
||||
}
|
||||
|
||||
inflate.findViewById(R.id.imprint_close).setOnClickListener(v -> dialog.dismiss());
|
||||
LinearLayout content = inflate.findViewById(R.id.imprint_content);
|
||||
((TextView) inflate.findViewById(R.id.imprint_title)).setText(titleName);
|
||||
View head = LayoutInflater.from(context).inflate(R.layout.imprint_content_item, null);
|
||||
content.addView(head, LinearLayout.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(30));
|
||||
LimitHeightLinearLayout imprintContainer = inflate.findViewById(R.id.imprint_container);
|
||||
imprintContainer.setLimitHeight((int) (context.getResources().getDisplayMetrics().heightPixels * 0.8));
|
||||
|
||||
ArrayList<ApkEntity> list = gameEntity.getApk();
|
||||
SettingsEntity settings = Config.getSettings();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ApkEntity apk = gameEntity.getApk().get(i);
|
||||
if (settings != null && settings.getGameDownloadBlackList().contains(apk.getPackageName())) {
|
||||
continue;
|
||||
}
|
||||
View item = LayoutInflater.from(context).inflate(R.layout.imprint_content_item, null);
|
||||
ImprintContentItemBinding bind = DataBindingUtil.bind(item);
|
||||
bind.setApk(apk);
|
||||
bind.setPlatformName(PlatformUtils.getInstance(context).getPlatformName(apk.getPlatform()));
|
||||
content.addView(item, LinearLayout.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(40));
|
||||
}
|
||||
|
||||
|
||||
// close line
|
||||
View view = new View(context);
|
||||
view.setBackgroundColor(context.getResources().getColor(R.color.text_5d5d5d));
|
||||
view.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(1)));
|
||||
content.addView(view);
|
||||
}
|
||||
|
||||
public static void showKaifuRemindDialog(Context context, String content, String gameName) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new TrackableDialog(context, R.style.GhAlertDialog, "开服说明弹窗", "弹窗", gameName, null, null, true);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_kaifu_remind, null);
|
||||
|
||||
TextView contentTv = contentView.findViewById(R.id.contentTv);
|
||||
MaxHeightNestedScrollView scrollView = contentView.findViewById(R.id.scrollView);
|
||||
contentTv.setText(Html.fromHtml(content));
|
||||
TextView ok = contentView.findViewById(R.id.dialog_ok);
|
||||
scrollView.setScrollChangedListener((l, t, oldl, oldt) -> {
|
||||
MtaHelper.onEvent("开服说明弹窗", "滑动内容", gameName);
|
||||
});
|
||||
ok.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("开服说明弹窗", "弹窗", "点击我知道了");
|
||||
MtaHelper.onEvent("开服说明弹窗", "点击我知道了", gameName);
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context may be is application context
|
||||
* @return activity context
|
||||
|
||||
@ -188,7 +188,7 @@ object DirectUtils {
|
||||
|
||||
"column_collection", "专题合集" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
|
||||
|
||||
"server" -> {
|
||||
"server", "game_server" -> {
|
||||
context.startActivity(GameServersActivity.getIntent(context, entrance, path))
|
||||
}
|
||||
|
||||
@ -204,6 +204,20 @@ object DirectUtils {
|
||||
|
||||
"game_video" -> directToGameVideo(context, linkEntity.link ?: "", entrance, path)
|
||||
|
||||
"libao" -> directToGiftDetail(context, linkEntity.link ?: "", entrance)
|
||||
|
||||
"feedback" -> directToFeedback(context, linkEntity.name, linkEntity.text, entrance)
|
||||
|
||||
"qa" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "")
|
||||
|
||||
"qa_collection" -> directToQaCollection(context, linkEntity.text ?: "", linkEntity.link
|
||||
?: "")
|
||||
|
||||
"anliwall" -> directToAmway(context, fixedTopAmwayCommentId = null, entrance = entrance, path = path)
|
||||
|
||||
"" -> {
|
||||
// do nothing
|
||||
}
|
||||
else -> {
|
||||
if (unknownCallback != null) {
|
||||
unknownCallback.invoke()
|
||||
@ -214,11 +228,25 @@ object DirectUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至QA
|
||||
*/
|
||||
fun directToQa(context: Context, text: String, id: String) {
|
||||
context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaId = id))
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至QA合集
|
||||
*/
|
||||
fun directToQaCollection(context: Context, text: String, id: String) {
|
||||
context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaCollectionId = id))
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至专题合集
|
||||
*/
|
||||
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String) {
|
||||
context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance))
|
||||
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String, columnName: String = "") {
|
||||
context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance, columnName))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -315,12 +343,21 @@ object DirectUtils {
|
||||
// 反馈
|
||||
@JvmStatic
|
||||
fun directToFeedback(context: Context, content: String? = null, entrance: String? = null) {
|
||||
directToFeedback(context, content, null, entrance)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToFeedback(context: Context, content: String? = null, hintType: String? = null, entrance: String? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, SuggestionActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_CONTENT, content)
|
||||
bundle.putString(KEY_SUGGEST_HINT_TYPE, KEY_PLUGIN)
|
||||
bundle.putSerializable(EntranceUtils.KEY_SUGGESTTYPE, SuggestType.gameQuestion)
|
||||
if (TextUtils.isEmpty(hintType)) {
|
||||
bundle.putString(KEY_SUGGEST_HINT_TYPE, KEY_PLUGIN)
|
||||
} else {
|
||||
bundle.putString(KEY_SUGGEST_HINT_TYPE, hintType)
|
||||
}
|
||||
bundle.putSerializable(KEY_SUGGESTTYPE, SuggestType.gameQuestion)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -449,6 +486,7 @@ object DirectUtils {
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
// 未安装手Q或安装的版本不支持
|
||||
Utils.toast(context, "请安装QQ客户端")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,13 +8,21 @@ import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.CertificationDialog;
|
||||
import com.gh.common.dialog.DeviceRemindDialog;
|
||||
import com.gh.common.dialog.ReserveDialogFragment;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.common.view.DownloadDialog;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
@ -32,12 +40,9 @@ 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;
|
||||
|
||||
/**
|
||||
* todo 下载判断不能以按钮文案为判断条件,否则按钮文案修改时又要修改判断逻辑
|
||||
*/
|
||||
public class DownloadItemUtils {
|
||||
|
||||
// 更新下载进度条
|
||||
@ -125,20 +130,20 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadBtn.setTextColor(Color.WHITE);
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_pause_dn);
|
||||
}
|
||||
if (gameEntity.isLibaoExists()) {
|
||||
holder.gameLibaoIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.gameLibaoIcon.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
|
||||
boolean isShowPlatform) {
|
||||
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game);
|
||||
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, false);
|
||||
}
|
||||
|
||||
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
|
||||
boolean isShowPlatform, PluginLocation pluginLocation) {
|
||||
boolean isShowPlatform, boolean hideDownloadBtnIfNoAvailableContent) {
|
||||
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, hideDownloadBtnIfNoAvailableContent);
|
||||
}
|
||||
|
||||
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
|
||||
boolean isShowPlatform, PluginLocation pluginLocation, boolean hideDownloadBtnIfNoAvailableContent) {
|
||||
|
||||
// 控制是否显示下载按钮
|
||||
if (!Config.isShowDownload(gameEntity.getId()) || context.getString(R.string.app_name).equals(gameEntity.getName())) {
|
||||
@ -147,12 +152,6 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadBtn.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (gameEntity.isLibaoExists()) {
|
||||
holder.gameLibaoIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.gameLibaoIcon.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// 显示预约
|
||||
if (gameEntity.isReservable()) {
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
@ -171,14 +170,14 @@ public class DownloadItemUtils {
|
||||
}
|
||||
|
||||
if (gameEntity.getApk().isEmpty()
|
||||
|| gameEntity.getDownloadOffStatus() != null) {
|
||||
|| 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);
|
||||
|
||||
|
||||
if (h5LinkEntity != null) {
|
||||
if ("play".equals(h5LinkEntity.getType())) {
|
||||
holder.gameDownloadBtn.setText("开始玩");
|
||||
@ -195,6 +194,9 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadBtn.setText("暂无");
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColor(context, R.color.button_gray));
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.news_detail_comment);
|
||||
if (hideDownloadBtnIfNoAvailableContent) {
|
||||
holder.gameDownloadBtn.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
}
|
||||
@ -334,10 +336,10 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadBtn.setText(R.string.install);
|
||||
holder.gameDownloadBtn.setTextColor(Color.WHITE);
|
||||
if (downloadEntity.isPluggable()
|
||||
&& PackagesManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
&& PackagesManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.download_button_pluggable_style);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.download_button_normal_style);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -420,7 +422,7 @@ public class DownloadItemUtils {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (gameEntity.getApk().size() == 0 && gameEntity.getH5Link() != null) {
|
||||
downloadBtn.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("H5页面", "入口", "列表页_" + gameEntity.getName());
|
||||
@ -449,7 +451,15 @@ public class DownloadItemUtils {
|
||||
clickCallback.onCallback();
|
||||
}
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(context, () -> {
|
||||
DownloadDialog.getInstance(context).showPopupWindow(v, gameEntity, entrance, location, traceEvent);
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
|
||||
DownloadDialog.showDownloadDialog(
|
||||
v.getContext(),
|
||||
gameEntity,
|
||||
entrance,
|
||||
location);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -480,19 +490,38 @@ public class DownloadItemUtils {
|
||||
if (str.equals(context.getString(R.string.download))) {
|
||||
// 先弹下载弹窗(如果需要的话)
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
});
|
||||
|
||||
DataLogUtils.uploadGameLog(context, gameEntity.getId(), gameEntity.getName(), entrance);
|
||||
} else if (str.equals(context.getString(R.string.pluggable))) {
|
||||
} else if (str.equals(context.getString(R.string.attempt))) {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
DataLogUtils.uploadGameLog(context, gameEntity.getId(), gameEntity.getName(), entrance);
|
||||
} else if (str.contains("化")) {
|
||||
if (entrance.contains("我的游戏")) {
|
||||
MtaHelper.onEvent("我的游戏_启动", "插件化", gameEntity.getName());
|
||||
}
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> plugin(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
if (gameEntity.getPluggableCollection() != null) {
|
||||
DownloadDialog.showDownloadDialog(context, gameEntity, entrance, location);
|
||||
} else {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> plugin(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
});
|
||||
}
|
||||
} else if (str.equals(context.getString(R.string.install))) {
|
||||
install(context, gameEntity, position, adapter);
|
||||
} else if (str.equals(context.getString(R.string.launch))) {
|
||||
@ -536,6 +565,7 @@ public class DownloadItemUtils {
|
||||
downloadBtn.setText(R.string.downloading);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
|
||||
DeviceRemindDialog.Companion.showDeviceRemindDialog(context, gameEntity);
|
||||
} else {
|
||||
Utils.toast(context, msg);
|
||||
}
|
||||
@ -575,6 +605,8 @@ public class DownloadItemUtils {
|
||||
gameEntity.getEntryMap().remove(apkEntity.getPlatform());
|
||||
}
|
||||
adapter.notifyItemChanged(position);
|
||||
} else if (PackageUtils.isCanPluggable(apkEntity)) {
|
||||
DialogUtils.showPluginDialog(context, () -> context.startActivity(PackageUtils.getUninstallIntent(context, path)));
|
||||
} else {
|
||||
PackageUtils.launchSetup(context, downloadEntity);
|
||||
}
|
||||
@ -584,12 +616,12 @@ public class DownloadItemUtils {
|
||||
//更新
|
||||
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);
|
||||
.getPlatform(), traceEvent, downloadType);
|
||||
DownloadManager.createDownload(context, gameEntity, "更新", entrance, location, isSubscribe, downloadExposureEvent);
|
||||
}
|
||||
|
||||
|
||||
@ -35,13 +35,15 @@ import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
object DownloadObserver {
|
||||
|
||||
|
||||
private val mApplication = HaloApp.getInstance().application
|
||||
|
||||
@JvmStatic
|
||||
fun initObserver() {
|
||||
val dataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
val gameId = downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER)
|
||||
|
||||
if (downloadEntity.status != DownloadStatus.downloading) {
|
||||
LogUtils.uploadDownloadEvent(downloadEntity)
|
||||
}
|
||||
@ -51,7 +53,7 @@ object DownloadObserver {
|
||||
processHijack(downloadEntity)
|
||||
val nameAndPlatform = (downloadEntity.name + ":"
|
||||
+ PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
|
||||
MtaHelper.onEvent( "下载劫持",
|
||||
MtaHelper.onEvent("下载劫持",
|
||||
"游戏名字", nameAndPlatform,
|
||||
"网络状态", DeviceUtils.getNetwork(mApplication))
|
||||
return
|
||||
@ -70,7 +72,7 @@ object DownloadObserver {
|
||||
SuggestionActivity.startSuggestionActivity(AppManager.getInstance().currentActivity(),
|
||||
SuggestType.gameQuestion, "notfound",
|
||||
StringUtils.buildString(downloadEntity.name, ",问题反馈:下载链接失效"),
|
||||
SimpleGameEntity(downloadEntity.gameId, downloadEntity.name, ""))
|
||||
SimpleGameEntity(gameId, downloadEntity.name, ""))
|
||||
}, null)
|
||||
return
|
||||
} else if (DownloadStatus.neterror == downloadEntity.status || DownloadStatus.timeout == downloadEntity.status) {
|
||||
@ -126,7 +128,7 @@ object DownloadObserver {
|
||||
}
|
||||
|
||||
// 统计下载完成
|
||||
uploadData(downloadEntity.gameId, downloadEntity.platform)
|
||||
uploadData(gameId, downloadEntity.platform)
|
||||
}
|
||||
|
||||
// 下载过程分析统计
|
||||
@ -142,7 +144,7 @@ object DownloadObserver {
|
||||
}
|
||||
|
||||
if (downloadEntity.status == DownloadStatus.done) {
|
||||
EventBus.getDefault().post(EBDownloadStatus("done", "", "", "", "", ""))
|
||||
EventBus.getDefault().post(EBDownloadStatus("done", "", "", "", downloadEntity.packageName, ""))
|
||||
}
|
||||
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
@ -188,7 +190,7 @@ object DownloadObserver {
|
||||
val kv3 = HashMap<String, Any>()
|
||||
kv3["下载"] = "下载完成"
|
||||
kv3["版本"] = downloadEntity.platform
|
||||
kv3["位置"] = downloadEntity.entrance ?: "null"
|
||||
kv3["位置"] = downloadEntity.entrance ?: "null"
|
||||
type = ExposureUtils.DownloadType.PLUGIN_DOWNLOAD
|
||||
DataUtils.onEvent(mApplication, "插件化", downloadEntity.name, kv3)
|
||||
|
||||
@ -201,7 +203,7 @@ object DownloadObserver {
|
||||
}
|
||||
|
||||
ExposureUtils.logADownloadCompleteExposureEvent(
|
||||
GameEntity(downloadEntity.gameId, downloadEntity.name),
|
||||
GameEntity(downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER), downloadEntity.name),
|
||||
downloadEntity.platform,
|
||||
downloadEntity.exposureTrace,
|
||||
type)
|
||||
|
||||
@ -86,6 +86,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_OLDERUSER = "isOldUser";
|
||||
public static final String KEY_SEARCHKEY = "searchKey";
|
||||
public static final String KEY_HINT = "hint";
|
||||
public static final String KEY_GAME = "game";
|
||||
public static final String KEY_GAME_ICON_URL = "gameIconUrl";
|
||||
public static final String KEY_SHARECONTENT = "shareContent";
|
||||
public static final String KEY_SUGGESTTYPE = "suggestType";
|
||||
@ -138,6 +139,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_DIRECT_COMMENT = "directComment";
|
||||
public static final String KEY_SORT = "sort";
|
||||
public static final String KEY_AMWAY = "amway";
|
||||
public static final String KEY_SKIP_SUCCESS_PAGE = "skipSuccessPage";
|
||||
public static final String KEY_COLLECTION_ID = "collectionId";
|
||||
public static final String KEY_NAVIGATION_TITLE = "navigationTitle";
|
||||
public static final String KEY_IMAGE_CROP_RATIO = "imageCropRatio";
|
||||
@ -149,6 +151,9 @@ public class EntranceUtils {
|
||||
public static final String KEY_WEB_SHARE = "webShare";
|
||||
public static final String KEY_ACTIVITY_NAME = "activityName";//活动名称
|
||||
public static final String KEY_REQUIRE_REDIRECT = "require_redirect"; // 标记需要再跳转
|
||||
public static final String KEY_COLUMNNAME = "columnName";
|
||||
public static final String KEY_QA_ID = "qaId";
|
||||
public static final String KEY_QA_COLLECTION_ID = "qaCollectionId";
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
@ -237,6 +237,15 @@ inline fun tryCatchInRelease(action: (() -> Unit)) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 debug 状态下抛出异常
|
||||
*/
|
||||
fun throwExceptionInDebug(message: String = "", predicate: Boolean = true) {
|
||||
if (predicate && BuildConfig.DEBUG) {
|
||||
throw RuntimeException(message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String related
|
||||
*/
|
||||
|
||||
@ -82,11 +82,70 @@ object GameRepositoryHelper {
|
||||
return null
|
||||
}
|
||||
|
||||
fun replaceInstalledApp(gameList: MutableList<GameEntity>,
|
||||
alreadyDisplayedGameIdSet: HashSet<String>,
|
||||
relatedCollectionId: String,
|
||||
shouldLogReplaceEvent: Boolean) {
|
||||
val positionOfTheGameToReplaceList = arrayListOf<Int>()
|
||||
|
||||
// 标记需要替换的已安装游戏
|
||||
for ((index, game) in gameList.withIndex()) {
|
||||
|
||||
// 是大图形式的游戏时不标记替换
|
||||
if ((index == 0 && !gameList[0].image.isNullOrEmpty())) {
|
||||
continue
|
||||
}
|
||||
|
||||
var isThisPositionAdded = false
|
||||
// 检查是否已安装该游戏里同包名的 APK
|
||||
for (apk in game.getApk()) {
|
||||
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
|
||||
// 将该位置的游戏标记为需要替换
|
||||
positionOfTheGameToReplaceList.add(index)
|
||||
isThisPositionAdded = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 若此游戏所包含的 apk 没有已安装,那么再检查是否已安装有预设相关包名
|
||||
if (!isThisPositionAdded) {
|
||||
var relatedPackageList = arrayListOf<String>()
|
||||
for (entity in PackageHelper.relatedPackageList) {
|
||||
if (entity.gameId == game.id) {
|
||||
relatedPackageList = ArrayList(entity.packages)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for (packageName in relatedPackageList) {
|
||||
if (PackageHelper.validLocalPackageNameSet.contains(packageName)) {
|
||||
positionOfTheGameToReplaceList.add(index)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (positionOfTheGameToReplaceList.isNotEmpty()) {
|
||||
if (shouldLogReplaceEvent) {
|
||||
MtaHelper.onEvent("首页_加载", "启动光环", "替换游戏")
|
||||
}
|
||||
for (position in positionOfTheGameToReplaceList) {
|
||||
val replacingGame = getOneUniqueGame(relatedCollectionId, alreadyDisplayedGameIdSet)
|
||||
replacingGame?.let {
|
||||
gameList[position] = replacingGame
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun isThisGameUnique(game: GameEntity, gameIdList: HashSet<String>): Boolean {
|
||||
// 若该补充游戏已经存在关联关系,判定为非唯一
|
||||
for (relatedId in game.relatedGameIds!!) {
|
||||
gameIdList.contains(relatedId)
|
||||
return false
|
||||
if (gameIdList.contains(relatedId)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for (apk in game.getApk()) {
|
||||
// 检查本地是否已安装该游戏,已过滤那部分框架服务的包名
|
||||
|
||||
@ -5,12 +5,12 @@ import android.graphics.Color;
|
||||
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;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.ApkLink;
|
||||
import com.gh.gamecenter.entity.GameCollectionEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
@ -19,8 +19,11 @@ import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
|
||||
public class GameUtils {
|
||||
|
||||
@ -53,13 +56,13 @@ public class GameUtils {
|
||||
String status = getDownloadBtnText(context, gameEntity, pluginLocation);
|
||||
downloadBtn.setTextColor(Color.WHITE);
|
||||
downloadBtn.setText(status);
|
||||
if ("插件化".equals(status)) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
} else if ("打开".equals(status) || "启动".equals(status)) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.detail_download_open_style);
|
||||
downloadBtn.setTextColor(ContextCompat.getColor(context, R.color.theme_font));
|
||||
if (context.getString(R.string.pluggable).equals(status)) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.download_button_pluggable_style);
|
||||
String pluginDesc = gameEntity.getPluginDesc();
|
||||
if (pluginDesc.length() > 3) pluginDesc = pluginDesc.substring(0, 3);
|
||||
downloadBtn.setText((pluginDesc + "化"));
|
||||
} else {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
downloadBtn.setBackgroundResource(R.drawable.download_button_normal_style);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +70,10 @@ public class GameUtils {
|
||||
* 获取下载按钮文案
|
||||
*/
|
||||
public static String getDownloadBtnText(Context context, GameEntity gameEntity, PluginLocation pluginLocation) {
|
||||
if (gameEntity.getApk().size() > 1) {
|
||||
return context.getString(R.string.expand);
|
||||
}
|
||||
|
||||
int doneCount = 0; // 下载完成数量
|
||||
int pluginCount = 0; // 可插件化数量
|
||||
int updateCount = 0; // 可更新数量
|
||||
@ -118,18 +125,59 @@ public class GameUtils {
|
||||
} else if (updateCount != 0) {
|
||||
return context.getString(R.string.update);
|
||||
} else if (installCount != 0) {
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
return context.getString(R.string.launch);
|
||||
} else {
|
||||
return context.getString(R.string.open);
|
||||
}
|
||||
return context.getString(R.string.launch);
|
||||
} else if (gameEntity.getVersionNumber().contains("无版号") && Config.isGameDomeSwitchOpen()) {
|
||||
return context.getString(R.string.attempt);
|
||||
} else {
|
||||
return context.getString(R.string.download);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取GameUpdateEntity
|
||||
* 获取简单的下载按钮文案,只需要知道是否已下载,是否已安装
|
||||
*/
|
||||
public static String getSimpleDownloadBtnText(Context context, GameEntity gameEntity) {
|
||||
int doneCount = 0; // 下载完成数量
|
||||
int installCount = 0; // 已安装数量
|
||||
|
||||
DownloadEntity downloadEntity;
|
||||
Object gh_id;
|
||||
apkFor:
|
||||
for (ApkEntity apkEntity : gameEntity.getApk()) {
|
||||
// filter by packageName
|
||||
SettingsEntity settings = Config.getSettings();
|
||||
if (settings != null && gameEntity.getApk().size() > 1) {
|
||||
for (String pkgName : settings.getGameDownloadBlackList()) {
|
||||
if (pkgName.equals(apkEntity.getPackageName())) {
|
||||
continue apkFor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
downloadEntity = DownloadManager.getInstance(context).getDownloadEntityByUrl(apkEntity.getUrl());
|
||||
if (downloadEntity != null) {
|
||||
if (downloadEntity.getStatus().equals(DownloadStatus.done)) {
|
||||
doneCount++;
|
||||
}
|
||||
}
|
||||
if (PackagesManager.INSTANCE.isInstalled(apkEntity.getPackageName())) {
|
||||
gh_id = PackageUtils.getMetaData(context, apkEntity.getPackageName(), "gh_id");
|
||||
if (gh_id == null || gh_id.equals(gameEntity.getId())) {
|
||||
installCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (doneCount != 0) {
|
||||
return context.getString(R.string.install);
|
||||
} else if (installCount != 0) {
|
||||
return context.getString(R.string.launch);
|
||||
} else {
|
||||
return context.getString(R.string.download);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取GameUpdateEntity(插件化)
|
||||
*/
|
||||
public static GameUpdateEntity getGameUpdateEntity(GameEntity gameEntity, ApkEntity apkEntity) {
|
||||
GameUpdateEntity gameUpdateEntity = new GameUpdateEntity();
|
||||
@ -150,7 +198,50 @@ public class GameUtils {
|
||||
gameUpdateEntity.setPlugin(apkEntity.getPlugin());
|
||||
gameUpdateEntity.setDownload(gameEntity.getDownload());
|
||||
gameUpdateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
gameUpdateEntity.setPluginDesc(gameEntity.getPluginDesc());
|
||||
|
||||
GameCollectionEntity pluggableCollection = getPluggableCollectionFromGameEntity(gameEntity, apkEntity.getPackageName());
|
||||
if (pluggableCollection != null) {
|
||||
gameUpdateEntity.setPluggableCollection(pluggableCollection);
|
||||
}
|
||||
return gameUpdateEntity;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GameCollectionEntity getPluggableCollectionFromGameEntity(GameEntity gameEntity, String targetPkg) {
|
||||
// 添加插件化包所在的合集
|
||||
for (GameCollectionEntity collectionEntity : gameEntity.getCollection()) {
|
||||
if (collectionEntity.getPackages().contains(targetPkg)) {
|
||||
ArrayList<ApkEntity> saveApkEntity = new ArrayList<>();
|
||||
for (String pkg : collectionEntity.getPackages()) {
|
||||
for (ApkEntity apk : gameEntity.getApk()) {
|
||||
if (pkg.equals(apk.getPackageName())) {
|
||||
saveApkEntity.add(apk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<ApkLink> apkLinks = gameEntity.getApkLink();
|
||||
if (apkLinks != null) {
|
||||
for (ApkLink apkLink : apkLinks) {
|
||||
if (apkLink.getCollection().equals(collectionEntity.getId())) {
|
||||
ApkEntity element = new ApkEntity();
|
||||
element.setApkLink(apkLink);
|
||||
if (saveApkEntity.size() > apkLink.getSort()) {
|
||||
saveApkEntity.add(apkLink.getSort(), element);
|
||||
} else {
|
||||
saveApkEntity.add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectionEntity.setSaveApkEntity(saveApkEntity);
|
||||
return collectionEntity;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -10,6 +10,9 @@ import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.TagStyleEntity;
|
||||
|
||||
@ -21,8 +24,6 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
/**
|
||||
* @author 温冠超
|
||||
* @email 294299195@qq.com
|
||||
@ -32,21 +33,16 @@ import androidx.core.content.ContextCompat;
|
||||
*/
|
||||
public class GameViewUtils {
|
||||
|
||||
public static void setLabelList(Context context, LinearLayout labelLayout, List<String> tag, String tagType, List<TagStyleEntity> tagStyle) {
|
||||
public static void setLabelList(Context context, LinearLayout labelLayout, List<TagStyleEntity> tagStyle) {
|
||||
labelLayout.removeAllViews();
|
||||
if (tag == null || tag.isEmpty()) {
|
||||
labelLayout.addView(getGameTagView(context, "官方版", 0, tagType, null));
|
||||
if (tagStyle == null || tagStyle.isEmpty()) {
|
||||
TagStyleEntity tagEntity = new TagStyleEntity();
|
||||
tagEntity.setName("官方版");
|
||||
labelLayout.addView(getNewGameTagView(context, tagEntity, 0));
|
||||
} else {
|
||||
for (int i = 0, size = tag.size(); i < size; i++) {
|
||||
View view;
|
||||
if (i == size - 1) {
|
||||
view = getGameTagView(context, tag.get(i), 0, tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
|
||||
} else {
|
||||
view = getGameTagView(context, tag.get(i), DisplayUtils.dip2px(context, 8), tagType, tagStyle.size() > i ? tagStyle.get(i) : null);
|
||||
}
|
||||
if (view != null) {
|
||||
labelLayout.addView(view);
|
||||
}
|
||||
for (int i = 0, size = tagStyle.size(); i < size; i++) {
|
||||
View view = getNewGameTagView(context, tagStyle.get(i), i == size - 1 ? 0 : DisplayUtils.dip2px(context, 8));
|
||||
labelLayout.addView(view);
|
||||
if (labelLayout.getChildCount() == 3) {
|
||||
break;
|
||||
}
|
||||
@ -76,6 +72,32 @@ public class GameViewUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// 新的游戏标签样式 version>=4.0.0
|
||||
private static TextView getNewGameTagView(Context context, TagStyleEntity tagEntity, int rightMargin) {
|
||||
// 参数不全,用旧样式实现
|
||||
if (TextUtils.isEmpty(tagEntity.getBackground())) {
|
||||
return getGameTagView(context, tagEntity.getName(), rightMargin, "type", tagEntity);
|
||||
}
|
||||
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
|
||||
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
lparams.rightMargin = rightMargin;
|
||||
TextView tag = new TextView(context);
|
||||
tag.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
|
||||
tag.setSingleLine(true);
|
||||
tag.setText(tagEntity.getName());
|
||||
tag.setLayoutParams(lparams);
|
||||
tag.setPadding(
|
||||
DisplayUtils.dip2px(context, 4),
|
||||
0,
|
||||
DisplayUtils.dip2px(context, 4),
|
||||
DisplayUtils.dip2px(context, 1));
|
||||
|
||||
tag.setTextColor(Color.parseColor("#" + tagEntity.getColor()));
|
||||
tag.setBackground(DrawableView.getServerDrawable(Color.parseColor("#" + tagEntity.getBackground())));
|
||||
return tag;
|
||||
}
|
||||
|
||||
private static TextView getGameTagView(Context context, String tagStr, int rightMargin, String tagType, TagStyleEntity tagEntity) {
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
|
||||
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
|
||||
@ -22,6 +22,12 @@ object GsonUtils {
|
||||
return gson.fromJson(json.toString(), type)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun <T> fromJsonList(json: String): List<T> {
|
||||
val type = object : TypeToken<List<T>>() {}.type
|
||||
return gson.fromJson(json, type)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun toJson(any: Any?): String {
|
||||
return gson.toJson(any)
|
||||
|
||||
@ -16,12 +16,14 @@ import com.facebook.drawee.controller.ControllerListener
|
||||
import com.facebook.drawee.drawable.ScalingUtils
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.facebook.imagepipeline.core.ImagePipeline
|
||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
||||
import com.facebook.imagepipeline.image.ImageInfo
|
||||
import com.facebook.imagepipeline.request.ImageRequest
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
|
||||
@ -323,6 +325,14 @@ object ImageUtils {
|
||||
draweeView.setImageURI("res:///" + res)
|
||||
}
|
||||
|
||||
//预加载图片
|
||||
@JvmStatic
|
||||
fun prefetchToDiskCache(url: String){
|
||||
val imagePipeline = Fresco.getImagePipeline()
|
||||
val imageRequest = ImageRequest.fromUri(url)
|
||||
imagePipeline.prefetchToDiskCache(imageRequest, HaloApp.getInstance().application)
|
||||
}
|
||||
|
||||
public interface OnImageloadListener {
|
||||
fun onLoadFinal(imageInfo: ImageInfo?)
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ public class InstallUtils {
|
||||
if (!TextUtils.isEmpty(installVersion) && downloadEntity != null &&
|
||||
installVersion.equals(downloadEntity.getVersionName())) {
|
||||
if (!downloadEntity.isPluggable() || PackageUtils.isSignature(context, packageName)) {
|
||||
EventBus.getDefault().post(new EBPackage("安装", packageName));
|
||||
EventBus.getDefault().post(new EBPackage("安装", packageName, installVersion));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,7 +85,7 @@ public class InstallUtils {
|
||||
keys.add(packageName);
|
||||
} else if (!list.contains(packageName)) {
|
||||
keys.add(packageName);
|
||||
EventBus.getDefault().post(new EBPackage("卸载", packageName));
|
||||
EventBus.getDefault().post(new EBPackage("卸载", packageName, ""));
|
||||
}
|
||||
}
|
||||
for (String key : keys) {
|
||||
|
||||
@ -11,8 +11,6 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.LibaoDetailAdapter;
|
||||
@ -37,6 +35,7 @@ import org.json.JSONObject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
@ -151,76 +150,76 @@ public class LibaoUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public static void setLiBaoBtnStatus(final TextView libaoBtn, String status, Context context) {
|
||||
public static void setLiBaoBtnStatusRound(final TextView libaoBtn, String status, Context context) {
|
||||
libaoBtn.setTextColor(Color.WHITE);
|
||||
if (TextUtils.isEmpty(status)) return;
|
||||
switch (status) {
|
||||
case "ling":
|
||||
libaoBtn.setText(R.string.libao_ling);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
case "tao":
|
||||
libaoBtn.setText(R.string.libao_tao);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
case "coming":
|
||||
libaoBtn.setText(R.string.libao_coming);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "used_up":
|
||||
libaoBtn.setText(R.string.libao_used_up);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "finish":
|
||||
libaoBtn.setText(R.string.libao_finish);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_gray);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_round_gray);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.button_gray));
|
||||
break;
|
||||
case "linged":
|
||||
libaoBtn.setText(R.string.libao_linged);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "taoed":
|
||||
libaoBtn.setText(R.string.libao_taoed);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "copy":
|
||||
libaoBtn.setText(R.string.libao_copy);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
case "repeatLing":
|
||||
libaoBtn.setText(R.string.libao_repeat_ling);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "repeatLinged":
|
||||
libaoBtn.setText(R.string.libao_repeat_ling);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
case "repeatTao":
|
||||
libaoBtn.setText(R.string.libao_repeat_tao);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_border);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_border);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.theme_font));
|
||||
break;
|
||||
case "repeatTaoed":
|
||||
libaoBtn.setText(R.string.libao_repeat_tao);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
case "unshelve":
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_gray);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_round_gray);
|
||||
libaoBtn.setText(R.string.libao_unshelve);
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.button_gray));
|
||||
break;
|
||||
case "check":
|
||||
libaoBtn.setText(R.string.libao_check);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_style);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_normal_round_style);
|
||||
break;
|
||||
default:
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_gray);
|
||||
libaoBtn.setBackgroundResource(R.drawable.button_border_round_gray);
|
||||
libaoBtn.setText("异常");
|
||||
libaoBtn.setTextColor(context.getResources().getColor(R.color.button_gray));
|
||||
break;
|
||||
@ -230,7 +229,7 @@ public class LibaoUtils {
|
||||
public static void initLibaoBtn(final Context context, final TextView libaoBtn, final LibaoEntity libaoEntity,
|
||||
final boolean isInstallRequired, final LibaoDetailAdapter adapter, final String entrance) {
|
||||
String status = libaoEntity.getStatus();
|
||||
setLiBaoBtnStatus(libaoBtn, status, context);
|
||||
setLiBaoBtnStatusRound(libaoBtn, status, context);
|
||||
|
||||
libaoBtn.setOnClickListener(v -> {
|
||||
String btnStatus = libaoBtn.getText().toString();
|
||||
|
||||
@ -46,7 +46,7 @@ public class NewsUtils {
|
||||
* 统计阅读量
|
||||
*/
|
||||
public static void statNewsViews(Context context, String news_id) {
|
||||
RetrofitManager.getInstance(context).getData().postNewsViews(news_id)
|
||||
RetrofitManager.getInstance(context).getApi().postArticleVisit(news_id)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>());
|
||||
|
||||
@ -8,7 +8,6 @@ import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.Signature;
|
||||
import android.content.pm.SigningInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@ -21,6 +20,7 @@ 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.gh.gamecenter.manager.PackagesManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -31,12 +31,17 @@ import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
public class PackageUtils {
|
||||
@ -46,47 +51,39 @@ public class PackageUtils {
|
||||
/*
|
||||
* 判断是否可以更新,只判断gh_version的大小
|
||||
*/
|
||||
public static List<GameUpdateEntity> isCanUpdate(Context context, GameEntity gameEntity) {
|
||||
public static List<GameUpdateEntity> getUpdateData(Context context, GameEntity gameEntity) {
|
||||
|
||||
List<GameUpdateEntity> updateList = new ArrayList<>();
|
||||
|
||||
boolean isAPluginGame = false;
|
||||
// 插件更新
|
||||
for (ApkEntity apkEntity : gameEntity.getApk()) {
|
||||
// 判断是否gh_version是否存在
|
||||
String gh_version = (String) PackageUtils.getMetaData(context, apkEntity.getPackageName(), "gh_version");
|
||||
Object gh_id = PackageUtils.getMetaData(context, apkEntity.getPackageName(), "gh_id");
|
||||
if (gh_version != null && apkEntity.getGhVersion() != null && gh_id != null) {
|
||||
|
||||
// 确定这是一个插件游戏
|
||||
if (!isAPluginGame) isAPluginGame = true;
|
||||
gh_version = gh_version.substring(2);
|
||||
if (Long.parseLong(gh_version) < Long.parseLong(apkEntity.getGhVersion()) && apkEntity.getForce()
|
||||
&& gh_id.equals(gameEntity.getId())) {
|
||||
GameUpdateEntity updateEntity = new GameUpdateEntity();
|
||||
updateEntity.setId(gameEntity.getId());
|
||||
updateEntity.setName(gameEntity.getName());
|
||||
updateEntity.setIcon(gameEntity.getIcon());
|
||||
updateEntity.setPackageName(apkEntity.getPackageName());
|
||||
updateEntity.setSize(apkEntity.getSize());
|
||||
updateEntity.setVersion(apkEntity.getVersion());
|
||||
updateEntity.setGhVersion(apkEntity.getGhVersion());
|
||||
updateEntity.setUrl(apkEntity.getUrl());
|
||||
updateEntity.setPlatform(apkEntity.getPlatform());
|
||||
updateEntity.setEtag(apkEntity.getEtag());
|
||||
updateEntity.setBrief(gameEntity.getBrief());
|
||||
updateEntity.setTag(gameEntity.getTag());
|
||||
updateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
updateEntity.setDownload(gameEntity.getDownload());
|
||||
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
updateList.add(updateEntity);
|
||||
}
|
||||
if (isCanUpdate(apkEntity, gameEntity.getId())) {
|
||||
GameUpdateEntity updateEntity = new GameUpdateEntity();
|
||||
updateEntity.setId(gameEntity.getId());
|
||||
updateEntity.setName(gameEntity.getName());
|
||||
updateEntity.setIcon(gameEntity.getIcon());
|
||||
updateEntity.setPackageName(apkEntity.getPackageName());
|
||||
updateEntity.setSize(apkEntity.getSize());
|
||||
updateEntity.setVersion(apkEntity.getVersion());
|
||||
updateEntity.setGhVersion(apkEntity.getGhVersion());
|
||||
updateEntity.setUrl(apkEntity.getUrl());
|
||||
updateEntity.setPlatform(apkEntity.getPlatform());
|
||||
updateEntity.setEtag(apkEntity.getEtag());
|
||||
updateEntity.setBrief(gameEntity.getBrief());
|
||||
updateEntity.setTag(gameEntity.getTag());
|
||||
updateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
updateEntity.setDownload(gameEntity.getDownload());
|
||||
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
updateEntity.setPluginDesc(gameEntity.getPluginDesc());
|
||||
updateList.add(updateEntity);
|
||||
}
|
||||
}
|
||||
|
||||
// 不是插件游戏
|
||||
if (!isAPluginGame) {
|
||||
for (ApkEntity apkEntity : gameEntity.getApkNormal()) {
|
||||
// 非插件游戏更新
|
||||
for (ApkEntity apkEntity : gameEntity.getApkNormal()) {
|
||||
|
||||
// ghVersion 不存在即是非插件游戏
|
||||
if (TextUtils.isEmpty(apkEntity.getGhVersion())) {
|
||||
String versionFromRequest = apkEntity.getVersion();
|
||||
String versionFromInstalledApp = getVersionByPackage(apkEntity.getPackageName());
|
||||
|
||||
@ -114,6 +111,7 @@ public class PackageUtils {
|
||||
updateEntity.setTag(gameEntity.getTag());
|
||||
updateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
updateEntity.setPluginDesc(gameEntity.getPluginDesc());
|
||||
updateList.add(updateEntity);
|
||||
}
|
||||
}
|
||||
@ -139,6 +137,19 @@ public class PackageUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取已安装游戏的光环ID(游戏ID)
|
||||
*
|
||||
* @param packageName
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public static Object getGhId(String packageName) {
|
||||
return getMetaData(HaloApp.getInstance().getApplication(), packageName, "gh_id");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 判断是否是插件包
|
||||
*/
|
||||
@ -182,6 +193,28 @@ public class PackageUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 从 APK 中获取公钥(只支持包含 V1 签名的 APK
|
||||
private static String getApkSignatureFromFile(String apkFilePath) {
|
||||
try {
|
||||
ZipFile apkFile = new ZipFile(apkFilePath);
|
||||
Enumeration<?> entries = apkFile.entries();
|
||||
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = ((ZipEntry) entries.nextElement());
|
||||
String entryName = entry.getName();
|
||||
if (entryName.contains("META-INF") && entryName.endsWith(".RSA")) {
|
||||
InputStream is = apkFile.getInputStream(entry);
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
X509Certificate cert = (X509Certificate) cf.generateCertificates(is).toArray()[0];
|
||||
return cert.getPublicKey().toString();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
} catch (Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 解析签名
|
||||
*/
|
||||
@ -197,7 +230,7 @@ public class PackageUtils {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 启动安装应用程序
|
||||
*/
|
||||
@ -223,6 +256,7 @@ public class PackageUtils {
|
||||
|
||||
/**
|
||||
* 根据 path 获取 apk 信息确定处理方式
|
||||
*
|
||||
* @return true 为直接唤起系统 PackageInstaller, false 为需要插件化
|
||||
*/
|
||||
public static boolean isCanLaunchSetup(Context context, String path) {
|
||||
@ -231,7 +265,7 @@ public class PackageUtils {
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
return true;
|
||||
}
|
||||
boolean isContain = com.gh.gamecenter.manager.PackagesManager.INSTANCE.isInstalled(packageName);
|
||||
boolean isContain = PackagesManager.isInstalled(packageName);
|
||||
if (!isContain) {
|
||||
return true;
|
||||
}
|
||||
@ -246,6 +280,12 @@ public class PackageUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 从 APK 文件里读取公钥,与已安装的公钥比较判断是否一样
|
||||
String signatureFromApk = getApkSignatureFromFile(path);
|
||||
if (!TextUtils.isEmpty(signatureFromApk)) {
|
||||
return signatureFromApk.equals(getApkSignatureByPackageName(context, packageName));
|
||||
}
|
||||
|
||||
// 若已安装的应用的签名与即将要安装的签名一致也返回 true
|
||||
return compareSignatureBetweenInstalledAppWithApk(context, packageName, path);
|
||||
}
|
||||
@ -458,4 +498,55 @@ public class PackageUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* todo 统一判断
|
||||
* <p>
|
||||
* 判断游戏包是否可以更新
|
||||
*
|
||||
* @param apkEntity apkEntity 必须是已安装的游戏
|
||||
* @param gameId 游戏id
|
||||
* @return true:可以更新 false:不可以更新
|
||||
*/
|
||||
public static boolean isCanUpdate(ApkEntity apkEntity, String gameId) {
|
||||
// gh_version: gh + timestamp
|
||||
String gh_version = (String) PackageUtils.getMetaData(
|
||||
HaloApp.getInstance().getApplication(),
|
||||
apkEntity.getPackageName(),
|
||||
"gh_version");
|
||||
|
||||
// gh_version: game id
|
||||
Object gh_id = PackageUtils.getMetaData(
|
||||
HaloApp.getInstance().getApplication(),
|
||||
apkEntity.getPackageName(),
|
||||
"gh_id");
|
||||
|
||||
if (gh_version != null && apkEntity.getGhVersion() != null && gh_id != null) {
|
||||
gh_version = gh_version.substring(2);
|
||||
return Long.parseLong(gh_version) < Long.parseLong(apkEntity.getGhVersion())
|
||||
&& apkEntity.getForce()
|
||||
&& gh_id.equals(gameId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* todo 统一判断
|
||||
* <p>
|
||||
* 判断游戏包是否可以插件化
|
||||
*
|
||||
* @param apkEntity apkEntity 必须是已安装的游戏
|
||||
* @return true:可以插件化 false:不可以插件化
|
||||
*/
|
||||
public static boolean isCanPluggable(ApkEntity apkEntity) {
|
||||
String gh_id = (String) PackageUtils.getMetaData(
|
||||
HaloApp.getInstance().getApplication(),
|
||||
apkEntity.getPackageName(),
|
||||
"gh_id");
|
||||
|
||||
return PackageUtils.isInstalled(HaloApp.getInstance().getApplication(), apkEntity.getPackageName())
|
||||
&& gh_id == null
|
||||
&& !TextUtils.isEmpty(apkEntity.getGhVersion())
|
||||
&& !PackageUtils.isSignature(HaloApp.getInstance().getApplication(), apkEntity.getPackageName());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,102 +0,0 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public class RSEUtils {
|
||||
|
||||
/**
|
||||
* 公钥
|
||||
*/
|
||||
private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQConqikyOCl5f/VO/vZ+s6wVOhFJcI7o7hYvaLQ5Lzt5/HXbozTeRrGonKFPJurapf9hzjkg0F4/BNFMGXRVlReVdwh+Px5rbXU/ceikF8Ouf67qxiGAuDVC+4e3eIHh+mH68DlqWFJ78sB80iSLXelflGuHkbTOTtaC5F2l+AgxQIDAQAB";
|
||||
|
||||
/**
|
||||
* 加密算法RSA
|
||||
*/
|
||||
private static final String KEY_ALGORITHM = "RSA";
|
||||
|
||||
/**
|
||||
* 使用公钥加密
|
||||
*
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
public static String encryptByPublic(String content) {
|
||||
try {
|
||||
PublicKey pubkey = getPublicKeyFromX509();
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, pubkey);
|
||||
|
||||
byte[] data = content.getBytes("UTF-8");
|
||||
byte[] output = cipher.doFinal(data);
|
||||
|
||||
String s = new String(Base64.encode(output, Base64.DEFAULT));
|
||||
|
||||
return s;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到公钥
|
||||
*
|
||||
* @return PublicKey 公钥
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidKeySpecException
|
||||
*/
|
||||
private static PublicKey getPublicKeyFromX509() throws Exception {
|
||||
byte[] decodedKey = Base64.decode(PUBLIC_KEY, Base64.DEFAULT);
|
||||
X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
||||
return keyFactory.generatePublic(x509);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用公钥解密
|
||||
*
|
||||
* @param content 密文
|
||||
* @return 解密后的字符串
|
||||
*/
|
||||
public static String decryptByPublic(String content) {
|
||||
try {
|
||||
PublicKey pubkey = getPublicKeyFromX509();
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, pubkey);
|
||||
InputStream ins = new ByteArrayInputStream(Base64.decode(content,
|
||||
Base64.DEFAULT));
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[128];
|
||||
int len;
|
||||
while ((len = ins.read(buffer)) != -1) {
|
||||
byte[] block;
|
||||
if (buffer.length == len) {
|
||||
block = buffer;
|
||||
} else {
|
||||
block = new byte[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
block[i] = buffer[i];
|
||||
}
|
||||
}
|
||||
baos.write(cipher.doFinal(block));
|
||||
}
|
||||
return new String(baos.toByteArray(), "utf-8");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -206,9 +206,9 @@ public class ShareUtils {
|
||||
arrLogo[7] = R.drawable.share_cancel_logo;
|
||||
}
|
||||
|
||||
popupWindow = new PopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT
|
||||
popupWindow = new SharePopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT
|
||||
, LinearLayout.LayoutParams.MATCH_PARENT, true);
|
||||
popupWindow.setAnimationStyle(R.style.mypopwindow_anim_style);
|
||||
popupWindow.setAnimationStyle(R.style.popwindow_exit_only_anim_style);
|
||||
//解决PopupWindow无法覆盖状态栏
|
||||
popupWindow.setClippingEnabled(false);
|
||||
|
||||
@ -655,5 +655,20 @@ public class ShareUtils {
|
||||
|
||||
void onCancel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class SharePopupWindow extends PopupWindow {
|
||||
SharePopupWindow(View contentView, int width, int height, boolean focusable) {
|
||||
super(contentView, width, height, focusable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
View backgroundView = getContentView().findViewById(R.id.share_container);
|
||||
if (backgroundView != null) {
|
||||
backgroundView.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
getContentView().postDelayed(super::dismiss, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
@ -21,6 +22,14 @@ class SpanBuilder(content: String) {
|
||||
return this
|
||||
}
|
||||
|
||||
fun color(start: Int, end: Int, colorHexInString: String): SpanBuilder {
|
||||
tryWithDefaultCatch {
|
||||
val colorSpan = ForegroundColorSpan(Color.parseColor(colorHexInString))
|
||||
spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun size(start: Int, end: Int, dpSize: Int): SpanBuilder {
|
||||
val s = AbsoluteSizeSpan(dpSize, true)
|
||||
spannableString.setSpan(s, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
|
||||
@ -5,6 +5,7 @@ import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.text.*
|
||||
import android.text.style.ClickableSpan
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.text.style.RelativeSizeSpan
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
@ -92,7 +93,8 @@ object TextHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun highlightTextThatIsWrappedInsideWrapperByDefault(textView: TextView, text: String?) {
|
||||
textView.text = getHighlightedSpannableStringThatIsWrappedInsideWrapper(textView.context, text ?: "", "###", R.color.theme_font, object : SimpleCallback<String> {
|
||||
textView.text = getHighlightedSpannableStringThatIsWrappedInsideWrapper(textView.context, text
|
||||
?: "", "###", R.color.theme_font, object : SimpleCallback<String> {
|
||||
override fun onCallback(arg: String) {
|
||||
val application = HaloApp.getInstance().application
|
||||
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
@ -185,8 +187,8 @@ object TextHelper {
|
||||
*/
|
||||
fun getCommentLabelSpannableStringBuilder(comment: CharSequence,
|
||||
amwayStyle: Boolean = false,
|
||||
tagStrokeColor: String = "#FFDAA2",
|
||||
tagTextColor: String = "#FF9B06"): SpannableStringBuilder {
|
||||
tagStrokeColor: String = "#FA8E00",
|
||||
tagTextColor: String = "#FA8E00"): SpannableStringBuilder {
|
||||
val contents = SpannableStringBuilder()
|
||||
var count = 0
|
||||
val splits = comment.split("<tag>")
|
||||
@ -220,6 +222,35 @@ object TextHelper {
|
||||
return contents
|
||||
}
|
||||
|
||||
fun getCommentLabelSpannableStringBuilder(comment: CharSequence, colorRes: Int): SpannableStringBuilder {
|
||||
val contents = SpannableStringBuilder()
|
||||
var count = 0
|
||||
val splits = comment.split("<tag>")
|
||||
splits.forEachIndexed { index, s ->
|
||||
if (index != 0) {
|
||||
val item = "<tag>$s"
|
||||
val pattern = Pattern.compile("<tag>(\\S+)</tag>([\\S\\s\n]+)")
|
||||
val matcher = pattern.matcher(item)
|
||||
if (matcher.find()) {
|
||||
val label = matcher.group(1)
|
||||
var content = item.substring(item.indexOf("</tag>") + 6)
|
||||
if (index == splits.size - 1) content += " "
|
||||
val newLabel = "#$label# "
|
||||
contents.append(newLabel)
|
||||
contents.setSpan(ForegroundColorSpan(ContextCompat.getColor(HaloApp.getInstance().application, colorRes)),
|
||||
count, count + newLabel.length - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
count += newLabel.length
|
||||
contents.append(content)
|
||||
count += content.length
|
||||
}
|
||||
} else {
|
||||
contents.append(s)
|
||||
count += s.length
|
||||
}
|
||||
}
|
||||
return contents
|
||||
}
|
||||
|
||||
private fun getRoundStrokeBackgroundColorSpan(amwayStyle: Boolean,
|
||||
tagStrokeColor: String,
|
||||
tagTextColor: String): RoundStrokeBackgroundColorSpan {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@ -19,4 +20,57 @@ object TimeUtils {
|
||||
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
|
||||
return formatter.format(date)
|
||||
}
|
||||
|
||||
fun getFormatTime(time: Long, pattern: String = "yyyy-MM-dd"): String {
|
||||
val f = SimpleDateFormat(pattern, Locale.CHINA)
|
||||
return f.format(Date(time * 1000))
|
||||
}
|
||||
|
||||
fun getFormatDate(timestamp: Long): String {
|
||||
val format = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
|
||||
format.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
|
||||
val testDate: String
|
||||
val today = format.parse(format.format(Date())).time
|
||||
val day = timestamp * 1000
|
||||
val timeFormat = SimpleDateFormat("HH:mm", Locale.CHINA)
|
||||
val time = timeFormat.format(day)
|
||||
|
||||
testDate = if (day >= today && day < today + 86400 * 1000) {
|
||||
"今天 $time"
|
||||
} else if (day >= today + 86400 * 1000 && day < today + 86400 * 1000 * 2) {
|
||||
"明天 $time"
|
||||
} else {
|
||||
SimpleDateFormat("MM-dd HH:mm", Locale.CHINA).format(day)
|
||||
}
|
||||
return testDate
|
||||
}
|
||||
|
||||
//判断是不是今天
|
||||
fun isToday(timestamp: Long): Boolean {
|
||||
val format = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
|
||||
format.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
|
||||
val today = format.parse(format.format(Date())).time
|
||||
val day = timestamp * 1000
|
||||
if (day >= today && day < today + 86400 * 1000) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断时间戳是多少天前
|
||||
*/
|
||||
fun getBeforeDays(timestamp: Long):Int{
|
||||
var days: Long = 0
|
||||
val format = SimpleDateFormat("yyyyMMdd HH:mm", Locale.getDefault())
|
||||
try {
|
||||
val today = format.parse(format.format(Date())).time
|
||||
val day = timestamp * 1000
|
||||
days = (today - day) / 86400000
|
||||
} catch (e: ParseException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
return days.toInt()
|
||||
}
|
||||
}
|
||||
@ -1,188 +0,0 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.net.TrafficStats;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
public class TrafficUtils {
|
||||
|
||||
static TrafficUtils instance;
|
||||
DB db;
|
||||
Context context;
|
||||
|
||||
private TrafficUtils(Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
db = new DB(this.context);
|
||||
}
|
||||
|
||||
public static TrafficUtils getInstance(Context context) {
|
||||
return getInstance(context, false);
|
||||
}
|
||||
|
||||
public static TrafficUtils getInstance(Context context, boolean update) {
|
||||
if (instance == null) {
|
||||
synchronized (TrafficUtils.class) {
|
||||
if (instance == null) {
|
||||
instance = new TrafficUtils(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (update) {
|
||||
instance.update();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
|
||||
// 获取所有的安装在手机上的应用软件的信息,并且获取这些软件里面的权限信息
|
||||
PackageManager pm = context.getPackageManager();// 获取系统应用包管理
|
||||
// 获取每个包内的androidmanifest.xml信息,它的权限等等
|
||||
List<PackageInfo> pinfos = pm.getInstalledPackages(PackageManager.GET_PERMISSIONS);
|
||||
// 遍历每个应用包信息
|
||||
for (PackageInfo info : pinfos) {
|
||||
// 请求每个程序包对应的androidManifest.xml里面的权限
|
||||
String[] premissions = info.requestedPermissions;
|
||||
if (premissions != null && premissions.length > 0) {
|
||||
// 找出需要网络服务的应用程序
|
||||
for (String premission : premissions) {
|
||||
if ("android.permission.INTERNET".equals(premission)) {
|
||||
// 获取每个应用程序在操作系统内的进程id
|
||||
int uId = info.applicationInfo.uid;
|
||||
// 如果返回-1,代表不支持使用该方法,注意必须是2.2以上的
|
||||
long rx = TrafficStats.getUidRxBytes(uId);
|
||||
// 如果返回-1,代表不支持使用该方法,注意必须是2.2以上的
|
||||
long tx = TrafficStats.getUidTxBytes(uId);
|
||||
if (rx >= 0 && tx >= 0) {
|
||||
db.update(info.packageName, rx + tx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
db.clean(Calendar.getInstance().getTimeInMillis() - 3600 * 24 * 30);
|
||||
}
|
||||
|
||||
public long getTraffic(List<String> packageNameList) {
|
||||
return this.getTraffic(packageNameList, Calendar.getInstance()
|
||||
.getTimeInMillis() - 3600 * 24 * 7);
|
||||
}
|
||||
|
||||
public long getTraffic(List<String> packageNameList, long from) {
|
||||
return this.getTraffic(packageNameList, from, Calendar.getInstance()
|
||||
.getTimeInMillis());
|
||||
}
|
||||
|
||||
public long getTraffic(List<String> packageNameList, long from, long to) {
|
||||
long traffic = 0;
|
||||
for (String packageName : packageNameList) {
|
||||
traffic += db.getTraffic(packageName, from, to);
|
||||
}
|
||||
return traffic;
|
||||
}
|
||||
|
||||
public long getTraffice(String packageName) {
|
||||
return db.getTraffic(packageName, Calendar.getInstance()
|
||||
.getTimeInMillis() - 3600 * 24 * 7);
|
||||
}
|
||||
|
||||
public long getTraffice(String packageName, long from) {
|
||||
return db.getTraffic(packageName, from);
|
||||
}
|
||||
|
||||
class DB extends SQLiteOpenHelper {
|
||||
|
||||
static final String name = "gh_traffic.db";
|
||||
static final int version = 1;
|
||||
String traffic = "CREATE TABLE traffic(" + "package text,"
|
||||
+ "traffic integer not null," + "time integer not null" + ");";
|
||||
|
||||
public DB(Context context) {
|
||||
super(context, name, null, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(traffic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
}
|
||||
|
||||
public void update(String packageName, long traffic) {
|
||||
String sql = "INSERT INTO traffic (package, traffic, time) VALUES (?, ?, ?)";
|
||||
Object[] bindArgs = new Object[]{packageName, traffic,
|
||||
Calendar.getInstance().getTimeInMillis()};
|
||||
this.getWritableDatabase().execSQL(sql, bindArgs);
|
||||
}
|
||||
|
||||
public void clean(long time) {
|
||||
String sql = "DELETE FROM traffic WHERE time < ? ";
|
||||
Object[] bindArgs = new Object[]{time};
|
||||
this.getWritableDatabase().execSQL(sql, bindArgs);
|
||||
}
|
||||
|
||||
public long getTraffic(String packageName, long from) {
|
||||
return getTraffic(packageName, from, Calendar.getInstance()
|
||||
.getTimeInMillis());
|
||||
}
|
||||
|
||||
public long getTraffic(String packageName, long from, long to) {
|
||||
long traffic = 0;
|
||||
String sql = "SELECT * FROM traffic WHERE package = ? AND time >= ? AND time <= ? ORDER BY time DESC";
|
||||
String selectionArgs[] = new String[]{packageName,
|
||||
String.valueOf(from), String.valueOf(to)};
|
||||
Cursor cursor = this.getReadableDatabase().rawQuery(sql,
|
||||
selectionArgs);
|
||||
if (cursor.getCount() > 1) {
|
||||
cursor.moveToFirst();
|
||||
long traffic1 = cursor
|
||||
.getLong(cursor.getColumnIndex("traffic"));
|
||||
// long time1 = cursor.getLong(cursor.getColumnIndex("time"));
|
||||
cursor.moveToLast();
|
||||
long traffic2 = cursor
|
||||
.getLong(cursor.getColumnIndex("traffic"));
|
||||
// long time2 = cursor.getLong(cursor.getColumnIndex("time"));
|
||||
traffic = traffic1 - traffic2;
|
||||
// long cha = traffic1 - traffic2;
|
||||
// if(cha > 0){
|
||||
// traffic = cha / (time2 - time1);
|
||||
// }
|
||||
} else if (cursor.getCount() == 1) {
|
||||
sql = "SELECT * FROM traffic WHERE package = ? AND time < ? ORDER BY time DESC";
|
||||
selectionArgs = new String[]{packageName,
|
||||
String.valueOf(from)};
|
||||
Cursor cursor2 = this.getReadableDatabase().rawQuery(sql,
|
||||
selectionArgs);
|
||||
if (cursor2.moveToNext()) {
|
||||
cursor.moveToFirst();
|
||||
long traffic1 = cursor.getLong(cursor
|
||||
.getColumnIndex("traffic"));
|
||||
// long time1 =
|
||||
// cursor.getLong(cursor.getColumnIndex("time"));
|
||||
long traffic2 = cursor2.getLong(cursor
|
||||
.getColumnIndex("traffic"));
|
||||
// long time2 =
|
||||
// cursor2.getLong(cursor.getColumnIndex("time"));
|
||||
traffic = traffic1 - traffic2;
|
||||
// long cha = traffic1 - traffic2;
|
||||
// if(cha > 0){
|
||||
// traffic = cha / (time2 - time1);
|
||||
// }
|
||||
}
|
||||
cursor2.close();
|
||||
}
|
||||
cursor.close();
|
||||
return traffic;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,7 +68,6 @@ class AdBannerView : LinearLayout {
|
||||
val params = LayoutParams(LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(5F))
|
||||
params.topMargin = DisplayUtils.dip2px(8f)
|
||||
layoutParams = params
|
||||
visibility = View.GONE
|
||||
}
|
||||
addView(mIndicatorLayout)
|
||||
}
|
||||
@ -191,13 +190,7 @@ class AdBannerView : LinearLayout {
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val ad = mDatas[position % mDatas.size]
|
||||
val view = holder.itemView as SimpleDraweeView
|
||||
ImageUtils.addLimitWidthAndLoad(view, ad.image, bannerWidth, object : ImageUtils.OnImageloadListener {
|
||||
override fun onLoadFinal(imageInfo: ImageInfo?) {
|
||||
if (mIndicatorLayout.visibility == View.GONE) {
|
||||
mIndicatorLayout.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
})
|
||||
ImageUtils.display(view, ad.image)
|
||||
holder.itemView.setOnClickListener {
|
||||
onItemClick?.invoke(position % mDatas.size)
|
||||
}
|
||||
|
||||
@ -14,26 +14,26 @@ public class CenterImageSpan extends ImageSpan {
|
||||
public CenterImageSpan(Context context, int resourceId) {
|
||||
super(context, resourceId);
|
||||
}
|
||||
|
||||
public CenterImageSpan(Drawable drawable) {
|
||||
super( drawable);
|
||||
super(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(Paint paint, CharSequence text, int start, int end,
|
||||
Paint.FontMetricsInt fm) {
|
||||
Drawable d = getDrawable();
|
||||
Rect rect = d.getBounds();
|
||||
if (fm != null) {
|
||||
Paint.FontMetricsInt fontMetricsInt) {
|
||||
Drawable drawable = getDrawable();
|
||||
Rect rect = drawable.getBounds();
|
||||
if (fontMetricsInt != null) {
|
||||
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
|
||||
int fontHeight = fmPaint.bottom - fmPaint.top;
|
||||
int fontHeight = fmPaint.descent - fmPaint.ascent;
|
||||
int drHeight = rect.bottom - rect.top;
|
||||
int centerY = fmPaint.ascent + fontHeight / 2;
|
||||
|
||||
int top = drHeight / 2 - fontHeight / 4;
|
||||
int bottom = drHeight / 2 + fontHeight / 4;
|
||||
|
||||
fm.ascent = -bottom;
|
||||
fm.top = -bottom;
|
||||
fm.bottom = top;
|
||||
fm.descent = top;
|
||||
fontMetricsInt.ascent = centerY - drHeight / 2;
|
||||
fontMetricsInt.top = fontMetricsInt.ascent;
|
||||
fontMetricsInt.bottom = centerY + drHeight / 2 + 1; // fuck 这里不加 1px 会导致图片底部被截掉 1px
|
||||
fontMetricsInt.descent = fontMetricsInt.bottom;
|
||||
}
|
||||
return rect.right;
|
||||
}
|
||||
@ -41,14 +41,14 @@ public class CenterImageSpan extends ImageSpan {
|
||||
@Override
|
||||
public void draw(Canvas canvas, CharSequence text, int start, int end,
|
||||
float x, int top, int y, int bottom, Paint paint) {
|
||||
Drawable b = getDrawable();
|
||||
Drawable drawable = getDrawable();
|
||||
canvas.save();
|
||||
int transY;
|
||||
transY = ((bottom - top) - b.getBounds().bottom) / 2 + top;
|
||||
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
|
||||
int fontHeight = fmPaint.descent - fmPaint.ascent;
|
||||
int centerY = y + fmPaint.descent - fontHeight / 2;
|
||||
int transY = centerY - (drawable.getBounds().bottom - drawable.getBounds().top) / 2;
|
||||
canvas.translate(x, transY);
|
||||
if (b.isVisible()) {
|
||||
b.draw(canvas);
|
||||
}
|
||||
drawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
class CustomDividerItemDecoration(
|
||||
context: Context,
|
||||
var onlyDecorateTheFirstItem: Boolean = false,
|
||||
var notDecorateTheFirstItem: Boolean = false,
|
||||
var notDecorateTheLastItem: Boolean = false,
|
||||
var notDecorateTheFirstTwoItems: Boolean = false) : DividerItemDecoration(context, LinearLayout.VERTICAL) {
|
||||
|
||||
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
|
||||
if (onlyDecorateTheFirstItem) {
|
||||
if (parent.getChildAdapterPosition(view) == 0) outRect[0, 0, 0] = drawable!!.intrinsicHeight
|
||||
} else {
|
||||
if (parent.getChildAdapterPosition(view) == 0
|
||||
&& (notDecorateTheFirstItem || notDecorateTheFirstTwoItems)) {
|
||||
outRect.set(0, 0, 0, 0)
|
||||
} else if (parent.getChildAdapterPosition(view) == 1 && notDecorateTheFirstTwoItems) {
|
||||
outRect.set(0, 0, 0, 0)
|
||||
} else if (parent.getChildAdapterPosition(view) == parent.adapter!!.itemCount - 1 && notDecorateTheLastItem) {
|
||||
outRect.set(0, 0, 0, 0)
|
||||
} else {
|
||||
outRect[0, 0, 0] = drawable!!.intrinsicHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,25 +1,63 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.text.Layout;
|
||||
import android.text.Selection;
|
||||
import android.text.Spannable;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class CustomLinkMovementMethod extends LinkMovementMethod {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
|
||||
boolean b = super.onTouchEvent(widget, buffer, event);
|
||||
int action = event.getAction();
|
||||
boolean isTouchEventConsumed = false;
|
||||
|
||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
|
||||
int x = (int) event.getX();
|
||||
int y = (int) event.getY();
|
||||
|
||||
x -= widget.getTotalPaddingLeft();
|
||||
y -= widget.getTotalPaddingTop();
|
||||
|
||||
x += widget.getScrollX();
|
||||
y += widget.getScrollY();
|
||||
|
||||
Layout layout = widget.getLayout();
|
||||
int line = layout.getLineForVertical(y);
|
||||
int off = layout.getOffsetForHorizontal(line, x);
|
||||
|
||||
ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);
|
||||
|
||||
if (links.length != 0) {
|
||||
ClickableSpan link = links[0];
|
||||
if (action == MotionEvent.ACTION_UP) {
|
||||
link.onClick(widget);
|
||||
} else if (action == MotionEvent.ACTION_DOWN) {
|
||||
// 下面这行代码会造成触摸 clickbleSpan 时 RecyclerView 的 item 高度变更 : (
|
||||
// 看起来像是跟文字选择相关的东西,反正我们的 clickSpan 也不让选,直接屏蔽掉了
|
||||
// Selection.setSelection(buffer,
|
||||
// buffer.getSpanStart(link),
|
||||
// buffer.getSpanEnd(link));
|
||||
}
|
||||
isTouchEventConsumed = true;
|
||||
} else {
|
||||
Selection.removeSelection(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
//解决点击事件冲突问题
|
||||
if (!b && event.getAction() == MotionEvent.ACTION_UP) {
|
||||
if (!isTouchEventConsumed && event.getAction() == MotionEvent.ACTION_UP) {
|
||||
ViewParent parent = iterateViewParentForClicking(widget.getParent());//处理widget的父控件点击事件
|
||||
if (parent != null && parent instanceof ViewGroup) {
|
||||
if (parent instanceof ViewGroup) {
|
||||
return ((ViewGroup) parent).performClick();
|
||||
}
|
||||
}
|
||||
return b;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -33,14 +71,13 @@ public class CustomLinkMovementMethod extends LinkMovementMethod {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static CustomLinkMovementMethod getInstance() {
|
||||
if (sInstance == null) sInstance = new CustomLinkMovementMethod();
|
||||
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static CustomLinkMovementMethod sInstance;
|
||||
|
||||
|
||||
}
|
||||
@ -1,662 +0,0 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
|
||||
import android.text.TextUtils;
|
||||
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.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.util.ClickUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.OnCollectionCallBackListener;
|
||||
import com.gh.gamecenter.adapter.PlatformPagerAdapter;
|
||||
import com.gh.gamecenter.databinding.ImprintContentItemBinding;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.ApkLink;
|
||||
import com.gh.gamecenter.entity.GameCollectionEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.eventbus.EBPackage;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DataWatcher;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
/**
|
||||
* @author 温冠超
|
||||
* @email 294299195@qq.com
|
||||
* @date 2015-8-12
|
||||
* @update 2015-8-12
|
||||
* @des 弹出游戏版本下载按钮,点击并添加到下载任务中
|
||||
*/
|
||||
public class DownloadDialog implements OnCollectionCallBackListener {
|
||||
private Context mContext;
|
||||
|
||||
private PopupWindow popupWindow;
|
||||
|
||||
private ViewPager viewPager;
|
||||
private ViewPager collectionViewPager;
|
||||
private LinearLayout dialog_ll_collection_hint;
|
||||
private LinearLayout dialog_ll_hint;
|
||||
private LinearLayout dialog_ll_collection;
|
||||
private View mDialogMorePlatformHint;
|
||||
|
||||
private List<ApkEntity> gameApk;
|
||||
private GameEntity gameEntity;
|
||||
|
||||
private PlatformPagerAdapter adapter;
|
||||
private PlatformPagerAdapter collectionAdapter;
|
||||
|
||||
private ExposureEvent traceEvent;
|
||||
|
||||
private static final String DOWNLOAD_PLATFORM_HINT = "download_platform_hint";
|
||||
|
||||
private String entrance;
|
||||
private String location;
|
||||
private String mAutoDownloadPlatform;
|
||||
|
||||
private final int row = 3;
|
||||
private final int column = 3;
|
||||
private boolean isLoadPlatform;
|
||||
|
||||
private DataWatcher dataWatcher = new DataWatcher() {
|
||||
@Override
|
||||
public void onDataChanged(DownloadEntity downloadEntity) {
|
||||
if (downloadEntity.getName().equals(gameEntity.getName())
|
||||
&& !DownloadStatus.delete.equals(DownloadManager.getInstance(mContext).getStatus(downloadEntity.getUrl()))) {
|
||||
|
||||
adapter.putDownloadEntity(downloadEntity);
|
||||
|
||||
if (collectionAdapter != null) {
|
||||
collectionAdapter.putDownloadEntity(downloadEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private DownloadDialog(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public static DownloadDialog getInstance(Context context) {
|
||||
return new DownloadDialog(context);
|
||||
}
|
||||
|
||||
// 自动下载并翻到相应页面
|
||||
public void showPopupWindowAutoDownload(View view, GameEntity gameEntity, String autoDownloadPlatform,
|
||||
String entrance, String location, ExposureEvent traceEvent) {
|
||||
mAutoDownloadPlatform = autoDownloadPlatform;
|
||||
showPopupWindow(view, gameEntity, entrance, location, traceEvent);
|
||||
}
|
||||
|
||||
public void showPopupWindow(View view, GameEntity gameEntity, String entrance, String location) {
|
||||
showPopupWindow(view, gameEntity, entrance, location, null);
|
||||
}
|
||||
|
||||
public void showPopupWindow(View view, GameEntity gameEntity, String entrance, String location,
|
||||
@Nullable ExposureEvent traceEvent) {
|
||||
if (ClickUtils.isFastDoubleClick()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.gameEntity = gameEntity;
|
||||
this.entrance = entrance;
|
||||
this.location = location;
|
||||
this.traceEvent = traceEvent;
|
||||
|
||||
gameApk = gameEntity.getApk();
|
||||
if (gameEntity.getCollection() != null) {
|
||||
mergeApkCollection(gameEntity);
|
||||
}
|
||||
|
||||
if (gameEntity.getApkLink() != null) {
|
||||
mergeApkLink(gameEntity);
|
||||
}
|
||||
|
||||
sortApk();
|
||||
|
||||
// 一个自定义的布局,作为显示的内容
|
||||
View contentView = View.inflate(mContext, R.layout.game_download_dialog, null);
|
||||
|
||||
TextView title = contentView.findViewById(R.id.dialog_title);
|
||||
title.setText(gameEntity.getName());
|
||||
|
||||
viewPager = contentView.findViewById(R.id.dialog_viewPager);
|
||||
dialog_ll_hint = contentView.findViewById(R.id.dialog_ll_hint);
|
||||
dialog_ll_collection = contentView.findViewById(R.id.dialog_ll_collection);
|
||||
dialog_ll_collection_hint = contentView.findViewById(R.id.dialog_ll_collection_hint);
|
||||
collectionViewPager = contentView.findViewById(R.id.dialog_collection_viewPager);
|
||||
mDialogMorePlatformHint = contentView.findViewById(R.id.dialog_more_platform_hit);
|
||||
TextView dialogAd = contentView.findViewById(R.id.dialog_ad);
|
||||
TextView dialogAdMirror = contentView.findViewById(R.id.dialog_ad_mirror);
|
||||
mDialogMorePlatformHint.setOnClickListener(v -> {
|
||||
mDialogMorePlatformHint.setVisibility(View.GONE);
|
||||
SPUtils.setBoolean(DOWNLOAD_PLATFORM_HINT, false);
|
||||
});
|
||||
|
||||
LinkEntity downloadAd = gameEntity.getDownloadAd();
|
||||
if (downloadAd != null) {
|
||||
dialogAd.setVisibility(View.VISIBLE);
|
||||
dialogAd.setText(downloadAd.getTitle());
|
||||
dialogAdMirror.setVisibility(View.INVISIBLE);
|
||||
dialogAdMirror.setText(downloadAd.getTitle());
|
||||
dialogAd.setOnClickListener(v -> {
|
||||
if ("imprint".equals(downloadAd.getType())) {
|
||||
showImprintDialog(downloadAd.getTitle());
|
||||
} else {
|
||||
DirectUtils.directToLinkPage(
|
||||
mContext,
|
||||
downloadAd,
|
||||
entrance, "下载多平台弹窗");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isLoadPlatform = false;
|
||||
|
||||
init(new ArrayList<>(gameApk));
|
||||
|
||||
viewPager.addOnPageChangeListener(new MyPageChangeListener(dialog_ll_hint));
|
||||
|
||||
popupWindow = new PopupWindow(contentView, LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.MATCH_PARENT, true);
|
||||
|
||||
contentView.setOnClickListener(v -> popupWindow.dismiss());
|
||||
contentView.setFocusable(true);
|
||||
contentView.setFocusableInTouchMode(true);
|
||||
contentView.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0
|
||||
&& popupWindow != null && popupWindow.isShowing()) {
|
||||
popupWindow.dismiss();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
popupWindow.setOnDismissListener(() -> {
|
||||
EventBus.getDefault().unregister(DownloadDialog.this);
|
||||
DownloadManager.getInstance(mContext).removeObserver(dataWatcher);
|
||||
});
|
||||
|
||||
popupWindow.setTouchable(true);
|
||||
popupWindow.setFocusable(true);
|
||||
|
||||
// 设置popWindow的显示和消失动画
|
||||
popupWindow.setAnimationStyle(R.style.mypopwindow_anim_style);
|
||||
|
||||
// 设置好参数之后再show
|
||||
popupWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);
|
||||
|
||||
if (!EventBus.getDefault().isRegistered(DownloadDialog.this)) {
|
||||
EventBus.getDefault().register(DownloadDialog.this);
|
||||
}
|
||||
|
||||
DownloadManager.getInstance(mContext).addObserver(dataWatcher);
|
||||
}
|
||||
|
||||
private void showImprintDialog(String titleName) {
|
||||
Dialog dialog = new Dialog(mContext, R.style.full_dialog);
|
||||
View inflate = LayoutInflater.from(mContext).inflate(R.layout.imprint_dialog, null);
|
||||
dialog.setContentView(inflate);
|
||||
dialog.show();
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
WindowManager.LayoutParams params;
|
||||
if (window != null) {
|
||||
params = window.getAttributes();
|
||||
params.width = (int) (mContext.getResources().getDisplayMetrics().widthPixels * 0.9);
|
||||
window.setAttributes(params);
|
||||
window.setBackgroundDrawableResource(R.drawable.full_dialog_background);
|
||||
}
|
||||
|
||||
inflate.findViewById(R.id.imprint_close).setOnClickListener(v -> dialog.dismiss());
|
||||
LinearLayout content = inflate.findViewById(R.id.imprint_content);
|
||||
((TextView) inflate.findViewById(R.id.imprint_title)).setText(titleName);
|
||||
View head = LayoutInflater.from(mContext).inflate(R.layout.imprint_content_item, null);
|
||||
content.addView(head, LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(30));
|
||||
LimitHeightLinearLayout imprintContainer = inflate.findViewById(R.id.imprint_container);
|
||||
imprintContainer.setLimitHeight((int) (mContext.getResources().getDisplayMetrics().heightPixels * 0.8));
|
||||
|
||||
ArrayList<ApkEntity> list = gameEntity.getApk();
|
||||
SettingsEntity settings = Config.getSettings();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ApkEntity apk = gameEntity.getApk().get(i);
|
||||
if (settings != null && settings.getGameDownloadBlackList().contains(apk.getPackageName())) {
|
||||
continue;
|
||||
}
|
||||
View item = LayoutInflater.from(mContext).inflate(R.layout.imprint_content_item, null);
|
||||
ImprintContentItemBinding bind = DataBindingUtil.bind(item);
|
||||
bind.setApk(apk);
|
||||
bind.setPlatformName(PlatformUtils.getInstance(mContext).getPlatformName(apk.getPlatform()));
|
||||
content.addView(item, LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(40));
|
||||
}
|
||||
|
||||
|
||||
// close line
|
||||
View view = new View(mContext);
|
||||
view.setBackgroundColor(mContext.getResources().getColor(R.color.text_5d5d5d));
|
||||
view.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(1)));
|
||||
content.addView(view);
|
||||
}
|
||||
|
||||
private void sortApk() {
|
||||
for (ApkEntity apkEntity : gameApk) {
|
||||
GameCollectionEntity apkCollection = apkEntity.getApkCollection();
|
||||
if (apkCollection != null) {
|
||||
List<ApkEntity> saveApkEntity = apkCollection.getSaveApkEntity();
|
||||
if (saveApkEntity != null) {
|
||||
for (ApkEntity entity : saveApkEntity) {
|
||||
int sortValue = getSortValue(entity);
|
||||
if (apkEntity.getOrder() < sortValue) {
|
||||
apkEntity.setOrder(sortValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
apkEntity.setOrder(getSortValue(apkEntity));
|
||||
}
|
||||
|
||||
Comparator<ApkEntity> comparator = (lhs, rhs) -> rhs.getOrder() - lhs.getOrder();
|
||||
Collections.sort(gameApk, comparator);
|
||||
}
|
||||
|
||||
private int getSortValue(ApkEntity apkEntity) {
|
||||
/*
|
||||
* 安装插件 10
|
||||
* 插件化下载中 9
|
||||
* 插件化 8
|
||||
* 安装更新 7
|
||||
* 更新下载中 6
|
||||
* 更新 5
|
||||
* 安装 4
|
||||
* 下载中 3
|
||||
* 启动 2
|
||||
* 默认(有图片)1
|
||||
* 默认(无图片)0
|
||||
*/
|
||||
|
||||
Object gh_id;
|
||||
String packageName = apkEntity.getPackageName();
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(mContext).getDownloadEntityByUrl(apkEntity.getUrl());
|
||||
if (downloadEntity == null) {
|
||||
if (!TextUtils.isEmpty(packageName) && PackagesManager.INSTANCE.isInstalled(packageName)) {
|
||||
gh_id = PackageUtils.getMetaData(mContext, packageName, "gh_id");
|
||||
if (gh_id == null || gh_id.equals(gameEntity.getId())) {
|
||||
if (!PackageUtils.isSignature(mContext, packageName)) {
|
||||
return 8;
|
||||
} else if (PackagesManager.INSTANCE.isCanUpdate(gameEntity.getId(), packageName)) {
|
||||
return 5;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (apkEntity.getOrder() < 1) apkEntity.setOrder(1);
|
||||
|
||||
String platform = apkEntity.getPlatform();
|
||||
int id = PlatformUtils.getInstance(mContext).getPlatformPic(platform);
|
||||
if (id == 0) {
|
||||
String path = PlatformUtils.getInstance(mContext).getPlatformPicUrl(platform);
|
||||
if (path == null) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (downloadEntity.getStatus().equals(DownloadStatus.done)) {
|
||||
if (downloadEntity.isPluggable()) {
|
||||
return 10;
|
||||
} else if (downloadEntity.isUpdate()) {
|
||||
return 7;
|
||||
} else {
|
||||
return 4;
|
||||
}
|
||||
} else {
|
||||
if (downloadEntity.isPluggable()) {
|
||||
return 9;
|
||||
} else if (downloadEntity.isUpdate()) {
|
||||
return 6;
|
||||
} else {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 合并ApkLink
|
||||
private void mergeApkLink(GameEntity gameEntity) {
|
||||
for (ApkLink apkLink : gameEntity.getApkLink()) {
|
||||
if (!TextUtils.isEmpty(apkLink.getCollection())) {
|
||||
for (int i = 0; i < gameApk.size(); i++) {
|
||||
ApkEntity apkEntity = gameApk.get(i);
|
||||
GameCollectionEntity apkCollection = apkEntity.getApkCollection();
|
||||
if (apkCollection != null && apkCollection.getSaveApkEntity() != null) {
|
||||
List<ApkEntity> saveApkEntity = apkCollection.getSaveApkEntity();
|
||||
if (apkLink.getCollection().equals(apkCollection.getId())) {
|
||||
ApkEntity element = new ApkEntity();
|
||||
element.setApkLink(apkLink);
|
||||
if (saveApkEntity.size() > apkLink.getSort()) {
|
||||
saveApkEntity.add(apkLink.getSort(), element);
|
||||
} else {
|
||||
saveApkEntity.add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ApkEntity element = new ApkEntity();
|
||||
element.setApkLink(apkLink);
|
||||
if (gameApk.size() > apkLink.getSort()) {
|
||||
gameApk.add(apkLink.getSort(), element);
|
||||
} else {
|
||||
gameApk.add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 合并ApkCollection
|
||||
private void mergeApkCollection(GameEntity gameEntity) {
|
||||
List<ApkEntity> gameCollectionApk = new ArrayList<>();
|
||||
ConcurrentHashMap<String, Integer> hashMap = new ConcurrentHashMap<>();
|
||||
boolean isCollection;
|
||||
|
||||
for (ApkEntity apkEntity : gameApk) {
|
||||
isCollection = false;
|
||||
for (GameCollectionEntity gameCollectionEntity : gameEntity.getCollection()) {
|
||||
for (String packageName : gameCollectionEntity.getPackage()) {
|
||||
if (packageName.equals(apkEntity.getPackageName())) {
|
||||
isCollection = true;
|
||||
if (hashMap.get(gameCollectionEntity.getName()) != null) {
|
||||
gameCollectionApk.get(hashMap.get(gameCollectionEntity.getName()))
|
||||
.getApkCollection().getSaveApkEntity().add(apkEntity);
|
||||
} else {
|
||||
ApkEntity newApkEntity = new ApkEntity();
|
||||
GameCollectionEntity collectionEntity = new GameCollectionEntity();
|
||||
List<ApkEntity> saveApkList = new ArrayList<>();
|
||||
saveApkList.add(apkEntity);
|
||||
collectionEntity.setSaveApkEntity(saveApkList);
|
||||
collectionEntity.setId(gameCollectionEntity.getId());
|
||||
collectionEntity.setName(gameCollectionEntity.getName());
|
||||
collectionEntity.setIcon(gameCollectionEntity.getIcon());
|
||||
collectionEntity.setColor(gameCollectionEntity.getColor());
|
||||
newApkEntity.setApkCollection(collectionEntity);
|
||||
gameCollectionApk.add(newApkEntity);
|
||||
|
||||
hashMap.put(gameCollectionEntity.getName(), gameCollectionApk.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isCollection) {
|
||||
gameCollectionApk.add(apkEntity);
|
||||
}
|
||||
}
|
||||
|
||||
gameApk = gameCollectionApk;
|
||||
}
|
||||
|
||||
private void init(List<ApkEntity> apkList) {
|
||||
for (int i = 0; i < apkList.size(); i++) {
|
||||
String platformName = PlatformUtils.getInstance(mContext)
|
||||
.getPlatformName(apkList.get(i).getPlatform());
|
||||
if (platformName == null) {
|
||||
apkList.remove(i);
|
||||
i--;
|
||||
if (!isLoadPlatform) {
|
||||
PlatformUtils.getInstance(mContext).getPlatform();
|
||||
isLoadPlatform = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ApkEntity skipEntiy = new ApkEntity();
|
||||
skipEntiy.setPackageName("求版本");
|
||||
apkList.add(skipEntiy); // 添加一个跳转投票
|
||||
|
||||
dialog_ll_hint.removeAllViews();
|
||||
int size = (int) Math.ceil(apkList.size() / (double) (row * column));
|
||||
addHintPoint(dialog_ll_hint, size);
|
||||
|
||||
if (size >= 2) {
|
||||
boolean isShowPlatformHint = SPUtils.getBoolean(DOWNLOAD_PLATFORM_HINT, true);
|
||||
if (isShowPlatformHint) {
|
||||
mDialogMorePlatformHint.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
int count = apkList.size();
|
||||
int vpHeight;
|
||||
if (count <= 3) {
|
||||
vpHeight = 90;
|
||||
} else if (count <= 6) {
|
||||
vpHeight = 150;
|
||||
} else {
|
||||
vpHeight = 210;
|
||||
}
|
||||
ViewGroup.LayoutParams layoutParams = viewPager.getLayoutParams();
|
||||
layoutParams.height = DisplayUtils.dip2px(mContext, vpHeight);
|
||||
viewPager.setLayoutParams(layoutParams);
|
||||
|
||||
int currentItem = 0;
|
||||
if (viewPager != null) {
|
||||
currentItem = viewPager.getCurrentItem();
|
||||
}
|
||||
if (!TextUtils.isEmpty(mAutoDownloadPlatform)) {
|
||||
for (int i = 0; i < apkList.size(); i++) {
|
||||
ApkEntity apkEntity = apkList.get(i);
|
||||
if (mAutoDownloadPlatform.equals(apkEntity.getPlatform())) {
|
||||
currentItem = (i / 9);
|
||||
break;
|
||||
}
|
||||
GameCollectionEntity apkCollection = apkEntity.getApkCollection();
|
||||
if (apkCollection != null) {
|
||||
List<ApkEntity> saveApkEntity = apkCollection.getSaveApkEntity();
|
||||
if (saveApkEntity != null) {
|
||||
for (ApkEntity entity : saveApkEntity) {
|
||||
if (mAutoDownloadPlatform.equals(entity.getPlatform())) {
|
||||
currentItem = (i / 9);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Utils.log("currentItem = " + currentItem);
|
||||
adapter = new PlatformPagerAdapter(mContext, this,
|
||||
gameEntity, apkList, mAutoDownloadPlatform, entrance, location, traceEvent);
|
||||
viewPager.setAdapter(adapter);
|
||||
viewPager.setCurrentItem(currentItem);
|
||||
if (currentItem != 0) setDownloadOvalHint(dialog_ll_hint, currentItem);
|
||||
}
|
||||
|
||||
private void addHintPoint(LinearLayout linearLayout, int size) {
|
||||
if (size <= 1) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
ImageView imageView = new ImageView(mContext);
|
||||
LayoutParams lparams = new LayoutParams(
|
||||
DisplayUtils.dip2px(mContext, 6), DisplayUtils.dip2px(mContext, 6));
|
||||
if (i == 0) {
|
||||
lparams.leftMargin = 0;
|
||||
imageView.setImageResource(R.drawable.download_oval_hint_up);
|
||||
} else {
|
||||
lparams.leftMargin = DisplayUtils.dip2px(mContext, 9);
|
||||
imageView.setImageResource(R.drawable.oval_hint_gray_bg);
|
||||
}
|
||||
imageView.setLayoutParams(lparams);
|
||||
linearLayout.addView(imageView);
|
||||
}
|
||||
}
|
||||
|
||||
// 接收安装成功的消息,更新界面
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEvent(EBPackage busFour) {
|
||||
if ("安装".equals(busFour.getType())) {
|
||||
adapter.removeDownloadEntityByPackageName(busFour.getPackageName());
|
||||
if (collectionAdapter != null) {
|
||||
collectionAdapter.removeDownloadEntityByPackageName(busFour.getPackageName());
|
||||
}
|
||||
} else if ("卸载".equals(busFour.getType())) {
|
||||
adapter.updateItem(busFour.getPackageName());
|
||||
if (collectionAdapter != null) {
|
||||
collectionAdapter.updateItem(busFour.getPackageName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//接收下载被删除消息
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEvent(EBDownloadStatus status) {
|
||||
if ("delete".equals(status.getStatus())) {
|
||||
String url = status.getUrl();
|
||||
adapter.removeDownloadEntityByUrl(url);
|
||||
if (collectionAdapter != null) {
|
||||
collectionAdapter.removeDownloadEntityByUrl(url);
|
||||
}
|
||||
// DownloadManager.getInstance(mContext).putStatus(url, "delete");
|
||||
}
|
||||
}
|
||||
|
||||
// 接收platform数据改变消息,更新界面
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEvent(EBReuse reuse) {
|
||||
if ("PlatformChanged".equals(reuse.getType())) {
|
||||
DownloadManager.getInstance(mContext).removeObserver(dataWatcher);
|
||||
init(new ArrayList<>(gameApk));
|
||||
DownloadManager.getInstance(mContext).addObserver(dataWatcher);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示合集
|
||||
@Override
|
||||
public void showCollection(GameCollectionEntity gameCollectionEntity) {
|
||||
dialog_ll_collection.setVisibility(View.VISIBLE);
|
||||
|
||||
List<ApkEntity> saveApkList = gameCollectionEntity.getSaveApkEntity();
|
||||
int count = saveApkList.size();
|
||||
int vpHeight;
|
||||
if (count <= 3) {
|
||||
vpHeight = 82;
|
||||
} else if (count <= 6) {
|
||||
vpHeight = 142;
|
||||
} else {
|
||||
vpHeight = 202;
|
||||
}
|
||||
|
||||
ViewGroup.LayoutParams layoutParams = collectionViewPager.getLayoutParams();
|
||||
layoutParams.height = DisplayUtils.dip2px(mContext, vpHeight);
|
||||
collectionViewPager.setLayoutParams(layoutParams);
|
||||
|
||||
dialog_ll_collection_hint.removeAllViews();
|
||||
int size = (int) Math.ceil(count / (double) (row * column));
|
||||
addHintPoint(dialog_ll_collection_hint, size);
|
||||
|
||||
collectionAdapter = new PlatformPagerAdapter(
|
||||
mContext, null, gameEntity, saveApkList,
|
||||
mAutoDownloadPlatform, entrance, location, traceEvent);
|
||||
collectionViewPager.setAdapter(collectionAdapter);
|
||||
|
||||
collectionViewPager.addOnPageChangeListener(new MyPageChangeListener(dialog_ll_collection_hint));
|
||||
|
||||
int currentItem = 0;
|
||||
if (!TextUtils.isEmpty(mAutoDownloadPlatform)) {
|
||||
for (int i = 0; i < saveApkList.size(); i++) {
|
||||
ApkEntity apkEntity = saveApkList.get(i);
|
||||
if (mAutoDownloadPlatform.equals(apkEntity.getPlatform())) {
|
||||
currentItem = (i / 9);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (currentItem != 0) {
|
||||
collectionViewPager.setCurrentItem(currentItem);
|
||||
setDownloadOvalHint(dialog_ll_collection_hint, currentItem);
|
||||
}
|
||||
mAutoDownloadPlatform = null;
|
||||
}
|
||||
|
||||
// 隐藏合集
|
||||
@Override
|
||||
public void hideCollection() {
|
||||
dialog_ll_collection.setVisibility(View.GONE);
|
||||
collectionAdapter = null;
|
||||
}
|
||||
|
||||
private class MyPageChangeListener implements OnPageChangeListener {
|
||||
|
||||
private LinearLayout linearLayout;
|
||||
|
||||
public MyPageChangeListener(LinearLayout linearLayout) {
|
||||
this.linearLayout = linearLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int i, float v, int i1) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
setDownloadOvalHint(linearLayout, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int i) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void setDownloadOvalHint(LinearLayout linearLayout, int position) {
|
||||
for (int i = 0, size = linearLayout.getChildCount(); i < size; i++) {
|
||||
if (i == position % size) {
|
||||
((ImageView) linearLayout.getChildAt(i))
|
||||
.setImageResource(R.drawable.download_oval_hint_up);
|
||||
} else {
|
||||
((ImageView) linearLayout.getChildAt(i))
|
||||
.setImageResource(R.drawable.oval_hint_gray_bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -24,9 +24,7 @@ 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;
|
||||
public static final int DOWNLOAD_RECT_STYLE = 1;
|
||||
public static final int DOWNLOAD_IMAGE_STYLE = 2;
|
||||
public static final int DOWNLOAD_SLIDE_STYLE = 3;
|
||||
|
||||
public enum DownloadType {
|
||||
NORMAL,
|
||||
@ -115,8 +113,6 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
int color = Color.WHITE;
|
||||
if (DOWNLOAD_IMAGE_STYLE == mDownloadStyle) {
|
||||
color = Color.BLACK;
|
||||
} else if (DOWNLOAD_SLIDE_STYLE == mDownloadStyle) {
|
||||
color = getResources().getColor(R.color.theme_font);
|
||||
}
|
||||
mPaint.setColor(color); // 反向颜色
|
||||
}
|
||||
@ -167,73 +163,48 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
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));
|
||||
mDefaultColor = Color.WHITE;
|
||||
break;
|
||||
case DOWNLOAD_IMAGE_STYLE:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_download_normal_image_style));
|
||||
mDefaultColor = Color.BLACK;
|
||||
break;
|
||||
default:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.game_item_btn_download_style));
|
||||
mDefaultColor = Color.WHITE;
|
||||
break;
|
||||
if (mDownloadStyle == DOWNLOAD_IMAGE_STYLE) {
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_download_normal_image_style));
|
||||
mDefaultColor = Color.BLACK;
|
||||
} else {
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.download_button_normal_style));
|
||||
mDefaultColor = Color.WHITE;
|
||||
}
|
||||
setProgress(0);
|
||||
break;
|
||||
case PLUGIN:
|
||||
case INSTALL_PLUGIN:
|
||||
setProgressDrawable(getResources().getDrawable(mDownloadStyle == DOWNLOAD_RECT_STYLE
|
||||
? R.drawable.detail_download_plugin_install_rect_style : R.drawable.game_item_btn_plugin_style));
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.download_button_pluggable_style));
|
||||
mDefaultColor = Color.WHITE;
|
||||
setProgress(0);
|
||||
break;
|
||||
case NONE:
|
||||
setProgressDrawable(getResources().getDrawable(mDownloadStyle == DOWNLOAD_RECT_STYLE
|
||||
? R.drawable.detail_download_none_rect_style : R.drawable.news_detail_comment));
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.news_detail_comment));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.hint);
|
||||
setProgress(0);
|
||||
break;
|
||||
case LAUNCH_OR_OPEN:
|
||||
switch (mDownloadStyle) {
|
||||
case DOWNLOAD_RECT_STYLE:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_download_open_rect_style));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.theme_font);
|
||||
break;
|
||||
case DOWNLOAD_IMAGE_STYLE:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_download_open_image_style));
|
||||
mDefaultColor = Color.WHITE;
|
||||
break;
|
||||
default:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_download_open_style));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.theme_font);
|
||||
break;
|
||||
if (mDownloadStyle == DOWNLOAD_IMAGE_STYLE) {
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_download_open_image_style));
|
||||
mDefaultColor = Color.WHITE;
|
||||
} else {
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.download_button_normal_style));
|
||||
mDefaultColor = Color.WHITE;
|
||||
}
|
||||
setProgress(0);
|
||||
break;
|
||||
case DOWNLOADING_NORMAL:
|
||||
switch (mDownloadStyle) {
|
||||
case DOWNLOAD_RECT_STYLE:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_downloading_normal_rect_style));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.theme_font);
|
||||
break;
|
||||
case DOWNLOAD_IMAGE_STYLE:
|
||||
case DOWNLOAD_SLIDE_STYLE:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_downloading_normal_image_style));
|
||||
mDefaultColor = Color.WHITE;
|
||||
break;
|
||||
default:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_downloading_normal_style));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.theme_font);
|
||||
break;
|
||||
if (mDownloadStyle == DOWNLOAD_IMAGE_STYLE) {
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_downloading_normal_image_style));
|
||||
mDefaultColor = Color.WHITE;
|
||||
} else {
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_downloading_normal_style));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.theme_font);
|
||||
}
|
||||
break;
|
||||
case DOWNLOADING_PLUGIN:
|
||||
setProgressDrawable(getResources().getDrawable(mDownloadStyle == DOWNLOAD_RECT_STYLE
|
||||
? R.drawable.detail_downloading_plugin_rect_style : R.drawable.detail_downloading_plugin_style));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.btn_plugin);
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_downloading_plugin_style));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.text_00B8B8);
|
||||
break;
|
||||
case RESERVABLE:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.button_reserve));
|
||||
|
||||
@ -97,6 +97,13 @@ object DrawableView {
|
||||
return drawable
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getCornerGradientDrawable(startColor: Int, endColor: Int, radius: Float = 999F): Drawable {
|
||||
val drawable = GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, intArrayOf(startColor, endColor))
|
||||
drawable.cornerRadius = DisplayUtils.dip2px(radius).toFloat()
|
||||
return drawable
|
||||
}
|
||||
|
||||
fun convertAlphaKey(percent: Int): String {
|
||||
val hexString = Integer.toHexString(Math.round((255 * percent / 100).toFloat()))
|
||||
return (if (hexString.length < 2) "0" else "") + hexString
|
||||
|
||||
@ -1,33 +1,36 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Build;
|
||||
import android.text.Layout;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextPaint;
|
||||
import android.text.style.BackgroundColorSpan;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class ExpandTextView extends AppCompatTextView {
|
||||
|
||||
private CharSequence mSnapshotText;
|
||||
|
||||
private String mExpendText = "...全文";
|
||||
private String mEndText = "...";
|
||||
private String mExpandText = mEndText + "全文";
|
||||
private boolean mUseGradientAlphaEndText = false;
|
||||
|
||||
private int mMaxLines = 3; // 由于sdk版本限制(getMaxLines) 这里设置默认值
|
||||
|
||||
private static int DEFAULT_ADDITIONAL_END_TEXT_COUNT = 2;
|
||||
|
||||
private boolean mInitLayout = false;
|
||||
private boolean mOpenLayout = false;
|
||||
private boolean mIsExpanded = false; // 位于 recyclerView 时需要自行在外层管理是否已展开
|
||||
|
||||
private ExpandCallback mExpandCallback;
|
||||
|
||||
@ -40,20 +43,25 @@ public class ExpandTextView extends AppCompatTextView {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
mMaxLines = getMaxLines();
|
||||
}
|
||||
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ExpandTextView);
|
||||
mUseGradientAlphaEndText = ta.getBoolean(R.styleable.ExpandTextView_useGradientAlphaEndText, false);
|
||||
mEndText = ta.getString(R.styleable.ExpandTextView_endText) == null ? mEndText : ta.getString(R.styleable.ExpandTextView_endText);
|
||||
mExpandText = ta.getString(R.styleable.ExpandTextView_expandText) == null ? mExpandText : ta.getString(R.styleable.ExpandTextView_expandText);
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
if (mInitLayout && !mOpenLayout && getLineCount() > mMaxLines) {
|
||||
if (mInitLayout && !mIsExpanded && getLineCount() > mMaxLines) {
|
||||
mSnapshotText = getText();
|
||||
mInitLayout = false;
|
||||
showExpendButton();
|
||||
showExpandButton();
|
||||
}
|
||||
}
|
||||
|
||||
public void setExpendText(String text) {
|
||||
this.mExpendText = text;
|
||||
this.mExpandText = text;
|
||||
}
|
||||
|
||||
public void setExpandCallback(ExpandCallback callback) {
|
||||
@ -66,7 +74,9 @@ public class ExpandTextView extends AppCompatTextView {
|
||||
super.setText(text, type);
|
||||
}
|
||||
|
||||
private void showExpendButton() {
|
||||
private void showExpandButton() {
|
||||
String finalEndText = "";
|
||||
|
||||
Layout layout = getLayout();
|
||||
int start = layout.getLineStart(0);
|
||||
int lastLineEnd = layout.getLineEnd(mMaxLines - 1);
|
||||
@ -74,28 +84,59 @@ public class ExpandTextView extends AppCompatTextView {
|
||||
float lastLineRight = layout.getLineRight(mMaxLines - 1);
|
||||
|
||||
int viewWidth = getWidth() - getPaddingRight() - getPaddingLeft();
|
||||
int additionalEndTextCount = 0;
|
||||
|
||||
TextPaint paint = getPaint();
|
||||
float expendTextWidth = paint.measureText(mExpendText);
|
||||
float expandTextWidth;
|
||||
if (mUseGradientAlphaEndText) {
|
||||
additionalEndTextCount = DEFAULT_ADDITIONAL_END_TEXT_COUNT;
|
||||
// 如果不加多个括号的话有可能算不对,惊了,明明是同样的 paint 同样的文字,长度却会略有不同
|
||||
expandTextWidth = paint.measureText(mEndText + mExpandText + " ");
|
||||
} else {
|
||||
expandTextWidth = paint.measureText(mExpandText);
|
||||
}
|
||||
|
||||
CharSequence content = mSnapshotText.subSequence(start, lastLineEnd);
|
||||
if (viewWidth - lastLineRight > expendTextWidth) {
|
||||
content = content.toString().trim() + mExpendText;
|
||||
|
||||
if (viewWidth - lastLineRight > expandTextWidth) {
|
||||
if (mUseGradientAlphaEndText) {
|
||||
finalEndText = content.toString().substring(content.length() - additionalEndTextCount, content.length()) + mEndText;
|
||||
finalEndText = finalEndText.replace("\n", "");
|
||||
|
||||
content = content.subSequence(0, content.length() - additionalEndTextCount) + finalEndText + mExpandText;
|
||||
} else {
|
||||
content = content.toString().trim() + mExpandText;
|
||||
}
|
||||
} else {
|
||||
CharSequence lastText = mSnapshotText.subSequence(lastLineStart, lastLineEnd);
|
||||
for (int i = lastText.length() - 1; i > 0; i--) {
|
||||
CharSequence sequence = lastText.subSequence(0, i);
|
||||
float w = paint.measureText(sequence.toString());
|
||||
if (viewWidth - w - DisplayUtils.dip2px(5) > expendTextWidth) {
|
||||
content = mSnapshotText.subSequence(start, lastLineStart + i) + mExpendText;
|
||||
if (viewWidth - w - DisplayUtils.dip2px(5) > expandTextWidth) {
|
||||
if (mUseGradientAlphaEndText) {
|
||||
finalEndText = lastText.subSequence(i - additionalEndTextCount, i) + mEndText;
|
||||
finalEndText = finalEndText.replace("\n", "");
|
||||
|
||||
content = mSnapshotText.subSequence(start, lastLineStart + i - additionalEndTextCount) + finalEndText + mExpandText;
|
||||
} else {
|
||||
content = mSnapshotText.subSequence(start, lastLineStart + i) + mExpandText;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpannableStringBuilder msp = new SpannableStringBuilder(mSnapshotText);
|
||||
int length = msp.length();
|
||||
int startPosition = content.length() - mExpendText.length();
|
||||
startPosition = startPosition < 0 ? 0 : startPosition;
|
||||
msp.replace(startPosition, length, mExpendText);
|
||||
int startPosition = 0;
|
||||
startPosition = content.length() - finalEndText.length() - mExpandText.length();
|
||||
startPosition = Math.max(startPosition, 0);
|
||||
|
||||
// 避免越界
|
||||
if (startPosition >= length) return;
|
||||
|
||||
msp.replace(startPosition, length, finalEndText + mExpandText);
|
||||
|
||||
msp.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(TextPaint ds) {
|
||||
@ -106,7 +147,7 @@ public class ExpandTextView extends AppCompatTextView {
|
||||
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
mOpenLayout = true;
|
||||
mIsExpanded = true;
|
||||
setMaxLines(Integer.MAX_VALUE);
|
||||
setText(mSnapshotText);
|
||||
|
||||
@ -114,15 +155,21 @@ public class ExpandTextView extends AppCompatTextView {
|
||||
mExpandCallback.onExpand();
|
||||
}
|
||||
}
|
||||
}, startPosition + 3, msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
msp.setSpan(new BackgroundColorSpan(Color.WHITE), startPosition, msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}, startPosition + mEndText.length(), msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
msp.setSpan(new GradientAlphaTextSpan(), startPosition, startPosition + finalEndText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
setText(msp);
|
||||
setMovementMethod(CustomLinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* 此方法仅更改标记,不做实际展开的操作
|
||||
*/
|
||||
public void setIsExpanded(boolean isExpanded) {
|
||||
mIsExpanded = isExpanded;
|
||||
}
|
||||
|
||||
public void setExpendMaxLines(int maxLines) {
|
||||
public void setExpandMaxLines(int maxLines) {
|
||||
mMaxLines = maxLines;
|
||||
setMaxLines(maxLines);
|
||||
}
|
||||
|
||||
124
app/src/main/java/com/gh/common/view/FlexLinearLayout.kt
Normal file
124
app/src/main/java/com/gh/common/view/FlexLinearLayout.kt
Normal file
@ -0,0 +1,124 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.TagStyleEntity
|
||||
import kotlin.math.ceil
|
||||
|
||||
/**
|
||||
* 标签最多显示一行,显示的个数由行宽决定
|
||||
*/
|
||||
class FlexLinearLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) {
|
||||
|
||||
private var mTotalCount = 0
|
||||
private var mTags = ArrayList<TagStyleEntity>()
|
||||
private var mItemHeight = DisplayUtils.dip2px(20F)
|
||||
private var mPadding = DisplayUtils.dip2px(5F)
|
||||
private var mMargin = DisplayUtils.dip2px(4F)
|
||||
private var mTextSize = 10F
|
||||
private var mLastItemWidth = DisplayUtils.dip2px(18F)//最后更多按钮宽度
|
||||
private var mTotalWidth = 0
|
||||
var onClickListener: OnItemClickListener? = null
|
||||
|
||||
init {
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
}
|
||||
|
||||
fun setTags(tags: ArrayList<TagStyleEntity>) {
|
||||
mTags.clear()
|
||||
mTotalCount = tags.size
|
||||
mTotalWidth = measuredWidth
|
||||
val paint = Paint()
|
||||
paint.textSize = DisplayUtils.sp2px(context, mTextSize).toFloat()
|
||||
|
||||
var currentWidth = mLastItemWidth.toFloat()
|
||||
tags.forEach {
|
||||
val strWidth = getTextWidth(paint, it.name)
|
||||
if (currentWidth + strWidth + mPadding * 2 + mMargin <= mTotalWidth) {
|
||||
currentWidth += strWidth + mPadding * 2 + mMargin
|
||||
mTags.add(it)
|
||||
}
|
||||
}
|
||||
if (mTags.isNotEmpty()) {
|
||||
addTags()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTextWidth(paint: Paint, str: String?): Int {
|
||||
var width = 0
|
||||
if (str != null && str.isNotEmpty()) {
|
||||
val len = str.length
|
||||
val widths = FloatArray(len)
|
||||
paint.getTextWidths(str, widths)
|
||||
for (i in 0 until len) {
|
||||
width += ceil(widths[i].toDouble()).toInt()
|
||||
}
|
||||
}
|
||||
return width
|
||||
}
|
||||
|
||||
private fun addTags() {
|
||||
removeAllViews()
|
||||
mTags.forEach {
|
||||
addView(createView(it))
|
||||
}
|
||||
if (mTotalCount != mTags.size) {
|
||||
val imageView = ImageView(context).apply {
|
||||
val params = LayoutParams(mLastItemWidth, mItemHeight)
|
||||
layoutParams = params
|
||||
setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_game_detail_label_more))
|
||||
background = createBackgroundDrawable()
|
||||
scaleType=ImageView.ScaleType.CENTER
|
||||
}
|
||||
imageView.setOnClickListener {
|
||||
onClickListener?.onMoreClickListener()
|
||||
}
|
||||
addView(imageView)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createView(tag: TagStyleEntity): View {
|
||||
return TextView(context).apply {
|
||||
text = tag.name
|
||||
includeFontPadding = false
|
||||
textSize = mTextSize
|
||||
gravity = Gravity.CENTER
|
||||
setTextColor(Color.parseColor("#333333"))
|
||||
|
||||
val params = LayoutParams(LayoutParams.WRAP_CONTENT, mItemHeight)
|
||||
params.setMargins(0, 0, mMargin, 0)
|
||||
setPadding(mPadding, 0, mPadding, 0)
|
||||
layoutParams = params
|
||||
|
||||
val gradientDrawable = createBackgroundDrawable()
|
||||
background = gradientDrawable
|
||||
setOnClickListener {
|
||||
onClickListener?.onItemClickListener(tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createBackgroundDrawable(): GradientDrawable {
|
||||
val gradientDrawable = GradientDrawable()
|
||||
gradientDrawable.setColor(Color.TRANSPARENT)
|
||||
gradientDrawable.setStroke(DisplayUtils.dip2px(context, 1f), Color.parseColor("#C2C6CC"))
|
||||
gradientDrawable.cornerRadius = DisplayUtils.dip2px(2f).toFloat()
|
||||
return gradientDrawable
|
||||
}
|
||||
|
||||
interface OnItemClickListener {
|
||||
fun onMoreClickListener()
|
||||
fun onItemClickListener(tag: TagStyleEntity)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.LinearGradient
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Shader
|
||||
import android.text.style.ReplacementSpan
|
||||
import androidx.core.graphics.ColorUtils
|
||||
|
||||
class GradientAlphaTextSpan() : ReplacementSpan() {
|
||||
|
||||
override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int {
|
||||
return paint.measureText(text, start, end).toInt()
|
||||
}
|
||||
|
||||
override fun draw(canvas: Canvas, text: CharSequence?, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {
|
||||
val originalColor = paint.color
|
||||
val originalColorWithAlphaChanged = ColorUtils.setAlphaComponent(paint.color, 1)
|
||||
|
||||
val textWidth = paint.measureText(text, start, end).toInt()
|
||||
|
||||
val mShader = LinearGradient(x, 0F, x + textWidth - 10, 0F,
|
||||
originalColor, originalColorWithAlphaChanged, Shader.TileMode.CLAMP)
|
||||
paint.shader = mShader
|
||||
|
||||
canvas.drawText(text, start, end, x, y.toFloat(), paint)
|
||||
|
||||
paint.shader = null
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.graphics.*
|
||||
import android.text.style.ReplacementSpan
|
||||
import androidx.annotation.Dimension
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
|
||||
class GradientRoundBackgroundColorSpan(private val startColor: String,
|
||||
private val endColor: String,
|
||||
private val textColor: String,
|
||||
@Dimension(unit = Dimension.SP)
|
||||
private val textSize: Int = 0) : ReplacementSpan() {
|
||||
|
||||
|
||||
override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int {
|
||||
return paint.measureText(text, start, end).toInt()
|
||||
}
|
||||
|
||||
override fun draw(canvas: Canvas, text: CharSequence, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {
|
||||
val originalColor = paint.color
|
||||
val originalTextSize = paint.textSize
|
||||
|
||||
paint.style = Paint.Style.FILL
|
||||
|
||||
val fontMetrics = paint.fontMetrics
|
||||
|
||||
// 原文字宽度
|
||||
val originalTextWidth = paint.measureText(text, start, end).toInt()
|
||||
// 当目标字体大小与原字体大小不一样时,需要先用目标字体大小测量字体宽度
|
||||
if (textSize != 0) {
|
||||
paint.textSize = DisplayUtils.sp2px(HaloApp.getInstance().application, textSize.toFloat()).toFloat()
|
||||
}
|
||||
// 目标文字宽度
|
||||
val textWidth = paint.measureText(text, start, end).toInt()
|
||||
|
||||
// 用原字体大小画椭圆
|
||||
paint.textSize = originalTextSize
|
||||
//添加渐变Shader
|
||||
val mShader = LinearGradient(0F, top.toFloat(), x + originalTextWidth, top + fontMetrics.bottom - fontMetrics.top,
|
||||
Color.parseColor(startColor), Color.parseColor(endColor), Shader.TileMode.CLAMP)
|
||||
paint.shader = mShader
|
||||
canvas.drawRoundRect(RectF(
|
||||
x,
|
||||
top.toFloat(),
|
||||
x + originalTextWidth,
|
||||
top + fontMetrics.bottom - fontMetrics.top),
|
||||
DisplayUtils.dip2px(HaloApp.getInstance().application, 5f).toFloat(),
|
||||
DisplayUtils.dip2px(HaloApp.getInstance().application, 5f).toFloat(),
|
||||
paint)
|
||||
|
||||
//重置paint
|
||||
paint.color = Color.parseColor(this.textColor)
|
||||
//移除渐变Shader,否则绘制的文字也是渐变色
|
||||
paint.shader = null
|
||||
paint.style = Paint.Style.FILL
|
||||
|
||||
// 用目标字体大小画字
|
||||
if (textSize != 0) {
|
||||
paint.textSize = DisplayUtils.sp2px(HaloApp.getInstance().application, textSize.toFloat()).toFloat()
|
||||
}
|
||||
val offsetX = (originalTextWidth - textWidth) / 2
|
||||
canvas.drawText(text, start, end, x + offsetX, y.toFloat(), paint)
|
||||
|
||||
paint.color = originalColor
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.ViewConfiguration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlin.math.abs
|
||||
|
||||
class InterceptRecyclerView : RecyclerView {
|
||||
constructor(context: Context) : super(context)
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||
|
||||
private var startX = 0F
|
||||
private var startY = 0F
|
||||
|
||||
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
|
||||
if (ev.action == MotionEvent.ACTION_DOWN) {
|
||||
startX = ev.x
|
||||
startY = ev.y
|
||||
} else if (ev.action == MotionEvent.ACTION_MOVE) {
|
||||
val dx = ev.x - startX
|
||||
val dy = ev.y - startY
|
||||
val scaledTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
|
||||
if (layoutManager != null && layoutManager is LinearLayoutManager) {
|
||||
val orientation = (layoutManager as LinearLayoutManager).orientation
|
||||
if (orientation == HORIZONTAL) {
|
||||
if (abs(dx) > scaledTouchSlop && abs(dx) > abs(dy)) {
|
||||
parent.requestDisallowInterceptTouchEvent(true)
|
||||
} else if (abs(dy) > scaledTouchSlop && abs(dy) > abs(dx)) {
|
||||
parent.requestDisallowInterceptTouchEvent(false)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return super.dispatchTouchEvent(ev)
|
||||
}
|
||||
}
|
||||
@ -30,6 +30,7 @@ public class MarqueeView extends ViewFlipper {
|
||||
private int animDuration = 500;
|
||||
private int textSize = 14;
|
||||
private int textColor = 0xffffffff;
|
||||
private boolean useSingleLineText = false;
|
||||
|
||||
public MarqueeView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@ -51,6 +52,7 @@ public class MarqueeView extends ViewFlipper {
|
||||
textSize = DisplayUtils.px2sp(mContext, textSize);
|
||||
}
|
||||
textColor = typedArray.getColor(R.styleable.MarqueeViewStyle_mvTextColor, textColor);
|
||||
useSingleLineText = typedArray.getBoolean(R.styleable.MarqueeViewStyle_mvSingleLine, useSingleLineText);
|
||||
typedArray.recycle();
|
||||
|
||||
setFlipInterval(interval);
|
||||
@ -114,6 +116,10 @@ public class MarqueeView extends ViewFlipper {
|
||||
// 创建ViewFlipper下的TextView
|
||||
private TextView createTextView(String text) {
|
||||
TextView tv = new TextView(mContext);
|
||||
if (useSingleLineText) {
|
||||
tv.setSingleLine(true);
|
||||
tv.setEllipsize(TextUtils.TruncateAt.END);
|
||||
}
|
||||
tv.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
|
||||
tv.setText(text);
|
||||
tv.setTextColor(textColor);
|
||||
@ -127,6 +133,10 @@ public class MarqueeView extends ViewFlipper {
|
||||
start();
|
||||
}
|
||||
|
||||
public void enableSingleLineText() {
|
||||
useSingleLineText = true;
|
||||
}
|
||||
|
||||
public List<String> getNotices() {
|
||||
return notices;
|
||||
}
|
||||
|
||||
@ -4,9 +4,19 @@ import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.widget.RelativeLayout
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
class MaterializedRelativeLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
|
||||
: RelativeLayout(context, attrs) {
|
||||
class MaterializedRelativeLayout : RelativeLayout {
|
||||
|
||||
private var mConsumeWindowInset: Boolean = false
|
||||
|
||||
constructor(context: Context) : super(context)
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
||||
val ta = context.obtainStyledAttributes(attrs, R.styleable.MaterializedRelativeLayout)
|
||||
mConsumeWindowInset = ta.getBoolean(R.styleable.MaterializedRelativeLayout_consumeWindowInsets, false)
|
||||
ta.recycle()
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 windowInsets 传递给子 view [https://medium.com/androiddevelopers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec#.raoa9t506]
|
||||
@ -16,9 +26,16 @@ class MaterializedRelativeLayout @JvmOverloads constructor(context: Context, att
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
setOnApplyWindowInsetsListener { _, insets ->
|
||||
val childCount = childCount
|
||||
for (index in 0 until childCount) {
|
||||
getChildAt(index).dispatchApplyWindowInsets(insets)
|
||||
if (mConsumeWindowInset) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
|
||||
insets.replaceSystemWindowInsets(insets.systemWindowInsetLeft, 0, insets.systemWindowInsetRight, insets.systemWindowInsetBottom)
|
||||
insets.consumeSystemWindowInsets()
|
||||
}
|
||||
} else {
|
||||
val childCount = childCount
|
||||
for (index in 0 until childCount) {
|
||||
getChildAt(index).dispatchApplyWindowInsets(insets)
|
||||
}
|
||||
}
|
||||
insets
|
||||
}
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
|
||||
class MaxHeightNestedScrollView(context: Context, attrs: AttributeSet? = null) : NestedScrollView(context, attrs) {
|
||||
|
||||
var maxHeight = 0F
|
||||
var scrollChangedListener: ScrollScrollChangedListener? = null
|
||||
|
||||
init {
|
||||
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.MaxHeightNestedScrollView)
|
||||
maxHeight = typedArray.getDimension(R.styleable.MaxHeightNestedScrollView_mMaxHeight, 0f)
|
||||
typedArray.recycle()
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
var newHeightMeasureSpec = 0
|
||||
try {
|
||||
newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight.toInt(), MeasureSpec.AT_MOST)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
//重新计算控件高、宽
|
||||
super.onMeasure(widthMeasureSpec, newHeightMeasureSpec)
|
||||
}
|
||||
|
||||
override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
|
||||
super.onScrollChanged(l, t, oldl, oldt)
|
||||
scrollChangedListener?.onScrollChanged(l, t, oldl, oldt)
|
||||
}
|
||||
|
||||
interface ScrollScrollChangedListener {
|
||||
fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.TypedArray
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
class MaxHeightRecyclerView : RecyclerView {
|
||||
private var mMaxHeight: Int = 0
|
||||
|
||||
constructor(context: Context) : super(context) {}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
||||
initialize(context, attrs)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
||||
initialize(context, attrs)
|
||||
}
|
||||
|
||||
private fun initialize(context: Context, attrs: AttributeSet) {
|
||||
val arr = context.obtainStyledAttributes(attrs, R.styleable.MaxHeightRecyclerView)
|
||||
mMaxHeight = arr.getLayoutDimension(R.styleable.MaxHeightRecyclerView_mRvMaxHeight, mMaxHeight)
|
||||
arr.recycle()
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
var heightMeasureSpec = heightMeasureSpec
|
||||
if (mMaxHeight > 0) {
|
||||
heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(mMaxHeight, MeasureSpec.AT_MOST)
|
||||
}
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
}
|
||||
}
|
||||
164
app/src/main/java/com/gh/common/view/NestedScrollWebView.java
Normal file
164
app/src/main/java/com/gh/common/view/NestedScrollWebView.java
Normal file
@ -0,0 +1,164 @@
|
||||
package com.gh.common.view;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.core.view.MotionEventCompat;
|
||||
import androidx.core.view.NestedScrollingChild;
|
||||
import androidx.core.view.NestedScrollingChildHelper;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import wendu.dsbridge.DWebView;
|
||||
|
||||
public class NestedScrollWebView extends DWebView implements NestedScrollingChild {
|
||||
|
||||
public static final String TAG = NestedScrollWebView.class.getSimpleName();
|
||||
|
||||
private int mLastMotionY;
|
||||
|
||||
private final int[] mScrollOffset = new int[2];
|
||||
private final int[] mScrollConsumed = new int[2];
|
||||
|
||||
private int mNestedYOffset;
|
||||
private boolean mChange;
|
||||
|
||||
private NestedScrollingChildHelper mChildHelper;
|
||||
|
||||
public NestedScrollWebView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public NestedScrollWebView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
private void init() {
|
||||
mChildHelper = new NestedScrollingChildHelper(this);
|
||||
setNestedScrollingEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
getParent().requestDisallowInterceptTouchEvent(true);
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
boolean result = false;
|
||||
|
||||
MotionEvent trackedEvent = MotionEvent.obtain(event);
|
||||
|
||||
final int action = MotionEventCompat.getActionMasked(event);
|
||||
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
mNestedYOffset = 0;
|
||||
}
|
||||
|
||||
int y = (int) event.getY();
|
||||
|
||||
event.offsetLocation(0, mNestedYOffset);
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mLastMotionY = y;
|
||||
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
|
||||
result = super.onTouchEvent(event);
|
||||
mChange = false;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
int deltaY = mLastMotionY - y;
|
||||
|
||||
if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
|
||||
deltaY -= mScrollConsumed[1];
|
||||
trackedEvent.offsetLocation(0, mScrollOffset[1]);
|
||||
mNestedYOffset += mScrollOffset[1];
|
||||
}
|
||||
|
||||
int oldY = getScrollY();
|
||||
mLastMotionY = y - mScrollOffset[1];
|
||||
int newScrollY = Math.max(0, oldY + deltaY);
|
||||
deltaY -= newScrollY - oldY;
|
||||
if (dispatchNestedScroll(0, newScrollY - deltaY, 0, deltaY, mScrollOffset)) {
|
||||
mLastMotionY -= mScrollOffset[1];
|
||||
trackedEvent.offsetLocation(0, mScrollOffset[1]);
|
||||
mNestedYOffset += mScrollOffset[1];
|
||||
}
|
||||
if(mScrollConsumed[1]==0 && mScrollOffset[1]==0) {
|
||||
if(mChange){
|
||||
mChange =false;
|
||||
trackedEvent.setAction(MotionEvent.ACTION_DOWN);
|
||||
super.onTouchEvent(trackedEvent);
|
||||
}else {
|
||||
result = super.onTouchEvent(trackedEvent);
|
||||
}
|
||||
trackedEvent.recycle();
|
||||
}else{
|
||||
if(Math.abs(mLastMotionY - y) >= 10) {
|
||||
if (!mChange) {
|
||||
mChange = true;
|
||||
super.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
stopNestedScroll();
|
||||
result = super.onTouchEvent(event);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// NestedScrollingChild
|
||||
@Override
|
||||
public void setNestedScrollingEnabled(boolean enabled) {
|
||||
mChildHelper.setNestedScrollingEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNestedScrollingEnabled() {
|
||||
return mChildHelper.isNestedScrollingEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startNestedScroll(int axes) {
|
||||
return mChildHelper.startNestedScroll(axes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopNestedScroll() {
|
||||
mChildHelper.stopNestedScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNestedScrollingParent() {
|
||||
return mChildHelper.hasNestedScrollingParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
|
||||
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
|
||||
return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
|
||||
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
|
||||
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,13 +4,14 @@ import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class VerticalItemDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
private Paint paint;
|
||||
@ -18,13 +19,21 @@ public class VerticalItemDecoration extends RecyclerView.ItemDecoration {
|
||||
private int mIntervalLR;
|
||||
private boolean mIsShowIntervalTop;
|
||||
|
||||
public VerticalItemDecoration(Context context, float interval, boolean isShowIntervalTop) {
|
||||
public VerticalItemDecoration(Context context, float interval, boolean isShowIntervalTop, int colorRes) {
|
||||
paint = new Paint();
|
||||
paint.setColor(ContextCompat.getColor(context, R.color.background));
|
||||
if (colorRes != 0) {
|
||||
paint.setColor(ContextCompat.getColor(context, colorRes));
|
||||
} else {
|
||||
paint.setColor(ContextCompat.getColor(context, R.color.background));
|
||||
}
|
||||
mInterval = DisplayUtils.dip2px(context, interval);
|
||||
mIsShowIntervalTop = isShowIntervalTop;
|
||||
}
|
||||
|
||||
public VerticalItemDecoration(Context context, float interval, boolean isShowIntervalTop) {
|
||||
this(context, interval, isShowIntervalTop, 0);
|
||||
}
|
||||
|
||||
public VerticalItemDecoration(Context context, int interval, boolean isShowIntervalTop, int intervalLR) {
|
||||
paint = new Paint();
|
||||
paint.setColor(ContextCompat.getColor(context, R.color.background));
|
||||
|
||||
@ -42,28 +42,28 @@ class WelcomeDialog : BaseDialogFragment() {
|
||||
binding.ivOpeningCover.setOnClickListener {
|
||||
when (mWelcomeEntity?.type) {
|
||||
EntranceUtils.HOST_ARTICLE -> {
|
||||
DirectUtils.directToArticle(context!!, mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
|
||||
DirectUtils.directToArticle(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
|
||||
}
|
||||
EntranceUtils.HOST_GAME -> {
|
||||
DirectUtils.directToGameDetail(context!!, mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
|
||||
DirectUtils.directToGameDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
|
||||
}
|
||||
EntranceUtils.HOST_COLUMN -> {
|
||||
DirectUtils.directToSubject(context!!, mWelcomeEntity?.link!!, null, EntranceUtils.ENTRANCE_WELCOME)
|
||||
DirectUtils.directToSubject(requireContext(), mWelcomeEntity?.link!!, null, EntranceUtils.ENTRANCE_WELCOME)
|
||||
}
|
||||
EntranceUtils.HOST_QUESTION -> {
|
||||
DirectUtils.directToQuestionDetail(context!!, mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
|
||||
DirectUtils.directToQuestionDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
|
||||
}
|
||||
EntranceUtils.HOST_ANSWER -> {
|
||||
DirectUtils.directToAnswerDetail(context!!, mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
|
||||
DirectUtils.directToAnswerDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
|
||||
}
|
||||
EntranceUtils.HOST_WEB -> {
|
||||
DirectUtils.directToWebView(context!!, mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
|
||||
DirectUtils.directToWebView(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
|
||||
}
|
||||
EntranceUtils.HOST_QQ -> {
|
||||
DirectUtils.directToQqConversation(context!!, mWelcomeEntity?.link!!)
|
||||
DirectUtils.directToQqConversation(requireContext(), mWelcomeEntity?.link!!)
|
||||
}
|
||||
EntranceUtils.HOST_COMMUNITY -> {
|
||||
DirectUtils.directToCommunity(context!!, CommunityEntity(mWelcomeEntity?.link!!, mWelcomeEntity?.text!!))
|
||||
DirectUtils.directToCommunity(requireContext(), CommunityEntity(mWelcomeEntity?.link!!, mWelcomeEntity?.text!!))
|
||||
}
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
@ -75,10 +75,19 @@ class WelcomeDialog : BaseDialogFragment() {
|
||||
|
||||
binding.ivOpeningCover.loadingCallback = object : WrapContentDraweeView.LoadingCallback {
|
||||
override fun loaded() {
|
||||
binding.ivClose.visibility = View.VISIBLE
|
||||
binding.root.post {
|
||||
if (binding.ivOpeningCover.measuredHeight > binding.root.resources.displayMetrics.heightPixels * .8) {
|
||||
binding.ivCloseBackup.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.ivClose.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.ivCloseBackup.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
binding.ivClose.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
@ -3,8 +3,8 @@ package com.gh.common.view
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.net.Uri
|
||||
import androidx.annotation.Nullable
|
||||
import android.util.AttributeSet
|
||||
import androidx.annotation.Nullable
|
||||
import com.facebook.drawee.backends.pipeline.PipelineDraweeControllerBuilder
|
||||
import com.facebook.drawee.controller.BaseControllerListener
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
|
||||
@ -0,0 +1,436 @@
|
||||
package com.gh.common.view.divider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.DimenRes;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
public abstract class FlexibleDividerDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
private static final int DEFAULT_SIZE = 2;
|
||||
private static final int[] ATTRS = new int[]{
|
||||
android.R.attr.listDivider
|
||||
};
|
||||
|
||||
protected enum DividerType {
|
||||
DRAWABLE, PAINT, COLOR
|
||||
}
|
||||
|
||||
protected DividerType mDividerType = DividerType.DRAWABLE;
|
||||
protected VisibilityProvider mVisibilityProvider;
|
||||
protected PaintProvider mPaintProvider;
|
||||
protected ColorProvider mColorProvider;
|
||||
protected DrawableProvider mDrawableProvider;
|
||||
protected SizeProvider mSizeProvider;
|
||||
protected boolean mShowLastDivider;
|
||||
protected boolean mPositionInsideItem;
|
||||
private Paint mPaint;
|
||||
|
||||
protected FlexibleDividerDecoration(Builder builder) {
|
||||
if (builder.mPaintProvider != null) {
|
||||
mDividerType = DividerType.PAINT;
|
||||
mPaintProvider = builder.mPaintProvider;
|
||||
} else if (builder.mColorProvider != null) {
|
||||
mDividerType = DividerType.COLOR;
|
||||
mColorProvider = builder.mColorProvider;
|
||||
mPaint = new Paint();
|
||||
setSizeProvider(builder);
|
||||
} else {
|
||||
mDividerType = DividerType.DRAWABLE;
|
||||
if (builder.mDrawableProvider == null) {
|
||||
TypedArray a = builder.mContext.obtainStyledAttributes(ATTRS);
|
||||
final Drawable divider = a.getDrawable(0);
|
||||
a.recycle();
|
||||
mDrawableProvider = new DrawableProvider() {
|
||||
@Override
|
||||
public Drawable drawableProvider(int position, RecyclerView parent) {
|
||||
return divider;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
mDrawableProvider = builder.mDrawableProvider;
|
||||
}
|
||||
mSizeProvider = builder.mSizeProvider;
|
||||
}
|
||||
|
||||
mVisibilityProvider = builder.mVisibilityProvider;
|
||||
mShowLastDivider = builder.mShowLastDivider;
|
||||
mPositionInsideItem = builder.mPositionInsideItem;
|
||||
}
|
||||
|
||||
private void setSizeProvider(Builder builder) {
|
||||
mSizeProvider = builder.mSizeProvider;
|
||||
if (mSizeProvider == null) {
|
||||
mSizeProvider = new SizeProvider() {
|
||||
@Override
|
||||
public int dividerSize(int position, RecyclerView parent) {
|
||||
return DEFAULT_SIZE;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
||||
RecyclerView.Adapter adapter = parent.getAdapter();
|
||||
if (adapter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int itemCount = adapter.getItemCount();
|
||||
int lastDividerOffset = getLastDividerOffset(parent);
|
||||
int validChildCount = parent.getChildCount();
|
||||
int lastChildPosition = -1;
|
||||
for (int i = 0; i < validChildCount; i++) {
|
||||
View child = parent.getChildAt(i);
|
||||
int childPosition = parent.getChildAdapterPosition(child);
|
||||
|
||||
if (childPosition < lastChildPosition) {
|
||||
// Avoid remaining divider when animation starts
|
||||
continue;
|
||||
}
|
||||
lastChildPosition = childPosition;
|
||||
|
||||
if (!mShowLastDivider && childPosition >= itemCount - lastDividerOffset) {
|
||||
// Don't draw divider for last line if mShowLastDivider = false
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wasDividerAlreadyDrawn(childPosition, parent)) {
|
||||
// No need to draw divider again as it was drawn already by previous column
|
||||
continue;
|
||||
}
|
||||
|
||||
int groupIndex = getGroupIndex(childPosition, parent);
|
||||
if (mVisibilityProvider.shouldHideDivider(groupIndex, parent)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Rect bounds = getDividerBound(groupIndex, parent, child);
|
||||
switch (mDividerType) {
|
||||
case DRAWABLE:
|
||||
Drawable drawable = mDrawableProvider.drawableProvider(groupIndex, parent);
|
||||
drawable.setBounds(bounds);
|
||||
drawable.draw(c);
|
||||
break;
|
||||
case PAINT:
|
||||
mPaint = mPaintProvider.dividerPaint(groupIndex, parent);
|
||||
c.drawLine(bounds.left, bounds.top, bounds.right, bounds.bottom, mPaint);
|
||||
break;
|
||||
case COLOR:
|
||||
mPaint.setColor(mColorProvider.dividerColor(groupIndex, parent));
|
||||
mPaint.setStrokeWidth(mSizeProvider.dividerSize(groupIndex, parent));
|
||||
c.drawLine(bounds.left, bounds.top, bounds.right, bounds.bottom, mPaint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect rect, View v, RecyclerView parent, RecyclerView.State state) {
|
||||
int position = parent.getChildAdapterPosition(v);
|
||||
int itemCount = parent.getAdapter().getItemCount();
|
||||
int lastDividerOffset = getLastDividerOffset(parent);
|
||||
if (!mShowLastDivider && position >= itemCount - lastDividerOffset) {
|
||||
// Don't set item offset for last line if mShowLastDivider = false
|
||||
return;
|
||||
}
|
||||
|
||||
int groupIndex = getGroupIndex(position, parent);
|
||||
if (mVisibilityProvider.shouldHideDivider(groupIndex, parent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setItemOffsets(rect, groupIndex, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if recyclerview is reverse layout
|
||||
*
|
||||
* @param parent RecyclerView
|
||||
* @return true if recyclerview is reverse layout
|
||||
*/
|
||||
protected boolean isReverseLayout(RecyclerView parent) {
|
||||
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
|
||||
if (layoutManager instanceof LinearLayoutManager) {
|
||||
return ((LinearLayoutManager) layoutManager).getReverseLayout();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case mShowLastDivider = false,
|
||||
* Returns offset for how many views we don't have to draw a divider for,
|
||||
* for LinearLayoutManager it is as simple as not drawing the last child divider,
|
||||
* but for a GridLayoutManager it needs to take the span count for the last items into account
|
||||
* until we use the span count configured for the grid.
|
||||
*
|
||||
* @param parent RecyclerView
|
||||
* @return offset for how many views we don't have to draw a divider or 1 if its a
|
||||
* LinearLayoutManager
|
||||
*/
|
||||
private int getLastDividerOffset(RecyclerView parent) {
|
||||
if (parent.getLayoutManager() instanceof GridLayoutManager) {
|
||||
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
|
||||
GridLayoutManager.SpanSizeLookup spanSizeLookup = layoutManager.getSpanSizeLookup();
|
||||
int spanCount = layoutManager.getSpanCount();
|
||||
int itemCount = parent.getAdapter().getItemCount();
|
||||
for (int i = itemCount - 1; i >= 0; i--) {
|
||||
if (spanSizeLookup.getSpanIndex(i, spanCount) == 0) {
|
||||
return itemCount - i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether divider was already drawn for the row the item is in,
|
||||
* effectively only makes sense for a grid
|
||||
*
|
||||
* @param position current view position to draw divider
|
||||
* @param parent RecyclerView
|
||||
* @return true if the divider can be skipped as it is in the same row as the previous one.
|
||||
*/
|
||||
private boolean wasDividerAlreadyDrawn(int position, RecyclerView parent) {
|
||||
if (parent.getLayoutManager() instanceof GridLayoutManager) {
|
||||
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
|
||||
GridLayoutManager.SpanSizeLookup spanSizeLookup = layoutManager.getSpanSizeLookup();
|
||||
int spanCount = layoutManager.getSpanCount();
|
||||
return spanSizeLookup.getSpanIndex(position, spanCount) > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group index for GridLayoutManager.
|
||||
* for LinearLayoutManager, always returns position.
|
||||
*
|
||||
* @param position current view position to draw divider
|
||||
* @param parent RecyclerView
|
||||
* @return group index of items
|
||||
*/
|
||||
private int getGroupIndex(int position, RecyclerView parent) {
|
||||
if (parent.getLayoutManager() instanceof GridLayoutManager) {
|
||||
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
|
||||
GridLayoutManager.SpanSizeLookup spanSizeLookup = layoutManager.getSpanSizeLookup();
|
||||
int spanCount = layoutManager.getSpanCount();
|
||||
return spanSizeLookup.getSpanGroupIndex(position, spanCount);
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
protected abstract Rect getDividerBound(int position, RecyclerView parent, View child);
|
||||
|
||||
protected abstract void setItemOffsets(Rect outRect, int position, RecyclerView parent);
|
||||
|
||||
/**
|
||||
* Interface for controlling divider visibility
|
||||
*/
|
||||
public interface VisibilityProvider {
|
||||
|
||||
/**
|
||||
* Returns true if divider should be hidden.
|
||||
*
|
||||
* @param position Divider position (or group index for GridLayoutManager)
|
||||
* @param parent RecyclerView
|
||||
* @return True if the divider at position should be hidden
|
||||
*/
|
||||
boolean shouldHideDivider(int position, RecyclerView parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for controlling paint instance for divider drawing
|
||||
*/
|
||||
public interface PaintProvider {
|
||||
|
||||
/**
|
||||
* Returns {@link Paint} for divider
|
||||
*
|
||||
* @param position Divider position (or group index for GridLayoutManager)
|
||||
* @param parent RecyclerView
|
||||
* @return Paint instance
|
||||
*/
|
||||
Paint dividerPaint(int position, RecyclerView parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for controlling divider color
|
||||
*/
|
||||
public interface ColorProvider {
|
||||
|
||||
/**
|
||||
* Returns {@link android.graphics.Color} value of divider
|
||||
*
|
||||
* @param position Divider position (or group index for GridLayoutManager)
|
||||
* @param parent RecyclerView
|
||||
* @return Color value
|
||||
*/
|
||||
int dividerColor(int position, RecyclerView parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for controlling drawable object for divider drawing
|
||||
*/
|
||||
public interface DrawableProvider {
|
||||
|
||||
/**
|
||||
* Returns drawable instance for divider
|
||||
*
|
||||
* @param position Divider position (or group index for GridLayoutManager)
|
||||
* @param parent RecyclerView
|
||||
* @return Drawable instance
|
||||
*/
|
||||
Drawable drawableProvider(int position, RecyclerView parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for controlling divider size
|
||||
*/
|
||||
public interface SizeProvider {
|
||||
|
||||
/**
|
||||
* Returns size value of divider.
|
||||
* Height for horizontal divider, width for vertical divider
|
||||
*
|
||||
* @param position Divider position (or group index for GridLayoutManager)
|
||||
* @param parent RecyclerView
|
||||
* @return Size of divider
|
||||
*/
|
||||
int dividerSize(int position, RecyclerView parent);
|
||||
}
|
||||
|
||||
public static class Builder<T extends Builder> {
|
||||
|
||||
private Context mContext;
|
||||
protected Resources mResources;
|
||||
private PaintProvider mPaintProvider;
|
||||
private ColorProvider mColorProvider;
|
||||
private DrawableProvider mDrawableProvider;
|
||||
private SizeProvider mSizeProvider;
|
||||
private VisibilityProvider mVisibilityProvider = new VisibilityProvider() {
|
||||
@Override
|
||||
public boolean shouldHideDivider(int position, RecyclerView parent) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
private boolean mShowLastDivider = false;
|
||||
private boolean mPositionInsideItem = false;
|
||||
|
||||
public Builder(Context context) {
|
||||
mContext = context;
|
||||
mResources = context.getResources();
|
||||
}
|
||||
|
||||
public T paint(final Paint paint) {
|
||||
return paintProvider(new PaintProvider() {
|
||||
@Override
|
||||
public Paint dividerPaint(int position, RecyclerView parent) {
|
||||
return paint;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public T paintProvider(PaintProvider provider) {
|
||||
mPaintProvider = provider;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T color(final int color) {
|
||||
return colorProvider(new ColorProvider() {
|
||||
@Override
|
||||
public int dividerColor(int position, RecyclerView parent) {
|
||||
return color;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public T colorResId(@ColorRes int colorId) {
|
||||
return color(ContextCompat.getColor(mContext, colorId));
|
||||
}
|
||||
|
||||
public T colorProvider(ColorProvider provider) {
|
||||
mColorProvider = provider;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T drawable(@DrawableRes int id) {
|
||||
return drawable(ContextCompat.getDrawable(mContext, id));
|
||||
}
|
||||
|
||||
public T drawable(final Drawable drawable) {
|
||||
return drawableProvider(new DrawableProvider() {
|
||||
@Override
|
||||
public Drawable drawableProvider(int position, RecyclerView parent) {
|
||||
return drawable;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public T drawableProvider(DrawableProvider provider) {
|
||||
mDrawableProvider = provider;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T size(final int size) {
|
||||
return sizeProvider(new SizeProvider() {
|
||||
@Override
|
||||
public int dividerSize(int position, RecyclerView parent) {
|
||||
return size;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public T sizeResId(@DimenRes int sizeId) {
|
||||
return size(mResources.getDimensionPixelSize(sizeId));
|
||||
}
|
||||
|
||||
public T sizeProvider(SizeProvider provider) {
|
||||
mSizeProvider = provider;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T visibilityProvider(VisibilityProvider provider) {
|
||||
mVisibilityProvider = provider;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T showLastDivider() {
|
||||
mShowLastDivider = true;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T positionInsideItem(boolean positionInsideItem) {
|
||||
mPositionInsideItem = positionInsideItem;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
protected void checkBuilderParams() {
|
||||
if (mPaintProvider != null) {
|
||||
if (mColorProvider != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Use setColor method of Paint class to specify line color. Do not provider ColorProvider if you set PaintProvider.");
|
||||
}
|
||||
if (mSizeProvider != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Use setStrokeWidth method of Paint class to specify line size. Do not provider SizeProvider if you set PaintProvider.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,171 @@
|
||||
package com.gh.common.view.divider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.DimenRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
public class HorizontalDividerItemDecoration extends FlexibleDividerDecoration {
|
||||
|
||||
private MarginProvider mMarginProvider;
|
||||
|
||||
protected HorizontalDividerItemDecoration(Builder builder) {
|
||||
super(builder);
|
||||
mMarginProvider = builder.mMarginProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rect getDividerBound(int position, RecyclerView parent, View child) {
|
||||
Rect bounds = new Rect(0, 0, 0, 0);
|
||||
int transitionX = (int) ViewCompat.getTranslationX(child);
|
||||
int transitionY = (int) ViewCompat.getTranslationY(child);
|
||||
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||
bounds.left = parent.getPaddingLeft() +
|
||||
mMarginProvider.dividerLeftMargin(position, parent) + transitionX;
|
||||
bounds.right = parent.getWidth() - parent.getPaddingRight() -
|
||||
mMarginProvider.dividerRightMargin(position, parent) + transitionX;
|
||||
|
||||
int dividerSize = getDividerSize(position, parent);
|
||||
boolean isReverseLayout = isReverseLayout(parent);
|
||||
if (mDividerType == DividerType.DRAWABLE) {
|
||||
// set top and bottom position of divider
|
||||
if (isReverseLayout) {
|
||||
bounds.bottom = child.getTop() - params.topMargin + transitionY;
|
||||
bounds.top = bounds.bottom - dividerSize;
|
||||
} else {
|
||||
bounds.top = child.getBottom() + params.bottomMargin + transitionY;
|
||||
bounds.bottom = bounds.top + dividerSize;
|
||||
}
|
||||
} else {
|
||||
// set center point of divider
|
||||
int halfSize = dividerSize / 2;
|
||||
if (isReverseLayout) {
|
||||
bounds.top = child.getTop() - params.topMargin - halfSize + transitionY;
|
||||
} else {
|
||||
bounds.top = child.getBottom() + params.bottomMargin + halfSize + transitionY;
|
||||
}
|
||||
bounds.bottom = bounds.top;
|
||||
}
|
||||
|
||||
if (mPositionInsideItem) {
|
||||
if (isReverseLayout) {
|
||||
bounds.top += dividerSize;
|
||||
bounds.bottom += dividerSize;
|
||||
} else {
|
||||
bounds.top -= dividerSize;
|
||||
bounds.bottom -= dividerSize;
|
||||
}
|
||||
}
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setItemOffsets(Rect outRect, int position, RecyclerView parent) {
|
||||
if (mPositionInsideItem) {
|
||||
outRect.set(0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isReverseLayout(parent)) {
|
||||
outRect.set(0, getDividerSize(position, parent), 0, 0);
|
||||
} else {
|
||||
outRect.set(0, 0, 0, getDividerSize(position, parent));
|
||||
}
|
||||
}
|
||||
|
||||
private int getDividerSize(int position, RecyclerView parent) {
|
||||
if (mPaintProvider != null) {
|
||||
return (int) mPaintProvider.dividerPaint(position, parent).getStrokeWidth();
|
||||
} else if (mSizeProvider != null) {
|
||||
return mSizeProvider.dividerSize(position, parent);
|
||||
} else if (mDrawableProvider != null) {
|
||||
Drawable drawable = mDrawableProvider.drawableProvider(position, parent);
|
||||
return drawable.getIntrinsicHeight();
|
||||
}
|
||||
throw new RuntimeException("failed to get size");
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for controlling divider margin
|
||||
*/
|
||||
public interface MarginProvider {
|
||||
|
||||
/**
|
||||
* Returns left margin of divider.
|
||||
*
|
||||
* @param position Divider position (or group index for GridLayoutManager)
|
||||
* @param parent RecyclerView
|
||||
* @return left margin
|
||||
*/
|
||||
int dividerLeftMargin(int position, RecyclerView parent);
|
||||
|
||||
/**
|
||||
* Returns right margin of divider.
|
||||
*
|
||||
* @param position Divider position (or group index for GridLayoutManager)
|
||||
* @param parent RecyclerView
|
||||
* @return right margin
|
||||
*/
|
||||
int dividerRightMargin(int position, RecyclerView parent);
|
||||
}
|
||||
|
||||
public static class Builder extends FlexibleDividerDecoration.Builder<Builder> {
|
||||
|
||||
private MarginProvider mMarginProvider = new MarginProvider() {
|
||||
@Override
|
||||
public int dividerLeftMargin(int position, RecyclerView parent) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dividerRightMargin(int position, RecyclerView parent) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
public Builder(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public Builder margin(final int leftMargin, final int rightMargin) {
|
||||
return marginProvider(new MarginProvider() {
|
||||
@Override
|
||||
public int dividerLeftMargin(int position, RecyclerView parent) {
|
||||
return leftMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dividerRightMargin(int position, RecyclerView parent) {
|
||||
return rightMargin;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Builder margin(int horizontalMargin) {
|
||||
return margin(horizontalMargin, horizontalMargin);
|
||||
}
|
||||
|
||||
public Builder marginResId(@DimenRes int leftMarginId, @DimenRes int rightMarginId) {
|
||||
return margin(mResources.getDimensionPixelSize(leftMarginId),
|
||||
mResources.getDimensionPixelSize(rightMarginId));
|
||||
}
|
||||
|
||||
public Builder marginResId(@DimenRes int horizontalMarginId) {
|
||||
return marginResId(horizontalMarginId, horizontalMarginId);
|
||||
}
|
||||
|
||||
public Builder marginProvider(MarginProvider provider) {
|
||||
mMarginProvider = provider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HorizontalDividerItemDecoration build() {
|
||||
checkBuilderParams();
|
||||
return new HorizontalDividerItemDecoration(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,172 @@
|
||||
package com.gh.common.view.divider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.DimenRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
|
||||
public class VerticalDividerItemDecoration extends FlexibleDividerDecoration {
|
||||
|
||||
private MarginProvider mMarginProvider;
|
||||
|
||||
protected VerticalDividerItemDecoration(Builder builder) {
|
||||
super(builder);
|
||||
mMarginProvider = builder.mMarginProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rect getDividerBound(int position, RecyclerView parent, View child) {
|
||||
Rect bounds = new Rect(0, 0, 0, 0);
|
||||
int transitionX = (int) ViewCompat.getTranslationX(child);
|
||||
int transitionY = (int) ViewCompat.getTranslationY(child);
|
||||
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||
bounds.top = parent.getPaddingTop() +
|
||||
mMarginProvider.dividerTopMargin(position, parent) + transitionY;
|
||||
bounds.bottom = parent.getHeight() - parent.getPaddingBottom() -
|
||||
mMarginProvider.dividerBottomMargin(position, parent) + transitionY;
|
||||
|
||||
int dividerSize = getDividerSize(position, parent);
|
||||
boolean isReverseLayout = isReverseLayout(parent);
|
||||
if (mDividerType == DividerType.DRAWABLE) {
|
||||
// set left and right position of divider
|
||||
if (isReverseLayout) {
|
||||
bounds.right = child.getLeft() - params.leftMargin + transitionX;
|
||||
bounds.left = bounds.right - dividerSize;
|
||||
} else {
|
||||
bounds.left = child.getRight() + params.rightMargin + transitionX;
|
||||
bounds.right = bounds.left + dividerSize;
|
||||
}
|
||||
} else {
|
||||
// set center point of divider
|
||||
int halfSize = dividerSize / 2;
|
||||
if (isReverseLayout) {
|
||||
bounds.left = child.getLeft() - params.leftMargin - halfSize + transitionX;
|
||||
} else {
|
||||
bounds.left = child.getRight() + params.rightMargin + halfSize + transitionX;
|
||||
}
|
||||
bounds.right = bounds.left;
|
||||
}
|
||||
|
||||
if (mPositionInsideItem) {
|
||||
if (isReverseLayout) {
|
||||
bounds.left += dividerSize;
|
||||
bounds.right += dividerSize;
|
||||
} else {
|
||||
bounds.left -= dividerSize;
|
||||
bounds.right -= dividerSize;
|
||||
}
|
||||
}
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setItemOffsets(Rect outRect, int position, RecyclerView parent) {
|
||||
if (mPositionInsideItem) {
|
||||
outRect.set(0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isReverseLayout(parent)) {
|
||||
outRect.set(getDividerSize(position, parent), 0, 0, 0);
|
||||
} else {
|
||||
outRect.set(0, 0, getDividerSize(position, parent), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private int getDividerSize(int position, RecyclerView parent) {
|
||||
if (mPaintProvider != null) {
|
||||
return (int) mPaintProvider.dividerPaint(position, parent).getStrokeWidth();
|
||||
} else if (mSizeProvider != null) {
|
||||
return mSizeProvider.dividerSize(position, parent);
|
||||
} else if (mDrawableProvider != null) {
|
||||
Drawable drawable = mDrawableProvider.drawableProvider(position, parent);
|
||||
return drawable.getIntrinsicWidth();
|
||||
}
|
||||
throw new RuntimeException("failed to get size");
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for controlling divider margin
|
||||
*/
|
||||
public interface MarginProvider {
|
||||
|
||||
/**
|
||||
* Returns top margin of divider.
|
||||
*
|
||||
* @param position Divider position (or group index for GridLayoutManager)
|
||||
* @param parent RecyclerView
|
||||
* @return top margin
|
||||
*/
|
||||
int dividerTopMargin(int position, RecyclerView parent);
|
||||
|
||||
/**
|
||||
* Returns bottom margin of divider.
|
||||
*
|
||||
* @param position Divider position (or group index for GridLayoutManager)
|
||||
* @param parent RecyclerView
|
||||
* @return bottom margin
|
||||
*/
|
||||
int dividerBottomMargin(int position, RecyclerView parent);
|
||||
}
|
||||
|
||||
public static class Builder extends FlexibleDividerDecoration.Builder<Builder> {
|
||||
|
||||
private MarginProvider mMarginProvider = new MarginProvider() {
|
||||
@Override
|
||||
public int dividerTopMargin(int position, RecyclerView parent) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dividerBottomMargin(int position, RecyclerView parent) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
public Builder(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public Builder margin(final int topMargin, final int bottomMargin) {
|
||||
return marginProvider(new MarginProvider() {
|
||||
@Override
|
||||
public int dividerTopMargin(int position, RecyclerView parent) {
|
||||
return topMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dividerBottomMargin(int position, RecyclerView parent) {
|
||||
return bottomMargin;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Builder margin(int verticalMargin) {
|
||||
return margin(verticalMargin, verticalMargin);
|
||||
}
|
||||
|
||||
public Builder marginResId(@DimenRes int topMarginId, @DimenRes int bottomMarginId) {
|
||||
return margin(mResources.getDimensionPixelSize(topMarginId),
|
||||
mResources.getDimensionPixelSize(bottomMarginId));
|
||||
}
|
||||
|
||||
public Builder marginResId(@DimenRes int verticalMarginId) {
|
||||
return marginResId(verticalMarginId, verticalMarginId);
|
||||
}
|
||||
|
||||
public Builder marginProvider(MarginProvider provider) {
|
||||
mMarginProvider = provider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VerticalDividerItemDecoration build() {
|
||||
checkBuilderParams();
|
||||
return new VerticalDividerItemDecoration(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -23,15 +23,15 @@ public class MaterialRatingDrawable extends LayerDrawable {
|
||||
public MaterialRatingDrawable(Context context, boolean fillBackgroundStars) {
|
||||
super(new Drawable[]{
|
||||
createLayerDrawableWithTintAttrRes(fillBackgroundStars ?
|
||||
R.drawable.ic_star
|
||||
: R.drawable.ic_star_border, fillBackgroundStars ?
|
||||
R.drawable.ic_icon_star_ratting
|
||||
: R.drawable.ic_icon_star_ratting_gray, fillBackgroundStars ?
|
||||
R.attr.colorControlHighlight : R.attr.colorControlNormal, context),
|
||||
fillBackgroundStars ? createClippedLayerDrawableWithTintColor(
|
||||
R.drawable.ic_star, Color.TRANSPARENT, context)
|
||||
R.drawable.ic_icon_star_ratting, Color.TRANSPARENT, context)
|
||||
: createClippedLayerDrawableWithTintAttrRes(
|
||||
R.drawable.ic_star_border, R.attr.colorControlActivated,
|
||||
R.drawable.ic_icon_star_ratting_gray, R.attr.colorControlActivated,
|
||||
context),
|
||||
createClippedLayerDrawableWithTintAttrRes(R.drawable.ic_star,
|
||||
createClippedLayerDrawableWithTintAttrRes(R.drawable.ic_icon_star_ratting,
|
||||
R.attr.colorControlActivated, context)
|
||||
});
|
||||
|
||||
|
||||
@ -2,14 +2,15 @@ package com.gh.download;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.collection.ArrayMap;
|
||||
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.util.AppDebugConfig;
|
||||
@ -55,11 +56,6 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.collection.ArrayMap;
|
||||
|
||||
import static android.os.Build.MANUFACTURER;
|
||||
|
||||
public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
private static DownloadManager mInstance;
|
||||
@ -229,7 +225,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
@Nullable ExposureEvent traceEvent) {
|
||||
|
||||
// 安装指引
|
||||
if ("Huawei".equalsIgnoreCase(MANUFACTURER) || "Oppo".equalsIgnoreCase(MANUFACTURER)) {
|
||||
/*if ("Huawei".equalsIgnoreCase(MANUFACTURER) || "Oppo".equalsIgnoreCase(MANUFACTURER)) {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final SharedPreferences.Editor edit = sp.edit();
|
||||
if (sp.getBoolean("InstallHint" + PackageUtils.getVersionName(), true)) {
|
||||
@ -241,7 +237,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
edit.putBoolean("InstallHint" + PackageUtils.getVersionName(), false).apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// 插件版本下载互斥弹窗
|
||||
List<String> mutexPackage = gameEntity.getMutexPackage();
|
||||
@ -275,12 +271,15 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
}
|
||||
}
|
||||
downloadEntity.setInstalled(installed);
|
||||
if ("更新".equals(method)) {
|
||||
downloadEntity.setUpdate(true);
|
||||
} else if ("插件化".equals(method)) {
|
||||
|
||||
// todo 不是应该实时判断吗?
|
||||
if (PackageUtils.isCanPluggable(apkEntity)) {
|
||||
downloadEntity.setPluggable(true);
|
||||
} else if (PackageUtils.isCanUpdate(apkEntity, gameEntity.getId())) {
|
||||
downloadEntity.setUpdate(true);
|
||||
}
|
||||
downloadEntity.setPlugin(gameEntity.getTag() != null && gameEntity.getTag().size() != 0);
|
||||
|
||||
downloadEntity.setPlugin(!TextUtils.isEmpty(apkEntity.getGhVersion()));
|
||||
|
||||
if (isSubscribe) {
|
||||
DownloadManager.getInstance(context).subscribe(downloadEntity);
|
||||
@ -634,6 +633,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
// 开启下载服务, Fuck me, 即便是在启动页调用的方法,依然有可能触发 `unable is in background`
|
||||
startDownloadService();
|
||||
checkRetryDownload();
|
||||
}
|
||||
|
||||
public void addObserver(DataWatcher dataWatcher) {
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.download.cache
|
||||
|
||||
import android.net.Uri
|
||||
import com.gh.common.runOnIoThread
|
||||
import com.gh.common.util.DeviceUtils
|
||||
import com.gh.common.util.NetworkUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.google.android.exoplayer2.upstream.DataSpec
|
||||
@ -20,11 +21,18 @@ import tv.danmaku.ijk.media.exo2.source.GSYExoHttpDataSourceFactory
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
|
||||
object ExoCacheManager {
|
||||
|
||||
private val threads = ConcurrentHashMap<String, AtomicBoolean>()
|
||||
private const val preLength = 50 * 1024 * 1024L //预加载视频大小
|
||||
|
||||
private val preLength by lazy {
|
||||
val totalRamSizeOfDevice = DeviceUtils.getTotalRamSizeOfDevice(HaloApp.getInstance().application)
|
||||
if (totalRamSizeOfDevice <= 2 * 1024) {
|
||||
10 * 1024 * 1024L
|
||||
} else {
|
||||
50 * 1024 * 1024L
|
||||
}
|
||||
}
|
||||
|
||||
fun preload(videoUri: String) {
|
||||
if (NetworkUtils.isWifiConnected(HaloApp.getInstance().application)) {
|
||||
@ -48,7 +56,7 @@ object ExoCacheManager {
|
||||
Utils.log("$requestLength--$bytesCached--$newBytesCached")
|
||||
}
|
||||
}, threads[videoUri])
|
||||
} catch (e: Exception) {
|
||||
} catch (e: Throwable) {
|
||||
threads.remove(videoUri)
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
423
app/src/main/java/com/gh/download/dialog/DownloadDialog.kt
Normal file
423
app/src/main/java/com/gh/download/dialog/DownloadDialog.kt
Normal file
@ -0,0 +1,423 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.recyclerview.widget.*
|
||||
import androidx.recyclerview.widget.RecyclerView.SmoothScroller
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.TimeElapsedHelper
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DialogDownloadBinding
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import com.lightgame.utils.AppManager
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import java.util.*
|
||||
|
||||
|
||||
class DownloadDialog : BaseDialogFragment(), View.OnTouchListener {
|
||||
|
||||
private lateinit var mGameEntity: GameEntity
|
||||
private lateinit var mViewModel: DownloadViewModel
|
||||
private lateinit var mBinding: DialogDownloadBinding
|
||||
|
||||
private lateinit var mElapsedHelper: TimeElapsedHelper
|
||||
|
||||
private lateinit var mGestureDetector: GestureDetector
|
||||
|
||||
private var mAdapter: DownloadDialogAdapter? = null
|
||||
|
||||
// 合集页面保持和后台一样的顺序
|
||||
private var mCollectionAdapter: DownloadDialogAdapter? = null
|
||||
|
||||
/**
|
||||
* 例子:在首页跳转至专题详情点击下载
|
||||
* mEntrance-> (首页)+(专题详情)
|
||||
* mLocation-> 专题名称:游戏名称
|
||||
*
|
||||
* 注意:location 只用于下载统计,具体的 entrance = entrance + path
|
||||
*/
|
||||
private var mEntrance: String = "" // 入口位置
|
||||
private var mLocation: String = "" // 最终位置
|
||||
|
||||
private var mInitPositionY = 0f
|
||||
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
if (downloadEntity.gameId == mGameEntity?.id &&
|
||||
DownloadStatus.delete != DownloadManager.getInstance(requireContext()).getStatus(downloadEntity.url)) {
|
||||
mAdapter?.listData?.forEachIndexed { index, entity ->
|
||||
if (entity.normal?.packageName == downloadEntity.packageName
|
||||
|| entity.installed?.packageName == downloadEntity.packageName) {
|
||||
mAdapter?.notifyItemChanged(index)
|
||||
}
|
||||
}
|
||||
|
||||
mCollectionAdapter?.listData?.forEachIndexed { index, entity ->
|
||||
if (entity.normal?.packageName == downloadEntity.packageName
|
||||
|| entity.installed?.packageName == downloadEntity.packageName) {
|
||||
mCollectionAdapter?.notifyItemChanged(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val createDialog = super.onCreateDialog(savedInstanceState)
|
||||
createDialog.setCanceledOnTouchOutside(true)
|
||||
|
||||
val window = createDialog.window
|
||||
window?.setGravity(Gravity.BOTTOM)
|
||||
window?.setWindowAnimations(R.style.community_publication_animation)
|
||||
return createDialog
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
EventBus.getDefault().register(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mGameEntity = requireArguments().getParcelable(GameEntity::class.java.simpleName)!!
|
||||
mEntrance = requireArguments().getString(EntranceUtils.KEY_ENTRANCE) ?: ""
|
||||
mLocation = requireArguments().getString(EntranceUtils.KEY_LOCATION) ?: ""
|
||||
|
||||
val factory = DownloadViewModel.Factory(HaloApp.getInstance().application, mGameEntity)
|
||||
mViewModel = ViewModelProviders.of(this, factory).get(DownloadViewModel::class.java)
|
||||
mViewModel.listLiveData.observeNonNull(this, callback = { itemList ->
|
||||
mAdapter = DownloadDialogAdapter(requireContext(), mViewModel, itemList, false, mEntrance, mLocation)
|
||||
mBinding.contentList.layoutManager = createLayoutManager(itemList)
|
||||
mBinding.contentList.adapter = mAdapter
|
||||
})
|
||||
|
||||
mViewModel.collectionLiveData.observe(this, Observer { collection ->
|
||||
if (collection != null) {
|
||||
postBrowseMta()
|
||||
|
||||
mBinding.title.text = collection.name
|
||||
val saveApkList = collection.saveApkEntity
|
||||
throwExceptionInDebug("collection content must not be empty", saveApkList.isNullOrEmpty())
|
||||
|
||||
val itemList: MutableList<DownloadDialogItemData> = ArrayList()
|
||||
saveApkList?.forEach { apk ->
|
||||
itemList.add(DownloadDialogItemData(normal = apk))
|
||||
}
|
||||
if (collection.downloadInstruction.isNotEmpty()) {
|
||||
itemList.add(DownloadDialogItemData(instruction = collection.downloadInstruction))
|
||||
}
|
||||
|
||||
mCollectionAdapter = DownloadDialogAdapter(requireContext(), mViewModel, itemList, true, mEntrance, mLocation)
|
||||
mBinding.collectionList.layoutManager = createLayoutManager(itemList)
|
||||
mBinding.collectionList.adapter = mCollectionAdapter
|
||||
|
||||
if (mAdapter != null) collectionEnterAnimation()
|
||||
} else {
|
||||
mBinding.title.text = ("选择下载" + mGameEntity?.pluginDesc + "版本")
|
||||
|
||||
mCollectionAdapter = null
|
||||
collectionExitAnimation()
|
||||
}
|
||||
})
|
||||
mViewModel.dismissLiveData.observe(this, Observer {
|
||||
dismiss()
|
||||
})
|
||||
|
||||
mElapsedHelper = TimeElapsedHelper()
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
mBinding = DataBindingUtil.inflate(inflater, R.layout.dialog_download, container, false)
|
||||
mBinding.title.text = ("选择下载" + mGameEntity.pluginDesc + "版本")
|
||||
|
||||
val downloadNotice = mGameEntity.downloadAd
|
||||
if (downloadNotice != null) {
|
||||
mBinding.downloadNotice.visibility = View.VISIBLE
|
||||
mBinding.downloadNotice.text = downloadNotice.title
|
||||
mBinding.downloadNotice.setOnClickListener {
|
||||
if ("imprint" == downloadNotice.type) {
|
||||
DialogUtils.showImprintDialog(requireContext(), mGameEntity, downloadNotice.title)
|
||||
} else {
|
||||
DirectUtils.directToLinkPage(
|
||||
requireContext(),
|
||||
downloadNotice,
|
||||
mEntrance, "下载多平台弹窗")
|
||||
}
|
||||
MtaHelper.onEvent(MTA_KEY, "点击", mViewModel.gameEntity.name + "_" + downloadNotice.title)
|
||||
}
|
||||
}
|
||||
|
||||
mBinding.back.setOnClickListener {
|
||||
if (mCollectionAdapter != null && mAdapter != null) {
|
||||
postBrowseMta()
|
||||
mViewModel.collectionLiveData.postValue(null)
|
||||
} else {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
mGestureDetector = GestureDetector(requireContext(), SingleTapConfirm())
|
||||
mBinding.dragClose.setOnTouchListener(this)
|
||||
mBinding.back.setOnTouchListener(this)
|
||||
mBinding.downloadNotice.setOnTouchListener(this)
|
||||
|
||||
(mBinding.contentList.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
(mBinding.collectionList.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
mBinding.contentList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
val layoutManager = mBinding.contentList.layoutManager
|
||||
if (layoutManager is LinearLayoutManager) {
|
||||
val position = layoutManager.findLastVisibleItemPosition()
|
||||
mBinding.otherVersionButtonContainer.goneIf(position > mViewModel.otherSectionPosition - 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
val smoothScroller: SmoothScroller = object : LinearSmoothScroller(requireContext()) {
|
||||
override fun getVerticalSnapPreference(): Int {
|
||||
return SNAP_TO_START
|
||||
}
|
||||
}
|
||||
mBinding.otherVersionButtonContainer.setOnClickListener {
|
||||
smoothScroller.targetPosition = mViewModel.otherSectionPosition
|
||||
mBinding.contentList.layoutManager?.startSmoothScroll(smoothScroller)
|
||||
}
|
||||
return mBinding.root
|
||||
}
|
||||
|
||||
private fun collectionEnterAnimation() {
|
||||
val backAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_collection_back_enter)
|
||||
backAnimation.fillAfter = true
|
||||
mBinding.back.startAnimation(backAnimation)
|
||||
|
||||
val contentAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_content_enter)
|
||||
contentAnimation.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationRepeat(animation: Animation?) {
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animation?) {
|
||||
mBinding.contentListContainer.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onAnimationStart(animation: Animation?) {
|
||||
}
|
||||
})
|
||||
mBinding.contentListContainer.startAnimation(contentAnimation)
|
||||
|
||||
val collectionAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_collection_content_enter)
|
||||
mBinding.collectionList.startAnimation(collectionAnimation)
|
||||
mBinding.collectionList.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun collectionExitAnimation() {
|
||||
val backAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_collection_back_exit)
|
||||
backAnimation.fillAfter = true
|
||||
mBinding.back.startAnimation(backAnimation)
|
||||
|
||||
val contentAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_content_exit)
|
||||
mBinding.contentListContainer.startAnimation(contentAnimation)
|
||||
mBinding.contentListContainer.visibility = View.VISIBLE
|
||||
|
||||
val collectionAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_collection_content_exit)
|
||||
collectionAnimation.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationRepeat(animation: Animation?) {
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animation?) {
|
||||
mBinding.collectionList.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onAnimationStart(animation: Animation?) {
|
||||
}
|
||||
})
|
||||
mBinding.collectionList.startAnimation(collectionAnimation)
|
||||
}
|
||||
|
||||
private fun createLayoutManager(listData: List<DownloadDialogItemData>): RecyclerView.LayoutManager {
|
||||
val layoutManager = GridLayoutManager(requireContext(), 2)
|
||||
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return if (listData[position].normal == null) 2 else 1
|
||||
}
|
||||
}
|
||||
return layoutManager
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
mCollectionAdapter?.notifyDataSetChanged()
|
||||
super.onResume()
|
||||
DownloadManager.getInstance(requireContext()).addObserver(mDataWatcher)
|
||||
mElapsedHelper.resetCounting()
|
||||
mElapsedHelper.resumeCounting()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
DownloadManager.getInstance(requireContext()).removeObserver(mDataWatcher)
|
||||
mElapsedHelper.pauseCounting()
|
||||
postBrowseMta()
|
||||
}
|
||||
|
||||
private fun postBrowseMta() {
|
||||
if (mCollectionAdapter == null) {
|
||||
MtaHelper.onEventWithTime(MTA_KEY, mElapsedHelper.elapsedTime, "浏览", mGameEntity?.name)
|
||||
} else {
|
||||
val collectionData = mViewModel.collectionLiveData.value
|
||||
MtaHelper.onEventWithTime(MTA_KEY, mElapsedHelper.elapsedTime, "浏览", mGameEntity?.name + "_" + collectionData?.name)
|
||||
throwExceptionInDebug("collectionData must be not null", collectionData == null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = HaloApp.getInstance().application.resources.displayMetrics.widthPixels
|
||||
val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
dialog?.window?.setLayout(width, height)
|
||||
}
|
||||
|
||||
override fun onBack(): Boolean {
|
||||
if (mCollectionAdapter != null && mAdapter != null) {
|
||||
postBrowseMta()
|
||||
mViewModel.collectionLiveData.postValue(null)
|
||||
return true
|
||||
}
|
||||
return super.onBack()
|
||||
}
|
||||
|
||||
// dialog drag animation
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
||||
if (mGestureDetector.onTouchEvent(event) && mBinding.root.y == 0F) {
|
||||
v.performClick()
|
||||
return true
|
||||
}
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
mInitPositionY = mBinding.root.y - event.rawY
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
val offsetY = event.rawY + mInitPositionY
|
||||
val dialogY = mBinding.root.y
|
||||
if (dialogY + offsetY > 0) {
|
||||
mBinding.root.animate()
|
||||
.y(offsetY)
|
||||
.setDuration(0)
|
||||
.start()
|
||||
} else {
|
||||
resetDialogPosition()
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_CANCEL,
|
||||
MotionEvent.ACTION_UP,
|
||||
MotionEvent.ACTION_OUTSIDE -> {
|
||||
if (mBinding.root.y >= mBinding.root.height / 2) {
|
||||
dismiss()
|
||||
} else {
|
||||
resetDialogPosition(300)
|
||||
}
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun resetDialogPosition(duration: Long = 0) {
|
||||
mBinding.root.animate()
|
||||
.y(0F)
|
||||
.setDuration(duration)
|
||||
.start()
|
||||
}
|
||||
|
||||
private class SingleTapConfirm : GestureDetector.SimpleOnGestureListener() {
|
||||
override fun onSingleTapUp(event: MotionEvent): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
//安装、卸载事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busFour: EBPackage) {
|
||||
if (::mViewModel.isInitialized && mViewModel.gameEntity.pluggableCollection == null) {
|
||||
val listData = mViewModel.listLiveData.value ?: return
|
||||
listData.forEach { itemData ->
|
||||
if (itemData.installed != null) {
|
||||
if (itemData.installed?.packageName == busFour.packageName) {
|
||||
mViewModel.initListData()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (itemData.normal != null) {
|
||||
if (itemData.normal?.packageName == busFour.packageName) {
|
||||
mViewModel.initListData()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(context: Context?, gameEntity: GameEntity, entrance: String?, location: String?) {
|
||||
val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
|
||||
context
|
||||
} else if (BuildConfig.DEBUG) {
|
||||
throw IllegalStateException("DownloadDialog context must be FragmentActivity")
|
||||
} else {
|
||||
val currentActivity = AppManager.getInstance().currentActivity()
|
||||
if (currentActivity is FragmentActivity) {
|
||||
currentActivity
|
||||
} else {
|
||||
throw IllegalStateException("current activity context must be FragmentActivity")
|
||||
}
|
||||
}
|
||||
|
||||
// 防止重复弹出
|
||||
if (hasDownloadDialogInCurrentActivity(fragmentActivity)) return
|
||||
|
||||
val downloadDialog = DownloadDialog().apply {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance)
|
||||
bundle.putString(EntranceUtils.KEY_LOCATION, location)
|
||||
bundle.putParcelable(GameEntity::class.java.simpleName, gameEntity)
|
||||
arguments = bundle
|
||||
}
|
||||
downloadDialog.show(fragmentActivity.supportFragmentManager, DownloadDialog::class.java.name)
|
||||
}
|
||||
|
||||
private fun hasDownloadDialogInCurrentActivity(fragmentActivity: FragmentActivity): Boolean {
|
||||
val fragments: List<Fragment> = fragmentActivity.supportFragmentManager.fragments
|
||||
fragments.forEach { fragment ->
|
||||
if (fragment is DownloadDialog) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const val MTA_KEY = "多版本下载"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,130 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.base.OnViewClickListener
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.util.throwExceptionInDebug
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
import com.gh.gamecenter.QaActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.*
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
class DownloadDialogAdapter(context: Context,
|
||||
val viewModel: DownloadViewModel,
|
||||
val listData: List<DownloadDialogItemData>,
|
||||
val isCollectionPage: Boolean,
|
||||
private val mEntrance: String,
|
||||
private val mLocation: String) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
|
||||
private val mPath = if (isCollectionPage) {
|
||||
"下载弹窗-二级页"
|
||||
} else {
|
||||
"下载弹窗"
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val itemData = listData[position]
|
||||
if (itemData.links != null) return ITEM_LINK
|
||||
if (itemData.section != null) return ITEM_SECTION
|
||||
if (itemData.installed != null) return ITEM_INSTALLED
|
||||
if (itemData.instruction != null) return ITEM_INSTRUCTION
|
||||
if (itemData.platformRequest != null) return ITEM_PLATFORM_REQUEST
|
||||
return ITEM_NORMAL
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val view: View
|
||||
return when (viewType) {
|
||||
ITEM_LINK -> {
|
||||
view = mLayoutInflater.inflate(R.layout.download_dialog_link_item, parent, false)
|
||||
DownloadDialogLinkItemViewHolder(DownloadDialogLinkItemBinding.bind(view))
|
||||
}
|
||||
ITEM_SECTION -> {
|
||||
view = mLayoutInflater.inflate(R.layout.download_dialog_section_item, parent, false)
|
||||
DownloadDialogSectionItemViewHolder(DownloadDialogSectionItemBinding.bind(view))
|
||||
}
|
||||
ITEM_INSTALLED -> {
|
||||
view = mLayoutInflater.inflate(R.layout.download_dialog_installed_item, parent, false)
|
||||
DownloadDialogInstalledItemViewHolder(DownloadDialogInstalledItemBinding.bind(view))
|
||||
}
|
||||
ITEM_INSTRUCTION -> {
|
||||
view = mLayoutInflater.inflate(R.layout.download_dialog_instruction_item, parent, false)
|
||||
DownloadDialogInstructionItemViewHolder(DownloadDialogInstructionItemBinding.bind(view))
|
||||
}
|
||||
ITEM_PLATFORM_REQUEST -> {
|
||||
view = mLayoutInflater.inflate(R.layout.download_dialog_platform_request_item, parent, false)
|
||||
DownloadDialogPlatformRequestItemViewHolder(DownloadDialogPlatformRequestItemBinding.bind(view))
|
||||
}
|
||||
else -> {
|
||||
view = mLayoutInflater.inflate(R.layout.download_dialog_item, parent, false)
|
||||
DownloadDialogItemViewHolder(DownloadDialogItemBinding.bind(view))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is DownloadDialogSectionItemViewHolder -> {
|
||||
holder.binding.type = listData[position].section
|
||||
}
|
||||
is DownloadDialogLinkItemViewHolder -> {
|
||||
holder.binding.links = listData[position].links
|
||||
holder.binding.clickListener = OnViewClickListener<GameEntity.PluginLink> { _, data ->
|
||||
when (data.linkType) {
|
||||
"dialog" -> {
|
||||
DownloadLinkDialog.showDownloadDialog(mContext, data)
|
||||
}
|
||||
"article" -> {
|
||||
mContext.startActivity(NewsDetailActivity.getIntentById(mContext, data.linkId, mEntrance))
|
||||
}
|
||||
"qa" -> {
|
||||
mContext.startActivity(QaActivity.getIntent(mContext, data.linkText, qaId = data.linkId))
|
||||
}
|
||||
"qa_collection" -> {
|
||||
mContext.startActivity(QaActivity.getIntent(mContext, data.linkText, qaCollectionId = data.linkId))
|
||||
}
|
||||
else -> {
|
||||
Utils.toast(mContext, "暂不支持类型:" + data.linkType)
|
||||
}
|
||||
}
|
||||
|
||||
MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", viewModel.gameEntity.name + "_" + data.title)
|
||||
}
|
||||
}
|
||||
is DownloadDialogInstructionItemViewHolder -> {
|
||||
holder.bindItem(listData[position].instruction!!)
|
||||
}
|
||||
is DownloadDialogPlatformRequestItemViewHolder -> {
|
||||
holder.bindItem(viewModel.gameEntity)
|
||||
}
|
||||
is DownloadDialogInstalledItemViewHolder -> {
|
||||
holder.bindInstalledItem(listData[position].installed!!, viewModel, mEntrance, mPath, mLocation)
|
||||
throwExceptionInDebug("合集页面不应该存在该条数据", isCollectionPage)
|
||||
}
|
||||
is DownloadDialogItemViewHolder -> {
|
||||
holder.bindItem(listData[position].normal!!, viewModel, isCollectionPage, mEntrance, mPath, mLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return listData.size
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ITEM_LINK = 200
|
||||
private const val ITEM_SECTION = 201
|
||||
private const val ITEM_INSTALLED = 202
|
||||
private const val ITEM_NORMAL = 203
|
||||
private const val ITEM_INSTRUCTION = 204
|
||||
private const val ITEM_PLATFORM_REQUEST = 205
|
||||
|
||||
const val ITEM_TAG_KEY = R.id.download_item_type
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,128 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import android.view.View
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.util.goneIf
|
||||
import com.gh.common.util.throwExceptionInDebug
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DownloadDialogInstalledItemBinding
|
||||
import com.gh.gamecenter.entity.ApkEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadStatus
|
||||
|
||||
class DownloadDialogInstalledItemViewHolder(val binding: DownloadDialogInstalledItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindInstalledItem(apkEntity: ApkEntity, viewModel: DownloadViewModel, entrance: String, path: String, location: String) {
|
||||
|
||||
val gameEntity = viewModel.gameEntity
|
||||
val apkCollection = apkEntity.apkCollection
|
||||
binding.pluginDesc = gameEntity.pluginDesc
|
||||
binding.apk = if (apkCollection != null) {
|
||||
ApkEntity(platformIcon = apkCollection.newIcon, platformName = apkCollection.name, remark = apkCollection.remark)
|
||||
} else apkEntity
|
||||
binding.root.setBackgroundResource(R.drawable.download_dialog_item_background)
|
||||
|
||||
if (apkEntity.apkLink != null) {
|
||||
throwExceptionInDebug("apkLink 不应该出现在这里")
|
||||
} else if (apkCollection != null || apkEntity.downloadInstruction.isNotEmpty()) {
|
||||
binding.collection.visibility = View.VISIBLE
|
||||
binding.downloadStatusIcon.visibility = View.GONE
|
||||
binding.progressbar.visibility = View.GONE
|
||||
binding.pluggable.visibility = View.GONE
|
||||
binding.install.visibility = View.GONE
|
||||
binding.update.visibility = View.GONE
|
||||
binding.status.visibility = View.GONE
|
||||
binding.launch.visibility = View.GONE
|
||||
if (apkCollection != null) {
|
||||
binding.remark.goneIf(apkCollection.remark.isEmpty())
|
||||
binding.root.setBackgroundResource(R.drawable.download_dialog_item_collection_background)
|
||||
} else {
|
||||
binding.remark.goneIf(apkEntity.remark.isEmpty())
|
||||
}
|
||||
|
||||
binding.collection.text = if (apkCollection != null) {
|
||||
"查看合集"
|
||||
} else "查看详情"
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.COLLECTION)
|
||||
} else {
|
||||
binding.collection.visibility = View.GONE
|
||||
|
||||
val downloadEntity = DownloadManager.getInstance(HaloApp.getInstance().application).getDownloadEntityByUrl(apkEntity.url)
|
||||
if (downloadEntity != null) {
|
||||
binding.downloadStatusIcon.visibility = View.VISIBLE
|
||||
binding.progressbar.visibility = View.VISIBLE
|
||||
binding.status.visibility = View.VISIBLE
|
||||
binding.remark.visibility = View.GONE
|
||||
binding.launch.visibility = View.GONE
|
||||
binding.pluggable.visibility = View.GONE
|
||||
binding.update.visibility = View.GONE
|
||||
binding.install.goneIf(DownloadStatus.done != downloadEntity.status)
|
||||
|
||||
binding.downloadStatusIcon.setImageResource(R.drawable.download_dialog_status_pause)
|
||||
binding.progressbar.progress = downloadEntity.percent.toInt()
|
||||
binding.status.text = DownloadDialogItemViewHolder.getDownloadingStatusText(downloadEntity)
|
||||
|
||||
if (DownloadStatus.done == downloadEntity.status) {
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.INSTALL)
|
||||
} else {
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.DOWNLOADING)
|
||||
}
|
||||
} else {
|
||||
binding.downloadStatusIcon.visibility = View.GONE
|
||||
binding.progressbar.visibility = View.GONE
|
||||
binding.status.visibility = View.GONE
|
||||
binding.install.visibility = View.GONE
|
||||
binding.remark.goneIf(apkEntity.remark.isEmpty())
|
||||
|
||||
if (PackageUtils.isCanPluggable(apkEntity)) {
|
||||
binding.pluggable.visibility = View.VISIBLE
|
||||
binding.update.visibility = View.GONE
|
||||
binding.launch.visibility = View.GONE
|
||||
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.PLUGGABLE)
|
||||
} else if (PackageUtils.isCanUpdate(apkEntity, gameEntity.id)) {
|
||||
binding.update.visibility = View.VISIBLE
|
||||
binding.pluggable.visibility = View.GONE
|
||||
binding.launch.visibility = View.GONE
|
||||
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.UPDATE)
|
||||
} else if (PackageUtils.getGhId(apkEntity.packageName) == gameEntity.id) {
|
||||
binding.status.visibility = View.VISIBLE
|
||||
binding.pluggable.visibility = View.GONE
|
||||
binding.update.visibility = View.GONE
|
||||
|
||||
var isFilter = false
|
||||
Config.getSettings()?.gameDownloadBlackList?.forEach { pkgName ->
|
||||
if (pkgName == apkEntity.packageName) {
|
||||
isFilter = true
|
||||
}
|
||||
}
|
||||
|
||||
if (isFilter) {
|
||||
// 已安装
|
||||
binding.status.visibility = View.VISIBLE
|
||||
binding.launch.visibility = View.GONE
|
||||
|
||||
binding.status.text = "已安装"
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.INSTALLED)
|
||||
} else {
|
||||
// 点击启动
|
||||
binding.launch.visibility = View.VISIBLE
|
||||
binding.status.visibility = View.GONE
|
||||
|
||||
binding.status.text = "点击启动"
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.LAUNCH)
|
||||
}
|
||||
} else {
|
||||
throwExceptionInDebug("下载弹窗-我的版本出现未知类型")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DownloadDialogItemViewHolder.setDownloadClickListener(itemView, apkEntity, viewModel, entrance, path, location)
|
||||
binding.executePendingBindings()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import android.graphics.Color
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.databinding.DownloadDialogInstructionItemBinding
|
||||
|
||||
class DownloadDialogInstructionItemViewHolder(val binding: DownloadDialogInstructionItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindItem(instruction: String) {
|
||||
binding.webView.loadDataWithBaseURL(
|
||||
null,
|
||||
"<body style='margin:0;padding:0;'>$instruction</body>",
|
||||
"text/html",
|
||||
"utf-8", null)
|
||||
binding.webView.settings
|
||||
binding.webView.setBackgroundColor(Color.TRANSPARENT)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import com.gh.gamecenter.entity.ApkEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
|
||||
data class DownloadDialogItemData(var links: List<GameEntity.PluginLink>? = null,
|
||||
var section: DownloadDialogSectionType? = null,
|
||||
var installed: ApkEntity? = null,
|
||||
var normal: ApkEntity? = null,
|
||||
var instruction: String? = null,
|
||||
var platformRequest: Any? = null)
|
||||
|
||||
enum class DownloadDialogSectionType {
|
||||
INSTALLED,
|
||||
OTHER
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
enum class DownloadDialogItemStatus {
|
||||
DOWNLOAD,
|
||||
LAUNCH,
|
||||
DOWNLOADING,
|
||||
INSTALL,
|
||||
PLUGGABLE,
|
||||
UPDATE,
|
||||
COLLECTION,
|
||||
LINK,
|
||||
INSTALLED,
|
||||
IGNORE
|
||||
}
|
||||
@ -0,0 +1,288 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.dialog.CertificationDialog
|
||||
import com.gh.common.dialog.DeviceRemindDialog
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DirectUtils.directToLinkPage
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.DownloadManagerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DownloadDialogItemBinding
|
||||
import com.gh.gamecenter.entity.ApkEntity
|
||||
import com.gh.gamecenter.entity.GameCollectionEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import com.lightgame.download.FileUtils
|
||||
import com.lightgame.utils.AppManager
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindItem(apkEntity: ApkEntity,
|
||||
viewModel: DownloadViewModel,
|
||||
isCollectionPage: Boolean,
|
||||
entrance: String,
|
||||
path: String,
|
||||
location: String) {
|
||||
|
||||
val gameEntity = viewModel.gameEntity
|
||||
val apkLink = apkEntity.apkLink
|
||||
val apkCollection = apkEntity.apkCollection
|
||||
|
||||
binding.apk = when {
|
||||
apkLink != null -> ApkEntity(
|
||||
platformIcon = apkLink.icon,
|
||||
platformName = apkLink.name,
|
||||
remark = apkLink.remark)
|
||||
apkCollection != null -> ApkEntity(
|
||||
platformIcon = apkCollection.newIcon,
|
||||
platformName = apkCollection.name,
|
||||
remark = apkCollection.remark)
|
||||
else -> apkEntity
|
||||
}
|
||||
binding.root.setBackgroundResource(R.drawable.download_dialog_item_background)
|
||||
|
||||
if (apkLink != null) {
|
||||
binding.downloadStatusIcon.visibility = View.VISIBLE
|
||||
binding.status.visibility = View.VISIBLE
|
||||
binding.progressbar.visibility = View.GONE
|
||||
binding.install.visibility = View.GONE
|
||||
binding.remark.goneIf(apkLink.remark.isEmpty())
|
||||
|
||||
binding.status.text = "点击查看"
|
||||
binding.downloadStatusIcon.setImageResource(R.drawable.download_dialog_collection_status_link)
|
||||
binding.root.setBackgroundResource(R.drawable.download_dialog_installed_background)
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.LINK)
|
||||
} else if (apkCollection != null || (!isCollectionPage && apkEntity.downloadInstruction.isNotEmpty())) {
|
||||
binding.downloadStatusIcon.visibility = View.VISIBLE
|
||||
binding.progressbar.visibility = View.GONE
|
||||
binding.install.visibility = View.GONE
|
||||
binding.status.visibility = View.GONE
|
||||
if (apkCollection != null) {
|
||||
binding.remark.goneIf(apkCollection.remark.isEmpty())
|
||||
binding.root.setBackgroundResource(R.drawable.download_dialog_item_collection_background)
|
||||
} else {
|
||||
binding.remark.goneIf(apkEntity.remark.isEmpty())
|
||||
}
|
||||
|
||||
binding.downloadStatusIcon.setImageResource(R.drawable.download_dialog_status_collection)
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.COLLECTION)
|
||||
} else {
|
||||
|
||||
val downloadEntity = DownloadManager.getInstance(HaloApp.getInstance().application).getDownloadEntityByUrl(apkEntity.url)
|
||||
if (downloadEntity != null) {
|
||||
binding.downloadStatusIcon.visibility = View.VISIBLE
|
||||
binding.progressbar.visibility = View.VISIBLE
|
||||
binding.status.visibility = View.VISIBLE
|
||||
binding.remark.visibility = View.GONE
|
||||
binding.install.goneIf(DownloadStatus.done != downloadEntity.status)
|
||||
|
||||
binding.downloadStatusIcon.setImageResource(R.drawable.download_dialog_status_pause)
|
||||
binding.progressbar.progress = downloadEntity.percent.toInt()
|
||||
binding.status.text = getDownloadingStatusText(downloadEntity)
|
||||
|
||||
if (DownloadStatus.done == downloadEntity.status) {
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.INSTALL)
|
||||
} else {
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.DOWNLOADING)
|
||||
}
|
||||
} else {
|
||||
binding.progressbar.visibility = View.GONE
|
||||
binding.install.visibility = View.GONE
|
||||
binding.remark.goneIf(apkEntity.remark.isEmpty())
|
||||
|
||||
if (PackageUtils.isCanUpdate(apkEntity, gameEntity.id)) {
|
||||
binding.downloadStatusIcon.visibility = View.VISIBLE
|
||||
binding.status.visibility = View.VISIBLE
|
||||
|
||||
binding.status.text = "可更新"
|
||||
binding.downloadStatusIcon.setImageResource(R.drawable.download_dialog_collection_status_update)
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.UPDATE)
|
||||
} else if (PackageUtils.getGhId(apkEntity.packageName) == gameEntity.id) {
|
||||
binding.downloadStatusIcon.visibility = View.GONE
|
||||
binding.status.visibility = View.VISIBLE
|
||||
binding.root.setBackgroundResource(R.drawable.download_dialog_installed_background)
|
||||
|
||||
var isFilter = false
|
||||
Config.getSettings()?.gameDownloadBlackList?.forEach { pkgName ->
|
||||
if (pkgName == apkEntity.packageName) {
|
||||
isFilter = true
|
||||
}
|
||||
}
|
||||
|
||||
if (isFilter) {
|
||||
// 已安装
|
||||
binding.status.text = "已安装"
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.INSTALLED)
|
||||
} else {
|
||||
// 点击启动
|
||||
binding.status.text = "点击启动"
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.LAUNCH)
|
||||
}
|
||||
} else {
|
||||
binding.downloadStatusIcon.visibility = View.VISIBLE
|
||||
binding.status.visibility = View.GONE
|
||||
|
||||
binding.downloadStatusIcon.setImageResource(R.drawable.download_dialog_status_download)
|
||||
if (PackageUtils.isCanPluggable(apkEntity)) {
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.PLUGGABLE)
|
||||
} else {
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.DOWNLOAD)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setDownloadClickListener(itemView, apkEntity, viewModel, entrance, path, location)
|
||||
binding.executePendingBindings()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getDownloadingStatusText(downloadEntity: DownloadEntity): String {
|
||||
return when (downloadEntity.status) {
|
||||
DownloadStatus.waiting -> "等待中"
|
||||
DownloadStatus.done -> "等待安装"
|
||||
DownloadStatus.downloading -> SpeedUtils.getSpeed(downloadEntity.speed)
|
||||
else -> "已暂停"
|
||||
}
|
||||
}
|
||||
|
||||
fun setDownloadClickListener(itemView: View,
|
||||
apkEntity: ApkEntity,
|
||||
viewModel: DownloadViewModel,
|
||||
entrance: String,
|
||||
path: String,
|
||||
location: String) {
|
||||
|
||||
val gameEntity = viewModel.gameEntity
|
||||
itemView.setOnClickListener {
|
||||
var mtaValue = "未知"
|
||||
when (itemView.getTag(DownloadDialogAdapter.ITEM_TAG_KEY)) {
|
||||
DownloadDialogItemStatus.DOWNLOAD -> {
|
||||
createDownloadTask(it.context, apkEntity, gameEntity, "下载", entrance, location)
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_下载"
|
||||
}
|
||||
DownloadDialogItemStatus.LAUNCH -> {
|
||||
PackageUtils.launchApplicationByPackageName(it.context, apkEntity.packageName)
|
||||
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_启动"
|
||||
}
|
||||
DownloadDialogItemStatus.DOWNLOADING -> {
|
||||
// 打开下载管理界面
|
||||
it.context.startActivity(DownloadManagerActivity.getDownloadMangerIntent(
|
||||
it.context,
|
||||
apkEntity.url,
|
||||
BaseActivity.mergeEntranceAndPath(entrance, path)))
|
||||
if (AppManager.getInstance().currentActivity() is DownloadManagerActivity) {
|
||||
viewModel.dismissLiveData.postValue(Any())
|
||||
}
|
||||
|
||||
val downloadEntity = DownloadManager.getInstance(it.context).getDownloadEntityByUrl(apkEntity.url)
|
||||
if (downloadEntity.status == DownloadStatus.pause) {
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_暂停中"
|
||||
} else if (downloadEntity.status == DownloadStatus.waiting) {
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_等待中"
|
||||
} else if (downloadEntity.status == DownloadStatus.subscribe) {
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_排队中"
|
||||
} else {
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_下载中"
|
||||
}
|
||||
|
||||
}
|
||||
DownloadDialogItemStatus.INSTALL -> {
|
||||
val downloadEntity = DownloadManager.getInstance(it.context).getDownloadEntityByUrl(apkEntity.url)
|
||||
if (FileUtils.isEmptyFile(downloadEntity.path)) {
|
||||
Utils.toast(it.context, R.string.install_failure_hint)
|
||||
DownloadManager.getInstance(it.context).cancel(apkEntity.url)
|
||||
} else {
|
||||
if (PackageUtils.isCanPluggable(apkEntity)) {
|
||||
DialogUtils.showPluginDialog(it.context) {
|
||||
it.context.startActivity(PackageUtils.getUninstallIntent(it.context, downloadEntity.path))
|
||||
}
|
||||
} else {
|
||||
PackageUtils.launchSetup(it.context, downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadEntity.isPluggable) {
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_插件化安装"
|
||||
} else {
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_安装"
|
||||
}
|
||||
}
|
||||
DownloadDialogItemStatus.PLUGGABLE -> {
|
||||
createDownloadTask(it.context, apkEntity, gameEntity, "插件化", entrance, location)
|
||||
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_插件化"
|
||||
}
|
||||
DownloadDialogItemStatus.UPDATE -> {
|
||||
createDownloadTask(it.context, apkEntity, gameEntity, "更新", entrance, location)
|
||||
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_更新"
|
||||
}
|
||||
DownloadDialogItemStatus.COLLECTION -> {
|
||||
val apkCollection = apkEntity.apkCollection
|
||||
if (apkCollection != null) {
|
||||
viewModel.collectionLiveData.postValue(apkCollection)
|
||||
|
||||
mtaValue = gameEntity.name + "_" + apkCollection.name + "_查看合集"
|
||||
} else if (apkEntity.downloadInstruction.isNotEmpty()) {
|
||||
val fakeCollection = GameCollectionEntity()
|
||||
fakeCollection.saveApkEntity = arrayListOf(apkEntity)
|
||||
fakeCollection.name = apkEntity.getPlatformName()
|
||||
fakeCollection.downloadInstruction = apkEntity.downloadInstruction
|
||||
viewModel.collectionLiveData.postValue(fakeCollection)
|
||||
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_查看详情"
|
||||
} else {
|
||||
throwExceptionInDebug("合集和下载说明至少一个不为空")
|
||||
}
|
||||
}
|
||||
DownloadDialogItemStatus.LINK -> {
|
||||
directToLinkPage(it.context, apkEntity.apkLink?.getLinkEntity()!!, entrance, path)
|
||||
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.apkLink?.name
|
||||
}
|
||||
DownloadDialogItemStatus.INSTALLED -> {
|
||||
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_已安装"
|
||||
}
|
||||
}
|
||||
throwExceptionInDebug("无法识别当前状态", mtaValue == "未知")
|
||||
MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", mtaValue)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createDownloadTask(context: Context,
|
||||
apkEntity: ApkEntity,
|
||||
gameEntity: GameEntity,
|
||||
downloadMethod: String,
|
||||
entrance: String,
|
||||
location: String) {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apkEntity, object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, DialogUtils.ConfirmListener {
|
||||
DialogUtils.checkDownload(context, apkEntity.size) { isSubscribe ->
|
||||
DownloadManager.createDownload(
|
||||
context,
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
downloadMethod,
|
||||
entrance,
|
||||
location,
|
||||
isSubscribe, null)
|
||||
|
||||
DeviceRemindDialog.showDeviceRemindDialog(context, gameEntity)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.databinding.DownloadDialogLinkItemBinding
|
||||
|
||||
class DownloadDialogLinkItemViewHolder(val binding: DownloadDialogLinkItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.gamecenter.VoteActivity
|
||||
import com.gh.gamecenter.databinding.DownloadDialogPlatformRequestItemBinding
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
|
||||
class DownloadDialogPlatformRequestItemViewHolder(val binding: DownloadDialogPlatformRequestItemBinding)
|
||||
: BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindItem(gameEntity: GameEntity) {
|
||||
binding.content.setOnClickListener {
|
||||
val intent = VoteActivity.getIntent(it.context, gameEntity.name, gameEntity.id)
|
||||
it.context.startActivity(intent)
|
||||
MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", gameEntity.name + "_求版本")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.databinding.DownloadDialogLinkItemBinding
|
||||
import com.gh.gamecenter.databinding.DownloadDialogSectionItemBinding
|
||||
|
||||
class DownloadDialogSectionItemViewHolder(val binding: DownloadDialogSectionItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DialogDownloadLinkBinding
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.AppManager
|
||||
|
||||
|
||||
class DownloadLinkDialog : BaseDialogFragment() {
|
||||
|
||||
private lateinit var mLinkEntity: GameEntity.PluginLink
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val binding: DialogDownloadLinkBinding = DataBindingUtil.inflate(inflater, R.layout.dialog_download_link, container, false)
|
||||
binding.title.text = mLinkEntity.title
|
||||
binding.webView.loadDataWithBaseURL(null,
|
||||
mLinkEntity.content, "text/html", "utf-8", null)
|
||||
|
||||
binding.confirm.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = HaloApp.getInstance().application.resources.displayMetrics.widthPixels
|
||||
val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
dialog?.window?.setLayout(width - 60F.dip2px(), height)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(context: Context?, linkEntity: GameEntity.PluginLink) {
|
||||
val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
|
||||
context
|
||||
} else if (BuildConfig.DEBUG) {
|
||||
throw IllegalStateException("DownloadLinkDialog context must be FragmentActivity")
|
||||
} else {
|
||||
val currentActivity = AppManager.getInstance().currentActivity()
|
||||
if (currentActivity is FragmentActivity) {
|
||||
currentActivity
|
||||
} else {
|
||||
throw IllegalStateException("current activity context must be FragmentActivity")
|
||||
}
|
||||
}
|
||||
|
||||
val dialog = DownloadLinkDialog().apply { mLinkEntity = linkEntity }
|
||||
dialog.show(fragmentActivity.supportFragmentManager, DownloadLinkDialog::class.java.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
246
app/src/main/java/com/gh/download/dialog/DownloadViewModel.kt
Normal file
246
app/src/main/java/com/gh/download/dialog/DownloadViewModel.kt
Normal file
@ -0,0 +1,246 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.entity.ApkEntity
|
||||
import com.gh.gamecenter.entity.GameCollectionEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
/**
|
||||
* 已安装部分排序:安装插件化->安装更新->插件化下载中->更新下载中->插件化->更新->启动
|
||||
*
|
||||
* 其它部分排序:安装→下载中
|
||||
*
|
||||
* 注意:
|
||||
* 1.上述一级页面排序包含合集
|
||||
* 2.二级页面(合集详情),切勿打乱原有排序,按后台顺序显示
|
||||
*/
|
||||
class DownloadViewModel(application: Application, val gameEntity: GameEntity) : AndroidViewModel(application) {
|
||||
|
||||
val listLiveData: MutableLiveData<List<DownloadDialogItemData>> = MutableLiveData()
|
||||
val collectionLiveData: MutableLiveData<GameCollectionEntity> = MutableLiveData()
|
||||
val dismissLiveData: MutableLiveData<Any> = MutableLiveData()
|
||||
|
||||
private var mAllApkList: MutableList<ApkEntity> = ArrayList()
|
||||
private var mInstalledApkList: MutableList<ApkEntity> = ArrayList()
|
||||
private var mOtherApkList: MutableList<ApkEntity> = ArrayList()
|
||||
|
||||
var otherSectionPosition = -1
|
||||
|
||||
init {
|
||||
if (gameEntity.pluggableCollection != null) {
|
||||
collectionLiveData.postValue(gameEntity.pluggableCollection)
|
||||
} else {
|
||||
initListData()
|
||||
}
|
||||
}
|
||||
|
||||
fun initListData() {
|
||||
mAllApkList = ArrayList()
|
||||
mInstalledApkList = ArrayList()
|
||||
mOtherApkList = ArrayList()
|
||||
|
||||
mergeApkCollection()
|
||||
mergeApkLink()
|
||||
|
||||
mAllApkList.forEach { apk ->
|
||||
setSortValueToApkEntity(apk)
|
||||
|
||||
val installed = if (apk.apkCollection != null) {
|
||||
var isInstalled = false
|
||||
apk.apkCollection?.saveApkEntity?.let {
|
||||
for (entity in it) {
|
||||
isInstalled = PackagesManager.isInstalled(entity.packageName)
|
||||
if (isInstalled) break
|
||||
}
|
||||
}
|
||||
isInstalled
|
||||
} else {
|
||||
PackagesManager.isInstalled(apk.packageName)
|
||||
}
|
||||
if (installed) {
|
||||
mInstalledApkList.add(apk)
|
||||
} else {
|
||||
mOtherApkList.add(apk)
|
||||
}
|
||||
}
|
||||
|
||||
mInstalledApkList.sortWith(Comparator { o1, o2 -> o2.order - o1.order })
|
||||
mOtherApkList.sortWith(Comparator { o1, o2 -> o2.order - o1.order })
|
||||
|
||||
val itemList: MutableList<DownloadDialogItemData> = ArrayList()
|
||||
|
||||
val pluginLink = gameEntity.pluginLink
|
||||
if (pluginLink.isNotEmpty()) {
|
||||
itemList.add(DownloadDialogItemData(links = pluginLink))
|
||||
}
|
||||
|
||||
if (mInstalledApkList.isNotEmpty()) {
|
||||
itemList.add(DownloadDialogItemData(section = DownloadDialogSectionType.INSTALLED))
|
||||
}
|
||||
|
||||
mInstalledApkList.forEach { apk ->
|
||||
itemList.add(DownloadDialogItemData(installed = apk))
|
||||
}
|
||||
|
||||
if (mOtherApkList.isNotEmpty()) {
|
||||
otherSectionPosition = itemList.size
|
||||
itemList.add(DownloadDialogItemData(section = DownloadDialogSectionType.OTHER))
|
||||
}
|
||||
|
||||
mOtherApkList.forEach { apk ->
|
||||
itemList.add(DownloadDialogItemData(normal = apk))
|
||||
}
|
||||
|
||||
itemList.add(DownloadDialogItemData(platformRequest = Any()))
|
||||
|
||||
listLiveData.postValue(itemList)
|
||||
}
|
||||
|
||||
private fun setSortValueToApkEntity(apkEntity: ApkEntity) {
|
||||
apkEntity.apkCollection?.saveApkEntity?.forEach { saveApk ->
|
||||
val sortValue = getSortValue(saveApk)
|
||||
if (apkEntity.order < sortValue) {
|
||||
apkEntity.order = sortValue
|
||||
}
|
||||
}
|
||||
|
||||
if (apkEntity.order == 0) {
|
||||
apkEntity.order = getSortValue(apkEntity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSortValue(apkEntity: ApkEntity): Int {
|
||||
val packageName = apkEntity.packageName
|
||||
val downloadEntity = DownloadManager.getInstance(getApplication()).getDownloadEntityByUrl(apkEntity.url)
|
||||
if (downloadEntity == null) {
|
||||
if (PackagesManager.isInstalled(packageName)) {
|
||||
if (PackageUtils.isCanPluggable(apkEntity)) {
|
||||
return SORT_PLUGGABLE
|
||||
} else if (PackageUtils.isCanUpdate(apkEntity, gameEntity.id)) {
|
||||
return SORT_UPDATE
|
||||
} else if (PackageUtils.getMetaData(getApplication(), packageName, "gh_id") == gameEntity.id) {
|
||||
return SORT_NORMAL_LAUNCH
|
||||
}
|
||||
}
|
||||
return SORT_NORMAL
|
||||
} else {
|
||||
return if (downloadEntity.status == DownloadStatus.done) {
|
||||
if (downloadEntity.isPluggable) {
|
||||
SORT_PLUGGABLE_INSTALL
|
||||
} else if (downloadEntity.isUpdate) {
|
||||
SORT_UPDATE_INSTALL
|
||||
} else {
|
||||
SORT_NORMAL_INSTALL
|
||||
}
|
||||
} else {
|
||||
if (downloadEntity.isPluggable) {
|
||||
SORT_PLUGGABLE_DOWNLOADING
|
||||
} else if (downloadEntity.isUpdate) {
|
||||
SORT_UPDATE_DOWNLOADING
|
||||
} else {
|
||||
SORT_NORMAL_DOWNLOADING
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun mergeApkCollection() {
|
||||
val gameCollectionApk = ArrayList<ApkEntity>()
|
||||
val hashMap = ConcurrentHashMap<String, Int>()
|
||||
var isCollection: Boolean
|
||||
|
||||
for (apkEntity in gameEntity.getApk()) {
|
||||
isCollection = false
|
||||
for (gameCollectionEntity in gameEntity.collection) {
|
||||
for (packageName in gameCollectionEntity.packages) {
|
||||
if (packageName == apkEntity.packageName) {
|
||||
isCollection = true
|
||||
val index = hashMap[gameCollectionEntity.name]
|
||||
if (index != null) {
|
||||
gameCollectionApk[index].apkCollection?.saveApkEntity?.add(apkEntity)
|
||||
} else {
|
||||
val newApkEntity = ApkEntity()
|
||||
val saveApkList = ArrayList<ApkEntity>()
|
||||
saveApkList.add(apkEntity)
|
||||
gameCollectionEntity.saveApkEntity = saveApkList
|
||||
newApkEntity.apkCollection = gameCollectionEntity
|
||||
gameCollectionApk.add(newApkEntity)
|
||||
|
||||
hashMap[gameCollectionEntity.name] = gameCollectionApk.size - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isCollection) {
|
||||
gameCollectionApk.add(apkEntity)
|
||||
}
|
||||
}
|
||||
|
||||
mAllApkList = gameCollectionApk
|
||||
}
|
||||
|
||||
private fun mergeApkLink() {
|
||||
gameEntity.apkLink?.forEach { link ->
|
||||
val collection = link.collection
|
||||
if (collection.isNotEmpty()) {
|
||||
mAllApkList.forEach { apk ->
|
||||
apk.apkCollection?.let { apkCollection ->
|
||||
val saveApkEntity = apkCollection.saveApkEntity
|
||||
if (saveApkEntity != null && collection == apkCollection.id) {
|
||||
val element = ApkEntity()
|
||||
element.apkLink = link
|
||||
if (saveApkEntity.size > link.sort) {
|
||||
saveApkEntity.add(link.sort, element)
|
||||
} else {
|
||||
saveApkEntity.add(element)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val linkApkEntity = ApkEntity()
|
||||
linkApkEntity.apkLink = link
|
||||
if (mAllApkList.size > link.sort) {
|
||||
mAllApkList.add(link.sort, linkApkEntity)
|
||||
} else {
|
||||
mAllApkList.add(linkApkEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Factory(val mApplication: Application, val gameEntity: GameEntity) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return DownloadViewModel(mApplication, gameEntity) as T
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
// 需要修改排序的话,只需要修改以下数值即可(由大到小排序)
|
||||
const val SORT_PLUGGABLE_INSTALL = 10
|
||||
const val SORT_PLUGGABLE_DOWNLOADING = 9
|
||||
const val SORT_PLUGGABLE = 8
|
||||
|
||||
const val SORT_UPDATE_INSTALL = 7
|
||||
const val SORT_UPDATE_DOWNLOADING = 6
|
||||
const val SORT_UPDATE = 5
|
||||
|
||||
const val SORT_NORMAL_INSTALL = 4
|
||||
const val SORT_NORMAL_DOWNLOADING = 3
|
||||
const val SORT_NORMAL_LAUNCH = 2
|
||||
const val SORT_NORMAL = 1
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,6 @@ class HelpAndFeedbackActivity : BaseActivity_TabLayout() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setNavigationTitle("帮助与反馈")
|
||||
mTabIndicatorView.setIndicatorWidth(88)
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
@ -56,8 +55,10 @@ class HelpAndFeedbackActivity : BaseActivity_TabLayout() {
|
||||
const val SUGGESTION_ITEM = 1
|
||||
|
||||
@JvmStatic
|
||||
fun getIntent(context: Context): Intent {
|
||||
return Intent(context, HelpAndFeedbackActivity::class.java)
|
||||
fun getIntent(context: Context, position: Int = HELP_ITEM): Intent {
|
||||
val intent = Intent(context, HelpAndFeedbackActivity::class.java)
|
||||
intent.putExtra(PAGE_INDEX, position)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -96,8 +96,6 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
|
||||
private String mListStatus; // 记录列表领取状态(防止状态在详情改变导致列表状态改变)
|
||||
private String mName;
|
||||
private String mTitle;
|
||||
protected String mDownloadAddWord;
|
||||
protected String mDownloadOffText;
|
||||
|
||||
@Override
|
||||
protected void handleMessage(Message msg) {
|
||||
@ -148,7 +146,7 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
|
||||
|
||||
private DetailViewHolder getDetailViewHolder() {
|
||||
// 每次获取需要重新创建, 防止数据刷新
|
||||
return new DetailViewHolder(mContentView, mGameEntity, mDownloadEntity, mDownloadOffText, mDownloadAddWord,
|
||||
return new DetailViewHolder(mContentView, mGameEntity, mDownloadEntity,
|
||||
false, mEntrance, mName, mTitle, null); // 下载按钮ViewHolder
|
||||
}
|
||||
|
||||
@ -362,8 +360,6 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
|
||||
mGameEntity = response;
|
||||
mAdapter.setGameEntity(mGameEntity);
|
||||
|
||||
mDownloadAddWord = mGameEntity.getDownloadAddWord();
|
||||
mDownloadOffText = mGameEntity.getDownloadOffText();
|
||||
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), true);
|
||||
|
||||
mAdapter.addLibaoDetail(LibaoDetailActivity.this, true);
|
||||
|
||||
@ -23,6 +23,9 @@ import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
import com.gh.base.AppUncaughtHandler;
|
||||
import com.gh.base.BaseActivity;
|
||||
import com.gh.base.fragment.BaseFragment_ViewPager;
|
||||
@ -32,6 +35,7 @@ import com.gh.common.constant.Config;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.common.im.ImManager;
|
||||
import com.gh.common.loghub.LoghubUtils;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.common.util.ActivationHelper;
|
||||
import com.gh.common.util.ClassUtils;
|
||||
@ -87,8 +91,10 @@ import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.AppManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.tencent.bugly.beta.tinker.TinkerManager;
|
||||
import com.tencent.bugly.crashreport.CrashReport;
|
||||
import com.umeng.message.PushAgent;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
@ -113,8 +119,6 @@ import java.util.TimerTask;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.MediaType;
|
||||
@ -140,7 +144,6 @@ public class MainActivity extends BaseActivity {
|
||||
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";
|
||||
private final static String CURRENT_PAGE = "current_page";
|
||||
|
||||
private PackageViewModel mPackageViewModel;
|
||||
@ -160,17 +163,16 @@ public class MainActivity extends BaseActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setStatusBarColor(Color.TRANSPARENT);
|
||||
|
||||
mSp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
mMainWrapperFragment = new MainWrapperFragment();
|
||||
if (savedInstanceState != null) {
|
||||
mMainWrapperFragment.setArguments(savedInstanceState);
|
||||
} else if (getIntent() != null) {
|
||||
Bundle extras = getIntent().getExtras();
|
||||
mMainWrapperFragment.setArguments(extras);
|
||||
mMainWrapperFragment.setArguments(getIntent().getExtras());
|
||||
}
|
||||
replaceFragment(mMainWrapperFragment);
|
||||
|
||||
mSp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
isNewFirstLaunch = mSp.getBoolean("isNewFirstLaunchV" + PackageUtils.getVersionName(), true);
|
||||
if (isNewFirstLaunch) {
|
||||
final LunchType lunchType = DeviceTokenUtils.getLaunchType();
|
||||
@ -211,9 +213,10 @@ public class MainActivity extends BaseActivity {
|
||||
"玩家操作", "点击关闭"));
|
||||
}
|
||||
|
||||
// checkTinkerPath(); // todo 看情况是否需要显示弹窗
|
||||
// checkTinkerPath(); // 看情况是否需要显示补丁弹窗
|
||||
|
||||
checkRetryDownload();
|
||||
// 必须放在这里,否在会导致获取baseActivity不是本应用包名
|
||||
DownloadManager.getInstance(this).initDownloadService();
|
||||
|
||||
checkNotificationPermission();
|
||||
|
||||
@ -243,6 +246,7 @@ public class MainActivity extends BaseActivity {
|
||||
PushHelper.postPushClickAction(this.getApplicationContext(), null);
|
||||
}, 2000);
|
||||
|
||||
|
||||
// 耗时操作
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
// 上传数据
|
||||
@ -253,6 +257,8 @@ public class MainActivity extends BaseActivity {
|
||||
UpdateManager.getInstance(this).checkUpdate(true, null);
|
||||
// 初始化PlatformUtils
|
||||
PlatformUtils.getInstance(getApplicationContext());
|
||||
// 友盟记录启动
|
||||
PushAgent.getInstance(this).onAppStart();
|
||||
});
|
||||
|
||||
|
||||
@ -299,7 +305,6 @@ public class MainActivity extends BaseActivity {
|
||||
DisplayUtils.setLightStatusBar(this, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -694,15 +699,23 @@ public class MainActivity extends BaseActivity {
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBPackage busFour) {
|
||||
final String packageName = busFour.getPackageName();
|
||||
final String versionName = busFour.getVersionName();
|
||||
String gameId = "";
|
||||
|
||||
DownloadEntity mDownloadEntity = null;
|
||||
for (DownloadEntity downloadEntity : DownloadManager.getInstance(getApplicationContext()).getAll()) {
|
||||
//todo 根据包名获取DownloadEntity? 假如存在相同包名的下载任务,有可能会删除错误
|
||||
if (packageName.equals(downloadEntity.getPackageName())) {
|
||||
mDownloadEntity = downloadEntity;
|
||||
gameId = mDownloadEntity.getGameId();
|
||||
break;
|
||||
gameId = mDownloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER);
|
||||
if (TextUtils.isEmpty(busFour.getVersionName())) {
|
||||
// 没有版本号的事件直接选用第一个找到的 downloadEntity
|
||||
break;
|
||||
} else {
|
||||
// 有版本号的事件直接尽量找到版本一致的 downloadEntity
|
||||
if (versionName.equals(downloadEntity.getVersionName())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -748,7 +761,7 @@ public class MainActivity extends BaseActivity {
|
||||
public void onResponse(List<GameDigestEntity> response) {
|
||||
for (GameDigestEntity gameDigestEntity : response) {
|
||||
if (!TextUtils.isEmpty(gameDigestEntity.getId())) { // 关注游戏
|
||||
if (finalDownloadEntity != null && gameDigestEntity.getId().equals(finalDownloadEntity.getGameId())) {
|
||||
if (finalDownloadEntity != null && gameDigestEntity.getId().equals(finalDownloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER))) {
|
||||
ConcernUtils.INSTANCE.postConcernGameId(MainActivity.this, gameDigestEntity.getId(), null, false);
|
||||
}
|
||||
}
|
||||
@ -791,11 +804,23 @@ public class MainActivity extends BaseActivity {
|
||||
// 发送应用变更前都检查一下是否需要把所有应用都上传
|
||||
PackageRepository.checkAndUploadAppList();
|
||||
|
||||
// 更新已安装游戏
|
||||
JSONObject packageObject = PackageUtils.getAppBasicInfoByPackageName(packageName);
|
||||
JSONObject dataObject = new JSONObject();
|
||||
JSONObject wrapperObject = new JSONObject();
|
||||
try {
|
||||
dataObject.put("type", "POST");
|
||||
dataObject.put("device_id", HaloApp.getInstance().getGid());
|
||||
dataObject.put("app", packageObject);
|
||||
dataObject.put("time", Utils.getTime(getApplicationContext()));
|
||||
wrapperObject.put("content", dataObject.toString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
LoghubUtils.log(wrapperObject, "halo-api-device-installed", true);
|
||||
|
||||
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"),
|
||||
packageObject.toString());
|
||||
|
||||
// 更新已安装游戏
|
||||
RetrofitManager.getInstance(MainActivity.this).getApi()
|
||||
.postNewlyInstalledApp(HaloApp.getInstance().getGid(), requestBody)
|
||||
@ -827,6 +852,20 @@ public class MainActivity extends BaseActivity {
|
||||
// 发送应用变更前都检查一下是否需要把所有应用都上传
|
||||
PackageRepository.checkAndUploadAppList();
|
||||
|
||||
// 删除已安装游戏
|
||||
JSONObject dataObject = new JSONObject();
|
||||
JSONObject wrapperObject = new JSONObject();
|
||||
try {
|
||||
dataObject.put("type", "DELETE");
|
||||
dataObject.put("device_id", HaloApp.getInstance().getGid());
|
||||
dataObject.put("package", packageName);
|
||||
dataObject.put("time", Utils.getTime(getApplicationContext()));
|
||||
wrapperObject.put("content", dataObject.toString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
LoghubUtils.log(wrapperObject, "halo-api-device-installed", true);
|
||||
|
||||
// 删除已安装游戏
|
||||
RetrofitManager.getInstance(MainActivity.this).getApi()
|
||||
.deleteInstalledApp(HaloApp.getInstance().getGid(), packageName)
|
||||
@ -843,6 +882,11 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useButterKnife() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActivityNameInChinese() {
|
||||
return "游戏首页";
|
||||
|
||||
@ -118,7 +118,6 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
|
||||
private long start = 0L;
|
||||
|
||||
private String newsId;
|
||||
private String downloadOffText;
|
||||
|
||||
private SharedPreferences sp;
|
||||
|
||||
@ -168,7 +167,7 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
|
||||
|
||||
private DetailViewHolder getDetailViewHolder() {
|
||||
// 每次获取需要重新创建, 防止数据刷新
|
||||
return new DetailViewHolder(mContentView, gameEntity, mDownloadEntity, downloadOffText, null,
|
||||
return new DetailViewHolder(mContentView, gameEntity, mDownloadEntity,
|
||||
true, mEntrance, "新闻详情", adapter.getTitle(), null); // 下载按钮ViewHolder
|
||||
}
|
||||
|
||||
@ -343,7 +342,7 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
|
||||
|
||||
newsDetailEntity.getMe().setArticleFavorite(false);
|
||||
mNewsCollection.setEnabled(true);
|
||||
mNewsCollection.setIcon(R.drawable.menu_ic_collect_unselect);
|
||||
mNewsCollection.setIcon(R.drawable.community_content_detail_collect_unselect);
|
||||
toast(R.string.collection_cancel);
|
||||
}
|
||||
|
||||
@ -367,7 +366,7 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
|
||||
}
|
||||
userData.setArticleFavorite(true);
|
||||
mNewsCollection.setEnabled(true);
|
||||
mNewsCollection.setIcon(R.drawable.menu_ic_collect_select);
|
||||
mNewsCollection.setIcon(R.drawable.community_content_detail_collect_select);
|
||||
toast(R.string.collection_success);
|
||||
}
|
||||
|
||||
@ -446,9 +445,9 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
|
||||
mNewsCollection.setVisible(true);
|
||||
NewsDetailEntity newsDetailEntity = adapter.getNewsDetailEntity();
|
||||
if (newsDetailEntity.getMe() != null && newsDetailEntity.getMe().isArticleFavorite()) {
|
||||
mNewsCollection.setIcon(R.drawable.menu_ic_collect_select);
|
||||
mNewsCollection.setIcon(R.drawable.community_content_detail_collect_select);
|
||||
} else {
|
||||
mNewsCollection.setIcon(R.drawable.menu_ic_collect_unselect);
|
||||
mNewsCollection.setIcon(R.drawable.community_content_detail_collect_unselect);
|
||||
}
|
||||
}
|
||||
|
||||
@ -629,7 +628,6 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
|
||||
gameEntity = response;
|
||||
adapter.setGameEntity(gameEntity);
|
||||
adapter.notifyItemInserted(1);
|
||||
downloadOffText = gameEntity.getDownloadOffText();
|
||||
|
||||
mDetailBottomLl.setVisibility(View.VISIBLE);
|
||||
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), true);
|
||||
|
||||
25
app/src/main/java/com/gh/gamecenter/QaActivity.kt
Normal file
25
app/src/main/java/com/gh/gamecenter/QaActivity.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package com.gh.gamecenter
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.help.HelpContainerFragment
|
||||
|
||||
class QaActivity : NormalActivity() {
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* qaId 存在则是QA页面
|
||||
* qaCollectionId 存在则是QA合集页面
|
||||
* 两个都存在则默认时QA合集页面
|
||||
*/
|
||||
fun getIntent(context: Context, navigationTitle: String, qaId: String? = null, qaCollectionId: String? = null): Intent {
|
||||
val args = Bundle()
|
||||
args.putString(EntranceUtils.KEY_QA_ID, qaId)
|
||||
args.putString(EntranceUtils.KEY_QA_COLLECTION_ID, qaCollectionId)
|
||||
args.putString(EntranceUtils.KEY_NAVIGATION_TITLE, navigationTitle)
|
||||
return getTargetIntent(context, QaActivity::class.java, HelpContainerFragment::class.java, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,7 @@ import static com.gh.common.util.EntranceUtils.HOST_ANSWER;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_ARTICLE;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_COLUMN;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_COMMUNITY;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_COMMUNITY_COLUMN;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_DOWNLOAD;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_GAME;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_LIBAO;
|
||||
@ -51,7 +52,6 @@ import static com.gh.common.util.EntranceUtils.KEY_TYPE;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_VERSION;
|
||||
|
||||
/**
|
||||
* TODO 将此页面与 DefaultWebViewUrlHandler 的跳转格式写成文档
|
||||
* Created by LGT on 2016/11/16.
|
||||
* 链接跳转用
|
||||
*/
|
||||
@ -232,6 +232,13 @@ public class SkipActivity extends BaseActivity {
|
||||
String position = uri.getQueryParameter("position");
|
||||
DirectUtils.directToHomeActivity(this, path, TextUtils.isEmpty(position) ? -1 : Integer.parseInt(position), ENTRANCE_BROWSER, "浏览器");
|
||||
break;
|
||||
case HOST_COMMUNITY_COLUMN:
|
||||
CommunityEntity community = new CommunityEntity();
|
||||
community.setId(uri.getQueryParameter("community_id"));
|
||||
community.setName(uri.getQueryParameter("community_name"));
|
||||
String columnId = uri.getQueryParameter("column_id");
|
||||
DirectUtils.directToCommunityColumn(this, community, columnId, ENTRANCE_BROWSER, "");
|
||||
break;
|
||||
default:
|
||||
EntranceUtils.jumpActivity(this, new Bundle()); // 跳转至首页
|
||||
return;
|
||||
|
||||
@ -19,6 +19,7 @@ import com.g00fy2.versioncompare.Version;
|
||||
import com.gh.base.BaseActivity;
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DeviceTokenUtils;
|
||||
import com.gh.common.util.DeviceUtils;
|
||||
@ -26,19 +27,21 @@ import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.EmptyCallback;
|
||||
import com.gh.common.util.GameRepositoryHelper;
|
||||
import com.gh.common.util.GdtHelper;
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.common.util.TagUtils;
|
||||
import com.gh.common.util.TimestampUtils;
|
||||
import com.gh.common.util.UsageStatsHelper;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.entity.AuthDialogEntity;
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
|
||||
import com.gh.gamecenter.manager.FilterManager;
|
||||
import com.gh.gamecenter.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.gamecenter.user.UserRepository;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.qq.gdt.action.ActionType;
|
||||
@ -47,11 +50,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
@ -87,22 +92,17 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
isNewFirstLaunch = mSharedPreferences.getBoolean("isNewFirstLaunchV" + PackageUtils.getVersionName(), true);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
UserRepository.getInstance(getApplication()); // 初始化登录
|
||||
|
||||
// 处理助手已经在后台运行导致的再次启动助手
|
||||
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
TimestampUtils.initMap();
|
||||
|
||||
// 判断是不是这个版本的新用户
|
||||
if (isNewFirstLaunch) {
|
||||
// 删除更新后的光环助手包
|
||||
@ -120,6 +120,7 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
|
||||
// 判断是不是光环的新用户
|
||||
if (SPUtils.getBoolean(SP_BRAND_NEW_USER, true)) {
|
||||
HaloApp.getInstance().isBrandNewInstall = true;
|
||||
showPrivacyPolicy(() -> {
|
||||
// Dialog dismiss 后的回调
|
||||
guideLayout.setVisibility(View.VISIBLE);
|
||||
@ -136,7 +137,9 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
Config.getGhzsSettings();
|
||||
|
||||
deviceDialogSetting();
|
||||
getFilterDetailTags();
|
||||
getAuthDialog();
|
||||
UsageStatsHelper.checkAndPostUsageStats();
|
||||
GameRepositoryHelper.getGameRepository(this);
|
||||
|
||||
@ -160,8 +163,6 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
|
||||
// 更新本地时间
|
||||
DeviceTokenUtils.syncServerTime(this);
|
||||
|
||||
DownloadManager.getInstance(this).initDownloadService();
|
||||
});
|
||||
}
|
||||
|
||||
@ -173,6 +174,42 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void deviceDialogSetting() {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
|
||||
.getApi().deviceDialogs()
|
||||
.subscribe((entities, throwable) -> {
|
||||
if (entities.size() > 0) {
|
||||
SPUtils.setString(Constants.SP_DEVICE_REMIND, GsonUtils.toJson(entities));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void getFilterDetailTags() {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
|
||||
.getApi().getFilterDetailTags()
|
||||
.subscribe(new Response<ArrayList<String>>() {
|
||||
@Override
|
||||
public void onResponse(@Nullable ArrayList<String> response) {
|
||||
super.onResponse(response);
|
||||
SPUtils.setString(Constants.SP_FILTER_TAGS, GsonUtils.toJson(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void getAuthDialog() {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
|
||||
.getApi()
|
||||
.authDialog()
|
||||
.subscribe(new Response<List<AuthDialogEntity>>() {
|
||||
@Override
|
||||
public void onResponse(@Nullable List<AuthDialogEntity> response) {
|
||||
super.onResponse(response);
|
||||
SPUtils.setString(Constants.SP_AUTH_DIALOG, GsonUtils.toJson(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void showPrivacyPolicy(EmptyCallback callback) {
|
||||
RetrofitManager.getInstance(this).getApi()
|
||||
@ -199,15 +236,11 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
|
||||
final int layoutId;
|
||||
if (isNewFirstLaunch) {
|
||||
layoutId = R.layout.activity_splash_intro;
|
||||
return R.layout.activity_splash_intro;
|
||||
} else {
|
||||
layoutId = R.layout.activity_splash_normal;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return layoutId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -222,6 +255,16 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useEventBus() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useButterKnife() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 跳转到主界面
|
||||
private void launchMainActivity() {
|
||||
getUniqueId();
|
||||
|
||||
@ -86,6 +86,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
@ -483,8 +484,11 @@ public class SuggestionActivity extends ToolBarActivity implements OnRequestCall
|
||||
int widthPixels = getResources().getDisplayMetrics().widthPixels;
|
||||
reportTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
reportTv.setPadding(DisplayUtils.dip2px(SuggestionActivity.this, 20), DisplayUtils.dip2px(SuggestionActivity.this, 12),
|
||||
0, DisplayUtils.dip2px(SuggestionActivity.this, 12));
|
||||
reportTv.setPadding(
|
||||
DisplayUtils.dip2px(SuggestionActivity.this, 20),
|
||||
DisplayUtils.dip2px(SuggestionActivity.this, 12),
|
||||
DisplayUtils.dip2px(SuggestionActivity.this, 20),
|
||||
DisplayUtils.dip2px(SuggestionActivity.this, 12));
|
||||
container.addView(reportTv);
|
||||
|
||||
reportTv.setOnClickListener(v -> {
|
||||
@ -707,6 +711,7 @@ public class SuggestionActivity extends ToolBarActivity implements OnRequestCall
|
||||
R.style.GhAlertDialog,
|
||||
"意见反馈",
|
||||
"意见反馈-游戏收录弹窗",
|
||||
null,
|
||||
"点击空白",
|
||||
"点击手机返回键", false);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
|
||||
@ -43,13 +43,13 @@ import io.reactivex.schedulers.Schedulers;
|
||||
*/
|
||||
|
||||
public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayout.OnRefreshListener, OnRequestCallBackListener {
|
||||
|
||||
|
||||
@BindView(R.id.et_search)
|
||||
public EditText searchEt;
|
||||
@BindView(R.id.tv_search)
|
||||
public TextView searchTv;
|
||||
@BindView(R.id.tv_back)
|
||||
public TextView backTv;
|
||||
public View backTv;
|
||||
@BindView(R.id.toolbox_appbar)
|
||||
AppBarLayout mAppBar;
|
||||
@BindView(R.id.toolbox_rv)
|
||||
@ -64,51 +64,51 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
SwipeRefreshLayout mRefresh;
|
||||
@BindView(R.id.reuse_ll_loading)
|
||||
View mLoading;
|
||||
|
||||
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
private ToolBoxRvAdapter mRvAdapter;
|
||||
private ToolBoxRvAdapter mNormalRvAdapter;
|
||||
|
||||
|
||||
private boolean mIsSearch; // 记录页面状态 搜索页面/普通页面
|
||||
private String mSearchKey; // 记录搜索关键字
|
||||
|
||||
|
||||
Runnable runnable = () -> changeAdapter(true);
|
||||
|
||||
|
||||
@NonNull
|
||||
public static Intent getIntent(Context context, String entrance) {
|
||||
Intent intent = new Intent(context, ToolBoxActivity.class);
|
||||
intent.putExtra(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
return intent;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_toolbox;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setNavigationTitle("光环工具箱");
|
||||
|
||||
|
||||
mRefresh.setColorSchemeResources(R.color.theme);
|
||||
mRefresh.setOnRefreshListener(this);
|
||||
|
||||
|
||||
// 跳转到工具箱 https://gitlab.ghzs.com/pm/halo-app-issues/issues/636
|
||||
String gameId = getIntent().getStringExtra(EntranceUtils.KEY_GAMEID);
|
||||
String targetUrl = getIntent().getStringExtra(EntranceUtils.KEY_URL);
|
||||
if (!TextUtils.isEmpty(targetUrl) && !TextUtils.isEmpty(gameId)) {
|
||||
findGameAndOpenItsToolboxWebview(gameId, targetUrl);
|
||||
}
|
||||
|
||||
|
||||
mLayoutManager = new LinearLayoutManager(this);
|
||||
mToolboxRv.setLayoutManager(mLayoutManager);
|
||||
mRvAdapter = new ToolBoxRvAdapter(this, this, mIsSearch, mSearchKey);
|
||||
mToolboxRv.addItemDecoration(new VerticalItemDecoration(this, 8, false));
|
||||
mToolboxRv.setAdapter(mRvAdapter);
|
||||
|
||||
|
||||
mNormalRvAdapter = mRvAdapter;
|
||||
|
||||
|
||||
mToolboxRv.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||
@ -121,7 +121,7 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
mAppBar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
|
||||
if (verticalOffset == 0) {
|
||||
mRefresh.setEnabled(true);
|
||||
@ -133,10 +133,10 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
Util_System_Keyboard.hideSoftKeyboard(this);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
initSearch();
|
||||
}
|
||||
|
||||
|
||||
private void findGameAndOpenItsToolboxWebview(String gameId, String url) {
|
||||
RetrofitManager.getInstance(this)
|
||||
.getApi()
|
||||
@ -147,7 +147,7 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
@Override
|
||||
public void onResponse(@Nullable List<ToolBoxEntity> response) {
|
||||
if (response == null) return;
|
||||
|
||||
|
||||
for (ToolBoxEntity toolbox : response) {
|
||||
if (url.equals(toolbox.getUrl())) {
|
||||
Intent intent = WebActivity.getWebByCollectionTools(ToolBoxActivity.this, toolbox, false);
|
||||
@ -157,14 +157,14 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void initSearch() {
|
||||
backTv.setOnClickListener(v -> search(false, searchEt.getText().toString()));
|
||||
|
||||
|
||||
TextHelper.limitTheLengthOfEditText(searchEt, 20, () -> {
|
||||
Utils.toast(this, "最多输入20字");
|
||||
});
|
||||
|
||||
|
||||
searchTv.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("我的光环_新", "工具箱", "点击搜索");
|
||||
if (TextUtils.isEmpty(searchEt.getText().toString())) {
|
||||
@ -173,13 +173,13 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
}
|
||||
search(true, searchEt.getText().toString());
|
||||
});
|
||||
|
||||
|
||||
searchEt.setOnFocusChangeListener((v, hasFocus) -> {
|
||||
if (!hasFocus) {
|
||||
Util_System_Keyboard.hideSoftKeyboard(this, searchEt);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
searchEt.setOnEditorActionListener((v, actionId, event) -> {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
searchTv.performClick();
|
||||
@ -187,8 +187,8 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@OnClick({R.id.reuse_no_connection, R.id.reuse_none_data})
|
||||
public void onClick(View view) {
|
||||
if (view.getId() == R.id.reuse_no_connection) {
|
||||
@ -203,7 +203,7 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void loadDone() {
|
||||
mRefresh.setRefreshing(false);
|
||||
@ -211,12 +211,12 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
mNoConnection.setVisibility(View.GONE);
|
||||
mLoading.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void loadDone(Object obj) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void loadEmpty() {
|
||||
mRefresh.setRefreshing(false);
|
||||
@ -229,7 +229,7 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
mNoneDataTv.setText(getResources().getString(R.string.game_empty));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void loadError() {
|
||||
mRefresh.setRefreshing(false);
|
||||
@ -237,12 +237,12 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
mNoConnection.setVisibility(View.VISIBLE);
|
||||
mLoading.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
mRefresh.postDelayed(runnable, 1000);
|
||||
}
|
||||
|
||||
|
||||
public void search(boolean isSearch, String searchKey) {
|
||||
if (mNoneData.getVisibility() == View.VISIBLE) {
|
||||
mNoneData.setVisibility(View.GONE);
|
||||
@ -254,7 +254,7 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
mSearchKey = searchKey;
|
||||
changeAdapter(false);
|
||||
}
|
||||
|
||||
|
||||
private void changeAdapter(boolean isRefresh) {
|
||||
if (mIsSearch) {
|
||||
mRvAdapter = new ToolBoxRvAdapter(this, this, mIsSearch, mSearchKey);
|
||||
@ -267,12 +267,12 @@ public class ToolBoxActivity extends ToolBarActivity implements SwipeRefreshLayo
|
||||
}
|
||||
}
|
||||
mToolboxRv.setAdapter(mRvAdapter);
|
||||
|
||||
|
||||
if (mSearchKey != null) {
|
||||
searchEt.setText(mSearchKey);
|
||||
searchEt.setSelection(searchEt.getText().length());
|
||||
}
|
||||
|
||||
|
||||
if (mIsSearch) {
|
||||
backTv.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
|
||||
@ -21,6 +21,12 @@ import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
|
||||
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.imagepipeline.core.ImagePipeline;
|
||||
@ -37,7 +43,6 @@ import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.PermissionHelper;
|
||||
import com.gh.common.util.SimpleImageLoader;
|
||||
import com.gh.common.view.Gh_RelativeLayout;
|
||||
import com.gh.common.view.Gh_RelativeLayout.OnSingleTapListener;
|
||||
import com.gh.common.view.Gh_ViewPager;
|
||||
import com.gh.gamecenter.entity.ImageInfoEntity;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
@ -58,11 +63,6 @@ import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
|
||||
import butterknife.BindView;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
@ -71,6 +71,8 @@ import io.reactivex.schedulers.Schedulers;
|
||||
* 查看游戏截图页面
|
||||
*
|
||||
* @author 黄壮华
|
||||
*
|
||||
* todo BigImageView静态webp/动态webp(ImageInfoExtractor.getImageType(image))判断有问题,导致部分静态webp无法使用缩放功能
|
||||
*/
|
||||
public class ViewImageActivity extends BaseActivity implements OnPageChangeListener {
|
||||
|
||||
@ -291,23 +293,23 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void loadImage(String url, final BigImageView imageView) {
|
||||
if (TextUtils.isEmpty(url)) return;
|
||||
|
||||
|
||||
if (url.startsWith("data:image/png;base64")) {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
String base64String = url.replace("data:image/png;base64", "");
|
||||
try {
|
||||
File imageFile = new File(getCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".png");
|
||||
|
||||
|
||||
byte[] decodedString = Base64.decode(base64String, Base64.DEFAULT);
|
||||
|
||||
|
||||
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(imageFile));
|
||||
bos.write(decodedString);
|
||||
bos.flush();
|
||||
bos.close();
|
||||
|
||||
|
||||
AppExecutor.getUiExecutor().execute(() -> {
|
||||
imageView.setImageViewFactory(new FrescoImageViewFactory());
|
||||
imageView.showImage(Uri.fromFile(imageFile));
|
||||
@ -323,7 +325,7 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
|
||||
}
|
||||
}
|
||||
|
||||
private class ViewImageAdapter extends PagerAdapter implements OnSingleTapListener {
|
||||
private class ViewImageAdapter extends PagerAdapter {
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
@ -476,11 +478,5 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
|
||||
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
|
||||
return view == object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSingleTap() {
|
||||
finish();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,6 +86,14 @@ public class WebActivity extends NormalActivity {
|
||||
return getTargetIntent(context, WebActivity.class, WebFragment.class, bundle);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getCopyrighyRulesIntent(Context context) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_GAMENAME, context.getString(R.string.copyright_title));
|
||||
bundle.putString(EntranceUtils.KEY_URL, context.getString(R.string.copyright_rules_url));
|
||||
return getTargetIntent(context, WebActivity.class, WebFragment.class, bundle);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getSecurityCertificationIntent(Context context) {
|
||||
Bundle bundle = new Bundle();
|
||||
@ -168,6 +176,17 @@ public class WebActivity extends NormalActivity {
|
||||
return getTargetIntent(context, WebActivity.class, WebFragment.class, bundle);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getIntent(Context context, String url, String title, boolean autoCompletionTitle, boolean isOpenNativePage) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_URL, url);
|
||||
bundle.putString(EntranceUtils.KEY_GAMENAME, title);
|
||||
bundle.putBoolean(WebFragment.KEY_COMPLETION_TITLE, autoCompletionTitle);
|
||||
bundle.putBoolean(WebFragment.KEY_LEAVE_WEB_PAGE_TO_HANDLE_TITLE, false);
|
||||
bundle.putBoolean(WebFragment.KEY_OPEN_NATIVE_PAGE, isOpenNativePage);
|
||||
return getTargetIntent(context, WebActivity.class, WebFragment.class, bundle);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getIntentByUrl(Context context, String url) {
|
||||
return getIntentByUrl(context, url, false);
|
||||
@ -196,8 +215,13 @@ public class WebActivity extends NormalActivity {
|
||||
@Override
|
||||
protected View.OnClickListener provideNavigationItemClickListener() {
|
||||
Bundle bundle = getIntent().getBundleExtra(NORMAL_FRAGMENT_BUNDLE);
|
||||
if (bundle != null && bundle.getBoolean(WebFragment.KEY_ISTOOLS, false)) {
|
||||
return view -> finish();
|
||||
if (bundle != null) {
|
||||
boolean isTools = bundle.getBoolean(WebFragment.KEY_ISTOOLS, false);
|
||||
boolean isOpenNativePage = bundle.getBoolean(WebFragment.KEY_OPEN_NATIVE_PAGE, false);
|
||||
if (isTools || isOpenNativePage) {
|
||||
return view -> finish();
|
||||
}
|
||||
return super.provideNavigationItemClickListener();
|
||||
} else {
|
||||
return super.provideNavigationItemClickListener();
|
||||
}
|
||||
|
||||
@ -2,9 +2,6 @@ package com.gh.gamecenter.adapter;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
@ -41,6 +38,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import retrofit2.HttpException;
|
||||
@ -190,13 +190,21 @@ public class LibaoDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
linearLayoutManager.setStackFromEnd(true);
|
||||
holder.libaoCodeRv.setLayoutManager(linearLayoutManager);
|
||||
|
||||
int count = (int) (((float) mLibaoEntity.getAvailable() / (float) mLibaoEntity.getTotal()) * 100);
|
||||
float availablePercent = ((float) mLibaoEntity.getAvailable() / (float) mLibaoEntity.getTotal()) * 100;
|
||||
int count;
|
||||
if (availablePercent >= 1) {
|
||||
count = (int) availablePercent;
|
||||
} else if (availablePercent == 0) {
|
||||
count = 0;
|
||||
} else {
|
||||
count = 1;
|
||||
}
|
||||
Spanned content = null;
|
||||
String status = mLibaoEntity.getBeforeStatus();
|
||||
if ("coming".equals(status) || "finish".equals(status) || TextUtils.isEmpty(status)) {
|
||||
content = Html.fromHtml("剩余:--");
|
||||
} else if ("ling".equals(status) || "linged".equals(status)) {
|
||||
content = Html.fromHtml(StringUtils.buildString("剩余:", "<font color=\"#06D0A8\">", count + "%", "</font>"));
|
||||
content = Html.fromHtml(StringUtils.buildString("剩余:", "<font color=\"#1383EB\">", count + "%", "</font>"));
|
||||
} else if ("tao".equals(status) || "taoed".equals(status)) {
|
||||
content = Html.fromHtml(StringUtils.buildString("剩余:", String.valueOf(count), "%"));
|
||||
} else if ("used_up".equals(status)) {
|
||||
|
||||
@ -496,7 +496,7 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
}
|
||||
|
||||
private void statNewsViews(final String news_id) {
|
||||
RetrofitManager.getInstance(mContext).getData().postNewsViews(news_id)
|
||||
RetrofitManager.getInstance(mContext).getApi().postArticleVisit(news_id)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new JSONObjectResponse() {
|
||||
|
||||
@ -1,557 +0,0 @@
|
||||
package com.gh.gamecenter.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ClipDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
import com.gh.common.util.DataLogUtils;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DeviceUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.DownloadDialogHelper;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.PackageHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.VoteActivity;
|
||||
import com.gh.gamecenter.adapter.viewholder.PlatformViewHolder;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.ApkLink;
|
||||
import com.gh.gamecenter.entity.CollectionCloseEntity;
|
||||
import com.gh.gamecenter.entity.GameCollectionEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.collection.ArrayMap;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/9/27.
|
||||
*/
|
||||
public class PlatformAdapter extends BaseRecyclerAdapter<PlatformViewHolder> {
|
||||
|
||||
private OnCollectionCallBackListener mOnCollectionCallBackListener; // 为空则是合集ViewPager
|
||||
|
||||
private List<ApkEntity> mPlatformList;
|
||||
private ArrayMap<String, DownloadEntity> mEntryMap;
|
||||
private SparseArray<PlatformAdapter> mAdapterMap;
|
||||
|
||||
private GameEntity mGameEntity;
|
||||
private CollectionCloseEntity mCloseEntity;
|
||||
|
||||
private String mAutoDownloadPlatform;
|
||||
private String mEntrance;
|
||||
private String mLocation;
|
||||
private ExposureEvent mTraceEvent;
|
||||
|
||||
private int mAdapterPosition;
|
||||
private int mCount;
|
||||
private final int mRow = 3;
|
||||
private final int mColumn = 3;
|
||||
|
||||
public PlatformAdapter(Context context, OnCollectionCallBackListener listener, GameEntity gameEntity,
|
||||
CollectionCloseEntity closeEntity, ArrayMap<String, DownloadEntity> eMap,
|
||||
SparseArray<PlatformAdapter> aMap, List<ApkEntity> list, String entrance, String location,
|
||||
int position, ExposureEvent traceEvent, String autoDownloadPlatform) {
|
||||
super(context);
|
||||
|
||||
mOnCollectionCallBackListener = listener;
|
||||
mGameEntity = gameEntity;
|
||||
mCloseEntity = closeEntity;
|
||||
mEntryMap = eMap;
|
||||
mAdapterMap = aMap;
|
||||
mPlatformList = list;
|
||||
mEntrance = entrance;
|
||||
mLocation = location;
|
||||
mAdapterPosition = position;
|
||||
mTraceEvent = traceEvent;
|
||||
mAutoDownloadPlatform = autoDownloadPlatform;
|
||||
if (mPlatformList.size() <= (mRow * mColumn)) {
|
||||
mCount = mPlatformList.size();
|
||||
} else if (mPlatformList.size() - (mRow * mColumn) * mAdapterPosition >= (mRow * mColumn)) {
|
||||
mCount = (mRow * mColumn);
|
||||
} else {
|
||||
mCount = mPlatformList.size() - (mRow * mColumn) * mAdapterPosition;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = mLayoutInflater.inflate(R.layout.game_download_item, parent, false);
|
||||
return new PlatformViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final PlatformViewHolder viewHolder, int position) {
|
||||
final ApkEntity apkEntity = mPlatformList.get((mRow * mColumn) * mAdapterPosition + position);
|
||||
|
||||
if ("求版本".equals(apkEntity.getPackageName())) {
|
||||
viewHolder.mDownloadItemIvPic.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvHint.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemProgressbar.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemTvName.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemTvStatus.setVisibility(View.GONE);
|
||||
ImageUtils.display(viewHolder.mDownloadItemIvPic, R.drawable.platform_vote);
|
||||
viewHolder.itemView.setBackgroundDrawable(new ColorDrawable(0));
|
||||
viewHolder.itemView.setOnClickListener(v -> {
|
||||
Intent intent = VoteActivity.getIntent(mContext, mGameEntity.getName(), mGameEntity.getId());
|
||||
mContext.startActivity(intent);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (apkEntity.getApkCollection() == null) {
|
||||
// 非合集
|
||||
viewHolder.itemView.setOnClickListener(v -> {
|
||||
ApkLink apkLink = apkEntity.getApkLink();
|
||||
if (apkLink != null) {
|
||||
String entrance = mEntrance + "(" + apkLink.getName() + ")";
|
||||
DirectUtils.directToLinkPage(mContext, apkLink.getLinkEntity(), entrance, "下载多平台弹窗");
|
||||
} else if (viewHolder.mDownloadItemTvStatus.getVisibility() == View.GONE) {
|
||||
//下载游戏
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(mContext, mGameEntity, apkEntity, () -> {
|
||||
DialogUtils.checkDownload(mContext, apkEntity.getSize(),
|
||||
isSubscribe -> download(apkEntity, viewHolder.mDownloadItemTvStatus, "下载", isSubscribe));
|
||||
});
|
||||
|
||||
DataLogUtils.uploadGameLog(mContext, mGameEntity.getId(), mGameEntity.getName(), mEntrance);
|
||||
} else {
|
||||
String status = viewHolder.mDownloadItemTvStatus.getText().toString();
|
||||
switch (status) {
|
||||
case "下载中":
|
||||
case "等待中":
|
||||
case "插件化下载中":
|
||||
case "更新下载中":
|
||||
case "插件化等待中":
|
||||
case "更新等待中":
|
||||
// 打开下载管理界面
|
||||
mContext.startActivity(DownloadManagerActivity.getDownloadMangerIntent(mContext, apkEntity.getUrl()
|
||||
, mEntrance + "(" + mLocation.split(":")[0] + ")"));
|
||||
break;
|
||||
case "已安装":
|
||||
case "启动":
|
||||
Map<String, Object> kv = new HashMap<>();
|
||||
kv.put("版本", apkEntity.getPlatform());
|
||||
DataUtils.onEvent(mContext, "游戏启动", mGameEntity.getName(), kv);
|
||||
|
||||
PackageUtils.launchApplicationByPackageName(mContext, apkEntity.getPackageName());
|
||||
break;
|
||||
case "安装":
|
||||
case "安装更新":
|
||||
install(apkEntity, viewHolder.getAdapterPosition());
|
||||
break;
|
||||
case "插件化":
|
||||
DialogUtils.checkDownload(mContext, apkEntity.getSize(),
|
||||
isSubscribe -> download(apkEntity, viewHolder.mDownloadItemTvStatus, "插件化", isSubscribe));
|
||||
break;
|
||||
case "安装插件":
|
||||
showPluginDialog(apkEntity, PlatformAdapter.this, viewHolder.getAdapterPosition());
|
||||
break;
|
||||
case "更新":
|
||||
DialogUtils.checkDownload(mContext, apkEntity.getSize(), isSubscribe -> update(apkEntity, isSubscribe));
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
ApkLink apkLink = apkEntity.getApkLink();
|
||||
if (apkLink != null) {
|
||||
viewHolder.mDownloadItemIvPic.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvHint.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemTvName.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemTvStatus.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemProgressbar.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemTvHint.setText(apkLink.getName());
|
||||
ImageUtils.display(viewHolder.mDownloadItemIvPic, apkLink.getIcon());
|
||||
viewHolder.itemView.setBackgroundDrawable(new ColorDrawable(0));
|
||||
} else {
|
||||
Object gh_id = PackageUtils.getMetaData(mContext, apkEntity.getPackageName(), "gh_id");
|
||||
if (PackageHelper.INSTANCE.getLocalPackageNameSet().contains(apkEntity.getPackageName())
|
||||
&& (gh_id == null || gh_id.equals(mGameEntity.getId()))) {
|
||||
// 已安装
|
||||
viewHolder.mDownloadItemIvPic.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemTvHint.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemProgressbar.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvName.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvStatus.setVisibility(View.VISIBLE);
|
||||
|
||||
int color = Color.parseColor(PlatformUtils.getInstance(mContext)
|
||||
.getPlatformColor(apkEntity.getPlatform()));
|
||||
viewHolder.itemView.setBackgroundDrawable(getGradientDrawable(color));
|
||||
|
||||
viewHolder.mDownloadItemTvName.setTextColor(color);
|
||||
viewHolder.mDownloadItemTvName.setText(PlatformUtils
|
||||
.getInstance(mContext).getPlatformName(apkEntity.getPlatform()));
|
||||
|
||||
viewHolder.mDownloadItemProgressbar.setProgressDrawable(getLayerDrawable(color));
|
||||
|
||||
DownloadEntity downloadEntity = mEntryMap.get(apkEntity.getUrl());
|
||||
if (downloadEntity == null) {
|
||||
viewHolder.mDownloadItemProgressbar.setProgress(1000);
|
||||
if (mGameEntity.getTag() != null && mGameEntity.getTag().size() != 0
|
||||
&& !TextUtils.isEmpty(apkEntity.getGhVersion())
|
||||
&& !PackageUtils.isSignature(mContext, apkEntity.getPackageName())
|
||||
&& apkEntity.isShowPlugin(PluginLocation.only_game)) {
|
||||
viewHolder.mDownloadItemTvStatus.setText(R.string.pluggable);
|
||||
downloadEntity = DownloadManager.getInstance(mContext).getDownloadEntityByPackageName(apkEntity.getPackageName());
|
||||
if (downloadEntity == null
|
||||
|| downloadEntity.getUrl().equals(apkEntity.getUrl())) {
|
||||
viewHolder.itemView.setClickable(true);
|
||||
viewHolder.mDownloadItemProgressbar.setProgress(1000);
|
||||
} else {
|
||||
viewHolder.itemView.setClickable(false);
|
||||
viewHolder.mDownloadItemProgressbar.setProgress(0);
|
||||
}
|
||||
} else if (PackagesManager.INSTANCE.isCanUpdate(mGameEntity.getId(), apkEntity.getPackageName())) {
|
||||
viewHolder.mDownloadItemTvStatus.setText(R.string.update);
|
||||
} else {
|
||||
boolean isFilter = false;
|
||||
SettingsEntity settings = Config.getSettings();
|
||||
if (settings != null) {
|
||||
for (String pkgName : settings.getGameDownloadBlackList()) {
|
||||
if (pkgName.equals(apkEntity.getPackageName())) {
|
||||
isFilter = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isFilter) {
|
||||
viewHolder.mDownloadItemTvStatus.setText("已安装");
|
||||
} else {
|
||||
viewHolder.mDownloadItemTvStatus.setText(R.string.launch);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewHolder.mDownloadItemProgressbar.setProgress((int) (downloadEntity.getPercent() * 10));
|
||||
if (downloadEntity.isPluggable()) {
|
||||
if (downloadEntity.getStatus().equals(DownloadStatus.done)) {
|
||||
viewHolder.mDownloadItemTvStatus.setText("安装插件");
|
||||
} else if (downloadEntity.getStatus().equals(DownloadStatus.subscribe)) {
|
||||
viewHolder.mDownloadItemTvStatus.setText("插件化等待中");
|
||||
} else {
|
||||
viewHolder.mDownloadItemTvStatus.setText("插件化下载中");
|
||||
}
|
||||
} else if (downloadEntity.isUpdate()) {
|
||||
if (downloadEntity.getStatus().equals(DownloadStatus.done)) {
|
||||
viewHolder.mDownloadItemTvStatus.setText("安装更新");
|
||||
} else if (downloadEntity.getStatus().equals(DownloadStatus.subscribe)) {
|
||||
viewHolder.mDownloadItemTvStatus.setText("更新等待中");
|
||||
} else {
|
||||
viewHolder.mDownloadItemTvStatus.setText("更新下载中");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 未安装
|
||||
DownloadEntity downloadEntity = mEntryMap.get(apkEntity.getUrl());
|
||||
if (downloadEntity == null
|
||||
|| downloadEntity.getStatus().equals(DownloadStatus.cancel)
|
||||
|| downloadEntity.getStatus().equals(DownloadStatus.hijack)
|
||||
|| downloadEntity.getStatus().equals(DownloadStatus.notfound)) {
|
||||
String path = PlatformUtils.getInstance(mContext)
|
||||
.getPlatformPicUrl(apkEntity.getPlatform());
|
||||
|
||||
viewHolder.mDownloadItemIvPic.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvHint.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvName.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvStatus.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemProgressbar.setVisibility(View.GONE);
|
||||
viewHolder.itemView.setBackgroundColor(0x00ffffff);
|
||||
viewHolder.mDownloadItemTvHint.setText(
|
||||
PlatformUtils.getInstance(mContext).getPlatformName(apkEntity.getPlatform()));
|
||||
|
||||
if (TextUtils.isEmpty(path)) {
|
||||
int id = PlatformUtils.getInstance(mContext).getPlatformPic(
|
||||
apkEntity.getPlatform());
|
||||
ImageUtils.display(viewHolder.mDownloadItemIvPic, id);
|
||||
} else {
|
||||
ImageUtils.displayIcon(viewHolder.mDownloadItemIvPic, path);
|
||||
}
|
||||
} else {
|
||||
viewHolder.mDownloadItemIvPic.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemTvHint.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemProgressbar.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvName.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvStatus.setVisibility(View.VISIBLE);
|
||||
|
||||
int color = Color.parseColor(PlatformUtils.getInstance(
|
||||
mContext).getPlatformColor(apkEntity.getPlatform()));
|
||||
viewHolder.itemView.setBackgroundDrawable(getGradientDrawable(color));
|
||||
|
||||
viewHolder.mDownloadItemTvName.setTextColor(color);
|
||||
viewHolder.mDownloadItemTvName.setText(PlatformUtils
|
||||
.getInstance(mContext).getPlatformName(apkEntity.getPlatform()));
|
||||
|
||||
viewHolder.mDownloadItemProgressbar.setProgressDrawable(getLayerDrawable(color));
|
||||
viewHolder.mDownloadItemProgressbar.setProgress((int) (downloadEntity.getPercent() * 10));
|
||||
|
||||
DownloadStatus status = downloadEntity.getStatus();
|
||||
if (status.equals(DownloadStatus.pause)
|
||||
|| status.equals(DownloadStatus.timeout)
|
||||
|| status.equals(DownloadStatus.neterror)
|
||||
|| status.equals(DownloadStatus.downloading)
|
||||
|| status.equals(DownloadStatus.waiting)
|
||||
|| status.equals(DownloadStatus.overflow)) {
|
||||
viewHolder.mDownloadItemTvStatus.setText(R.string.downloading);
|
||||
} else if (status.equals(DownloadStatus.done)) {
|
||||
viewHolder.mDownloadItemTvStatus.setText(R.string.install);
|
||||
} else if (status.equals(DownloadStatus.subscribe)) {
|
||||
viewHolder.mDownloadItemTvStatus.setText(R.string.waiting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(mAutoDownloadPlatform) && mAutoDownloadPlatform.equals(apkEntity.getPlatform())) {
|
||||
mAutoDownloadPlatform = null;
|
||||
DialogUtils.checkDownload(mContext, apkEntity.getSize(),
|
||||
isSubscribe -> download(apkEntity, viewHolder.mDownloadItemTvStatus, "下载", isSubscribe));
|
||||
}
|
||||
} else {
|
||||
// 合集
|
||||
viewHolder.mDownloadItemIvPic.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvHint.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvName.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemTvStatus.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemProgressbar.setVisibility(View.GONE);
|
||||
viewHolder.itemView.setBackgroundColor(0x00ffffff);
|
||||
viewHolder.mDownloadItemTvHint.setText(apkEntity.getApkCollection().getName());
|
||||
|
||||
ImageUtils.displayIcon(viewHolder.mDownloadItemIvPic, apkEntity.getApkCollection().getIcon());
|
||||
if (mCloseEntity.getPosition() == position && mAdapterPosition == mCloseEntity.getAdapterPosition()) {
|
||||
viewHolder.mDownloadItemOpenCollection.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemColseCollection.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
viewHolder.mDownloadItemOpenCollection.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemColseCollection.setVisibility(View.GONE);
|
||||
}
|
||||
viewHolder.itemView.setOnClickListener(v -> {
|
||||
if (viewHolder.mDownloadItemOpenCollection.getVisibility() == View.VISIBLE) {
|
||||
if (mOnCollectionCallBackListener != null) {
|
||||
mOnCollectionCallBackListener.showCollection(apkEntity.getApkCollection());
|
||||
}
|
||||
mCloseEntity.setPosition(viewHolder.getAdapterPosition());
|
||||
mCloseEntity.setAdapterPosition(mAdapterPosition);
|
||||
for (int[] ints : mCloseEntity.getList()) {
|
||||
mAdapterMap.get(ints[0]).notifyItemChanged(ints[1]);
|
||||
}
|
||||
mCloseEntity.getList().clear();
|
||||
int[] arrCollectionPosition = {mAdapterPosition, viewHolder.getAdapterPosition()};
|
||||
mCloseEntity.getList().add(arrCollectionPosition);
|
||||
viewHolder.mDownloadItemOpenCollection.setVisibility(View.GONE);
|
||||
viewHolder.mDownloadItemColseCollection.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
if (mOnCollectionCallBackListener != null) {
|
||||
mOnCollectionCallBackListener.hideCollection();
|
||||
}
|
||||
mCloseEntity.setPosition(-1);
|
||||
mCloseEntity.setAdapterPosition(-1);
|
||||
viewHolder.mDownloadItemOpenCollection.setVisibility(View.VISIBLE);
|
||||
viewHolder.mDownloadItemColseCollection.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
|
||||
GameCollectionEntity apkCollection = apkEntity.getApkCollection();
|
||||
if (!TextUtils.isEmpty(mAutoDownloadPlatform) && apkCollection != null &&
|
||||
apkCollection.getSaveApkEntity() != null) {
|
||||
for (ApkEntity entity : apkCollection.getSaveApkEntity()) {
|
||||
if (mAutoDownloadPlatform.equals(entity.getPlatform())) {
|
||||
viewHolder.itemView.performClick();
|
||||
mAutoDownloadPlatform = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mCount;
|
||||
}
|
||||
|
||||
// 下载游戏
|
||||
public void download(ApkEntity apkEntity, TextView mDownloadItemTvStatus, String method, boolean isSubscribe) {
|
||||
String msg = FileUtils.isCanDownload(mContext, apkEntity.getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
String platform = PlatformUtils.getInstance(HaloApp.getInstance().getApplication()).getPlatformName(apkEntity.getPlatform());
|
||||
|
||||
Map<String, Object> kv = new HashMap<>();
|
||||
kv.put("游戏", mGameEntity.getName() + ":" + platform);
|
||||
kv.put("用户机型", Build.MODEL);
|
||||
kv.put("设备IMEI", Util_System_Phone_State.getDeviceId(HaloApp.getInstance().getApplication()));
|
||||
kv.put("网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
kv.put("光环助手版本", BuildConfig.VERSION_NAME);
|
||||
kv.put("位置", mEntrance);
|
||||
kv.put("类型", method);
|
||||
kv.put("厂商", Build.MANUFACTURER);
|
||||
kv.put("Android版本", Build.VERSION.RELEASE);
|
||||
DataUtils.onEvent(mContext, "游戏下载", mGameEntity.getName(), kv);
|
||||
|
||||
Map<String, Object> kv2 = new HashMap<>();
|
||||
kv2.put("版本", apkEntity.getPlatform() + "-开始");
|
||||
kv2.put("状态", "下载开始");
|
||||
kv2.put("位置", mEntrance + "-开始");
|
||||
kv2.put("游戏分平台", mGameEntity.getName() + ":" + platform + "-开始");
|
||||
kv2.put("光环助手版本", BuildConfig.VERSION_NAME + "-开始");
|
||||
DataUtils.onEvent(mContext, "游戏下载位置", mGameEntity.getName(), kv2);
|
||||
|
||||
Map<String, Object> kv6 = new HashMap<>();
|
||||
kv6.put("下载", "下载开始");
|
||||
kv6.put("版本", apkEntity.getPlatform());
|
||||
|
||||
ExposureUtils.DownloadType downloadType;
|
||||
|
||||
if ("插件化".equals(method)) {
|
||||
DataUtils.onEvent(mContext, "插件化", mGameEntity.getName(), kv6);
|
||||
DataUtils.onMtaEvent(mContext, "插件化_新", "位置", mEntrance, "游戏", mGameEntity.getName() + "-" + platform, "操作", "下载开始", "网络状态", DeviceUtils
|
||||
.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
|
||||
downloadType = ExposureUtils.DownloadType.PLUGIN_DOWNLOAD;
|
||||
} else {
|
||||
downloadType = ExposureUtils.DownloadType.DOWNLOAD;
|
||||
}
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(mGameEntity, apkEntity
|
||||
.getPlatform(), mTraceEvent, downloadType);
|
||||
DownloadManager.createDownload(mContext, apkEntity, mGameEntity, method, mEntrance, mLocation, isSubscribe, downloadExposureEvent);
|
||||
// DownloadManager.getInstance(mContext).putStatus(apkEntity.getUrl(), "downloading");
|
||||
|
||||
if (isSubscribe) {
|
||||
mDownloadItemTvStatus.setText(R.string.waiting);
|
||||
} else {
|
||||
mDownloadItemTvStatus.setText(R.string.downloading);
|
||||
}
|
||||
} else {
|
||||
Utils.toast(mContext, msg);
|
||||
}
|
||||
}
|
||||
|
||||
//安装游戏
|
||||
private void install(ApkEntity apkEntity, int position) {
|
||||
DownloadEntity downloadEntity = mEntryMap.get(apkEntity.getUrl());
|
||||
|
||||
if (downloadEntity != null) {
|
||||
if (downloadEntity.isPluggable()) {
|
||||
Map<String, Object> kv = new HashMap<>();
|
||||
kv.put("操作", "点击安装完成");
|
||||
DataUtils.onEvent(mContext, "插件化", downloadEntity.getName(), kv);
|
||||
}
|
||||
|
||||
DataUtils.onMtaEvent(mContext,
|
||||
"插件化_新",
|
||||
"位置", mEntrance,
|
||||
"游戏", mGameEntity.getName() + "-" + apkEntity.getPlatform(),
|
||||
"操作", "点击安装",
|
||||
"网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
|
||||
String path = downloadEntity.getPath();
|
||||
if (FileUtils.isEmptyFile(path)) {
|
||||
Utils.toast(mContext, R.string.install_failure_hint);
|
||||
mEntryMap.remove(apkEntity.getUrl());
|
||||
DownloadManager.getInstance(mContext).cancel(apkEntity.getUrl());
|
||||
notifyItemChanged(position);
|
||||
} else {
|
||||
PackageUtils.launchSetup(mContext, downloadEntity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 显示插件化
|
||||
private void showPluginDialog(final ApkEntity apkEntity, final PlatformAdapter adapter, final int location) {
|
||||
DialogUtils.showPluginDialog(mContext, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
Map<String, Object> kv6 = new HashMap<>();
|
||||
kv6.put("操作", "点击插件化安装完成");
|
||||
DataUtils.onEvent(mContext, "插件化", mGameEntity.getName(), kv6);
|
||||
|
||||
DataUtils.onMtaEvent(mContext,
|
||||
"插件化_新",
|
||||
"位置", mEntrance,
|
||||
"游戏", mGameEntity.getName() + "-" + apkEntity.getPlatform(),
|
||||
"操作", "点击插件化",
|
||||
"网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
|
||||
DownloadEntity downloadEntity = mEntryMap.get(apkEntity.getUrl());
|
||||
|
||||
if (downloadEntity == null) return;
|
||||
|
||||
String path = downloadEntity.getPath();
|
||||
if (FileUtils.isEmptyFile(path)) {
|
||||
Utils.toast(mContext, R.string.install_failure_hint);
|
||||
mEntryMap.remove(apkEntity.getUrl());
|
||||
DownloadManager.getInstance(mContext).cancel(apkEntity.getUrl());
|
||||
adapter.notifyItemChanged(location);
|
||||
} else {
|
||||
mContext.startActivity(PackageUtils.getUninstallIntent(mContext, path));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 下载可更新游戏
|
||||
private void update(ApkEntity apkEntity, boolean isSubscribe) {
|
||||
Map<String, Object> kv = new HashMap<>();
|
||||
kv.put("版本", apkEntity.getPlatform());
|
||||
kv.put("状态", "下载开始");
|
||||
DataUtils.onEvent(mContext, "游戏更新", mGameEntity.getName(), kv);
|
||||
|
||||
ExposureUtils.DownloadType downloadType = ExposureUtils.getUpdateType(apkEntity);
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(mGameEntity, apkEntity.getPlatform(), mTraceEvent, downloadType);
|
||||
|
||||
DownloadManager.createDownload(mContext, apkEntity, mGameEntity, "更新", mEntrance, mLocation, isSubscribe, downloadExposureEvent);
|
||||
}
|
||||
|
||||
private GradientDrawable getGradientDrawable(int color) {
|
||||
GradientDrawable gradientDrawable = new GradientDrawable();
|
||||
gradientDrawable.setColor(Color.WHITE);
|
||||
gradientDrawable.setStroke(DisplayUtils.dip2px(mContext, 1), color);
|
||||
return gradientDrawable;
|
||||
}
|
||||
|
||||
private LayerDrawable getLayerDrawable(int color) {
|
||||
Drawable[] layers = new Drawable[2];
|
||||
GradientDrawable drawable = new GradientDrawable();
|
||||
drawable.setColor(0xFFC7C7C7);
|
||||
layers[0] = drawable;
|
||||
ClipDrawable clipDrawable = new ClipDrawable(new ColorDrawable(color), Gravity.LEFT, ClipDrawable.HORIZONTAL);
|
||||
layers[1] = clipDrawable;
|
||||
LayerDrawable layerDrawable = new LayerDrawable(layers);
|
||||
layerDrawable.setId(0, android.R.id.background);
|
||||
layerDrawable.setId(1, android.R.id.progress);
|
||||
return layerDrawable;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user