Merge remote-tracking branch 'origin/dev-5.10.0' into dev
# Conflicts: # app/src/main/java/com/gh/common/view/RichEditor.java # app/src/main/java/com/gh/gamecenter/video/detail/VideoDetailContainerViewModel.kt
This commit is contained in:
@ -12,7 +12,6 @@ import android.util.Log;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.util.DataCollectionUtils;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.gamecenter.SplashScreenActivity;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.download.FileUtils;
|
||||
@ -127,8 +126,6 @@ public class AppUncaughtHandler implements UncaughtExceptionHandler {
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
DataUtils.onError(context, throwable);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,627 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Parcel;
|
||||
import android.os.TransactionTooLargeException;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.LayoutInflaterCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
import com.gh.base.fragment.BaseFragment;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.tracker.IBusiness;
|
||||
import com.gh.common.util.DialogHelper;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.EnvHelper;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.NightModeUtils;
|
||||
import com.gh.common.util.PackageFlavorHelper;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.QuickLoginHelper;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.common.util.StringUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.LoginActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.SplashScreenActivity;
|
||||
import com.gh.gamecenter.eventbus.EBShowDialog;
|
||||
import com.lightgame.BaseAppCompatActivity;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.tencent.tauth.Tencent;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import kotlin.Pair;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
|
||||
/**
|
||||
* 只提供基础的服务(EventBus/Share/GlobalDialog/Permissions)
|
||||
* <p>
|
||||
* 需要工具栏的页面请继承{@link ToolBarActivity}
|
||||
*/
|
||||
|
||||
public abstract class BaseActivity extends BaseAppCompatActivity implements EasyPermissions.PermissionCallbacks, IBusiness {
|
||||
|
||||
// global dialog key
|
||||
public final static String DOWNLOAD_HIJACK = "hijack";
|
||||
public final static String LOGIN_EXCEPTION = "loginException";
|
||||
public final static String PLUGGABLE = "plugin";
|
||||
public final static String SIGNATURE_CONFLICT = "signature_conflict";
|
||||
public final static int ID_ROOT_INDICATOR = 999;
|
||||
public final static int ID_NIGHT_INDICATOR = 998;
|
||||
public final int MAX_BUNDLE_SIZE = 300;
|
||||
|
||||
@NonNull
|
||||
protected String mEntrance;
|
||||
|
||||
private boolean mIsExistLogoutDialog;
|
||||
protected boolean mNightMode;
|
||||
public long startPageTime = 0;
|
||||
|
||||
protected final Handler mBaseHandler = new BaseHandler(this);
|
||||
|
||||
protected static class BaseHandler extends Handler {
|
||||
|
||||
private final WeakReference<BaseActivity> mActivityWeakReference;
|
||||
|
||||
BaseHandler(BaseActivity activity) {
|
||||
mActivityWeakReference = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
BaseActivity activity = mActivityWeakReference.get();
|
||||
if (activity != null) activity.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleMessage(Message msg) {
|
||||
|
||||
}
|
||||
|
||||
//接收QQ或者QQ空间分享回调
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
ExtensionsKt.tryCatchInRelease(() -> {
|
||||
if (requestCode == com.tencent.connect.common.Constants.REQUEST_QQ_SHARE
|
||||
|| requestCode == com.tencent.connect.common.Constants.REQUEST_QZONE_SHARE) {
|
||||
Tencent.onActivityResultData(requestCode, resultCode, data, ShareUtils.getInstance(this).QqShareListener);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
if (PackageFlavorHelper.IS_TEST_FLAVOR && isAutoResetViewBackgroundEnabled()) {
|
||||
LayoutInflaterCompat.setFactory2(getLayoutInflater(), new CustomLayoutInflaterFactory(this));
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (useEventBus()) EventBus.getDefault().register(this);
|
||||
mEntrance = getIntent().getStringExtra(KEY_ENTRANCE);
|
||||
if (TextUtils.isEmpty(mEntrance)) {
|
||||
mEntrance = Constants.ENTRANCE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("ACTIVITY_ENTRANCE -> " + mEntrance);
|
||||
}
|
||||
|
||||
disableAutofill();
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
String xapkUnzipActivity = SPUtils.getString(Constants.SP_XAPK_UNZIP_ACTIVITY);
|
||||
String xapkUrl = SPUtils.getString(Constants.SP_XAPK_URL);
|
||||
Utils.log("页面重建了--" + xapkUnzipActivity + "--" + xapkUrl);
|
||||
if (this.getClass().isAssignableFrom(SplashScreenActivity.class)) {
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "");
|
||||
SPUtils.setString(Constants.SP_XAPK_URL, "");
|
||||
return;
|
||||
}
|
||||
if (this.getClass().getName().equals(xapkUnzipActivity) && !TextUtils.isEmpty(xapkUrl)) {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntityByUrl(xapkUrl);
|
||||
if (downloadEntity != null) {
|
||||
PackageInstaller.install(this, downloadEntity, false);
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "");
|
||||
SPUtils.setString(Constants.SP_XAPK_URL, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
startPageTime = System.currentTimeMillis();
|
||||
|
||||
if (!NightModeUtils.INSTANCE.getSystemMode() && mNightMode != NightModeUtils.INSTANCE.isNightMode(this)) {
|
||||
onNightModeChange();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Override
|
||||
public void setContentView(View view) {
|
||||
if (!(this instanceof SplashScreenActivity) && PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
view = getRootViewWithEnvIndicator(view);
|
||||
}
|
||||
super.setContentView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (useEventBus()) EventBus.getDefault().unregister(this);
|
||||
mBaseHandler.removeCallbacksAndMessages(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
Utils.toast(this, msg);
|
||||
}
|
||||
|
||||
public void toast(int msg) {
|
||||
toast(getString(msg));
|
||||
}
|
||||
|
||||
public void showShare(String url,
|
||||
String icon,
|
||||
String shareTitle,
|
||||
String shareSummary,
|
||||
ShareUtils.ShareEntrance shareEntrance, String id) {
|
||||
ShareUtils.getInstance(this).showShareWindows(this,
|
||||
getWindow().getDecorView(),
|
||||
url,
|
||||
icon,
|
||||
shareTitle,
|
||||
shareSummary,
|
||||
shareEntrance, id);
|
||||
if (shareEntrance == ShareUtils.ShareEntrance.game || shareEntrance == ShareUtils.ShareEntrance.plugin) {
|
||||
MtaHelper.onEvent("内容分享", "内容分享", shareTitle + shareSummary);
|
||||
} else {
|
||||
MtaHelper.onEvent("内容分享", "内容分享", shareTitle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭 editText 自动填充帐号 (我们也用不上),开启的时候有小概率出发 TimeoutException
|
||||
*/
|
||||
private void disableAutofill() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
getWindow().getDecorView().setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
|
||||
}
|
||||
}
|
||||
|
||||
private View getRootViewWithEnvIndicator(View view) {
|
||||
RelativeLayout screenRootView = new RelativeLayout(this);
|
||||
screenRootView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
|
||||
|
||||
LinearLayout ll = new LinearLayout(this);
|
||||
TextView tv = new TextView(this);
|
||||
String envText = "正式环境";
|
||||
tv.setBackground(ContextCompat.getDrawable(this, R.color.theme));
|
||||
if (EnvHelper.isDevEnv()) {
|
||||
envText = "测试环境";
|
||||
tv.setBackground(ContextCompat.getDrawable(this, R.color.theme_red));
|
||||
}
|
||||
tv.setText(envText);
|
||||
tv.setGravity(Gravity.CENTER);
|
||||
tv.setTextColor(Color.WHITE);
|
||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
|
||||
tv.measure(0, 0);
|
||||
tv.setAlpha(0.15F);
|
||||
tv.setId(ID_ROOT_INDICATOR);
|
||||
int height = tv.getMeasuredHeight();
|
||||
int width = tv.getMeasuredWidth();
|
||||
tv.setPadding(DisplayUtils.dip2px(20), 0, DisplayUtils.dip2px(20), 0);
|
||||
ll.setTranslationX(DisplayUtils.dip2px(20));
|
||||
ll.setRotation(45);
|
||||
ll.addView(tv);
|
||||
ll.setPadding(0, (width - height) / 2, 0, (width - height) / 2);
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
tv.setOnLongClickListener(v -> {
|
||||
EntranceUtils.saveShortcut(this.getClass().getName(), getIntent().getExtras());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
screenRootView.addView(view);
|
||||
screenRootView.addView(ll);
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON) {
|
||||
screenRootView.addView(getNightModeIndicatorView());
|
||||
}
|
||||
|
||||
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) ll.getLayoutParams();
|
||||
lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
|
||||
view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
|
||||
return screenRootView;
|
||||
}
|
||||
|
||||
private View getNightModeIndicatorView() {
|
||||
LinearLayout ll = new LinearLayout(this);
|
||||
TextView tv = new TextView(this);
|
||||
String envText = NightModeUtils.INSTANCE.isNightMode(this) ? "夜间模式" : "日间模式";
|
||||
tv.setBackground(ContextCompat.getDrawable(this, R.color.theme));
|
||||
tv.setText(envText);
|
||||
tv.setGravity(Gravity.CENTER);
|
||||
tv.setTextColor(Color.WHITE);
|
||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
|
||||
tv.measure(0, 0);
|
||||
tv.setAlpha(NightModeUtils.INSTANCE.isNightMode(this) ? 0.8F : 0.15F);
|
||||
tv.setId(ID_NIGHT_INDICATOR);
|
||||
int height = tv.getMeasuredHeight();
|
||||
int width = tv.getMeasuredWidth();
|
||||
tv.setPadding(DisplayUtils.dip2px(20), 0, DisplayUtils.dip2px(20), 0);
|
||||
ll.setTranslationX(DisplayUtils.dip2px(-20));
|
||||
ll.setRotation(-45);
|
||||
ll.addView(tv);
|
||||
ll.setPadding(0, (width - height) / 2, 0, (width - height) / 2);
|
||||
|
||||
if (PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
tv.setOnClickListener(v -> {
|
||||
//切换深色模式
|
||||
String mode;
|
||||
String positive;
|
||||
String negative;
|
||||
if (NightModeUtils.INSTANCE.getSystemMode()) {
|
||||
mode = "跟随系统模式";
|
||||
positive = "普通模式";
|
||||
negative = "深色模式";
|
||||
} else if (NightModeUtils.INSTANCE.getNightMode()) {
|
||||
mode = "深色模式";
|
||||
positive = "跟随系统模式";
|
||||
negative = "普通模式";
|
||||
} else {
|
||||
mode = "普通模式";
|
||||
positive = "跟随系统模式";
|
||||
negative = "深色模式";
|
||||
}
|
||||
DialogHelper.showCenterDialog(this, "选择模式", "当前为 " + mode, positive, negative, () -> {
|
||||
if (NightModeUtils.INSTANCE.getSystemMode()) {
|
||||
NightModeUtils.INSTANCE.setNightMode(false);
|
||||
NightModeUtils.INSTANCE.setSystemMode(false);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||
}
|
||||
} else {
|
||||
NightModeUtils.INSTANCE.setSystemMode(true);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
|
||||
}
|
||||
}
|
||||
NightModeUtils.INSTANCE.initNightMode();
|
||||
}, () -> {
|
||||
if (NightModeUtils.INSTANCE.getSystemMode()) {
|
||||
NightModeUtils.INSTANCE.setNightMode(true);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
|
||||
}
|
||||
} else {
|
||||
boolean nightMode = NightModeUtils.INSTANCE.getNightMode();
|
||||
NightModeUtils.INSTANCE.setNightMode(!NightModeUtils.INSTANCE.getNightMode());
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
getDelegate().setLocalNightMode(nightMode ? AppCompatDelegate.MODE_NIGHT_NO : AppCompatDelegate.MODE_NIGHT_YES);
|
||||
}
|
||||
}
|
||||
NightModeUtils.INSTANCE.setSystemMode(false);
|
||||
NightModeUtils.INSTANCE.initNightMode();
|
||||
});
|
||||
});
|
||||
}
|
||||
return ll;
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(final EBShowDialog showDialog) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
|
||||
&& this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
if (DOWNLOAD_HIJACK.equals(showDialog.getType())) {
|
||||
DialogUtils.showQqSessionDialog(this);// 建议用户联系客服
|
||||
} else if (PLUGGABLE.equals(showDialog.getType())) {
|
||||
DialogHelper.showPluginDialog(this, () -> {
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
toast(R.string.install_failure_hint);
|
||||
} else {
|
||||
PackageInstaller.uninstall(BaseActivity.this, showDialog.getPath());
|
||||
}
|
||||
return null;
|
||||
});
|
||||
} else if (SIGNATURE_CONFLICT.equals(showDialog.getType())) {
|
||||
DialogHelper.showSignatureConflictDialog(this, () -> {
|
||||
PackageInstaller.uninstall(BaseActivity.this, showDialog.getPath());
|
||||
return null;
|
||||
});
|
||||
} else if (LOGIN_EXCEPTION.equals(showDialog.getType())) {
|
||||
if (mIsExistLogoutDialog) return;
|
||||
mIsExistLogoutDialog = true;
|
||||
try {
|
||||
JSONObject object = new JSONObject(showDialog.getPath());
|
||||
JSONObject device = object.getJSONObject("device");
|
||||
String model = device.getString("model");
|
||||
DialogHelper.showCenterDialog(this, "你的账号已在另外一台设备登录"
|
||||
, StringUtils.buildString("(", model, ")")
|
||||
, "知道了", "重新登录"
|
||||
, () -> {
|
||||
}
|
||||
, () -> {
|
||||
if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(BaseActivity.this)) {
|
||||
QuickLoginHelper.startLogin(BaseActivity.this, "你的账号已在另外一台设备登录多设备-重新登录");
|
||||
} else {
|
||||
startActivity(LoginActivity.getIntent(BaseActivity.this,
|
||||
"你的账号已在另外一台设备登录多设备-重新登录"));
|
||||
}
|
||||
}
|
||||
);
|
||||
mBaseHandler.postDelayed(() -> mIsExistLogoutDialog = false, 5000);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (isFinishing()) {
|
||||
onFinish();
|
||||
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
|
||||
if (fragment.isAdded() && fragment instanceof BaseFragment) {
|
||||
((BaseFragment) fragment).onParentActivityFinish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 此回调可用于确认当前 activity 已经执行了 finish() 方法并处于 isFinishing 状态
|
||||
*/
|
||||
protected void onFinish() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
@NonNull String[] permissions,
|
||||
@NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionsDenied(int requestCode, List<String> perms) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPermissionsGranted(int requestCode, List<String> perms) {
|
||||
|
||||
}
|
||||
|
||||
protected void setStatusBarColor(int color) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
window.setStatusBarColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供当前 activity 的中文名 (不重载的话为类名)
|
||||
*/
|
||||
public String getActivityNameInChinese() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entrance 上一个页面的链式入口名称
|
||||
* @param path 当前页面名称
|
||||
* @return 完整的链式入口名称
|
||||
*/
|
||||
public static String mergeEntranceAndPath(String entrance, String path) {
|
||||
if (TextUtils.isEmpty(entrance) && TextUtils.isEmpty(path)) return "";
|
||||
if (TextUtils.isEmpty(entrance) && !TextUtils.isEmpty(path)) {
|
||||
return StringUtils.buildString("(", path, ")");
|
||||
}
|
||||
if (!TextUtils.isEmpty(entrance) && TextUtils.isEmpty(path)) {
|
||||
return entrance;
|
||||
}
|
||||
return StringUtils.buildString(entrance, "+(", path, ")");
|
||||
}
|
||||
|
||||
protected boolean useEventBus() {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ActivityThread每次调用onSaveInstanceState时outState大小都会累加,最终会导致{@link TransactionTooLargeException}异常
|
||||
* 解决方案:判断每次获取到的outState大小,当达到300k时手动clear掉
|
||||
*/
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
if (preventRecreateFragmentByFragmentManager()) {
|
||||
outState = discardFragmentFromSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
long bundleSize = getBundleSize(outState);
|
||||
if (bundleSize > MAX_BUNDLE_SIZE * 1024) {
|
||||
outState.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否停用 Activity 重建时 FragmentManager 根据 saveState 自动重建保存的 Fragment 的功能
|
||||
*/
|
||||
protected boolean preventRecreateFragmentByFragmentManager() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private Bundle discardFragmentFromSaveInstanceState(Bundle outState) {
|
||||
if (outState != null) {
|
||||
outState.remove("android:support:fragments");
|
||||
}
|
||||
return outState;
|
||||
}
|
||||
|
||||
private long getBundleSize(Bundle bundle) {
|
||||
long dataSize;
|
||||
Parcel obtain = Parcel.obtain();
|
||||
try {
|
||||
obtain.writeBundle(bundle);
|
||||
dataSize = obtain.dataSize();
|
||||
} finally {
|
||||
obtain.recycle();
|
||||
}
|
||||
return dataSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<String, String> getBusinessId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
onNightModeChange();
|
||||
}
|
||||
|
||||
protected void onNightModeChange() {
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON) {
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(this);
|
||||
TextView tv = findViewById(ID_NIGHT_INDICATOR);
|
||||
if (tv != null) {
|
||||
tv.setText(NightModeUtils.INSTANCE.isNightMode(this) ? "夜间模式" : "日间模式");
|
||||
tv.setAlpha(NightModeUtils.INSTANCE.isNightMode(this) ? 0.8F : 0.15F);
|
||||
}
|
||||
if (isAutoResetViewBackgroundEnabled()) {
|
||||
updateStaticViewBackground(getWindow().getDecorView());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isAutoResetViewBackgroundEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动重置部分 view 的背景颜色/资源
|
||||
*
|
||||
* @param view 父 view
|
||||
*/
|
||||
private void updateStaticViewBackground(View view) {
|
||||
if (view instanceof ViewGroup) {
|
||||
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
|
||||
View child = ((ViewGroup) view).getChildAt(i);
|
||||
updateStaticViewBackground(child);
|
||||
}
|
||||
}
|
||||
|
||||
String backgroundString = (String) view.getTag(CustomLayoutInflaterFactory.TAG_BACKGROUND_ID);
|
||||
String textColorString = (String) view.getTag(CustomLayoutInflaterFactory.TAG_TEXT_COLOR_ID);
|
||||
if (backgroundString != null) {
|
||||
if (backgroundString.startsWith("#")) return;
|
||||
int backgroundId = Integer.parseInt(
|
||||
backgroundString
|
||||
.replace("@", "")
|
||||
.replace("?", "")
|
||||
);
|
||||
|
||||
if (backgroundId != 0) {
|
||||
try {
|
||||
TypedValue value = new TypedValue();
|
||||
getResources().getValue(backgroundId, value, true);
|
||||
|
||||
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
|
||||
view.setBackgroundColor(ExtensionsKt.toColor(backgroundId, this));
|
||||
} else {
|
||||
view.setBackground(ExtensionsKt.toDrawable(backgroundId, this));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (textColorString != null && view instanceof TextView) {
|
||||
if (textColorString.startsWith("#")) return;
|
||||
int textColorId = Integer.parseInt(
|
||||
textColorString
|
||||
.replace("@", "")
|
||||
.replace("?", "")
|
||||
);
|
||||
|
||||
if (textColorId != 0) {
|
||||
try {
|
||||
final ColorStateList colorStateList = ContextCompat.getColorStateList(this, textColorId);
|
||||
((TextView) view).setTextColor(colorStateList);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,21 +4,22 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.base.adapter.FragmentAdapter;
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout;
|
||||
import com.gh.common.view.TabIndicatorView;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.common.base.ToolBarActivity;
|
||||
import com.gh.gamecenter.common.base.adapter.FragmentAdapter;
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment_TabLayout;
|
||||
import com.gh.gamecenter.common.view.TabIndicatorView;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.lightgame.view.NoScrollableViewPager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
/**
|
||||
* Created by khy on 15/03/18.
|
||||
*/
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* 目前仅提供butterknife bind方法
|
||||
*
|
||||
* @author CsHeng
|
||||
* @Date 16/06/2017
|
||||
* @Time 9:55 AM
|
||||
*/
|
||||
|
||||
public abstract class BaseRecyclerViewHolder<T> extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
|
||||
private T mData;
|
||||
private OnListClickListener mListClickListener;
|
||||
|
||||
public BaseRecyclerViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
/**
|
||||
* 具体的设置监听在childViewHolder 设置
|
||||
*
|
||||
* @param itemView
|
||||
* @param data 一般情况下只传列表数据
|
||||
* @param listClickListener 列表事件接口
|
||||
*/
|
||||
public BaseRecyclerViewHolder(View itemView, T data, OnListClickListener listClickListener) {
|
||||
this(itemView);
|
||||
this.mData = data;
|
||||
this.mListClickListener = listClickListener;
|
||||
}
|
||||
|
||||
public BaseRecyclerViewHolder(View itemView, OnListClickListener listClickListener) {
|
||||
this(itemView);
|
||||
this.mListClickListener = listClickListener;
|
||||
}
|
||||
|
||||
public void setClickData(T clickData) {
|
||||
this.mData = clickData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
try {
|
||||
mListClickListener.onListClick(view, getAdapterPosition(), mData);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -14,12 +14,16 @@ import android.widget.CheckBox
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.lifecycle.Observer
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.runOnIoThread
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.common.view.RichEditor
|
||||
import com.gh.gamecenter.CropImageActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.ToolBarActivity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.qa.editor.*
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
@ -205,6 +209,7 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> : ToolBarAct
|
||||
mViewModel.setUploadVideoListener(this)
|
||||
mKeyboardHeightProvider = KeyboardHeightProvider(this)
|
||||
mRichEditor.post { mKeyboardHeightProvider?.start() }
|
||||
mRichEditor.enableForceDark(NightModeUtils.isNightMode(this))
|
||||
// 防止个别手机在Js里无法获取粘贴内容
|
||||
mRichEditor.addJavascriptInterface(OnPasteListener(), "onPasteListener")
|
||||
mRichEditor.addJavascriptInterface(OnCursorChangeListener(), "OnCursorChangeListener")
|
||||
@ -735,6 +740,14 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> : ToolBarAct
|
||||
abstract fun provideViewModel(): VM
|
||||
abstract fun getVideoGuideKey(): String
|
||||
|
||||
override fun isAutoResetViewBackgroundEnabled(): Boolean =true
|
||||
|
||||
override fun onNightModeChange() {
|
||||
super.onNightModeChange()
|
||||
updateStatusBarColor(R.color.black, R.color.white)
|
||||
mRichEditor.enableForceDark(NightModeUtils.isNightMode(this))
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ELEMENT_NAME_BOLD = " b "
|
||||
const val ELEMENT_NAME_ITALIC = " i "
|
||||
|
||||
@ -9,15 +9,17 @@ import android.text.TextUtils
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.base.fragment.WaitingDialogFragment
|
||||
import com.gh.common.runOnUiThread
|
||||
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.entity.ErrorEntity
|
||||
import com.gh.gamecenter.entity.LocalVideoEntity
|
||||
import com.gh.gamecenter.entity.QuoteCountEntity
|
||||
import com.gh.gamecenter.qa.BbsType
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import com.gh.gamecenter.video.upload.OnUploadListener
|
||||
|
||||
@ -1,93 +0,0 @@
|
||||
package com.gh.base
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
/**
|
||||
* 用 SP 实现的简单列表持久化结构
|
||||
*/
|
||||
abstract class BaseSimpleDao {
|
||||
|
||||
// 使用独有的 SP 文件
|
||||
private val mSp: SharedPreferences by lazy {
|
||||
HaloApp.getInstance().application.getSharedPreferences("SimpleDao", Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
fun add(key: String) {
|
||||
val originString = SPUtils.getString(mSp, getSPKey())
|
||||
|
||||
if (originString.isEmpty()) {
|
||||
// Insert keyword only for the very first time.
|
||||
SPUtils.setString(mSp, getSPKey(), key)
|
||||
} else {
|
||||
getAll()?.let {
|
||||
if (getMaxSize() != -1 && it.size > getMaxSize()) {
|
||||
it.removeAt(it.size - 1)
|
||||
}
|
||||
|
||||
// Move keyword to the very front if it exists.
|
||||
if (it.contains(key)) {
|
||||
it.remove(key)
|
||||
}
|
||||
it.add(0, key)
|
||||
val builder = StringBuilder()
|
||||
for ((index, k) in it.withIndex()) {
|
||||
builder.append(k)
|
||||
if (index != it.size - 1) {
|
||||
builder.append(DIVIDER_KEY)
|
||||
}
|
||||
}
|
||||
SPUtils.setString(mSp, getSPKey(), builder.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun delete(key: String) {
|
||||
val originString = SPUtils.getString(mSp, getSPKey())
|
||||
|
||||
if (originString.isEmpty()) {
|
||||
// do nothing
|
||||
} else {
|
||||
getAll()?.let {
|
||||
if (it.contains(key)) {
|
||||
it.remove(key)
|
||||
}
|
||||
val builder = StringBuilder()
|
||||
for ((index, k) in it.withIndex()) {
|
||||
builder.append(k)
|
||||
if (index != it.size - 1) {
|
||||
builder.append(DIVIDER_KEY)
|
||||
}
|
||||
}
|
||||
SPUtils.setString(mSp, getSPKey(), builder.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getAll(): ArrayList<String>? {
|
||||
val list = SPUtils.getString(mSp, getSPKey()).split(DIVIDER_KEY)
|
||||
|
||||
return if (list.size == 1 && list[0].isEmpty()) null else ArrayList(list)
|
||||
}
|
||||
|
||||
fun getRawString(): String = SPUtils.getString(mSp, getSPKey())
|
||||
|
||||
fun contains(key: String): Boolean {
|
||||
return getAll()?.contains(key) == true
|
||||
}
|
||||
|
||||
fun deleteAll() {
|
||||
SPUtils.setString(mSp, getSPKey(), "")
|
||||
}
|
||||
|
||||
open fun getMaxSize(): Int = -1
|
||||
|
||||
abstract fun getSPKey(): String
|
||||
|
||||
companion object {
|
||||
private const val DIVIDER_KEY = "<-||->"
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package com.gh.base
|
||||
|
||||
import android.app.Activity
|
||||
|
||||
object CurrentActivityHolder {
|
||||
|
||||
@JvmStatic
|
||||
val activitySet = HashSet<Activity>()
|
||||
|
||||
@JvmStatic
|
||||
fun getCurrentActivity(): Activity? {
|
||||
return if (activitySet.isEmpty()) {
|
||||
null
|
||||
} else {
|
||||
activitySet.iterator().next()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
package com.gh.base
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
class CustomLayoutInflaterFactory(
|
||||
private val mAppCompatActivity: AppCompatActivity
|
||||
) : LayoutInflater.Factory2 {
|
||||
|
||||
override fun onCreateView(
|
||||
parent: View?,
|
||||
name: String,
|
||||
context: Context,
|
||||
attrs: AttributeSet
|
||||
): View? {
|
||||
|
||||
val view: View?
|
||||
|
||||
try {
|
||||
view = mAppCompatActivity.delegate.createView(parent, name, context, attrs)
|
||||
?: mAppCompatActivity.onCreateView(parent, name, context, attrs)
|
||||
?: mAppCompatActivity.layoutInflater.createView(name, null, attrs)
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
|
||||
val n = attrs.attributeCount
|
||||
for (i in 0 until n) {
|
||||
val attributeName = attrs.getAttributeName(i).toString()
|
||||
if (attributeName.contains("background")) {
|
||||
view?.setTag(TAG_BACKGROUND_ID, attrs.getAttributeValue(i))
|
||||
} else if (attributeName.contains("textColor")) {
|
||||
view?.setTag(TAG_TEXT_COLOR_ID, attrs.getAttributeValue(i))
|
||||
}
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
|
||||
return mAppCompatActivity.onCreateView(name, context, attrs)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG_BACKGROUND_ID = R.string.background_id
|
||||
const val TAG_TEXT_COLOR_ID = R.string.text_color_id
|
||||
}
|
||||
|
||||
}
|
||||
115
app/src/main/java/com/gh/base/DownloadToolbarActivity.kt
Normal file
115
app/src/main/java/com/gh/base/DownloadToolbarActivity.kt
Normal file
@ -0,0 +1,115 @@
|
||||
package com.gh.base
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.DownloadManagerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.ToolBarActivity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils.getBoolean
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
// TODO:移动到module_download模块中
|
||||
abstract class DownloadToolbarActivity : ToolBarActivity() {
|
||||
|
||||
private var mDownloadCountHint: TextView? = null
|
||||
private var mPackageViewModel: PackageViewModel? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (!getBoolean(Constants.SP_TEENAGER_MODE) && showDownloadMenu()) {
|
||||
mPackageViewModel = ViewModelProviders.of(this, PackageViewModel.Factory())[PackageViewModel::class.java]
|
||||
mPackageViewModel = viewModelProvider(PackageViewModel.Factory())
|
||||
mPackageViewModel?.filterSameUpdateLiveData?.observe(this) { updateList: List<GameUpdateEntity> ->
|
||||
updateDownloadCountHint(updateList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setToolbarMenu(res: Int) {
|
||||
// 青少年模式下要隐藏下载按钮
|
||||
if (getBoolean(Constants.SP_TEENAGER_MODE) && res == R.menu.menu_download) return
|
||||
super.setToolbarMenu(res)
|
||||
}
|
||||
|
||||
override fun inflateMenu(res: Int) {
|
||||
super.inflateMenu(res)
|
||||
if (showDownloadMenu()) {
|
||||
createDownloadMenu(res)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createDownloadMenu(res: Int) {
|
||||
if (res != R.menu.menu_download) {
|
||||
menuInflater.inflate(R.menu.menu_download, mActionMenuView.menu)
|
||||
}
|
||||
if (mPackageViewModel != null) {
|
||||
updateDownloadCountHint(mPackageViewModel?.filterSameUpdateLiveData?.value)
|
||||
}
|
||||
val downloadMenuView = mActionMenuView.menu.findItem(R.id.menu_download).actionView
|
||||
mDownloadCountHint = downloadMenuView.findViewById(R.id.menu_download_count_hint)
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||
if (item!!.itemId == R.id.menu_download) {
|
||||
// MtaHelper.onEvent("下载管理", "下载管理入口", getActivityNameInChinese());
|
||||
val intent = DownloadManagerActivity.getDownloadMangerIntent(this, mEntrance)
|
||||
startActivity(intent)
|
||||
return true
|
||||
}
|
||||
return super.onMenuItemClick(item)
|
||||
}
|
||||
|
||||
private fun updateDownloadCountHint(updateList: List<GameUpdateEntity>?) {
|
||||
if (mDownloadCountHint == null || updateList.isNullOrEmpty()) return
|
||||
val count = DownloadManager.getInstance().getDownloadOrUpdateCount(updateList)
|
||||
if (count != null) {
|
||||
mDownloadCountHint!!.visibility = View.VISIBLE
|
||||
mDownloadCountHint!!.text = count
|
||||
val params = mDownloadCountHint!!.layoutParams
|
||||
if (TextUtils.isEmpty(count)) {
|
||||
params.width = DisplayUtils.dip2px(6f)
|
||||
params.height = DisplayUtils.dip2px(6f)
|
||||
} else {
|
||||
params.width = DisplayUtils.dip2px(12f)
|
||||
params.height = DisplayUtils.dip2px(12f)
|
||||
}
|
||||
mDownloadCountHint!!.layoutParams = params
|
||||
} else {
|
||||
mDownloadCountHint!!.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun showDownloadMenu(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(status: EBDownloadStatus?) {
|
||||
if (!getBoolean(Constants.SP_TEENAGER_MODE) && showDownloadMenu() && mPackageViewModel != null) {
|
||||
updateDownloadCountHint(mPackageViewModel?.filterSameUpdateLiveData?.value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNightModeChange() {
|
||||
super.onNightModeChange()
|
||||
if (showDownloadMenu() && getMenuItem(R.id.menu_download) != null) {
|
||||
(getMenuItem(R.id.menu_download).actionView.findViewById(R.id.menu_download_iv) as ImageView).setImageDrawable(
|
||||
ContextCompat.getDrawable(this, R.drawable.toolbar_download)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package com.gh.base
|
||||
|
||||
import java.util.concurrent.ThreadFactory
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
class GHThreadFactory(threadNamePrefix: String) : ThreadFactory {
|
||||
|
||||
private val THREAD_NAME_STEM = "${threadNamePrefix}_%d"
|
||||
private val mThreadId = AtomicInteger(0)
|
||||
|
||||
override fun newThread(r: Runnable?): Thread {
|
||||
val t = Thread(r)
|
||||
t.name = String.format(THREAD_NAME_STEM, mThreadId.getAndIncrement())
|
||||
return t
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,229 +0,0 @@
|
||||
//package com.gh.base
|
||||
//
|
||||
//import android.app.Notification
|
||||
//import android.app.NotificationChannel
|
||||
//import android.app.NotificationManager
|
||||
//import android.app.PendingIntent
|
||||
//import android.content.Context
|
||||
//import android.content.Intent
|
||||
//import android.os.Build
|
||||
//import android.os.Bundle
|
||||
//import android.preference.PreferenceManager
|
||||
//import android.text.TextUtils
|
||||
//import android.view.View
|
||||
//import androidx.core.app.NotificationCompat
|
||||
//import androidx.core.text.htmlEncode
|
||||
//import com.gh.common.notifier.Notifier
|
||||
//import com.gh.common.util.*
|
||||
//import com.gh.gamecenter.R
|
||||
//import com.gh.gamecenter.entity.PushEntity
|
||||
//import com.gh.gamecenter.entity.PushMessageEntity
|
||||
//import com.gh.gamecenter.entity.PushMessageUnreadEntity
|
||||
//import com.gh.gamecenter.entity.PushNotificationEntity
|
||||
//import com.gh.gamecenter.manager.UserManager
|
||||
//import com.gh.gamecenter.message.MessageUnreadRepository
|
||||
//import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
|
||||
//import com.gh.gamecenter.receiver.UmengMessageReceiver
|
||||
//import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_CLICK
|
||||
//import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_REMOVE
|
||||
//import com.gh.gamecenter.retrofit.Response
|
||||
//import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
//import com.google.gson.Gson
|
||||
//import com.umeng.message.UmengMessageService
|
||||
//import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
//import io.reactivex.schedulers.Schedulers
|
||||
//import okhttp3.MediaType
|
||||
//import okhttp3.RequestBody
|
||||
//import okhttp3.ResponseBody
|
||||
//import org.android.agoo.common.AgooConstants
|
||||
//import org.json.JSONObject
|
||||
//import retrofit2.HttpException
|
||||
//import java.util.*
|
||||
//
|
||||
//class GHUmengNotificationService : UmengMessageService() {
|
||||
//
|
||||
// companion object {
|
||||
// const val ACTION_UMENG = "com.gh.gamecenter.UMENG"
|
||||
// const val MESSAGE_FROM_SYSTEM = "message_from_system"
|
||||
// const val HALO_MESSAGE_DIALOG = "HALO_MESSAGE_DIALOG"
|
||||
// const val HALO_MESSAGE_CENTER = "HALO_MESSAGE_CENTER"
|
||||
// const val ANSWER = "answer"
|
||||
// const val FOLLOW_QUESTION = "follow_question"
|
||||
// const val NOTIFICATION_ID = 2015
|
||||
// const val DISPLAY_TYPE_NOTIFICATION = "notification"
|
||||
// const val DISPLAY_TYPE_CUSTOM = "custom"
|
||||
// const val MESSAGE_ID = "message_id"
|
||||
// const val NOTIFICATION_MESSAGE_ID = "notification_message_id" // 通知中心消息 ID
|
||||
// const val PUSH_ID = "push_id"
|
||||
// }
|
||||
//
|
||||
// val notificationTags = arrayOf("GH_UMENG_TAG_1", "GH_UMENG_TAG_2", "GH_UMENG_TAG_3")
|
||||
// val gson = Gson()
|
||||
//
|
||||
// override fun onMessage(context: Context, intent: Intent) {
|
||||
// val message = intent.getStringExtra(AgooConstants.MESSAGE_BODY)
|
||||
// val isMessageFromSystem = intent.getBooleanExtra(MESSAGE_FROM_SYSTEM, false)
|
||||
//
|
||||
// try {
|
||||
// val pushData = message.toObject<PushEntity>()
|
||||
// pushData?.let { handlePushData(context, it, message, isMessageFromSystem) }
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun handlePushData(context: Context, pushData: PushEntity, message: String, isMessageFromSystem: Boolean) {
|
||||
// val notificationManager = context.applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
//
|
||||
// if (pushData.displayType == DISPLAY_TYPE_NOTIFICATION) {
|
||||
// // 其它类型的透传信息
|
||||
// // 显示到通知栏
|
||||
// val msg = message.toObject<PushNotificationEntity>()
|
||||
// val data = msg?.extra?.data
|
||||
//
|
||||
// // 系统推送(非自定义信息),直接处理跳转
|
||||
// if (isMessageFromSystem) {
|
||||
// val intent = Intent()
|
||||
// intent.setClass(context, UmengMessageReceiver::class.java)
|
||||
// intent.putExtra(EntranceUtils.KEY_DATA, data?.link)
|
||||
// intent.putExtra(EntranceUtils.KEY_TYPE, UmengMessageReceiver.DIRECT_ONLY)
|
||||
// intent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
// intent.putExtra(NOTIFICATION_MESSAGE_ID, data?.messageId)
|
||||
// context.sendBroadcast(intent)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 用户未登录的情况下不生成消息中心通知,避免用户掉登录了还收到跳转至消息中心的通知
|
||||
// if (data != null
|
||||
// && data.link?.link == "system"
|
||||
// && !UserManager.getInstance().isLoggedIn) {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// val clickIntent = Intent()
|
||||
// val removeIntent = Intent()
|
||||
//
|
||||
// clickIntent.setClass(context, UmengMessageReceiver::class.java)
|
||||
// clickIntent.putExtra(EntranceUtils.KEY_DATA, data?.link)
|
||||
// clickIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
// clickIntent.putExtra(MESSAGE_ID, msg?.msgId)
|
||||
// clickIntent.putExtra(PUSH_ID, data?.pushId)
|
||||
// clickIntent.putExtra(NOTIFICATION_MESSAGE_ID, data?.messageId)
|
||||
// clickIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_CLICK)
|
||||
//
|
||||
// removeIntent.setClass(context, UmengMessageReceiver::class.java)
|
||||
// removeIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_REMOVE)
|
||||
// removeIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
//
|
||||
// val clickPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(),
|
||||
// clickIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
//
|
||||
// val deletePendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt() + 1,
|
||||
// removeIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
//
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// val channel = NotificationChannel("Halo_Push", "Halo_Push", NotificationManager.IMPORTANCE_DEFAULT)
|
||||
// notificationManager.createNotificationChannel(channel)
|
||||
// }
|
||||
//
|
||||
// val notification = NotificationCompat.Builder(context, "Halo_Push")
|
||||
// .setSmallIcon(R.drawable.ic_notification)
|
||||
// .setTicker(pushData.body?.ticker)
|
||||
// .setContentTitle(pushData.body?.title)
|
||||
// .setContentText(pushData.body?.text?.fromHtml())
|
||||
// .setContentIntent(clickPendingIntent)
|
||||
// .setDeleteIntent(deletePendingIntent)
|
||||
// .build()
|
||||
// notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL
|
||||
//
|
||||
// notificationManager.notify(getNotificationTag(context), NOTIFICATION_ID, notification)
|
||||
// } else {
|
||||
// if (UserManager.getInstance().isLoggedIn &&
|
||||
// HALO_MESSAGE_DIALOG == pushData.body?.custom &&
|
||||
// MessageUnreadRepository.unreadLiveData.value != null) {
|
||||
// // 回答了问题或者关注了问题的消息
|
||||
// val msg = gson.fromJson(message, PushMessageEntity::class.java)
|
||||
// val data = msg?.extra?.data
|
||||
//
|
||||
// val type = if (ANSWER == data?.type) {
|
||||
// "回答了你的问题"
|
||||
// } else {
|
||||
// "回答了你关注的问题"
|
||||
// }
|
||||
//
|
||||
// val userName = StringUtils.shrinkStringWithDot(data?.userEntity?.name, 8)
|
||||
// val displayText = userName + type
|
||||
//
|
||||
// if (Notifier.isActivityValid(CurrentActivityHolder.getCurrentActivity()) &&
|
||||
// Notifier.shouldShowNotifier(data?.answer?.id + displayText)) {
|
||||
// Notifier.create(CurrentActivityHolder.getCurrentActivity())
|
||||
// .setText(displayText)
|
||||
// .setDuration(5000)
|
||||
// .setIcon(data?.userEntity?.icon)
|
||||
// .setOnClickListener(View.OnClickListener {
|
||||
// val bundle = Bundle()
|
||||
// bundle.putString(EntranceUtils.KEY_ANSWER_ID, data?.answer?.id)
|
||||
// bundle.putString(EntranceUtils.KEY_ENTRANCE, EntranceUtils.ENTRANCE_UMENG)
|
||||
// bundle.putString(EntranceUtils.KEY_TO, AnswerDetailActivity::class.java.name)
|
||||
// EntranceUtils.jumpActivity(context, bundle)
|
||||
//
|
||||
// MtaHelper.onEvent("消息弹窗", type, "Does not contains any parameter.")
|
||||
//
|
||||
// // 标记已读
|
||||
// val jsonObject = JSONObject()
|
||||
// jsonObject.put("type", type)
|
||||
// val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
//
|
||||
// RetrofitManager.getInstance().api.postMessageRead(UserManager.getInstance().userId, data?.id, body)
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .observeOn(AndroidSchedulers.mainThread())
|
||||
// .subscribe(object : Response<ResponseBody>() {
|
||||
// override fun onResponse(response: ResponseBody?) {
|
||||
// super.onResponse(response)
|
||||
// MessageUnreadRepository.loadMessageUnreadData()
|
||||
// }
|
||||
//
|
||||
// override fun onFailure(e: HttpException?) {
|
||||
// e?.printStackTrace()
|
||||
// }
|
||||
// })
|
||||
// Notifier.hide()
|
||||
// })
|
||||
// .show(false)
|
||||
// Notifier.tagNotifierAsShowed(data?.answer?.id + displayText)
|
||||
// }
|
||||
// } else if (HALO_MESSAGE_CENTER == pushData.body?.custom) {
|
||||
// // 消息中心逻辑
|
||||
// val msg = gson.fromJson(message, PushMessageUnreadEntity::class.java)
|
||||
// val data = msg?.extra?.data
|
||||
// data?.let { MessageUnreadRepository.loadMessageUnreadData() }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 规则:最多三条消息,以旧换新
|
||||
// *
|
||||
// * @return NotificationTag
|
||||
// */
|
||||
// private fun getNotificationTag(context: Context): String {
|
||||
// val sp = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
// val edit = sp.edit()
|
||||
//
|
||||
// val timeTagMap = HashMap<Long, String>()
|
||||
// for (tag in notificationTags) {
|
||||
// val time = sp.getLong(tag, 0)
|
||||
// if (time == 0L) {
|
||||
// edit.putLong(tag, System.currentTimeMillis()).apply()
|
||||
// return tag
|
||||
// } else {
|
||||
// timeTagMap[time] = tag
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val minTime = Collections.min(timeTagMap.keys)
|
||||
// val tag = timeTagMap[minTime]
|
||||
// edit.putLong(tag, System.currentTimeMillis()).apply()
|
||||
// return if (TextUtils.isEmpty(tag)) notificationTags[0] else tag!!
|
||||
// }
|
||||
//}
|
||||
@ -3,12 +3,11 @@ package com.gh.base
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.os.Bundle
|
||||
import com.gh.common.notifier.Notifier
|
||||
import com.gh.common.util.DataUtils
|
||||
import com.gh.common.util.FloatingBackViewManager
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.SplashScreenActivity
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.energy.EnergyCenterActivity
|
||||
import com.gh.gamecenter.forum.detail.ForumDetailActivity
|
||||
import com.gh.gamecenter.forum.list.ForumListActivity
|
||||
@ -47,7 +46,6 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
}
|
||||
|
||||
if (HaloApp.isUserAcceptPrivacyPolicy(activity)) {
|
||||
DataUtils.onResume(activity)
|
||||
// FIXME 这里应该只是部分Activity需要
|
||||
try {
|
||||
// 初始化gameMap
|
||||
@ -73,17 +71,13 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
CurrentActivityHolder.activitySet.remove(activity)
|
||||
FloatingBackViewManager.dismissBackView()
|
||||
|
||||
if (HaloApp.isUserAcceptPrivacyPolicy(activity)) {
|
||||
DataUtils.onPause(activity)
|
||||
}
|
||||
|
||||
if (activity.isFinishing) {
|
||||
AppManager.getInstance().finishActivity(activity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityStopped(activity: Activity) {
|
||||
Notifier.hide()
|
||||
|
||||
}
|
||||
|
||||
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Created by khy on 25/04/18.
|
||||
*/
|
||||
|
||||
public abstract class OnDoubleTapListener implements View.OnTouchListener {
|
||||
private GestureDetector mGestureDetector;
|
||||
|
||||
protected OnDoubleTapListener(Context context) {
|
||||
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
|
||||
@Override
|
||||
public boolean onDoubleTap(MotionEvent e) {
|
||||
OnDoubleTapListener.this.onDoubleTap();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
mGestureDetector.onTouchEvent(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract void onDoubleTap();
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Created by khy on 26/09/17.
|
||||
*/
|
||||
|
||||
public interface OnListClickListener {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param view
|
||||
* @param position list position
|
||||
* @param data list data (直接强转 如果列表传入不同数据类型 请做好判断)
|
||||
* @param <T>
|
||||
*/
|
||||
<T> void onListClick(View view, int position, T data);
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2016/9/8.
|
||||
*
|
||||
* 逐步移除
|
||||
*/
|
||||
|
||||
@Deprecated
|
||||
public interface OnRequestCallBackListener<T> {
|
||||
|
||||
void loadDone();
|
||||
|
||||
void loadDone(T obj);
|
||||
|
||||
void loadError();
|
||||
|
||||
void loadEmpty();
|
||||
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
public interface OnViewClickListener<T> {
|
||||
void onClick(View v, T data);
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 05/05/2017
|
||||
* @Time 4:52 PM
|
||||
*/
|
||||
|
||||
public interface SearchBarHint {
|
||||
void setHint(ArrayList<String> hintList);
|
||||
}
|
||||
@ -1,336 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.widget.ActionMenuView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.common.view.GameIconView;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.normal.ToolbarController;
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel;
|
||||
import com.lightgame.OnTitleClickListener;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 需要用到工具栏的页面使用
|
||||
* <p>
|
||||
* 特殊页面请参考{@link BaseActivity}
|
||||
*/
|
||||
|
||||
public abstract class ToolBarActivity extends BaseActivity implements ToolbarController, ActionMenuView.OnMenuItemClickListener {
|
||||
|
||||
@Nullable
|
||||
private PackageViewModel mPackageViewModel;
|
||||
|
||||
protected View mToolbarContainer;
|
||||
|
||||
protected Toolbar mToolbar;
|
||||
|
||||
protected TextView mTitleTv;
|
||||
|
||||
protected LinearLayout mTitleContainer;
|
||||
|
||||
protected LinearLayout mIconTitleContainer;
|
||||
|
||||
protected FrameLayout mBackContainer;
|
||||
|
||||
protected ActionMenuView mActionMenuView;
|
||||
|
||||
protected View mBackBtn;
|
||||
|
||||
protected GameIconView mGameIconView;
|
||||
|
||||
protected SimpleDraweeView mUserAvatarIv;
|
||||
|
||||
protected TextView mIconTitle;
|
||||
|
||||
@Nullable
|
||||
private TextView mDownloadCountHint;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setStatusBarDarkMode(true, this);
|
||||
initToolbar();
|
||||
|
||||
if (!SPUtils.getBoolean(Constants.SP_TEENAGER_MODE) && showDownloadMenu()) {
|
||||
mPackageViewModel = ViewModelProviders.of(this, new PackageViewModel.Factory()).get(PackageViewModel.class);
|
||||
mPackageViewModel.getFilterSameUpdateLiveData().observe(this, this::updateDownloadCountHint);
|
||||
}
|
||||
}
|
||||
|
||||
// 小米沉浸式黑色字体
|
||||
@SuppressLint("PrivateApi")
|
||||
public void setStatusBarDarkMode(boolean darkmode, Activity activity) {
|
||||
Class<? extends Window> clazz = activity.getWindow().getClass();
|
||||
try {
|
||||
Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
int darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void initToolbar() {
|
||||
mToolbarContainer = findViewById(R.id.normal_toolbar_container);
|
||||
mToolbar = findViewById(R.id.normal_toolbar);
|
||||
mTitleTv = findViewById(R.id.normal_title);
|
||||
mActionMenuView = findViewById(R.id.actionMenuView);
|
||||
mTitleContainer = findViewById(R.id.titleContainer);
|
||||
mIconTitleContainer = findViewById(R.id.iconTitleContainer);
|
||||
mBackContainer = findViewById(R.id.backContainer);
|
||||
mBackBtn = findViewById(R.id.backBtn);
|
||||
mGameIconView = findViewById(R.id.gameIv);
|
||||
mUserAvatarIv = findViewById(R.id.userAvatar);
|
||||
mIconTitle = findViewById(R.id.iconTitle);
|
||||
if (mToolbar != null) {
|
||||
// setSupportActionBar(mToolbar); // 替换actionBar后 toolBar无法控制
|
||||
// mToolbar.setNavigationIcon(provideNavigationIcon());
|
||||
// mToolbar.setNavigationOnClickListener(provideNavigationItemClickListener());
|
||||
if (mBackBtn != null) mBackBtn.setOnClickListener(provideNavigationItemClickListener());
|
||||
if (mBackContainer != null) mBackContainer.setOnClickListener(provideNavigationItemClickListener());
|
||||
if (mTitleTv != null) {
|
||||
mTitleTv.setOnClickListener(view -> {
|
||||
final List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
|
||||
for (Fragment fragment : fragmentList) {
|
||||
if (fragment instanceof OnTitleClickListener) {
|
||||
((OnTitleClickListener) fragment).onTitleClick();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public int provideNavigationIcon() {
|
||||
return R.drawable.ic_bar_back; // default navigation icon
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNavigationTitle(String title) {
|
||||
if (mTitleTv != null) mTitleTv.setText(title);
|
||||
if (mIconTitle != null) mIconTitle.setText(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNavigationTitle(@StringRes int res) {
|
||||
setNavigationTitle(getString(res));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写此方法以将标题靠左显示
|
||||
*/
|
||||
public boolean showToolbarAtLeft() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setToolbarMenu(int res) {
|
||||
if (mActionMenuView == null) return;
|
||||
// 青少年模式下要隐藏下载按钮
|
||||
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE) && res == R.menu.menu_download) return;
|
||||
// mToolbar.inflateMenu(res);
|
||||
// mToolbar.setOnMenuItemClickListener(this);
|
||||
|
||||
getMenuInflater().inflate(res, mActionMenuView.getMenu());
|
||||
mActionMenuView.setOnMenuItemClickListener(this);
|
||||
|
||||
if (showDownloadMenu()) {
|
||||
createDownloadMenu(res);
|
||||
}
|
||||
|
||||
Menu menu = mActionMenuView.getMenu();
|
||||
for (int i = 0; i < menu.size(); i++) {
|
||||
MenuItem menuItem = menu.getItem(i);
|
||||
// menu设置actionLayout后,无法捕捉点击事件,以icon为tag,如果icon is null 手动设置menuItem点击事件
|
||||
if (menuItem != null && menuItem.getIcon() == null) {
|
||||
if (menuItem.getActionView() != null) {
|
||||
menuItem.getActionView().setOnClickListener((v) -> this.onMenuItemClick(menuItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showToolbarAtLeft() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && mTitleTv != null) {
|
||||
mTitleTv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
|
||||
}
|
||||
setTitleCenter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
setTitleCenter();
|
||||
}
|
||||
|
||||
// 设置标题居中
|
||||
public void setTitleCenter() {
|
||||
if (mActionMenuView != null && mTitleContainer != null && mBackContainer != null && !showToolbarAtLeft()) {
|
||||
mActionMenuView.post(() -> {
|
||||
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mTitleContainer.getLayoutParams();
|
||||
params.setMargins(mActionMenuView.getWidth() - mBackContainer.getWidth(), 0, 0, 0);
|
||||
mTitleContainer.setLayoutParams(params);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setGameIconToolbar(String icon, String iconSubscript) {
|
||||
mTitleContainer.setVisibility(View.GONE);
|
||||
mGameIconView.displayGameIcon(icon, iconSubscript);
|
||||
mGameIconView.setVisibility(View.VISIBLE);
|
||||
mIconTitleContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public void setUserAvatarIconToolbar(String icon) {
|
||||
mTitleContainer.setVisibility(View.GONE);
|
||||
ImageUtils.display(mUserAvatarIv, icon);
|
||||
mUserAvatarIv.setVisibility(View.VISIBLE);
|
||||
mIconTitleContainer.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void createDownloadMenu(int res) {
|
||||
if (res != R.menu.menu_download) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_download, mActionMenuView.getMenu());
|
||||
}
|
||||
|
||||
if (mPackageViewModel != null) {
|
||||
updateDownloadCountHint(mPackageViewModel.getFilterSameUpdateLiveData().getValue());
|
||||
}
|
||||
|
||||
View downloadMenuView = mActionMenuView.getMenu().findItem(R.id.menu_download).getActionView();
|
||||
mDownloadCountHint = downloadMenuView.findViewById(R.id.menu_download_count_hint);
|
||||
}
|
||||
|
||||
private void updateDownloadCountHint(List<GameUpdateEntity> updateList) {
|
||||
if (mDownloadCountHint == null) return;
|
||||
|
||||
String count = DownloadManager.getInstance().getDownloadOrUpdateCount(updateList);
|
||||
if (count != null) {
|
||||
mDownloadCountHint.setVisibility(View.VISIBLE);
|
||||
mDownloadCountHint.setText(count);
|
||||
|
||||
ViewGroup.LayoutParams params = mDownloadCountHint.getLayoutParams();
|
||||
if (TextUtils.isEmpty(count)) {
|
||||
params.width = DisplayUtils.dip2px(6);
|
||||
params.height = DisplayUtils.dip2px(6);
|
||||
} else {
|
||||
params.width = DisplayUtils.dip2px(12);
|
||||
params.height = DisplayUtils.dip2px(12);
|
||||
}
|
||||
mDownloadCountHint.setLayoutParams(params);
|
||||
} else {
|
||||
mDownloadCountHint.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBDownloadStatus status) {
|
||||
if (!SPUtils.getBoolean(Constants.SP_TEENAGER_MODE) && showDownloadMenu() && mPackageViewModel != null) {
|
||||
updateDownloadCountHint(mPackageViewModel.getFilterSameUpdateLiveData().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuItem getMenuItem(int res) {
|
||||
if (mToolbar == null) return null; //后续页面做好判断
|
||||
return mActionMenuView.getMenu().findItem(res);
|
||||
}
|
||||
|
||||
public void clearMenu() {
|
||||
if (mToolbar != null) {
|
||||
mActionMenuView.getMenu().clear();
|
||||
setTitleCenter();
|
||||
}
|
||||
}
|
||||
|
||||
public Menu getMenu() {
|
||||
return mActionMenuView.getMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.menu_download) {
|
||||
// MtaHelper.onEvent("下载管理", "下载管理入口", getActivityNameInChinese());
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(this, mEntrance);
|
||||
startActivity(intent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected View.OnClickListener provideNavigationItemClickListener() {
|
||||
return view -> onBackPressed();
|
||||
}
|
||||
|
||||
protected boolean showDownloadMenu() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideToolbar(boolean isHide) {
|
||||
if (mToolbarContainer != null) {
|
||||
mToolbarContainer.setVisibility(isHide ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNightModeChange() {
|
||||
super.onNightModeChange();
|
||||
if (mToolbar != null) {
|
||||
mToolbar.setBackgroundColor(ContextCompat.getColor(this, R.color.background_white));
|
||||
}
|
||||
if (mBackBtn != null) {
|
||||
if (mBackBtn instanceof ImageView) {
|
||||
((ImageView) mBackBtn).setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_bar_back));
|
||||
} else if (mBackBtn instanceof TextView) {
|
||||
((TextView) mBackBtn).setTextColor(ContextCompat.getColor(this, R.color.text_subtitle));
|
||||
}
|
||||
}
|
||||
if (mTitleTv != null) {
|
||||
mTitleTv.setTextColor(ContextCompat.getColor(this, R.color.text_black));
|
||||
}
|
||||
if (showDownloadMenu() && getMenuItem(R.id.menu_download) != null) {
|
||||
((ImageView) getMenuItem(R.id.menu_download).getActionView().findViewById(R.id.menu_download_iv)).setImageDrawable(ContextCompat.getDrawable(this, R.drawable.toolbar_download));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
package com.gh.base.adapter;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/11/17.
|
||||
* ViewPager FragmentAdapter
|
||||
*/
|
||||
public class FragmentAdapter extends FragmentPagerAdapter {
|
||||
|
||||
private List<Fragment> mFragmentList;
|
||||
|
||||
private List<String> mTitleList;
|
||||
|
||||
public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
|
||||
super(fm);
|
||||
this.mFragmentList = fragmentList;
|
||||
}
|
||||
|
||||
public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> titleList) {
|
||||
super(fm);
|
||||
this.mFragmentList = fragmentList;
|
||||
this.mTitleList = titleList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return mFragmentList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mFragmentList.size();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
if (mTitleList != null && mTitleList.size() > position) {
|
||||
return mTitleList.get(position);
|
||||
}
|
||||
return super.getPageTitle(position);
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package com.gh.base.adapter;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by khy on 7/12/28.
|
||||
*/
|
||||
public class FragmentStateAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
private List<Fragment> mFragmentList;
|
||||
|
||||
public FragmentStateAdapter(FragmentManager fm, List<Fragment> fragmentList) {
|
||||
super(fm);
|
||||
this.mFragmentList = fragmentList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return mFragmentList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mFragmentList.size();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,121 +0,0 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.gh.common.util.ClickUtils;
|
||||
import com.gh.common.util.NightModeUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.lightgame.utils.RuntimeUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 17/05/2017
|
||||
* @Time 4:30 PM
|
||||
*/
|
||||
|
||||
public class BaseDialogFragment extends DialogFragment {
|
||||
|
||||
protected boolean mNightMode;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(requireContext());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Dialog dialog = new Dialog(getActivity(), getThemeRes());
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
dialog.setOnKeyListener((dialog1, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && !ClickUtils.isFastDoubleClick()) {
|
||||
return onBack();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
dialog.setCancelable(false);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public int getThemeRes() {
|
||||
return R.style.DialogWindowTransparent;
|
||||
}
|
||||
|
||||
public void toast(@StringRes int res) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
|
||||
toast(getString(res));
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
|
||||
Utils.toast(getContext(), msg);
|
||||
}
|
||||
|
||||
public void toastLong(@StringRes int msg) {
|
||||
toastLong(getString(msg));
|
||||
}
|
||||
|
||||
public void toastLong(String msg) {
|
||||
RuntimeUtils.getInstance().toastLong(getContext(), msg);
|
||||
}
|
||||
|
||||
public boolean onBack() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(@NonNull FragmentManager manager, @Nullable String tag) {
|
||||
Fragment fragment = manager.findFragmentByTag(tag);
|
||||
if (fragment != null) {
|
||||
FragmentTransaction transaction = manager.beginTransaction();
|
||||
transaction.show(fragment);
|
||||
transaction.commit();
|
||||
} else {
|
||||
try {
|
||||
Class<?> clazz = DialogFragment.class;
|
||||
Field dismissed = clazz.getDeclaredField("mDismissed");
|
||||
dismissed.setAccessible(true);
|
||||
dismissed.set(this, false);
|
||||
|
||||
Field shownByMe = clazz.getDeclaredField("mShownByMe");
|
||||
shownByMe.setAccessible(true);
|
||||
shownByMe.set(this, true);
|
||||
FragmentTransaction transaction = manager.beginTransaction();
|
||||
transaction.add(this, tag);
|
||||
transaction.commitAllowingStateLoss();
|
||||
} catch (Exception e) {
|
||||
super.show(manager, tag);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
onNightModeChange();
|
||||
}
|
||||
|
||||
protected void onNightModeChange() {
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(requireContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
/**
|
||||
* Wrap another fragment with dialog fragment.
|
||||
*/
|
||||
public class BaseDialogWrapperFragment extends BaseDialogFragment {
|
||||
|
||||
private Fragment mFragmentToWrap;
|
||||
|
||||
public static BaseDialogWrapperFragment getInstance(Fragment fragmentToWrap) {
|
||||
BaseDialogWrapperFragment fragment = new BaseDialogWrapperFragment();
|
||||
fragment.mFragmentToWrap = fragmentToWrap;
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public static BaseDialogWrapperFragment getInstance(Fragment fragmentToWrap, boolean isCancelable) {
|
||||
BaseDialogWrapperFragment fragment = new BaseDialogWrapperFragment();
|
||||
fragment.mFragmentToWrap = fragmentToWrap;
|
||||
fragment.setCancelable(isCancelable);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_dialog_wrapper, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (mFragmentToWrap != null) {
|
||||
getChildFragmentManager().beginTransaction().replace(R.id.fragment_placeholder, mFragmentToWrap).commitNowAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
getDialog().getWindow().setGravity(Gravity.BOTTOM);
|
||||
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
dialog.setCanceledOnTouchOutside(true);
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
@ -1,359 +0,0 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.gh.base.OnListClickListener;
|
||||
import com.gh.base.OnRequestCallBackListener;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler;
|
||||
import com.gh.common.syncpage.SyncDataEntity;
|
||||
import com.gh.common.syncpage.SyncPageRepository;
|
||||
import com.gh.common.util.NightModeUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.eventbus.EBMiPush;
|
||||
import com.lightgame.OnTitleClickListener;
|
||||
import com.lightgame.utils.RuntimeUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import kotlin.Pair;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/9/4.
|
||||
* Fragment 基类
|
||||
*/
|
||||
public abstract class BaseFragment<T> extends Fragment implements OnRequestCallBackListener<T>,
|
||||
View.OnClickListener, OnListClickListener, OnTitleClickListener {
|
||||
|
||||
public static final int RESULT_REFRESH = 9528;
|
||||
|
||||
protected View mCachedView;
|
||||
|
||||
protected boolean isEverPause;
|
||||
|
||||
protected boolean mNightMode;
|
||||
|
||||
@NonNull
|
||||
protected String mEntrance = "";
|
||||
|
||||
public long startPageTime = 0;
|
||||
|
||||
protected final Handler mBaseHandler = new BaseFragment.BaseHandler(this);
|
||||
|
||||
protected static class BaseHandler extends Handler {
|
||||
private final WeakReference<BaseFragment> mFragmentWeakReference;
|
||||
|
||||
BaseHandler(BaseFragment fragment) {
|
||||
mFragmentWeakReference = new WeakReference<>(fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
BaseFragment fragment = mFragmentWeakReference.get();
|
||||
if (fragment != null) fragment.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleMessage(Message msg) {
|
||||
|
||||
}
|
||||
|
||||
@LayoutRes
|
||||
protected abstract int getLayoutId();
|
||||
|
||||
/**
|
||||
* 提供 Inflated 的 view ,可用于 data binding.
|
||||
*/
|
||||
protected View getInflatedLayout() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 责任链,谁处理了就返回true,否则返回super.handleOnClick(View view)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean handleOnClick(View view) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
handleOnClick(v);
|
||||
}
|
||||
|
||||
|
||||
protected void initView(View view) {
|
||||
View mBackBtn = view.findViewById(R.id.backBtn);
|
||||
View mBackContainer = view.findViewById(R.id.backContainer);
|
||||
if (mBackBtn != null && mBackContainer != null) {
|
||||
mBackBtn.setOnClickListener(v -> requireActivity().onBackPressed());
|
||||
mBackContainer.setOnClickListener(v -> requireActivity().onBackPressed());
|
||||
}
|
||||
}
|
||||
|
||||
protected void postRunnable(Runnable runnable) {
|
||||
RuntimeUtils.getInstance().runOnUiThread(runnable);
|
||||
}
|
||||
|
||||
// 定时任务全部改用这个方法, 在onDestroy做统一取消定时
|
||||
protected void postDelayedRunnable(Runnable runnable, long delayMillis) {
|
||||
RuntimeUtils.getInstance().runOnUiThread(runnable, delayMillis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final Intent intent = getActivity().getIntent();
|
||||
mEntrance = intent.getStringExtra(KEY_ENTRANCE);
|
||||
if (TextUtils.isEmpty(mEntrance) && getArguments() != null) {
|
||||
mEntrance = getArguments().getString(KEY_ENTRANCE);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(mEntrance)) {
|
||||
mEntrance = Constants.ENTRANCE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("FRAGMENT_ENTRANCE -> " + mEntrance);
|
||||
}
|
||||
|
||||
isEverPause = false;
|
||||
EventBus.getDefault().register(this);
|
||||
|
||||
// For data binding.
|
||||
mCachedView = getInflatedLayout();
|
||||
if (mCachedView == null) {
|
||||
mCachedView = View.inflate(getContext(), getLayoutId(), null);
|
||||
}
|
||||
|
||||
initView(mCachedView);
|
||||
|
||||
if (addSyncPageObserver()) {
|
||||
initSyncPageObserver();
|
||||
}
|
||||
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON) {
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(requireContext());
|
||||
} else {
|
||||
mNightMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void initSyncPageObserver() {
|
||||
SyncPageRepository.INSTANCE.getSyncPageLiveData().observe(this, syncDataEntities -> {
|
||||
try {
|
||||
Utils.log("SyncPageRepository initSyncPageObserver->" + syncDataEntities);
|
||||
List<SyncDataEntity> readyRemoveList = new ArrayList<>();
|
||||
if (syncDataEntities == null || syncDataEntities.isEmpty()) return;
|
||||
RecyclerView.Adapter adapter = provideSyncAdapter();
|
||||
if (!(adapter instanceof ISyncAdapterHandler)) return;
|
||||
for (int i = 0; i < adapter.getItemCount(); i++) {
|
||||
Pair<String, Object> syncKey = ((ISyncAdapterHandler) adapter).getSyncData(i);
|
||||
if (syncKey == null) continue;
|
||||
for (SyncDataEntity syncDataEntity : syncDataEntities) {
|
||||
if (syncDataEntity.getSyncId().equals(syncKey.getFirst())) {
|
||||
boolean isSuccess = SyncPageRepository.INSTANCE.handleSyncData(syncKey.getSecond(), syncDataEntity);
|
||||
if (isSuccess) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("SyncPageRepository notify position->" + i);
|
||||
}
|
||||
adapter.notifyItemChanged(i);
|
||||
|
||||
if (syncDataEntity.getRemove()) {
|
||||
readyRemoveList.add(syncDataEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBaseHandler.postDelayed(() -> SyncPageRepository.removeSyncData(readyRemoveList), 2000);
|
||||
} catch (Exception e) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
throw e;
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 必须的有subscribe才能register
|
||||
@Subscribe(threadMode = ThreadMode.BACKGROUND)
|
||||
public void onDummyEvent(EBMiPush push) {
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
if (container != null) {
|
||||
container.removeView(mCachedView);
|
||||
// TODO 页面重建 (framgent 的重新获取) 有大问题,这里只是修修补补
|
||||
if (mCachedView != null && mCachedView.getParent() instanceof ViewGroup) {
|
||||
((ViewGroup) mCachedView.getParent()).removeView(mCachedView);
|
||||
}
|
||||
}
|
||||
return mCachedView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
mCachedView = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
isEverPause = false;
|
||||
startPageTime = System.currentTimeMillis();
|
||||
|
||||
if (!NightModeUtils.INSTANCE.getSystemMode() && mNightMode != NightModeUtils.INSTANCE.isNightMode(requireContext())) {
|
||||
onNightModeChange();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
isEverPause = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mBaseHandler.removeCallbacksAndMessages(null);
|
||||
RuntimeUtils.getInstance().removeRunnable();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
public void toast(@StringRes int res) {
|
||||
toast(getString(res));
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
Utils.toast(getContext(), msg);
|
||||
}
|
||||
|
||||
public void toastLong(@StringRes int msg) {
|
||||
toastLong(getString(msg));
|
||||
}
|
||||
|
||||
public void toastLong(String msg) {
|
||||
RuntimeUtils.getInstance().toastLong(getContext(), msg);
|
||||
}
|
||||
|
||||
public boolean isEverPause() {
|
||||
return isEverPause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDone() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDone(T obj) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadError() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadEmpty() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <LIST> void onListClick(View view, int position, LIST data) {
|
||||
|
||||
}
|
||||
|
||||
protected <K> Observable<K> asyncCall(Observable<K> observable) {
|
||||
return observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
||||
// 将所有的Fragment都置为隐藏状态。
|
||||
protected void hideFragments(FragmentTransaction transaction) {
|
||||
List<Fragment> list = getChildFragmentManager().getFragments();
|
||||
for (Fragment fragment : list) {
|
||||
transaction.hide(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTitleClick() {
|
||||
List<Fragment> list = getChildFragmentManager().getFragments();
|
||||
for (Fragment fragment : list) {
|
||||
if (fragment instanceof OnTitleClickListener) {
|
||||
((OnTitleClickListener) fragment).onTitleClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 为 fragment 附加 bundle (setArgument())
|
||||
public BaseFragment with(Bundle bundle) {
|
||||
this.setArguments(bundle);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void onParentActivityFinish() {
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected RecyclerView.Adapter provideSyncAdapter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean addSyncPageObserver() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
onNightModeChange();
|
||||
}
|
||||
|
||||
protected void onNightModeChange() {
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(requireContext());
|
||||
}
|
||||
}
|
||||
@ -1,222 +0,0 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
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.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.gh.base.adapter.FragmentAdapter;
|
||||
import com.gh.common.view.TabIndicatorView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.normal.NormalFragment;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.lightgame.view.NoScrollableViewPager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by khy on 15/03/18.
|
||||
*/
|
||||
|
||||
public abstract class BaseFragment_TabLayout extends NormalFragment implements ViewPager.OnPageChangeListener {
|
||||
|
||||
public static final String PAGE_INDEX = "PAGE_INDEX";
|
||||
|
||||
protected TabLayout mTabLayout;
|
||||
protected NoScrollableViewPager mViewPager;
|
||||
protected TabIndicatorView mTabIndicatorView;
|
||||
@Nullable
|
||||
protected View mDividerLineView;
|
||||
|
||||
protected List<Fragment> mFragmentsList;
|
||||
|
||||
protected List<String> mTabTitleList;
|
||||
|
||||
protected int mCheckedIndex = 0;
|
||||
|
||||
protected abstract void initFragmentList(List<Fragment> fragments);
|
||||
|
||||
protected abstract void initTabTitleList(List<String> tabTitleList);
|
||||
|
||||
protected int provideIndicatorWidth() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
protected View provideTabView(int position, String tabTitle) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_tablayout_viewpager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
List<Fragment> fragments = getChildFragmentManager().getFragments();
|
||||
if (fragments != null) {
|
||||
for (Fragment fragment : fragments) {
|
||||
fragment.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Fragment> restoreFragments() {
|
||||
String tag = "android:switcher:" + mViewPager.getId() + ":";
|
||||
ArrayList<Fragment> fragments = new ArrayList<>();
|
||||
int childCount = mTabTitleList.size();
|
||||
for (int index = 0; index < childCount; index++) {
|
||||
Fragment fragment = getChildFragmentManager().findFragmentByTag(tag + index);
|
||||
if (fragment != null) {
|
||||
fragments.add(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
return fragments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
mTabLayout = view.findViewById(R.id.fragment_tab_layout);
|
||||
mViewPager = view.findViewById(R.id.fragment_view_pager);
|
||||
mTabIndicatorView = view.findViewById(R.id.fragment_tab_indicator);
|
||||
mDividerLineView = view.findViewById(R.id.dividerLine);
|
||||
|
||||
if (getArguments() != null) mCheckedIndex = getArguments().getInt(PAGE_INDEX, 0);
|
||||
mTabTitleList = new ArrayList<>();
|
||||
initTabTitleList(mTabTitleList);
|
||||
mFragmentsList = new ArrayList<>(restoreFragments());
|
||||
if (mFragmentsList.isEmpty() || mFragmentsList.size() != mTabTitleList.size()) {
|
||||
mFragmentsList.clear();
|
||||
initFragmentList(mFragmentsList);
|
||||
}
|
||||
|
||||
mViewPager.setOffscreenPageLimit(mFragmentsList.size());
|
||||
mViewPager.addOnPageChangeListener(this);
|
||||
mViewPager.setAdapter(new FragmentAdapter(getChildFragmentManager(), mFragmentsList, mTabTitleList));
|
||||
mViewPager.setCurrentItem(mCheckedIndex);
|
||||
mTabLayout.setupWithViewPager(mViewPager);
|
||||
mTabIndicatorView.setupWithTabLayout(mTabLayout);
|
||||
mTabIndicatorView.setupWithViewPager(mViewPager);
|
||||
mTabIndicatorView.setIndicatorWidth(provideIndicatorWidth());
|
||||
|
||||
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
|
||||
TabLayout.Tab tab = mTabLayout.getTabAt(i);
|
||||
if (tab == null) continue;
|
||||
String tabTitle = tab.getText() != null ? tab.getText().toString() : "";
|
||||
View tabView = provideTabView(i, tabTitle);
|
||||
if (tabView == null) tabView = createDefaultTabCustomView(requireContext(), 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public 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);
|
||||
tabTitle.setTextColor(ContextCompat.getColorStateList(tabTitle.getContext(), R.color.text_tabbar_style));
|
||||
}
|
||||
|
||||
// 如果不设置View的话,无法动态设置字体样式
|
||||
@NonNull
|
||||
public static View createDefaultTabCustomView(Context context, String title) {
|
||||
View view = LayoutInflater.from(context).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
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNightModeChange() {
|
||||
super.onNightModeChange();
|
||||
View container = requireView().findViewById(R.id.fragment_tab_container);
|
||||
if (container != null) {
|
||||
container.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.background_white));
|
||||
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
|
||||
TabLayout.Tab tab = mTabLayout.getTabAt(i);
|
||||
if (tab != null) {
|
||||
updateTabStyle(tab, tab.isSelected());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mDividerLineView != null) {
|
||||
mDividerLineView.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.divider));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,145 +0,0 @@
|
||||
/**
|
||||
* project: OPlay
|
||||
* <p/>
|
||||
* <p/>
|
||||
* ========================================================================
|
||||
* amend date amend user amend reason
|
||||
* 2013-3-6 CsHeng
|
||||
*/
|
||||
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.gamecenter.normal.NormalFragment;
|
||||
import com.lightgame.adapter.BaseFragmentPagerAdapter;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.view.DoubleTapTextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ViewPager 配合RadioGroup实现双切换<br/>
|
||||
* 记得自己控制onCreateView返回和radioGroup里面radiobutton个数,Viewpager的布局<br/>
|
||||
*
|
||||
* @author CsHeng
|
||||
* @date 2013-3-6
|
||||
*/
|
||||
public abstract class BaseFragment_ViewPager extends NormalFragment implements DoubleTapTextView.OnDoubleTapListener {
|
||||
|
||||
public static final String ARGS_INDEX = "index";
|
||||
protected int mCheckedIndex = 0;
|
||||
protected PagerAdapter mAdapter;
|
||||
protected List<Fragment> mFragmentsList;
|
||||
protected ViewPager mViewPager;
|
||||
|
||||
@LayoutRes
|
||||
protected abstract int getLayoutId();
|
||||
|
||||
@IdRes
|
||||
protected abstract int getViewPagerId();
|
||||
|
||||
protected abstract void initFragmentList(List<Fragment> fragments);
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mViewPager = view.findViewById(getViewPagerId());
|
||||
mFragmentsList = restoreFragments();
|
||||
if (mFragmentsList.size() == 0) {
|
||||
initFragmentList(mFragmentsList);
|
||||
}
|
||||
mAdapter = BaseFragmentPagerAdapter.newInstance(getChildFragmentManager(), mFragmentsList);
|
||||
final Bundle args = getArguments();
|
||||
if (args != null) {
|
||||
mCheckedIndex = args.getInt(ARGS_INDEX);
|
||||
}
|
||||
mViewPager.setOffscreenPageLimit(mFragmentsList.size());
|
||||
mViewPager.setAdapter(mAdapter);
|
||||
if (mCheckedIndex < mFragmentsList.size()) {
|
||||
mViewPager.setCurrentItem(mCheckedIndex, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (getArguments() != null) {
|
||||
getArguments().putInt(ARGS_INDEX, mCheckedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (mViewPager != null) {
|
||||
mViewPager.setAdapter(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mFragmentsList != null) {
|
||||
mFragmentsList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDoubleTap() {
|
||||
final Fragment fragment = mFragmentsList.get(mViewPager.getCurrentItem());
|
||||
return fragment instanceof DoubleTapTextView.OnDoubleTapListener && ((DoubleTapTextView.OnDoubleTapListener)
|
||||
fragment).onDoubleTap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (CommonDebug.IS_DEBUG) {
|
||||
CommonDebug.logMethodWithParams(this, requestCode, resultCode, data);
|
||||
}
|
||||
List<Fragment> fragments = getChildFragmentManager().getFragments();
|
||||
if (fragments != null) {
|
||||
for (Fragment fragment : fragments) {
|
||||
fragment.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<Fragment> restoreFragments() {
|
||||
String tag = "android:switcher:" + mViewPager.getId() + ":";
|
||||
ArrayList<Fragment> fragments = new ArrayList<>();
|
||||
int childCount = getChildCount();
|
||||
for (int index = 0; index < childCount; index++) {
|
||||
Fragment fragment = getChildFragmentManager().findFragmentByTag(tag + index);
|
||||
if (fragment != null) {
|
||||
fragments.add(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
return fragments;
|
||||
}
|
||||
|
||||
public abstract int getChildCount();
|
||||
|
||||
public int getCurrentItem() {
|
||||
return mViewPager != null ? mViewPager.getCurrentItem() : 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,145 +0,0 @@
|
||||
/**
|
||||
* project: OPlay
|
||||
* <p/>
|
||||
* <p/>
|
||||
* ========================================================================
|
||||
* amend date amend user amend reason
|
||||
* 2013-3-6 CsHeng
|
||||
*/
|
||||
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Checkable;
|
||||
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
|
||||
/**
|
||||
* ViewPager 配合ViewGroup Checkable实现双切换<br/>
|
||||
* 记得自己控制onCreateView返回和ViewGroup里面Checkable个数,ViewPager的布局<br/>
|
||||
*
|
||||
* @author CsHeng
|
||||
* @date 2013-3-6
|
||||
* @update 2014-09-29
|
||||
*/
|
||||
public abstract class BaseFragment_ViewPager_Checkable extends BaseFragment_ViewPager implements
|
||||
ViewPager.OnPageChangeListener {
|
||||
|
||||
protected ViewGroup mCheckableGroup;
|
||||
|
||||
private int mLastPosition = MainWrapperFragment.INDEX_HOME;
|
||||
|
||||
@IdRes
|
||||
protected abstract int getCheckableGroupId();
|
||||
|
||||
protected boolean getSmoothScroll() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mCheckableGroup = (ViewGroup) view.findViewById(getCheckableGroupId());
|
||||
for (int i = 0, size = mCheckableGroup.getChildCount(); i < size; i++) {
|
||||
mCheckableGroup.getChildAt(i).setOnClickListener(this);
|
||||
}
|
||||
mViewPager.addOnPageChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mViewPager.removeOnPageChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
checkIndex(mCheckedIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int index) {
|
||||
onPageChanged(index);
|
||||
try {
|
||||
// 补充Viewpager Fragment的生命周期, 先调用旧选中 fragment 的 onPause 再当前的 onResume
|
||||
if (mFragmentsList.size() > mLastPosition) {
|
||||
Fragment fragment = mFragmentsList.get(mLastPosition);
|
||||
fragment.onPause();
|
||||
|
||||
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
|
||||
List<Fragment> fragments = childFragmentManager.getFragments();
|
||||
for (Fragment childFragment : fragments) {
|
||||
childFragment.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
if (mFragmentsList.size() > index) {
|
||||
Fragment fragment = mFragmentsList.get(index);
|
||||
fragment.onResume();
|
||||
|
||||
FragmentManager childFragmentManager = fragment.getChildFragmentManager();
|
||||
List<Fragment> fragments = childFragmentManager.getFragments();
|
||||
for (Fragment childFragment : fragments) {
|
||||
childFragment.onResume();
|
||||
}
|
||||
}
|
||||
mLastPosition = index;
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean handleOnClick(View view) {
|
||||
final int toCheck = mCheckableGroup.indexOfChild(view);
|
||||
if (toCheck != -1) {
|
||||
mViewPager.setCurrentItem(toCheck, getSmoothScroll());
|
||||
return true;
|
||||
}
|
||||
return super.handleOnClick(view);
|
||||
}
|
||||
|
||||
protected void checkIndex(int index) {
|
||||
final int childCount = mCheckableGroup.getChildCount();
|
||||
if (index < childCount && mCheckedIndex < childCount) {
|
||||
final View toChecked = mCheckableGroup.getChildAt(index);
|
||||
if (toChecked instanceof Checkable) {
|
||||
((Checkable) toChecked).setChecked(true);
|
||||
}
|
||||
if (index != mCheckedIndex) {
|
||||
final View checkedChild = mCheckableGroup.getChildAt(mCheckedIndex);
|
||||
if (checkedChild instanceof Checkable) {
|
||||
((Checkable) checkedChild).setChecked(false);
|
||||
}
|
||||
}
|
||||
mCheckedIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
protected void onPageChanged(int index) {
|
||||
checkIndex(index);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,173 +0,0 @@
|
||||
package com.gh.base.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.normal.NormalFragment
|
||||
|
||||
/**
|
||||
* 懒加载(支持多层嵌套)
|
||||
*/
|
||||
abstract class BaseLazyFragment : NormalFragment() {
|
||||
|
||||
private var mIsFirstVisible = true
|
||||
|
||||
private var isViewCreated = false
|
||||
|
||||
protected var isSupportVisible = false
|
||||
|
||||
/**
|
||||
* 用于分发可见时间的时候获取 父fragment 是否隐藏
|
||||
*
|
||||
* @return true fragment 不可见, false 父 fragment 可见
|
||||
*/
|
||||
private val isParentInvisible: Boolean
|
||||
get() {
|
||||
val parentFragment = parentFragment
|
||||
return if (parentFragment is BaseLazyFragment) {
|
||||
val fragment = parentFragment as BaseLazyFragment?
|
||||
!fragment!!.isSupportVisible
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
||||
super.setUserVisibleHint(isVisibleToUser)
|
||||
// 对于默认 tab 和 间隔 checked tab 需要等到 isViewCreated = true 后才可以通过此通知用户可见
|
||||
// 这种情况下第一次可见不是在这里通知 因为 isViewCreated = false 成立,等从别的界面回到这里后会使用 onFragmentResume 通知可见
|
||||
// 对于非默认 tab mIsFirstVisible = true 会一直保持到选择则这个 tab 的时候,因为在 onActivityCreated 会返回 false
|
||||
if (isViewCreated) {
|
||||
if (isVisibleToUser && !isSupportVisible) {
|
||||
dispatchUserVisibleHint(true)
|
||||
} else if (!isVisibleToUser && isSupportVisible) {
|
||||
dispatchUserVisibleHint(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
isViewCreated = true
|
||||
// !isHidden() 默认为 true 在调用 hide show 的时候可以使用
|
||||
if (!isHidden && userVisibleHint) {
|
||||
dispatchUserVisibleHint(true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onHiddenChanged(hidden: Boolean) {
|
||||
super.onHiddenChanged(hidden)
|
||||
|
||||
if (hidden) {
|
||||
dispatchUserVisibleHint(false)
|
||||
} else {
|
||||
dispatchUserVisibleHint(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (!mIsFirstVisible) {
|
||||
if (!isHidden && !isSupportVisible && userVisibleHint) {
|
||||
dispatchUserVisibleHint(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
// 当前 Fragment 包含子 Fragment 的时候 dispatchUserVisibleHint 内部本身就会通知子 Fragment 不可见
|
||||
// 子 fragment 走到这里的时候自身又会调用一遍 ?
|
||||
if (isSupportVisible && userVisibleHint) {
|
||||
dispatchUserVisibleHint(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 统一处理 显示隐藏
|
||||
*
|
||||
* @param visible
|
||||
*/
|
||||
private fun dispatchUserVisibleHint(visible: Boolean) {
|
||||
//当前 Fragment 是 child 时候 作为缓存 Fragment 的子 fragment getUserVisibleHint = true
|
||||
//但当父 fragment 不可见所以 currentVisibleState = false 直接 return 掉
|
||||
// 这里限制则可以限制多层嵌套的时候子 Fragment 的分发
|
||||
if (visible && isParentInvisible) return
|
||||
|
||||
//此处是对子 Fragment 不可见的限制,因为 子 Fragment 先于父 Fragment回调本方法 currentVisibleState 置位 false
|
||||
// 当父 dispatchChildVisibleState 的时候第二次回调本方法 visible = false 所以此处 visible 将直接返回
|
||||
if (isSupportVisible == visible) {
|
||||
return
|
||||
}
|
||||
|
||||
isSupportVisible = visible
|
||||
|
||||
if (visible) {
|
||||
|
||||
// TODO 当 fragment 重建时这里的被调用很奇怪,onActivityCreated 回调触发,但此时的 view 是空的,原因是 createView 还没被调用
|
||||
// TODO 这样就造成了 onFragmentResume 里可能用到 view 的地方出现空指针异常,所以这里遇到 view 为空的时候 return 等下一次被调用才进去
|
||||
if (view == null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (mIsFirstVisible) {
|
||||
mIsFirstVisible = false
|
||||
onFragmentFirstVisible()
|
||||
}
|
||||
onFragmentResume()
|
||||
dispatchChildVisibleState(true)
|
||||
} else {
|
||||
// 当 fragment 重建时,这个代码块可能在第一次 view 为空的 visible 后调用导致在 onFragmentPause 里可能用到 view 的地方出现空指针异常
|
||||
if (!mIsFirstVisible) {
|
||||
dispatchChildVisibleState(false)
|
||||
onFragmentPause()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前 Fragment 是 child 时候 作为缓存 Fragment 的子 fragment 的唯一或者嵌套 VP 的第一 fragment 时 getUserVisibleHint = true
|
||||
* 但是由于父 Fragment 还未进入可见状态所以自身也是不可见的, 这个方法可以存在是因为庆幸的是 父 fragment 的生命周期回调总是先于子 Fragment
|
||||
* 所以在父 fragment 设置完成当前不可见状态后,需要通知子 Fragment 我不可见,你也不可见,
|
||||
*
|
||||
*
|
||||
* 因为 dispatchUserVisibleHint 中判断了 isParentInvisible 所以当 子 fragment 走到了 onActivityCreated 的时候直接 return 掉了
|
||||
*
|
||||
*
|
||||
* 当真正的外部 Fragment 可见的时候,走 setVisibleHint (VP 中)或者 onActivityCreated (hide show) 的时候
|
||||
* 从对应的生命周期入口调用 dispatchChildVisibleState 通知子 Fragment 可见状态
|
||||
*
|
||||
* @param visible
|
||||
*/
|
||||
private fun dispatchChildVisibleState(visible: Boolean) {
|
||||
val childFragmentManager = childFragmentManager
|
||||
val fragments = childFragmentManager.fragments
|
||||
if (!fragments.isEmpty()) {
|
||||
for (child in fragments) {
|
||||
if (child is BaseLazyFragment && !child.isHidden() && child.getUserVisibleHint()) {
|
||||
child.dispatchUserVisibleHint(visible)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open fun onFragmentFirstVisible() {
|
||||
//ULog.e("对用户第一次可见")
|
||||
}
|
||||
|
||||
open fun onFragmentResume() {
|
||||
//ULog.e("对用户可见")
|
||||
}
|
||||
|
||||
open fun onFragmentPause() {
|
||||
//ULog.e("对用户不可见")
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
isViewCreated = false
|
||||
mIsFirstVisible = true
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,142 +0,0 @@
|
||||
package com.gh.base.fragment
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager.widget.PagerAdapter
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.gh.base.adapter.FragmentAdapter
|
||||
import com.gh.common.view.TabIndicatorView
|
||||
import com.gh.gamecenter.R
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.lightgame.view.NoScrollableViewPager
|
||||
|
||||
abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeListener {
|
||||
|
||||
lateinit var mTabLayout: TabLayout
|
||||
lateinit var mViewPager: NoScrollableViewPager
|
||||
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)
|
||||
}
|
||||
|
||||
open fun providePagerAdapter(): PagerAdapter? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mTabLayout = view.findViewById(R.id.fragment_tab_layout)
|
||||
mViewPager = view.findViewById(R.id.fragment_view_pager)
|
||||
mTabIndicatorView = view.findViewById(R.id.fragment_tab_indicator)
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
super.onFragmentFirstVisible()
|
||||
mTabTitleList.clear()
|
||||
mFragmentsList.clear()
|
||||
|
||||
initTabTitleList(mTabTitleList)
|
||||
mFragmentsList.addAll(restoreFragments())
|
||||
if (mFragmentsList.isEmpty() || mFragmentsList.size != mTabTitleList.size) {
|
||||
mFragmentsList.clear()
|
||||
initFragmentList(mFragmentsList)
|
||||
}
|
||||
|
||||
mViewPager.offscreenPageLimit = mFragmentsList.size
|
||||
mViewPager.addOnPageChangeListener(this)
|
||||
mViewPager.adapter = providePagerAdapter()
|
||||
?: 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 = BaseFragment_TabLayout.createDefaultTabCustomView(requireContext(), tabTitle)
|
||||
tab.customView = tabView
|
||||
}
|
||||
BaseFragment_TabLayout.initTabStyle(mTabLayout, mCheckedIndex)
|
||||
}
|
||||
|
||||
private fun restoreFragments(): ArrayList<Fragment> {
|
||||
val tag = "android:switcher:${mViewPager.id}:"
|
||||
val fragments = ArrayList<Fragment>()
|
||||
val childCount = mTabTitleList.size
|
||||
for (index in 0 until childCount) {
|
||||
val fragment = childFragmentManager.findFragmentByTag("$tag$index")
|
||||
if (fragment != null) {
|
||||
restoreFragment(fragment)
|
||||
fragments.add(fragment)
|
||||
}
|
||||
}
|
||||
return fragments
|
||||
}
|
||||
|
||||
open fun restoreFragment(fragment: Fragment) {}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
|
||||
override fun onPageSelected(position: Int) {}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
|
||||
override fun onNightModeChange() {
|
||||
super.onNightModeChange()
|
||||
val container = requireView().findViewById<View>(R.id.fragment_tab_container)
|
||||
if (container != null) {
|
||||
container.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.background_white))
|
||||
for (i in 0 until mTabLayout.tabCount) {
|
||||
val tab = mTabLayout.getTabAt(i)
|
||||
if (tab != null) {
|
||||
BaseFragment_TabLayout.updateTabStyle(tab, tab.isSelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PAGE_INDEX = "PAGE_INDEX"
|
||||
}
|
||||
}
|
||||
@ -1,99 +0,0 @@
|
||||
package com.gh.base.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewStub
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
/**
|
||||
* 这是在 BaseLazyFragment 之上添加了一些通用功能的抽象类
|
||||
*
|
||||
* 怎么将一个已有的 fragment 转化为懒加载 (延迟渲染) 的 fragment 呢?
|
||||
* (继承 ListFragment 的类请改为继承 LazyListFragment)
|
||||
*
|
||||
* 0. 删掉旧的 getInflatedLayout() 的代码,现在由 getStubLayoutId() 提供 Stub 布局 (默认为 R.layout.fragment_stub,若重写请注意提供 id 为 stub 的 ViewStub)
|
||||
* 1. 重写 getRealLayoutId(),提供实际要延迟渲染的 layout Id
|
||||
* 1. 将原有在 onCreate() 的代码移动到 onFragmentFirstVisible()
|
||||
* 2. 将原有在 onViewCreated() 的代码移动到 initRealView()
|
||||
* (注意,initRealView() 在 onFragmentFirstVisible() 中被调用,如果要初始化 viewModel 等非 UI 对象请在 super.onFragmentVisible() 调用)
|
||||
* 3. 如需使用 ViewBinding ,在 onRealLayoutInflated() 的回调中初始化 ViewBinding 即可
|
||||
* 4. onResume() 的代码移动到 onFragmentResume(),onPause() 的代码移动到 onFragmentPause()
|
||||
* 5. Done!
|
||||
*/
|
||||
abstract class LazyFragment : BaseLazyFragment() {
|
||||
|
||||
// ViewStub + ViewBinding 有莫名的 bug,语法上没问题,但编译时通不过。
|
||||
private var mViewStub: ViewStub? = null
|
||||
|
||||
private var mIsRecreatedByFragmentManager = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
if (savedInstanceState != null) {
|
||||
mIsRecreatedByFragmentManager = true
|
||||
}
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"使用了 LazyFragment 以后不要 override getLayoutId(),建议 override getRealLayoutId() 或者 getStubLayoutId()",
|
||||
ReplaceWith("LazyFragment.getRealLayoutId()")
|
||||
)
|
||||
override fun getLayoutId() = if (isRecreatedByFragmentManager()) {
|
||||
getRealLayoutId()
|
||||
} else {
|
||||
getStubLayoutId()
|
||||
}
|
||||
|
||||
override fun initView(view: View?) {
|
||||
super.initView(view)
|
||||
if (!isRecreatedByFragmentManager()) {
|
||||
mViewStub = mCachedView.findViewById(R.id.stub)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
super.onFragmentFirstVisible()
|
||||
inflateRealView()
|
||||
initRealView()
|
||||
}
|
||||
|
||||
/**
|
||||
* 真正 inflate View 的地方
|
||||
*/
|
||||
protected open fun inflateRealView() {
|
||||
if (isRecreatedByFragmentManager()) {
|
||||
onRealLayoutInflated(mCachedView)
|
||||
} else {
|
||||
mViewStub?.layoutResource = getRealLayoutId()
|
||||
mViewStub?.setOnInflateListener { _, inflatedView -> onRealLayoutInflated(inflatedView) }
|
||||
mViewStub?.inflate()?.let { mCachedView = it }
|
||||
}
|
||||
}
|
||||
|
||||
protected fun isRecreatedByFragmentManager() = mIsRecreatedByFragmentManager
|
||||
|
||||
/**
|
||||
* 请在这个方法之后获取初始化后的各种 view
|
||||
*
|
||||
* 替换旧 fragment 实现时,等同于 onViewCreated
|
||||
*/
|
||||
protected open fun initRealView() {}
|
||||
|
||||
/**
|
||||
* 提供要 stub inflate 的 layout
|
||||
*/
|
||||
protected abstract fun getRealLayoutId(): Int
|
||||
|
||||
/**
|
||||
* 提供含有 stub 的 layout
|
||||
*/
|
||||
protected open fun getStubLayoutId(): Int {
|
||||
return R.layout.fragment_stub
|
||||
}
|
||||
|
||||
/**
|
||||
* 真实 layout inflate 完成的回调,可用于 viewBinding
|
||||
*/
|
||||
protected open fun onRealLayoutInflated(inflatedView: View) {}
|
||||
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
public interface OnDialogBackListener {
|
||||
void onBack();
|
||||
}
|
||||
@ -1,134 +0,0 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 17/05/2017
|
||||
* @Time 4:27 PM
|
||||
*/
|
||||
public class WaitingDialogFragment extends BaseDialogFragment {
|
||||
|
||||
public static final String KEY_MSG = "msg";
|
||||
|
||||
private OnDialogBackListener mBackListener;
|
||||
|
||||
private TextView message;
|
||||
|
||||
public static WaitingDialogFragment newInstance(String message) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(KEY_MSG, message);
|
||||
WaitingDialogFragment fragment = new WaitingDialogFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public static WaitingDialogFragment newInstance(String message, boolean isCancelable) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(KEY_MSG, message);
|
||||
WaitingDialogFragment fragment = new WaitingDialogFragment();
|
||||
fragment.setArguments(args);
|
||||
fragment.setCancelable(isCancelable);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
final View view = inflater.inflate(R.layout.set_wait_dialog, null);
|
||||
message = view.findViewById(R.id.set_wait_message);
|
||||
message.setText(getArguments().getString(KEY_MSG));
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
WindowManager.LayoutParams layoutParams = getDialog().getWindow().getAttributes();
|
||||
layoutParams.width = DisplayUtils.dip2px(160);
|
||||
getDialog().getWindow().setAttributes(layoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(FragmentManager manager, String tag) {
|
||||
try {
|
||||
super.show(manager, tag);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void show(FragmentManager manager, String tag, OnDialogBackListener backListener) {
|
||||
show(manager, tag);
|
||||
this.mBackListener = backListener;
|
||||
}
|
||||
|
||||
public void uploadWaitingHint(String hint) {
|
||||
if (message != null) message.setText(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBack() {
|
||||
if (mBackListener != null) {
|
||||
mBackListener.onBack();
|
||||
return true;
|
||||
}
|
||||
return super.onBack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
dismissAllowingStateLoss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismissAllowingStateLoss() {
|
||||
mBackListener = null;
|
||||
try {
|
||||
super.dismissAllowingStateLoss();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static class WaitingDialogData {
|
||||
private String msg;
|
||||
|
||||
private boolean isShow;
|
||||
|
||||
public WaitingDialogData(String msg, boolean isShow) {
|
||||
this.msg = msg;
|
||||
this.isShow = isShow;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public boolean isShow() {
|
||||
return isShow;
|
||||
}
|
||||
|
||||
public void setShow(boolean show) {
|
||||
isShow = show;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,74 +0,0 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.gh.base.GHThreadFactory
|
||||
import com.gh.common.AppExecutor.heavyWeightIoExecutor
|
||||
import com.gh.common.AppExecutor.ioExecutor
|
||||
import com.gh.common.AppExecutor.lightWeightIoExecutor
|
||||
import com.gh.common.AppExecutor.logExecutor
|
||||
import com.gh.common.AppExecutor.uiExecutor
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.util.concurrent.*
|
||||
|
||||
/**
|
||||
* APP 线程池管理类
|
||||
*
|
||||
* [ioExecutor] 是一个最大线程数固定的线程池,较为繁重的 IO 任务可以交给它
|
||||
* [uiExecutor] 是主线程的包裹,需要切换至主线程执行可以用它
|
||||
* [lightWeightIoExecutor] 是一个单线程的线程池,轻量级且需要保证同一线程的 IO 任务可以交给它
|
||||
* [heavyWeightIoExecutor] 重量级的线程池,一些高频调用但不用保证结果的任务可以交给它
|
||||
* [logExecutor] 只为上传 log 而使用的线程池
|
||||
*/
|
||||
object AppExecutor {
|
||||
|
||||
private val mCoreSize = Runtime.getRuntime().availableProcessors()
|
||||
private val mMinimumPoolSize = 6.coerceAtLeast(mCoreSize)
|
||||
private val mMaximumPoolSize = 24.coerceAtLeast(mCoreSize * 3)
|
||||
|
||||
@JvmStatic
|
||||
val uiExecutor by lazy { MainThreadExecutor() }
|
||||
|
||||
@JvmStatic
|
||||
val lightWeightIoExecutor: ExecutorService by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LIGHT_WEIGHT_IO_THREAD")) }
|
||||
|
||||
@JvmStatic
|
||||
val heavyWeightIoExecutor: ExecutorService by lazy { Executors.newFixedThreadPool(2, GHThreadFactory("GH_HEAVY_WEIGHT_IO_THREAD")) }
|
||||
|
||||
@JvmStatic
|
||||
val logExecutor: ExecutorService by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LOG_THREAD")) }
|
||||
|
||||
@JvmStatic
|
||||
val ioExecutor = ThreadPoolExecutor(
|
||||
mMinimumPoolSize,
|
||||
mMaximumPoolSize,
|
||||
20L, TimeUnit.SECONDS,
|
||||
LinkedBlockingQueue(256),
|
||||
GHThreadFactory("GH_IO_THREAD"))
|
||||
|
||||
val cachedScheduler by lazy { Schedulers.from(ioExecutor) }
|
||||
|
||||
class MainThreadExecutor : Executor {
|
||||
private val mainThreadHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
override fun execute(command: Runnable) {
|
||||
mainThreadHandler.post(command)
|
||||
}
|
||||
|
||||
fun executeWithDelay(command: Runnable, delay: Long) {
|
||||
mainThreadHandler.postDelayed(command, delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnIoThread(isLightWeightTask: Boolean = false, isHeavyWightTask: Boolean = false, f: () -> Unit) {
|
||||
when {
|
||||
isLightWeightTask -> lightWeightIoExecutor.execute(f)
|
||||
isHeavyWightTask -> heavyWeightIoExecutor.execute(f)
|
||||
else -> ioExecutor.execute(f)
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnUiThread(f: () -> Unit) {
|
||||
uiExecutor.execute(f)
|
||||
}
|
||||
@ -8,13 +8,21 @@ import android.webkit.JavascriptInterface
|
||||
import androidx.annotation.Keep
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.loghub.LoghubUtils
|
||||
import com.gh.common.tracker.Tracker
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.loghub.LoghubUtils
|
||||
import com.gh.gamecenter.common.tracker.Tracker
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.gamecenter.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.common.callback.BiCallback
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.energy.EnergyCenterActivity
|
||||
import com.gh.gamecenter.energy.EnergyHouseActivity
|
||||
import com.gh.gamecenter.entity.*
|
||||
|
||||
@ -5,8 +5,8 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import android.util.Base64
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DirectUtils.directToFeedback
|
||||
import com.gh.common.util.DirectUtils.directToGameDetailVideoStreaming
|
||||
@ -15,11 +15,16 @@ import com.gh.common.util.DirectUtils.directToGameVideo
|
||||
import com.gh.common.util.DirectUtils.directToLegacyVideoDetail
|
||||
import com.gh.common.util.DirectUtils.directToLinkPage
|
||||
import com.gh.common.util.DirectUtils.directToQa
|
||||
import com.gh.common.util.GsonUtils.gson
|
||||
import com.gh.gamecenter.core.utils.GsonUtils.gson
|
||||
import com.gh.gamecenter.LibaoDetailActivity
|
||||
import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.common.utils.DialogHelper
|
||||
import com.gh.gamecenter.common.utils.EnvHelper
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.gamecollection.publish.GameCollectionEditActivity
|
||||
import com.gh.gamecenter.qa.BbsType
|
||||
@ -78,7 +83,7 @@ object DefaultUrlHandler {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_QQ_QUN -> {
|
||||
EntranceConsts.HOST_QQ_QUN -> {
|
||||
val key = uri.getQueryParameter("key")
|
||||
if (!DirectUtils.directToQqGroup(context, key)) {
|
||||
Utils.toast(context, "请检查是否已经安装手机QQ")
|
||||
@ -146,7 +151,7 @@ object DefaultUrlHandler {
|
||||
)
|
||||
}
|
||||
}
|
||||
EntranceUtils.HOST_UPLOAD_VIDEO -> {
|
||||
EntranceConsts.HOST_UPLOAD_VIDEO -> {
|
||||
val titleParameter = uri.getQueryParameter("title")
|
||||
val title = if (titleParameter.isNullOrEmpty()) "" else "#$titleParameter#"
|
||||
val categoryId = uri.getQueryParameter("category_id") ?: ""
|
||||
@ -157,16 +162,16 @@ object DefaultUrlHandler {
|
||||
val tagActivityName = uri.getQueryParameter("tagActivityName") ?: ""
|
||||
val linkEntity = VideoLinkEntity(title, categoryId, link, tagActivityId, tagActivityName)
|
||||
val simpleGameEntity = SimpleGameEntity(gameId, gameName)
|
||||
CheckLoginUtils.checkLogin(context, null, true, EntranceUtils.ENTRANCE_BROWSER) {
|
||||
DirectUtils.directToVideoManager(context, linkEntity, simpleGameEntity, EntranceUtils.ENTRANCE_BROWSER, "")
|
||||
CheckLoginUtils.checkLogin(context, null, true, EntranceConsts.ENTRANCE_BROWSER) {
|
||||
DirectUtils.directToVideoManager(context, linkEntity, simpleGameEntity, EntranceConsts.ENTRANCE_BROWSER, "")
|
||||
}
|
||||
}
|
||||
EntranceUtils.HOST_USERHOME -> {
|
||||
EntranceConsts.HOST_USERHOME -> {
|
||||
val position = uri.getQueryParameter("position")
|
||||
val subtype = uri.getQueryParameter("sub_type") ?: ""
|
||||
DirectUtils.directToHomeActivity(context, id, subtype, if (position.isNullOrEmpty()) -1 else position.toInt(), entrance, "")
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_MORE -> {
|
||||
EntranceConsts.HOST_VIDEO_MORE -> {
|
||||
val referer = uri.getQueryParameter("referer") ?: ""
|
||||
val type = uri.getQueryParameter("type") ?: ""
|
||||
val act = uri.getQueryParameter("act") ?: ""
|
||||
@ -198,48 +203,48 @@ object DefaultUrlHandler {
|
||||
sectionName
|
||||
)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_DETAIL -> {
|
||||
EntranceConsts.HOST_VIDEO_DETAIL -> {
|
||||
DirectUtils.directToVideoDetail(context, id, entrance, path)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_SINGLE -> {
|
||||
EntranceConsts.HOST_VIDEO_SINGLE -> {
|
||||
val referer = uri.getQueryParameter("referer") ?: ""
|
||||
DirectUtils.directToVideoDetail(
|
||||
context, id, VideoDetailContainerViewModel.Location.SINGLE_VIDEO.value,
|
||||
false, "", entrance, "", if (TextUtils.isEmpty(referer)) "" else referer
|
||||
)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_STREAMING_HOME -> {
|
||||
EntranceConsts.HOST_VIDEO_STREAMING_HOME -> {
|
||||
intent = Intent(context, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
intent.putExtra(MainActivity.SWITCH_TO_VIDEO, true)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_STREAMING_DESC -> {
|
||||
EntranceConsts.HOST_VIDEO_STREAMING_DESC -> {
|
||||
directToGameDetailVideoStreaming(context, id, entrance)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_COLLECTION -> {
|
||||
EntranceConsts.HOST_VIDEO_COLLECTION -> {
|
||||
directToGameVideo(context, id, entrance, "")
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_CATEGORY -> {
|
||||
EntranceConsts.HOST_CATEGORY -> {
|
||||
val title = uri.getQueryParameter("title")
|
||||
DirectUtils.directCategoryDirectory(context, id, title ?: "", entrance, "")
|
||||
}
|
||||
EntranceUtils.HOST_COLUMN_COLLECTION -> {
|
||||
EntranceConsts.HOST_COLUMN_COLLECTION -> {
|
||||
val name = uri.getQueryParameter("name")
|
||||
DirectUtils.directToColumnCollection(context, id, -1, entrance, name ?: "")
|
||||
}
|
||||
EntranceUtils.HOST_COLUMN -> {
|
||||
DirectUtils.directToSubject(context, id, uri.getQueryParameter(EntranceUtils.KEY_NAME), entrance)
|
||||
EntranceConsts.HOST_COLUMN -> {
|
||||
DirectUtils.directToSubject(context, id, uri.getQueryParameter(EntranceConsts.KEY_NAME), entrance)
|
||||
}
|
||||
EntranceUtils.HOST_COMMUNITY_QUESTION_LABEL_DETAIL -> {
|
||||
EntranceConsts.HOST_COMMUNITY_QUESTION_LABEL_DETAIL -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = uri.getQueryParameter("community_id") ?: ""
|
||||
community.name = uri.getQueryParameter("community_name") ?: ""
|
||||
val tag = uri.getQueryParameter("tag") ?: ""
|
||||
DirectUtils.directAskColumnLabelDetail(context, tag, community, entrance, "")
|
||||
}
|
||||
EntranceUtils.HOST_COMMUNITY_COLUMN_DETAIL -> {
|
||||
EntranceConsts.HOST_COMMUNITY_COLUMN_DETAIL -> {
|
||||
val community = CommunityEntity()
|
||||
community.id = uri.getQueryParameter("community_id") ?: ""
|
||||
community.name = uri.getQueryParameter("community_name") ?: ""
|
||||
@ -247,42 +252,42 @@ object DefaultUrlHandler {
|
||||
DirectUtils.directAskColumnDetail(context, columnId, community, entrance, "")
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_BLOCK -> {
|
||||
EntranceConsts.HOST_BLOCK -> {
|
||||
val name = uri.getQueryParameter("name")
|
||||
?: ""
|
||||
val entity = SubjectRecommendEntity(link = id, name = name, text = name)
|
||||
DirectUtils.directToBlock(context, entity, entrance)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_SERVER_BLOCK -> {
|
||||
EntranceConsts.HOST_SERVER_BLOCK -> {
|
||||
DirectUtils.directToGameServers(context, entrance = entrance, path = "")
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_AMWAY_BLOCK -> {
|
||||
EntranceConsts.HOST_AMWAY_BLOCK -> {
|
||||
DirectUtils.directToAmway(context, entrance = entrance, path = "")
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_HELP -> {
|
||||
EntranceConsts.HOST_HELP -> {
|
||||
val name = uri.getQueryParameter("name")
|
||||
?: ""
|
||||
DirectUtils.directToQa(context, name, id)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_HELP_COLLECTION -> {
|
||||
EntranceConsts.HOST_HELP_COLLECTION -> {
|
||||
val name = uri.getQueryParameter("name")
|
||||
?: ""
|
||||
DirectUtils.directToQaCollection(context, name, id)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_UPLOAD -> {
|
||||
EntranceConsts.HOST_GAME_UPLOAD -> {
|
||||
DirectUtils.directGameUpload(context, entrance = entrance, path = "")
|
||||
}
|
||||
EntranceUtils.HOST_GAME_ZONE -> {
|
||||
EntranceConsts.HOST_GAME_ZONE -> {
|
||||
val zoneUrl = uri.getQueryParameter("url") ?: ""
|
||||
DirectUtils.directGameZone(context, id, zoneUrl, entrance)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_LINK -> {
|
||||
EntranceConsts.HOST_LINK -> {
|
||||
try {
|
||||
val dataString = uri.getQueryParameter("data")
|
||||
if (!TextUtils.isEmpty(dataString)) {
|
||||
@ -296,43 +301,43 @@ object DefaultUrlHandler {
|
||||
}
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_NEWS -> {
|
||||
EntranceConsts.HOST_GAME_NEWS -> {
|
||||
DirectUtils.directToGameNews(
|
||||
context,
|
||||
uri.getQueryParameter(EntranceUtils.KEY_GAME_ID),
|
||||
uri.getQueryParameter(EntranceUtils.KEY_GAME_NAME),
|
||||
uri.getQueryParameter(EntranceConsts.KEY_GAME_ID),
|
||||
uri.getQueryParameter(EntranceConsts.KEY_GAME_NAME),
|
||||
entrance
|
||||
);
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_CALENDAR -> {
|
||||
directToGameServerCalendar(context, uri.getQueryParameter(EntranceUtils.KEY_GAME_ID))
|
||||
EntranceConsts.HOST_GAME_CALENDAR -> {
|
||||
directToGameServerCalendar(context, uri.getQueryParameter(EntranceConsts.KEY_GAME_ID))
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_HISTORY_APK -> {
|
||||
DirectUtils.directToHistoryApk(context, uri.getQueryParameter(EntranceUtils.KEY_GAME_ID))
|
||||
EntranceConsts.HOST_HISTORY_APK -> {
|
||||
DirectUtils.directToHistoryApk(context, uri.getQueryParameter(EntranceConsts.KEY_GAME_ID))
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_FORUM_DETAIL -> {
|
||||
EntranceConsts.HOST_FORUM_DETAIL -> {
|
||||
DirectUtils.directForumDetail(context, id, entrance)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_RATING_DETAIL -> {
|
||||
EntranceConsts.HOST_GAME_RATING_DETAIL -> {
|
||||
DirectUtils.directToGameRatingDetail(
|
||||
context,
|
||||
uri.getQueryParameter(EntranceUtils.KEY_GAME_ID),
|
||||
uri.getQueryParameter(EntranceUtils.KEY_COMMENT_ID),
|
||||
EntranceUtils.ENTRANCE_BROWSER
|
||||
uri.getQueryParameter(EntranceConsts.KEY_GAME_ID),
|
||||
uri.getQueryParameter(EntranceConsts.KEY_COMMENT_ID),
|
||||
EntranceConsts.ENTRANCE_BROWSER
|
||||
)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_FORUM -> {
|
||||
val position = uri.getQueryParameter(EntranceUtils.KEY_POSITION)?.toInt()
|
||||
EntranceConsts.HOST_FORUM -> {
|
||||
val position = uri.getQueryParameter(EntranceConsts.KEY_POSITION)?.toInt()
|
||||
|
||||
DirectUtils.directToForum(context, position ?: 0)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_UPLOAD_VIDEO_NEW -> {
|
||||
EntranceConsts.HOST_UPLOAD_VIDEO_NEW -> {
|
||||
val activityName = uri.getQueryParameter("activity_name") ?: ""
|
||||
val activityId = uri.getQueryParameter("activity_id") ?: ""
|
||||
val original = uri.getQueryParameter("original") ?: ""
|
||||
@ -370,39 +375,39 @@ object DefaultUrlHandler {
|
||||
)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_SUGGESTION -> {
|
||||
val platform = uri.getQueryParameter(EntranceUtils.KEY_PLATFORM)
|
||||
EntranceConsts.HOST_SUGGESTION -> {
|
||||
val platform = uri.getQueryParameter(EntranceConsts.KEY_PLATFORM)
|
||||
val platformName = PlatformUtils.getInstance(context).getPlatformName(platform)
|
||||
val gameId = uri.getQueryParameter(EntranceUtils.KEY_GAMEID)
|
||||
val packageMd5 = uri.getQueryParameter(EntranceUtils.KEY_PACKAGE_MD5)
|
||||
val isQaFeedback = uri.getQueryParameter(EntranceUtils.KEY_IS_QA_FEEDBACK) == "true"
|
||||
val gameId = uri.getQueryParameter(EntranceConsts.KEY_GAMEID)
|
||||
val packageMd5 = uri.getQueryParameter(EntranceConsts.KEY_PACKAGE_MD5)
|
||||
val isQaFeedback = uri.getQueryParameter(EntranceConsts.KEY_IS_QA_FEEDBACK) == "true"
|
||||
val content = if (TextUtils.isEmpty(gameId) || TextUtils.isEmpty(packageMd5)) String.format(
|
||||
"%s-%s-V%s,",
|
||||
uri.getQueryParameter(EntranceUtils.KEY_GAME_NAME),
|
||||
uri.getQueryParameter(EntranceConsts.KEY_GAME_NAME),
|
||||
if (TextUtils.isEmpty(platformName)) platform else platformName,
|
||||
uri.getQueryParameter(EntranceUtils.KEY_VERSION)
|
||||
uri.getQueryParameter(EntranceConsts.KEY_VERSION)
|
||||
) else String.format(
|
||||
"%s-%s-V%s\n游戏ID:%s\n游戏包MD5:%s\n",
|
||||
uri.getQueryParameter(EntranceUtils.KEY_GAME_NAME),
|
||||
uri.getQueryParameter(EntranceConsts.KEY_GAME_NAME),
|
||||
if (TextUtils.isEmpty(platformName)) platform else platformName,
|
||||
uri.getQueryParameter(EntranceUtils.KEY_VERSION), gameId, packageMd5
|
||||
uri.getQueryParameter(EntranceConsts.KEY_VERSION), gameId, packageMd5
|
||||
)
|
||||
val qaId = uri.getQueryParameter("qa_id") ?: ""
|
||||
val qaContentId = uri.getQueryParameter(EntranceUtils.KEY_QA_CONTENT_ID) ?: ""
|
||||
val qaTitle = uri.getQueryParameter(EntranceUtils.KEY_QA_TITLE)
|
||||
val qaContentId = uri.getQueryParameter(EntranceConsts.KEY_QA_CONTENT_ID) ?: ""
|
||||
val qaTitle = uri.getQueryParameter(EntranceConsts.KEY_QA_TITLE)
|
||||
if (!TextUtils.isEmpty(qaId)) {
|
||||
directToQa(context, qaTitle, qaId)
|
||||
} else {
|
||||
directToFeedback(context, content, null, isQaFeedback, qaContentId, EntranceUtils.ENTRANCE_BROWSER)
|
||||
directToFeedback(context, content, null, isQaFeedback, qaContentId, EntranceConsts.ENTRANCE_BROWSER)
|
||||
}
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_HELP_AND_FEEDBACK -> {
|
||||
EntranceConsts.HOST_HELP_AND_FEEDBACK -> {
|
||||
val position = uri.getQueryParameter("position") ?: ""
|
||||
DirectUtils.directToHelpAndFeedback(context, position.toInt())
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_HELP_DETAIL -> {
|
||||
EntranceConsts.HOST_HELP_DETAIL -> {
|
||||
var url = uri.getQueryParameter("url")
|
||||
if (!url.isNullOrEmpty()) {
|
||||
context.startActivity(WebActivity.getIntent(context, url, false))
|
||||
@ -419,16 +424,19 @@ object DefaultUrlHandler {
|
||||
}
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_COLLECTION_DETAIL -> {
|
||||
EntranceConsts.HOST_GAME_COLLECTION_DETAIL -> {
|
||||
DirectUtils.directToGameCollectionDetail(context, id, entrance)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_COLLECTION_SQUARE -> {
|
||||
EntranceConsts.HOST_GAME_COLLECTION_SQUARE -> {
|
||||
DirectUtils.directToGameCollectionSquare(context, entrance)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_COLLECTION_EDIT -> {
|
||||
context.startActivity(GameCollectionEditActivity.getIntent(context, entrance))
|
||||
EntranceConsts.HOST_GAME_COLLECTION_EDIT -> {
|
||||
val activityId = uri.getQueryParameter("activity_id") ?: ""
|
||||
val activityName = uri.getQueryParameter("activity_name") ?: ""
|
||||
val gameId = uri.getQueryParameter("game_id") ?: ""
|
||||
context.startActivity(GameCollectionEditActivity.getIntent(context, activityId, activityName, gameId, entrance))
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
||||
@ -2,13 +2,13 @@ package com.gh.common
|
||||
|
||||
import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.loghub.LoghubUtils
|
||||
import com.gh.common.util.doOnMainProcessOnly
|
||||
import com.gh.common.util.tryCatchInRelease
|
||||
import com.gh.gamecenter.common.loghub.LoghubUtils
|
||||
import com.gh.gamecenter.common.utils.doOnMainProcessOnly
|
||||
import com.gh.gamecenter.common.utils.tryCatchInRelease
|
||||
import com.gh.common.videolog.VideoRecordUtils
|
||||
import com.gh.download.DownloadDataHelper
|
||||
import com.gh.gamecenter.entity.TimeEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
//package com.gh.common
|
||||
//
|
||||
//import android.content.BroadcastReceiver
|
||||
//import android.content.Context
|
||||
//import android.content.Intent
|
||||
//import com.gh.common.im.ImManager
|
||||
//import com.gh.gamecenter.manager.UserManager
|
||||
//import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
//import com.halo.assistant.HaloApp
|
||||
//import com.m7.imkfsdk.chat.ChatActivity
|
||||
//import io.reactivex.schedulers.Schedulers
|
||||
//
|
||||
///**
|
||||
// * 可使用 [LocalBroadcastManager] 来进行简单的模块间消息通知
|
||||
// */
|
||||
//
|
||||
//class LocalBroadcastReceiver : BroadcastReceiver() {
|
||||
//
|
||||
// override fun onReceive(context: Context?, intent: Intent?) {
|
||||
// intent?.let {
|
||||
// when (intent.action) {
|
||||
// ChatActivity.ACTION_DISMISS_FLOATING_WINDOW -> {
|
||||
// ImManager.dismissFloatingWindow()
|
||||
//
|
||||
// RetrofitManager.getInstance().api.postImEnding(UserManager.getInstance().userId)
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .subscribe()
|
||||
// }
|
||||
//
|
||||
// ChatActivity.ACTION_HIDE_UNREAD_DOT -> {
|
||||
// ImManager.updateShouldShowFloatingWindowDot(false)
|
||||
// }
|
||||
//
|
||||
// else -> return
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
@ -1,117 +0,0 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import com.gh.gamecenter.entity.AliasEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
object PushManager {
|
||||
|
||||
var deviceToken: String? = ""
|
||||
|
||||
private var mPreviousAlias: AliasEntity? = null
|
||||
private var mApplication = HaloApp.getInstance().application
|
||||
|
||||
const val SP_PUSH_ALIAS = "push_alias"
|
||||
|
||||
@JvmStatic
|
||||
fun init(channel: String) {
|
||||
// tryWithDefaultCatch {
|
||||
// //初始化友盟推送
|
||||
// UMConfigure.init(mApplication, Config.UMENG_APPKEY, channel, UMConfigure.DEVICE_TYPE_PHONE, Config.UMENG_MESSAGE_SECRET)
|
||||
//
|
||||
// val pushAgent = PushAgent.getInstance(mApplication)
|
||||
//
|
||||
// runOnIoThread { registerDevice() }
|
||||
//
|
||||
// // 注册小米、华为和魅族通道
|
||||
// MiPushRegistar.register(mApplication, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
|
||||
// HuaWeiRegister.register(mApplication)
|
||||
// MeizuRegister.register(mApplication, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
|
||||
//
|
||||
// val aliasInSp = PreferenceManager.getDefaultSharedPreferences(mApplication).getString(SP_PUSH_ALIAS, "")
|
||||
// mPreviousAlias = aliasInSp?.toObject()
|
||||
//
|
||||
// if (mPreviousAlias == null) {
|
||||
// getAndSetAlias()
|
||||
// }
|
||||
//
|
||||
// // 完全自定义处理(透传)
|
||||
// pushAgent.setPushIntentServiceClass(GHUmengNotificationService::class.java)
|
||||
// }
|
||||
}
|
||||
|
||||
private fun registerDevice() {
|
||||
// PushAgent.getInstance(mApplication).register(object : IUmengRegisterCallback {
|
||||
// override fun onSuccess(dToken: String) {
|
||||
// //注册成功会返回device token
|
||||
// deviceToken = dToken
|
||||
// getAndSetAlias()
|
||||
// Utils.log("deviceToken::$dToken")
|
||||
// }
|
||||
//
|
||||
// override fun onFailure(s: String, s1: String) {
|
||||
// Utils.log("deviceToken::" + "注册失败")
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun getAndSetAlias() {
|
||||
// if (deviceToken.isNullOrEmpty()) {
|
||||
// registerDevice()
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// val meta = MetaUtil.getMeta()
|
||||
//
|
||||
// val jsonObject = JSONObject()
|
||||
// jsonObject.put("device_token", deviceToken)
|
||||
// jsonObject.put("imei", meta.imei)
|
||||
// jsonObject.put("android_id", meta.android_id)
|
||||
// jsonObject.put("model", meta.model)
|
||||
// jsonObject.put("manufacturer", meta.manufacturer)
|
||||
// jsonObject.put("os", meta.os)
|
||||
// jsonObject.put("os_version", meta.android_version)
|
||||
// jsonObject.put("mac", meta.mac)
|
||||
// jsonObject.put("gid", meta.gid)
|
||||
//
|
||||
// val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
//
|
||||
// RetrofitManager.getInstance().api.getAlias(body)
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .subscribe(
|
||||
// { setAlias(it) },
|
||||
// { it.printStackTrace() }
|
||||
// )
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setAlias(alias: AliasEntity) {
|
||||
// val pushAgent = PushAgent.getInstance(mApplication)
|
||||
//
|
||||
// mPreviousAlias = alias
|
||||
// PreferenceManager.getDefaultSharedPreferences(mApplication).edit {
|
||||
// putString(SP_PUSH_ALIAS, mPreviousAlias?.toJson())
|
||||
// }
|
||||
//
|
||||
// pushAgent.setAlias(alias.alias, alias.aliasType) { b, s ->
|
||||
// Utils.log("注册别名 $b + $s")
|
||||
// }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun deleteAlias() {
|
||||
// val pushAgent = PushAgent.getInstance(mApplication)
|
||||
//
|
||||
// mPreviousAlias?.let {
|
||||
// pushAgent.deleteAlias(it.alias, it.aliasType) { b, s ->
|
||||
// Utils.log("删除别名 $b + $s")
|
||||
// }
|
||||
// }
|
||||
// PreferenceManager.getDefaultSharedPreferences(mApplication).edit {
|
||||
// putString(SP_PUSH_ALIAS, "")
|
||||
// }
|
||||
// mPreviousAlias = null
|
||||
}
|
||||
}
|
||||
@ -1,123 +0,0 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.gh.base.GHThreadFactory
|
||||
import com.halo.assistant.HaloApp
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
/**
|
||||
* 统计用户在当前 Fragment/Activity 的停留时间,在 onViewDestroy 或 onDestroy 里获取 elapsedTime 即可,单位为秒
|
||||
*/
|
||||
class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) {
|
||||
|
||||
constructor() : this(null, null)
|
||||
|
||||
constructor(fragment: Fragment) : this(fragment, null)
|
||||
|
||||
constructor(activity: Activity) : this(null, activity)
|
||||
|
||||
private var isWorking = false
|
||||
|
||||
var elapsedTime: Int = 0
|
||||
|
||||
var timeout: Int = 0
|
||||
var timeoutCallback: TimeoutCallback? = null
|
||||
|
||||
init {
|
||||
activity?.application?.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
|
||||
override fun onActivityStarted(a: Activity) {
|
||||
}
|
||||
|
||||
override fun onActivitySaveInstanceState(a: Activity, outState: Bundle) {
|
||||
}
|
||||
|
||||
override fun onActivityStopped(a: Activity) {
|
||||
}
|
||||
|
||||
override fun onActivityCreated(a: Activity, savedInstanceState: Bundle?) {
|
||||
}
|
||||
|
||||
override fun onActivityPaused(a: Activity) {
|
||||
if (activity == a) {
|
||||
pauseCounting()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResumed(a: Activity) {
|
||||
if (activity == a) {
|
||||
resumeCounting()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityDestroyed(a: Activity) {
|
||||
if (activity == a) {
|
||||
HaloApp.getInstance().application.unregisterActivityLifecycleCallbacks(this)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
fragment?.fragmentManager?.registerFragmentLifecycleCallbacks(
|
||||
object : FragmentManager.FragmentLifecycleCallbacks() {
|
||||
override fun onFragmentResumed(fm: FragmentManager, f: Fragment) {
|
||||
if (f === fragment) {
|
||||
resumeCounting()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFragmentPaused(fm: FragmentManager, f: Fragment) {
|
||||
if (f === fragment) {
|
||||
pauseCounting()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFragmentViewDestroyed(fm: FragmentManager, f: Fragment) {
|
||||
if (f === fragment) {
|
||||
fragment.fragmentManager?.unregisterFragmentLifecycleCallbacks(this)
|
||||
}
|
||||
}
|
||||
}, false)
|
||||
}
|
||||
|
||||
fun resumeCounting() {
|
||||
isWorking = true
|
||||
TimeElapsedThreadHolder.threadService.execute {
|
||||
while (isWorking) {
|
||||
try {
|
||||
elapsedTime++
|
||||
if (timeout != 0 && timeout == elapsedTime) {
|
||||
timeoutCallback?.run {
|
||||
AppExecutor.uiExecutor.execute {
|
||||
onTimeout()
|
||||
}
|
||||
}
|
||||
}
|
||||
Thread.sleep(1000)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun resetCounting() {
|
||||
elapsedTime = 0
|
||||
}
|
||||
|
||||
fun pauseCounting() {
|
||||
isWorking = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object TimeElapsedThreadHolder {
|
||||
val threadService: ExecutorService by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("TIME_ELAPSED_THREAD")) }
|
||||
}
|
||||
|
||||
interface TimeoutCallback {
|
||||
fun onTimeout()
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
package com.gh.common
|
||||
|
||||
typealias OnFastClickListener = (isSuccess: Boolean) -> Unit
|
||||
@ -1,16 +0,0 @@
|
||||
package com.gh.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 标记那些不需要检查的同步字段
|
||||
*
|
||||
* 同步字段冲突时使用
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SyncIgnore {
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
package com.gh.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SyncPage {
|
||||
String[] syncNames();
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
package com.gh.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Synchronize {
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package com.gh.common.avoidcallback;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
public class ActivityResultInfo {
|
||||
private int resultCode;
|
||||
private Intent data;
|
||||
|
||||
public ActivityResultInfo(int resultCode, Intent data) {
|
||||
this.resultCode = resultCode;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
||||
public int getResultCode() {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
public void setResultCode(int resultCode) {
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
public Intent getData() {
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(Intent data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
package com.gh.common.avoidcallback
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.SparseArray
|
||||
import androidx.fragment.app.Fragment
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.subjects.PublishSubject
|
||||
|
||||
class AvoidOnResultFragment : Fragment() {
|
||||
private val mSubjects = SparseArray<PublishSubject<ActivityResultInfo>>()
|
||||
private val mCallbacks = SparseArray<Callback>()
|
||||
|
||||
private var requestCode = 1000
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
retainInstance = true
|
||||
}
|
||||
|
||||
fun startForResult(intent: Intent): Observable<ActivityResultInfo> {
|
||||
val subject = PublishSubject.create<ActivityResultInfo>()
|
||||
return subject.doOnSubscribe {
|
||||
mSubjects.put(requestCode, subject)
|
||||
startActivityForResult(intent, requestCode)
|
||||
requestCode++
|
||||
}
|
||||
}
|
||||
|
||||
fun startForResult(intent: Intent, callback: Callback) {
|
||||
mCallbacks.put(requestCode, callback)
|
||||
startActivityForResult(intent, requestCode)
|
||||
requestCode++
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
val subject = mSubjects.get(requestCode)
|
||||
if (subject != null) {
|
||||
subject.onNext(ActivityResultInfo(resultCode, data))
|
||||
subject.onComplete()
|
||||
}
|
||||
mSubjects.remove(requestCode)
|
||||
val callback = mCallbacks.get(requestCode)
|
||||
callback?.onActivityResult(resultCode, data)
|
||||
mCallbacks.remove(requestCode)
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
package com.gh.common.avoidcallback
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import io.reactivex.Observable
|
||||
|
||||
|
||||
class AvoidOnResultManager {
|
||||
val TAG = "AvoidOnResultManager"
|
||||
private var mAvoidOnResultFragment: AvoidOnResultFragment
|
||||
|
||||
private constructor(activity: AppCompatActivity) {
|
||||
mAvoidOnResultFragment = getAvoidOnResultFragment(activity)
|
||||
}
|
||||
|
||||
private constructor(fragment: Fragment) : this(fragment.activity as AppCompatActivity)
|
||||
|
||||
companion object {
|
||||
fun getInstance(activity: AppCompatActivity): AvoidOnResultManager {
|
||||
return AvoidOnResultManager(activity)
|
||||
}
|
||||
|
||||
fun getInstance(fragment: Fragment): AvoidOnResultManager {
|
||||
return AvoidOnResultManager(fragment)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAvoidOnResultFragment(activity: AppCompatActivity): AvoidOnResultFragment {
|
||||
var avoidOnResultFragment = findAvoidOnResultFragment(activity)
|
||||
if (avoidOnResultFragment == null) {
|
||||
avoidOnResultFragment = AvoidOnResultFragment()
|
||||
val fragmentManager = activity.supportFragmentManager
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.add(avoidOnResultFragment, TAG)
|
||||
.commitAllowingStateLoss()
|
||||
fragmentManager.executePendingTransactions()
|
||||
}
|
||||
return avoidOnResultFragment
|
||||
}
|
||||
|
||||
private fun findAvoidOnResultFragment(activity: AppCompatActivity): AvoidOnResultFragment? {
|
||||
return activity.supportFragmentManager.findFragmentByTag(TAG) as? AvoidOnResultFragment
|
||||
}
|
||||
|
||||
fun startForResult(intent: Intent, callback: Callback) {
|
||||
mAvoidOnResultFragment.startForResult(intent, callback)
|
||||
}
|
||||
|
||||
fun startForResult(clazz: Class<*>, callback: Callback) {
|
||||
val intent = Intent(mAvoidOnResultFragment.activity, clazz)
|
||||
mAvoidOnResultFragment.startForResult(intent, callback)
|
||||
}
|
||||
|
||||
fun startForResult(intent: Intent): Observable<ActivityResultInfo> {
|
||||
return mAvoidOnResultFragment.startForResult(intent)
|
||||
}
|
||||
|
||||
fun startForResult(clazz: Class<*>): Observable<ActivityResultInfo> {
|
||||
val intent = Intent(mAvoidOnResultFragment.activity, clazz)
|
||||
return mAvoidOnResultFragment.startForResult(intent)
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
package com.gh.common.avoidcallback
|
||||
|
||||
import android.content.Intent
|
||||
|
||||
interface Callback {
|
||||
fun onActivityResult(resultCode: Int, data: Intent?)
|
||||
}
|
||||
@ -1,26 +1,28 @@
|
||||
package com.gh.common.constant;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.util.EnvHelper;
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.gh.gamecenter.common.utils.EnvHelper;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.common.util.PackageHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.SuggestionActivity;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.gh.gamecenter.entity.GameGuidePopupEntity;
|
||||
import com.gh.gamecenter.entity.NewSettingsEntity;
|
||||
import com.gh.gamecenter.entity.NewsEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -33,8 +35,6 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.ResponseBody;
|
||||
@ -45,10 +45,6 @@ public class Config {
|
||||
public static final String API_HOST = EnvHelper.getHost();
|
||||
public static final String NEW_API_HOST = EnvHelper.getNewHost();
|
||||
|
||||
/**
|
||||
* 需要配置的请使用{@link PreferenceManager#getDefaultSharedPreferences(Context)}
|
||||
*/
|
||||
|
||||
// Third-Party confs
|
||||
public static final String WECHAT_APPID = BuildConfig.WECHAT_APPID;
|
||||
public static final String WECHAT_SECRET = BuildConfig.WECHAT_SECRET;
|
||||
@ -59,10 +55,7 @@ public class Config {
|
||||
// http://www.ghzs666.com/article/${articleId}.html
|
||||
public static final String URL_ARTICLE = "http://www.ghzs666.com/article/"; // ghzs/ghzs666 统一
|
||||
|
||||
public static final String DEFAULT_CHANNEL = "GH_TEST3";
|
||||
public static final String DEFAULT_CHANNEL_FOR_RELEASE = "GH_LOST"; // 正式包的缺省渠道,避免因渠道丢失而回落到测试渠道
|
||||
|
||||
private static String SETTINGS_KEY = "settingsKey";
|
||||
private static final String SETTINGS_KEY = "settingsKey";
|
||||
|
||||
private static SettingsEntity mSettingsEntity;
|
||||
private static NewSettingsEntity mNewSettingsEntity;
|
||||
@ -270,13 +263,6 @@ public class Config {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isGameDomeSwitchOpen() {
|
||||
return getSettings() != null && getSettings().getGameDomeSwitch().equals("on");
|
||||
}
|
||||
public static boolean isPermissionPopupSwitchOpen() {
|
||||
return getSettings() != null && getSettings().getPermissionPopupSwitch().equals("on");
|
||||
}
|
||||
|
||||
public static void fixHideFunction() {
|
||||
SharedPreferences preferences = PreferenceManager.
|
||||
getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
|
||||
|
||||
@ -1,427 +0,0 @@
|
||||
package com.gh.common.constant;
|
||||
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.TimeUtils;
|
||||
import com.halo.assistant.HaloApp;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final int SEND_NEWS_FEEDBACK = 0x126;
|
||||
public static final int SEND_COMMENT_FEEDBACK = 0x127;
|
||||
|
||||
public final static int LIST_FOOTER_ITEM = 1;
|
||||
public final static int LIST_HEAD_ITEM = 1;
|
||||
|
||||
public final static int NOT_NETWORK_CODE = 504; // 没有网络的状态码(应该是这个吧!)
|
||||
|
||||
public static final String USER_TOKEN_KEY = "userTokenKey";
|
||||
public static final String USER_INFO_KEY = "userInfoKey";
|
||||
|
||||
public static final String WELCOME_DIALOG_ID = "welcome_dialog_id";
|
||||
public static final String WELCOME_DIALOG_LINK_TITLE = "welcome_dialog_link_title";
|
||||
|
||||
public static final String DEVICE_KEY = "deviceKey";
|
||||
|
||||
public static final String HAS_REQUESTED_NOTIFICATION_PERMISSIONS = "has_requested_notification_permissions";
|
||||
|
||||
public static final String SHOULD_SHOW_VIDEO_MOBILE_WARNING = "should_show_video_mobile_warning";
|
||||
|
||||
public static final String GAME_DETAIL_COME_IN = "game_detail_come_in"; // 从游戏详情进入
|
||||
|
||||
public static final String SPLASH_AD = "splash_ad"; // 启动广告
|
||||
|
||||
public static final String XPOSED_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
|
||||
|
||||
public static final String EB_QUIT_LOGIN = "quit_login";
|
||||
|
||||
public static final String EB_SHOW_AD = "show_ad";
|
||||
|
||||
public static final String EB_GAME_DETAIL = "eb_game_detail";
|
||||
|
||||
// 用于避免历史下载影响到部分依赖名字作为数据更新条件的修饰符
|
||||
public static final String GAME_NAME_DECORATOR = " ";
|
||||
|
||||
// 游戏详情进入时的自定义栏目标签是否已经默认展开过一次的标记
|
||||
public static final String SP_HAS_EXPANDED_GAME_DETAIL_TAGS = "has_expanded_game_detail_tags";
|
||||
// 游戏详情进入时的自定义栏目标签是否已经显示过一次展开更多的浮窗提示
|
||||
public static final String SP_HAS_SHOWN_EXPANDED_GAME_DETAIL_TAGS_HINT = "has_shown_expanded_game_detail_tags_hint";
|
||||
|
||||
// 最近显示的弹窗信息
|
||||
public static final String SP_LAST_OPENING_ID = "last_opening_dialog_id";
|
||||
public static final String SP_LAST_OPENING_TIME = "last_opening_dialog_time";
|
||||
|
||||
public static final String SP_LAST_ACCEPTED_PRIVACY_DIALOG_ID = "last_accepted_privacy_dialog_id";
|
||||
|
||||
// 游戏图标和图标角标
|
||||
public static final String RAW_GAME_ICON = "raw_game_icon";
|
||||
public static final String GAME_ICON_SUBSCRIPT = "game_icon_subscript";
|
||||
|
||||
public static final String IS_PLATFORM_RECOMMEND = "isPlatformRecommend";
|
||||
|
||||
// 下载 id,一般来说跟下载文件名一样
|
||||
public static final String DOWNLOAD_ID = "download_id";
|
||||
|
||||
public static final String GHZS_GAME_ID = "5ae4462c2924bc7936438d07";
|
||||
|
||||
public static final String EXTRA_DOWNLOAD_TYPE = "extra_download_type";
|
||||
public static final String SILENT_UPDATE = "静默更新";
|
||||
public static final String SIMULATOR_DOWNLOAD = "下载模拟器";
|
||||
public static final String SIMULATOR_GAME = "simulator_game";
|
||||
public static final String SIMULATOR = "simulator";
|
||||
public static final String GAME_NAME = "game_name";
|
||||
public static final String SIMULATOR_DOWNLOAD_START_TIME = "simulator_download_start_time";
|
||||
public static final String LAST_GHZS_UPDATE_FILE_SIZE = "last_ghzs_update_file_size";
|
||||
|
||||
// 新用户首次启动光环的时间
|
||||
public static final String SP_INITIAL_USAGE_TIME = "initial_usage_time";
|
||||
|
||||
public static final String SP_IMEI = "imei";
|
||||
public static final String SP_ANDROID_ID = "android_id";
|
||||
|
||||
// 安装类型
|
||||
public static final String SP_INSTALL_TYPE = "install_type";
|
||||
|
||||
public static final String LAST_INSTALL_GAME = "last_install_game";
|
||||
|
||||
// 骨架图配置
|
||||
public static final int SHIMMER_ANGLE = 18;
|
||||
public static final int SHIMMER_DURATION = 1200;
|
||||
public static final float MASK_WIDTH = 0.8F;
|
||||
public static final float GRADIENT_CENTER_COLOR_WIDTH = 0.1F;
|
||||
|
||||
//引导设置 “通知管理” 引导弹窗
|
||||
public static final String SP_SHOWED_NOTIFICATION_LOGIN = "show_notification_login_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_QUESTION = "show_notification_question_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_ANSWER = "show_notification_answer_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_ARTICLE = "show_notification_article_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_VIDEO = "show_notification_video_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_RATING = "show_notification_rating_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_GIFT = "show_notification_gift_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_RESERVE_GAME = "show_notification_reserve_game_hint";
|
||||
public static final String SP_SHOWED_NOTIFICATION_FEEDBACK = "show_notification_feedback_hint";
|
||||
// 新版本 也要触发一次“通知管理” 引导弹窗
|
||||
public static final String SP_SHOWED_NOTIFICATION_NEW_VERSION = "show_notification_new_version";
|
||||
// 今天是否已经触发了 “通知管理” 引导弹窗
|
||||
public static final String SP_IS_SHOWED_NOTIFICATION_TODAY = "show_is_notification_today";
|
||||
// v4.0.0已废弃,标记安装的游戏为已玩过弹窗,最多取消2次 (https://gitlab.ghzs.com/pm/halo-app-issues/issues/722 调整为版本相关) (不是常量了也放这里好像有点奇怪)
|
||||
public static final String SP_MARK_INSTALLED_GAME = "mark_installed_game" + PackageUtils.getGhVersionName();
|
||||
// 标记安装的游戏为已玩过弹窗(个人主页最多弹一次)
|
||||
public static final String SP_MARK_INSTALLED_GAME_USER_HOME = "mark_installed_game_user_home" + PackageUtils.getGhVersionName();
|
||||
// 标记安装的游戏为已玩过弹窗(我的游戏最多弹一次)
|
||||
public static final String SP_MARK_INSTALLED_GAME_MY_GAME = "mark_installed_game_my_game" + PackageUtils.getGhVersionName();
|
||||
//视频详情滑动引导
|
||||
public static final String SP_SHOW_SLIDE_GUIDE = "show_slide_guide";
|
||||
//视频详情点击引导
|
||||
public static final String SP_SHOW_CLICK_GUIDE = "show_click_guide";
|
||||
//视频详情双击点赞引导
|
||||
public static final String SP_SHOW_DOUBLE_CLICK_GUIDE = "show_double_click_guide";
|
||||
//顶部视频声音状态,重启恢复
|
||||
public static final String SP_TOP_VIDEO_VOICE = "top_video_voice";
|
||||
//我的光环提醒设置已读
|
||||
public static final String SP_ADDONS_FUNCS_HAVE_READ = "addons_funcs_have_read";
|
||||
//视频非wifi提醒只提醒一次,重启恢复
|
||||
public static final String SP_NON_WIFI_TIPS = "non_wifi_tips";
|
||||
//首页视频最新tab提示
|
||||
public static final String SP_HOME_NEW_VIDEO_TIPS = "home_new_video";
|
||||
//游戏设备弹窗提示
|
||||
public static final String 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 SP_GH_RED_POINT_REMIND = "gh_red_point_remind";
|
||||
//论坛首页引导
|
||||
public static final String SP_FORUM_GUIDE = "forum_guide";
|
||||
//礼仪考试开启状态
|
||||
public static final String SP_REGULATION_TEST_LAST_REMIND_TIME = "regulation_test_last_remind_time";
|
||||
public static final String SP_REGULATION_TEST_STATUS = "regulation_test_status";
|
||||
public static final String SP_REGULATION_TEST_PASS_STATUS = "regulation_test_pass_status";
|
||||
//相同设备号,每一种第三方登录方式登录后弹出绑定手机页面的次数
|
||||
public static final String SP_QQ_SHOW_BIND_PHONE_TIME = "qq_show_bind_phone_time" + HaloApp.getInstance().getGid();
|
||||
public static final String SP_WECHAT_SHOW_BIND_PHONE_TIME = "wechat_show_bind_phone_time" + HaloApp.getInstance().getGid();
|
||||
public static final String SP_WEIBO_SHOW_BIND_PHONE_TIME = "weibo_show_bind_phone_time" + HaloApp.getInstance().getGid();
|
||||
public static final String SP_DOUYIN_SHOW_BIND_PHONE_TIME = "douyin_show_bind_phone_time" + HaloApp.getInstance().getGid();
|
||||
//隐私政策是否有更新
|
||||
public static final String SP_PRIVACY_CURRENT_MD5 = "sp_privacy_current_md5";
|
||||
public static final String SP_PRIVACY_MINE_MD5 = "sp_privacy_mine_md5";
|
||||
public static final String SP_PRIVACY_SETTING_MD5 = "sp_privacy_setting_md5";
|
||||
public static final String SP_PRIVACY_MD5 = "sp_privacy_md5";
|
||||
|
||||
public static final String SP_IS_USER_ACCEPTED_PRIVACY_STATEMENT = "has_user_accepted_privacy_statement";
|
||||
public static final String SP_BRAND_NEW_USER = "brand_new_user";
|
||||
//包名检测是否点击不再提示
|
||||
public static final String SP_PACKAGE_CHECK = "package_check";
|
||||
//游戏详情预约引导提示
|
||||
public static final String SP_GAME_DETAIL_RESERVE_GUIDE = "game_detail_reserve_guide";
|
||||
|
||||
public static final String SP_XAPK_UNZIP_ACTIVITY = "xapk_unzip_activity";
|
||||
public static final String SP_XAPK_URL = "xapk_url";
|
||||
|
||||
//游戏详情推荐弹窗
|
||||
public static final String SP_RECOMMEND_POPUP = "recommend_popup";
|
||||
|
||||
// 设备实名信息
|
||||
public static final String SP_DEVICE_CERTIFICATION_PREFIX = "device_certification_prefix";
|
||||
|
||||
// 使用浏览器安装开关
|
||||
public static final String SP_USE_BROWSER_TO_INSTALL = "use_browser_to_install";
|
||||
// 游戏详情页底部使用浏览器安装提示
|
||||
public static final String SP_SHOULD_SHOW_GAMEDETAIL_USE_BROWSER_TO_INSTALL_HINT = "should_show_gamedetail_use_browser_to_install_hint";
|
||||
// 第一次普通安装推荐使用浏览器安装提示
|
||||
public static final String SP_SHOULD_SHOW_USE_BROWSER_TO_INSTALL_HINT = "should_show_use_browser_to_install_hint";
|
||||
// 游戏详情切换安装方式显示开关
|
||||
public static final String SP_SWITCH_INSTALL_VISIBLE = "sp_switch_install_visible";
|
||||
|
||||
//模拟器管理引导
|
||||
public static final String SP_SIMULATOR_GUIDE = "simulator_guide";
|
||||
//模拟器游戏引导
|
||||
public static final String SP_SIMULATOR_GAME_GUIDE = "simulator_game_guide";
|
||||
|
||||
// 临时设备ID (本地生成,与GID不相关)
|
||||
public static final String SP_TEMPORARY_DEVICE_ID = "temporary_device_id";
|
||||
|
||||
// 光环助手最后的安装(更新)时间
|
||||
public static final String SP_GH_LAST_UPDATE_TIME = "gh_last_update_time";
|
||||
|
||||
//首页视频播放进度
|
||||
public static final String SP_HOME_VIDEO_PLAY_RECORD = "home_video_play_record";
|
||||
|
||||
// 论坛内容视频播放进度
|
||||
public static final String SP_CONTENT_VIDEO_PLAY_RECORD = "content_video_play_record";
|
||||
|
||||
// 用户是否曾经永久拒绝过存储权限
|
||||
public static final String SP_USER_HAS_PERMANENTLY_DENIED_STORAGE_PERMISSION = "user_has_permanently_denied_storage_permission";
|
||||
|
||||
// 是否已经填写邀请码
|
||||
public static final String SP_HAS_COMPLETE_INVITE_CODE = "has_complete_invite_code";
|
||||
|
||||
// 补充配置项
|
||||
public static final String SP_NEW_SETTINGS = "new_settings";
|
||||
|
||||
// 头像挂件ID
|
||||
public static final String SP_CHOOSE_AVATAR_ID = "choose_avatar_id";
|
||||
|
||||
// 是否第一次进入新分类2.0
|
||||
public static final String SP_FIRST_ENTER_CATEGORY_V2 = "first_enter_category_v2";
|
||||
|
||||
// 是否成功取过号
|
||||
public static final String SP_HAS_GET_PHONE_INFO = "has_get_phone_info";
|
||||
|
||||
// 是否点击过更换背景按钮
|
||||
public static final String SP_HAS_CLICK_CHANGE_BG = "has_click_change_bg";
|
||||
// 是否显示更换背景提示
|
||||
public static final String SP_SHOW_CHANGE_BG_TIPS = "show_change_bg_tips" + TimeUtils.getStartTimeOfToday();
|
||||
|
||||
// 新分类2.0引导
|
||||
public static final String SP_SHOW_CATEGORY_GUIDE = "show_category_guide";
|
||||
|
||||
// 用户是否需要 weibo x86 so
|
||||
public static final String SP_USER_NEED_WEIBO_X86_SO = "user_need_weibo_x86_so";
|
||||
|
||||
// 当前设备是不是模拟器
|
||||
public static final String SP_IS_EMULATOR = "is_emulator";
|
||||
|
||||
// 内容视频播放选项
|
||||
public static final String SP_CONTENT_VIDEO_OPTION = "content_video_option";
|
||||
// 首页/游戏详情页视频播放选项
|
||||
public static final String SP_HOME_OR_DETAIL_VIDEO_OPTION = "home_or_detail_video_option";
|
||||
// 是否默认静音播放视频
|
||||
public static final String SP_VIDEO_PLAY_MUTE = "video_play_mute";
|
||||
//帖子发布页上传视频引导
|
||||
public static final String SP_ARTICLE_VIDEO_GUIDE = "article_video_guide";
|
||||
//问题发布页上传视频引导
|
||||
public static final String SP_QUESTION_VIDEO_GUIDE = "question_video_guide";
|
||||
// 论坛详情申请版主引导
|
||||
public static final String SP_FORUM_DETAIL_MODERATOR_GUIDE = "forum_detail_moderator_guide";
|
||||
// 游戏详情安装引导
|
||||
public static final String SP_GAME_DETAIL_INSTALL_GUIDE = "game_detail_install_guide";
|
||||
public static final String SP_SHOULD_SHOW_GAME_DETAIL_INSTALL_GUIDE = "should_show_game_detail_install_guide";
|
||||
// 儿童/青少年模式
|
||||
public static final String SP_TEENAGER_MODE = "teenager_mode";
|
||||
// 我的游戏引导
|
||||
public static final String SP_MY_GAME_GUIDE = "my_game_guide";
|
||||
//微信绑定配置信息
|
||||
public static final String SP_WECHAT_CONFIG = "wechat_config";
|
||||
//游戏库导航栏小红点提示
|
||||
public static final String SP_GAME_NAVIGATION = "game_navigation";
|
||||
|
||||
//手机号码匹配规则
|
||||
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
|
||||
public static final String REGEX_ACCOUNT = "^[a-zA-Z_]\\w{5,17}$";
|
||||
public static final String REGEX_PASSWORD = "^[a-zA-Z]\\w{5,31}$";
|
||||
|
||||
//输入规则
|
||||
public static final String INPUT_RULE = "0123456789abcdefghijklnmopqrstuvwxyzABCDEFGHIJKLNMOPQRSTUVWXYZ_";
|
||||
|
||||
// 微信绑定地址
|
||||
public static final String WECHAT_BIND_ADDRESS_DEV = "https://dev-and-static.ghzs.com/web/wechat_bind/index.html#/";
|
||||
public static final String WECHAT_BIND_ADDRESS = "https://and-static.ghzs.com/web/wechat_bind/index.html#/";
|
||||
|
||||
// 礼仪考试地址
|
||||
public static final String REGULATION_TEST_ADDRESS_DEV = "https://static-web.ghzs.com/etiquette-dev/index.html#/";
|
||||
public static final String REGULATION_TEST_ADDRESS = "https://static-web.ghzs.com/etiquette/index.html#/";
|
||||
|
||||
// 徽章中心
|
||||
public static final String BADGE_ADDRESS_DEV = "https://static-web.ghzs.com/badge-dev/index.html#/";
|
||||
public static final String BADGE_ADDRESS = "https://static-web.ghzs.com/badge/index.html#/";
|
||||
|
||||
// 徽章详情
|
||||
public static final String BADGE_DETAIL_ADDRESS_DEV = "https://static-web.ghzs.com/badge-dev/index.html#/badgedetail";
|
||||
public static final String BADGE_DETAIL_ADDRESS = "https://static-web.ghzs.com/badge/index.html#/badgedetail";
|
||||
|
||||
// 分享个人主页地址
|
||||
public static final String SHARE_USER_HOME_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs-userhome-dev/index.html#/";
|
||||
public static final String SHARE_USER_HOME_ADDRESS = "https://static-web.ghzs.com/ghzs-userhome/index.html#/";
|
||||
|
||||
// 腾讯企点地址
|
||||
public static final String TENCENT_QIDIAN_ADDRESS = "https://admin.qidian.qq.com/template/blue/mp/menu/qr-code-jump.html?linkType=0&env=ol&kfuin=2355094296&fid=457&key=c76dcb2e3d582b6ffbfb5bb22cde85ff&cate=1&source=&isLBS=&isCustomEntry=&type=16&ftype=1&_type=wpa&qidian=true";
|
||||
|
||||
//版规声明
|
||||
public static final String FORUM_REGULATIONS_NEWS_ID = "5f4db9cc34d44d01b92fd670";
|
||||
|
||||
// 权限使用场景地址
|
||||
public static final String PERMISSION_SCENARIO_ADDRESS = "https://resource.ghzs.com/page/permissions/android.html";
|
||||
|
||||
//帮助内容详情
|
||||
public static final String HELP_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs_help_dev/help.html?content=";
|
||||
public static final String HELP_ADDRESS = "https://static-web.ghzs.com/ghzs_help/help.html?content=";
|
||||
|
||||
// 注销页面
|
||||
public static final String LOGOUT_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs_help_dev/help.html?content=5f6b1f02786564003944a693&from=ghzs";
|
||||
public static final String LOGOUT_ADDRESS = "https://static-web.ghzs.com/ghzs_help/help.html?content=5f534111b1f72909fc225672&from=ghzs";
|
||||
|
||||
// 商品详情
|
||||
public static final String COMMODITY_DETAIL_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/product?from=ghzs";
|
||||
public static final String COMMODITY_DETAIL_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/product?from=ghzs";
|
||||
|
||||
// 光能记录
|
||||
public static final String ENERGY_RECORD_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/record?from=ghzs";
|
||||
public static final String ENERGY_RECORD_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/record?from=ghzs";
|
||||
|
||||
// 订单中心
|
||||
public static final String ORDER_CENTER_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/orders?from=ghzs";
|
||||
public static final String ORDER_CENTER_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/orders?from=ghzs";
|
||||
|
||||
// 订单详情
|
||||
public static final String ORDER_DETAIL_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/order-detail?from=ghzs";
|
||||
public static final String ORDER_DETAIL_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/order-detail?from=ghzs";
|
||||
|
||||
// 邀请好友
|
||||
public static final String INVITE_FRIENDS_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs_activity_dev/inviteFriends.html#/invite";
|
||||
public static final String INVITE_FRIENDS_ADDRESS = "https://static-web.ghzs.com/ghzs_activity_prod/inviteFriends.html#/invite";
|
||||
|
||||
// 等级页面
|
||||
public static final String LEVEL_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs-userhome-dev/index.html#/level";
|
||||
public static final String LEVEL_ADDRESS = "https://static-web.ghzs.com/ghzs-userhome/index.html#/level";
|
||||
|
||||
// 兑换规则
|
||||
public static final String EXCHANGE_RULE_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/exchange-rule?from=ghzs";
|
||||
public static final String EXCHANGE_RULE_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/exchange-rule?from=ghzs";
|
||||
|
||||
// 光能规则
|
||||
public static final String ENERGY_RULE_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/energy-rule?from=ghzs";
|
||||
public static final String ENERGY_RULE_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/energy-rule?from=ghzs";
|
||||
|
||||
// 兑换商品
|
||||
public static final String EXCHANGE_COMMODITY_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/exchange-log?from=ghzs";
|
||||
public static final String EXCHANGE_COMMODITY_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/exchange-log?from=ghzs";
|
||||
|
||||
// 抽奖乐园
|
||||
public static final String LOTTERY_PARADISE_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/lottery-list?from=ghzs";
|
||||
public static final String LOTTERY_PARADISE_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/lottery-list?from=ghzs";
|
||||
|
||||
// 我的奖品
|
||||
public static final String MY_PRIZE_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/mywin?from=ghzs";
|
||||
public static final String MY_PRIZE_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/mywin?from=ghzs";
|
||||
|
||||
// 中奖订单详情
|
||||
public static final String WIN_ORDER_DETAIL_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/win-order-detail?from=ghzs";
|
||||
public static final String WIN_ORDER_DETAIL_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/win-order-detail?from=ghzs";
|
||||
|
||||
// 地址信息
|
||||
public static final String ADDRESS_INFO_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/address-list?from=ghzs";
|
||||
public static final String ADDRESS_INFO_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/address-list?from=ghzs";
|
||||
|
||||
// 领奖信息
|
||||
public static final String PRIZE_INFO_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/user-info?from=ghzs";
|
||||
public static final String PRIZE_INFO_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/user-info?from=ghzs";
|
||||
|
||||
// 提现信息
|
||||
public static final String WITHDRAW_INFO_ADDRESS_DEV = "https://static-web.ghzs.com/shop-dev/index.html#/cash?from=ghzs";
|
||||
public static final String WITHDRAW_INFO_ADDRESS = "https://static-web.ghzs.com/shop/index.html#/cash?from=ghzs";
|
||||
|
||||
// 活动详情
|
||||
public static final String ACTIVITY_DETAIL_ADDRESS_DEV = "https://static-web.ghzs.com/ghzs_activity_dev/common.html?from=ghzs";
|
||||
public static final String ACTIVITY_DETAIL_ADDRESS = "https://static-web.ghzs.com/ghzs_activity_prod/common.html?from=ghzs";
|
||||
|
||||
// 游戏单详情分享链接
|
||||
public static final String GAME_COLLECTION_SHARE_ADDRESS_DEV = "https://dev-and-static.ghzs.com/web/game_collection/index.html#/?from=ghzs";
|
||||
public static final String GAME_COLLECTION_SHARE_ADDRESS = "https://and-static.ghzs.com/web/game_collection/index.html#/?from=ghzs";
|
||||
|
||||
// 游戏单活动分享链接 https://git.shanqu.cc/pm/halo-app-issues/-/issues/1638
|
||||
public static final String GAME_COLLECTION_ACTIVITY_ADDRESS_DEV = "https://dev-and-static.ghzs.com/web/ghzs_activity/haoyouUnlock.html";
|
||||
public static final String GAME_COLLECTION_ACTIVITY_ADDRESS = "https://and-static.ghzs.com/web/ghzs_activity/haoyouUnlock.html";
|
||||
|
||||
// 青少年模式找回密码
|
||||
public static final String TEEN_MODE_RESET_PASSWORD = "https://resource.ghzs.com/page/privacy_policies/help_password.html";
|
||||
|
||||
// 儿童/青少年使用须知
|
||||
public static final String TEEN_MODE_RULE = "https://resource.ghzs.com/page/privacy_policies/teenager_privacy.html";
|
||||
|
||||
//游戏单管理规范
|
||||
public static final String GAME_COLLECTION_RULE = "https://resource.ghzs.com/page/privacy_policies/game_collection.html";
|
||||
|
||||
public static final String SP_IS_DEV_ENV = "is_dev_env";
|
||||
|
||||
//最少需要多少数据才能上传
|
||||
public static final int DATA_AMOUNT = 20;
|
||||
|
||||
//游戏 cd间隔
|
||||
public static final int GAME_CD = 5 * 60 * 1000;
|
||||
//新闻 cd间隔
|
||||
public static final int NEWS_CD = 10 * 60 * 1000;
|
||||
//platform cd间隔
|
||||
public static final int PLATFORM_CD = 10 * 60 * 1000;
|
||||
//update cd间隔
|
||||
public static final int UPDATE_CD = 5 * 60 * 1000;
|
||||
//搜索 cd间隔
|
||||
public static final int SEARCH_CD = 5 * 60 * 1000;
|
||||
//评论 cd间隔
|
||||
public static final int COMMENT_CD = 60 * 1000;
|
||||
//我的光环功能分组 cd间隔
|
||||
public static final int ADDONS_CD = 10 * 60 * 1000;
|
||||
//已收录包名更新 cd间隔
|
||||
public static final int PACKAGES_CD = 60 * 1000;
|
||||
|
||||
public static final String[] REPORT_LIST = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息", "违法有害信息", "其他原因"};
|
||||
|
||||
public static final String ENTRANCE_UNKNOWN = "(unknown)";
|
||||
|
||||
public static final String DEFAULT_TEXT_WRAPPER = "###";
|
||||
|
||||
// 触发了安装事件的标记
|
||||
public static final String MARK_ALREADY_TRIGGERED_INSTALLATION = "triggered_installation";
|
||||
|
||||
// 标记下载重试标记(值为任务已下载大小,为空表示需要重试)
|
||||
public static final String MARK_RETRY_DOWNLOAD = "retry_download";
|
||||
|
||||
// 工具箱历史记录(最多4个)
|
||||
public static final String TOOLBOX_HISTORY = "toolbox_history";
|
||||
|
||||
// 浏览器安装说明url
|
||||
public static final String SP_BROWSER_HINT_URL = "browser_hint_url";
|
||||
public static final String DEFAULT_OPPO_BROWSER_HINT_URL = "https://static-web.ghzs.com/ghzs_help/help.html?content=5fa90fe143d91a022e0d33ff";
|
||||
public static final String DEFAULT_VIVO_BROWSER_HINT_URL = "https://static-web.ghzs.com/ghzs_help/help.html?content=618112ce04796e63e97643a4&from=ghzs";
|
||||
|
||||
public static final int FOLLOW_HINT_TRIGGER_HEIGHT = 10;
|
||||
|
||||
// 深色模式
|
||||
public static final String SP_NIGHT_MODE = "night_mode";
|
||||
// 跟随系统模式
|
||||
public static final String SP_SYSTEM_MODE = "system_mode";
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
package com.gh.common.constant;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/10/16.
|
||||
*/
|
||||
public class ItemViewType {
|
||||
|
||||
public static final int COLUMN_HEADER = 0; // 专题头部布局
|
||||
public static final int GAME_SLIDE = 1; // 滚动图布局
|
||||
public static final int GAME_NORMAL = 2; // 正常游戏布局
|
||||
public static final int GAME_SUBJECT = 19;
|
||||
public static final int GAME_SUBJECT_SLIDE = 26;
|
||||
public static final int GAME_TEST = 3; // 测试游戏布局
|
||||
public static final int GAME_IMAGE = 4; // 游戏大图布局
|
||||
public static final int NEWS_HEADER = 5; // 新闻头部布局
|
||||
public static final int NEWS_TEXT = 6; // 新闻文本布局
|
||||
public static final int NEWS_IMAGE = 7; // 新闻带图布局
|
||||
public static final int NEWS_IMAGE1 = 8; // 新闻带一张小图布局
|
||||
public static final int NEWS_IMAGE2 = 9; // 新闻带三张小图布局
|
||||
public static final int NEWS_IMAGE3 = 10; // 新闻带一张大图布局
|
||||
public static final int NEWS_DIGEST = 11; // 新闻摘要布局
|
||||
public static final int SEARCH_NORMAL = 12; // 搜索正常布局
|
||||
public static final int LOADING = 14; // 加载布局
|
||||
public static final int LIBAO_NORMAL = 15; // 礼包正常布局
|
||||
public static final int LIBAO_SKIP_CONCERN = 16; // 跳转关注管理页面布局
|
||||
public static final int KC_HINT = 17;
|
||||
public static final int GAME_PLUGIN = 18; // 游戏插件模块
|
||||
public static final int ASK_REFRESH = 19; // 问答精选 刷新
|
||||
public static final int ITEM_EMPTY = 20;
|
||||
public static final int ASK_CONCERN = 21; // 问答精选 关注
|
||||
public static final int RATING_ITEM = 22; // 问答精选 关注
|
||||
public static final int IMAGE_SLIDE_ITEM = 23;
|
||||
public static final int VERTICAL_SLIDE_ITEM = 24;
|
||||
public static final int COLUMN_COLLECTION = 25;
|
||||
public static final int GALLERY_SLIDE = 27; // 首页自动滚动画廊专题
|
||||
public static final int GALLERY = 28; // 首页倾斜画廊专题
|
||||
public static final int BLANK_DIVIDER = 29; // 空白补充区域
|
||||
public static final int COMMON_LINK_COLLECTION = 30; // 通用链接合集
|
||||
public static final int RANK_COLLECTION = 31; // 排行榜样式专题合集
|
||||
public static final int GAME_COLLECTION_ITEM = 32; // 游戏单
|
||||
|
||||
/**
|
||||
* 普通列表
|
||||
*/
|
||||
public static final int ITEM_BODY = 100;
|
||||
public static final int ITEM_FOOTER = 101;
|
||||
public static final int ITEM_HEADER = 102;
|
||||
|
||||
}
|
||||
@ -13,10 +13,10 @@ import android.widget.PopupWindow
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.databinding.BindingAdapter
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.gh.base.OnViewClickListener
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.common.util.toDrawable
|
||||
import com.gh.common.view.BugFixedPopupWindow
|
||||
import com.gh.gamecenter.common.callback.OnViewClickListener
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.gh.gamecenter.common.view.BugFixedPopupWindow
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.KaifuAddItemBinding
|
||||
import com.gh.gamecenter.databinding.LayoutAddKaifuPopupBinding
|
||||
@ -87,8 +87,8 @@ object AddKaiFuBindingAdapter {
|
||||
|
||||
})
|
||||
if (i == list.size - 1) {
|
||||
binding.kaifuAddTime.background = R.drawable.bg_add_kaifu_bottom_left.toDrawable()
|
||||
binding.kaifuAddServerName.background = R.drawable.bg_add_kaifu_bottom_right.toDrawable()
|
||||
binding.kaifuAddTime.background = R.drawable.bg_add_kaifu_bottom_left.toDrawable(view.context)
|
||||
binding.kaifuAddServerName.background = R.drawable.bg_add_kaifu_bottom_right.toDrawable(view.context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ import androidx.core.content.ContextCompat;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.OnViewClickListener;
|
||||
import com.gh.gamecenter.common.callback.OnViewClickListener;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.CertificationDialog;
|
||||
import com.gh.common.dialog.PackageCheckDialogFragment;
|
||||
@ -31,23 +31,23 @@ import com.gh.common.simulator.SimulatorGameManager;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.common.util.DownloadDialogHelper;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.gh.common.util.GameUtils;
|
||||
import com.gh.common.util.GameViewUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.common.util.NewsUtils;
|
||||
import com.gh.common.util.NumberUtils;
|
||||
import com.gh.gamecenter.core.utils.NumberUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.RealNameHelper;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.common.view.DownloadProgressBar;
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.gamecenter.common.view.DrawableView;
|
||||
import com.gh.common.view.GameIconView;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
@ -428,7 +428,6 @@ public class BindingAdapters {
|
||||
}
|
||||
return;
|
||||
}
|
||||
DataUtils.onGameLaunchEvent(v.getContext(), gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), location);
|
||||
PackageUtils.launchApplicationByPackageName(v.getContext(), gameEntity.getApk().get(0).getPackageName());
|
||||
} else {
|
||||
DownloadDialog.showDownloadDialog(
|
||||
@ -651,8 +650,6 @@ public class BindingAdapters {
|
||||
ApkEntity apkEntity = gameEntity.getApk().get(0);
|
||||
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity.getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(progressBar.getContext(), gameEntity.getName(), apkEntity.getPlatform(), entrance, "下载开始", method);
|
||||
|
||||
DownloadManager.createDownload(progressBar.getContext(),
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
|
||||
@ -6,12 +6,12 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.common.util.SpanBuilder
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.common.view.CustomLinkMovementMethod
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.core.utils.SpanBuilder
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.view.CustomLinkMovementMethod
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DialogApplyModeratorBinding
|
||||
|
||||
@ -27,7 +27,7 @@ class ApplyModeratorDialogFragment : BaseDialogFragment() {
|
||||
requireArguments().run {
|
||||
mGroupNumber = getString(KEY_GROUP_NUMBER) ?: ""
|
||||
mGroupKey = getString(KEY_GROUP_KEY) ?: ""
|
||||
mParentTag = getString(EntranceUtils.KEY_PARENT_TAG) ?: ""
|
||||
mParentTag = getString(EntranceConsts.KEY_PARENT_TAG) ?: ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ class ApplyModeratorDialogFragment : BaseDialogFragment() {
|
||||
arguments = Bundle().apply {
|
||||
putString(KEY_GROUP_NUMBER, number)
|
||||
putString(KEY_GROUP_KEY, key)
|
||||
putString(EntranceUtils.KEY_PARENT_TAG, tag)
|
||||
putString(EntranceConsts.KEY_PARENT_TAG, tag)
|
||||
}
|
||||
}.show(
|
||||
activity.supportFragmentManager,
|
||||
|
||||
@ -1,95 +0,0 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
abstract class BaseDraggableDialogFragment : BaseDialogFragment(), View.OnTouchListener {
|
||||
private var mInitPositionY = 0f
|
||||
private lateinit var mGestureDetector: GestureDetector
|
||||
private lateinit var mRootView: View
|
||||
private lateinit var mDragCloseView: View
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mRootView = getRootView()
|
||||
mDragCloseView = getDragCloseView()
|
||||
mDragCloseView.setOnTouchListener(this)
|
||||
mGestureDetector = GestureDetector(requireContext(), SingleTapConfirm())
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// dialog drag animation
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
||||
if (mGestureDetector.onTouchEvent(event) && mRootView.y == 0F) {
|
||||
v.performClick()
|
||||
return true
|
||||
}
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
mInitPositionY = mRootView.y - event.rawY
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
val offsetY = event.rawY + mInitPositionY
|
||||
val dialogY = mRootView.y
|
||||
if (dialogY + offsetY > 0) {
|
||||
mRootView.animate()
|
||||
.y(offsetY)
|
||||
.setDuration(0)
|
||||
.start()
|
||||
} else {
|
||||
resetDialogPosition()
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_CANCEL,
|
||||
MotionEvent.ACTION_UP,
|
||||
MotionEvent.ACTION_OUTSIDE -> {
|
||||
if (mRootView.y >= mRootView.height / 2) {
|
||||
dismissAllowingStateLoss()
|
||||
} else {
|
||||
resetDialogPosition(300)
|
||||
}
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun resetDialogPosition(duration: Long = 0) {
|
||||
mRootView.animate()
|
||||
.y(0F)
|
||||
.setDuration(duration)
|
||||
.start()
|
||||
}
|
||||
|
||||
private class SingleTapConfirm : GestureDetector.SimpleOnGestureListener() {
|
||||
override fun onSingleTapUp(event: MotionEvent): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
abstract fun getRootView(): View
|
||||
abstract fun getDragCloseView(): View
|
||||
override fun getThemeRes(): Int = R.style.DialogFragmentDimAmount
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.lightgame.dialog.BaseDialogFragment
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* 对 dialog 操作进行 MTA 事件记录的 dialog fragment
|
||||
*/
|
||||
abstract class BaseTrackableDialogFragment : BaseDialogFragment() {
|
||||
|
||||
abstract fun getEvent(): String
|
||||
abstract fun getKey(): String
|
||||
open fun getValue(): String = ""
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
private val mIsCanceledByClickOutsideOfDialog = AtomicBoolean(true)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (getEvent().isEmpty()) {
|
||||
throw IllegalStateException("需要提供非空的 Event 来供 MTA 进行事件记录")
|
||||
}
|
||||
|
||||
if (getKey().isEmpty()) {
|
||||
throw IllegalStateException("需要提供非空的 Key 来供 MTA 进行事件记录")
|
||||
}
|
||||
|
||||
onEvent("出现弹窗")
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
dialog?.setOnKeyListener { _, keyCode, event ->
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
|
||||
mIsCanceledByClickOutsideOfDialog.set(false)
|
||||
onEvent("点击返回")
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun onEvent(value: String) {
|
||||
if (trackWithBasicDeviceInfo()) {
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), value)
|
||||
} else {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), value)
|
||||
if (getValue().isNotEmpty()) {
|
||||
MtaHelper.onEvent(getEvent(), value, getValue())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCancel(dialog: DialogInterface) {
|
||||
super.onCancel(dialog)
|
||||
if (mIsCanceledByClickOutsideOfDialog.get()) {
|
||||
onEvent("点击空白")
|
||||
}
|
||||
}
|
||||
|
||||
open fun trackWithBasicDeviceInfo() = false
|
||||
|
||||
|
||||
override fun show(manager: FragmentManager, tag: String?) {
|
||||
val fragment = manager.findFragmentByTag(tag)
|
||||
if (fragment != null) {
|
||||
val transaction = manager.beginTransaction()
|
||||
transaction.show(fragment)
|
||||
transaction.commit()
|
||||
} else {
|
||||
try {
|
||||
val clazz: Class<*> = DialogFragment::class.java
|
||||
val dismissed = clazz.getDeclaredField("mDismissed")
|
||||
dismissed.isAccessible = true
|
||||
dismissed[this] = false
|
||||
val shownByMe = clazz.getDeclaredField("mShownByMe")
|
||||
shownByMe.isAccessible = true
|
||||
shownByMe[this] = true
|
||||
val transaction = manager.beginTransaction()
|
||||
transaction.add(this, tag)
|
||||
transaction.commitAllowingStateLoss()
|
||||
} catch (e: Exception) {
|
||||
super.show(manager, tag)
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14,12 +14,16 @@ 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.gamecenter.common.avoidcallback.AvoidOnResultManager
|
||||
import com.gh.gamecenter.common.avoidcallback.Callback
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.ShellActivity
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.core.utils.GsonUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.entity.AuthDialogEntity
|
||||
import com.gh.gamecenter.entity.AuthDialogLevel
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
@ -28,7 +32,7 @@ import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.fragment.user.UserInfoEditFragment
|
||||
import com.lightgame.utils.AppManager
|
||||
|
||||
class CertificationDialog(context: Context, private val authDialogEntity: AuthDialogEntity, val gameId: String, val listener: DialogUtils.ConfirmListener) :
|
||||
class CertificationDialog(context: Context, private val authDialogEntity: AuthDialogEntity, val gameId: String, val listener: ConfirmListener) :
|
||||
Dialog(context, R.style.GhAlertDialog) {
|
||||
|
||||
private lateinit var view: View
|
||||
@ -134,7 +138,7 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi
|
||||
context,
|
||||
ShellActivity.Type.REAL_NAME_INFO,
|
||||
).apply {
|
||||
putExtra(EntranceUtils.KEY_GAME_ID, gameId)
|
||||
putExtra(EntranceConsts.KEY_GAME_ID, gameId)
|
||||
}, object : Callback {
|
||||
override fun onActivityResult(resultCode: Int, data: Intent?) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
@ -152,7 +156,7 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun showCertificationDialog(context: Context, game: GameEntity, listener: DialogUtils.ConfirmListener) {
|
||||
fun showCertificationDialog(context: Context, game: GameEntity, listener: ConfirmListener) {
|
||||
//1.先判断是否登录 是执行2 否执行3
|
||||
//2.判断是否实名认证 是终止 否执行3
|
||||
//3.判断是否需要弹出认证弹窗接口
|
||||
@ -168,7 +172,7 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun authDialog(context: Context, game: GameEntity, listener: DialogUtils.ConfirmListener) {
|
||||
private fun authDialog(context: Context, game: GameEntity, listener: ConfirmListener) {
|
||||
var authDialog: AuthDialogEntity? = null
|
||||
if (game.authDialog != null) {
|
||||
authDialog = game.authDialog
|
||||
|
||||
@ -19,10 +19,14 @@ 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.gamecenter.common.constant.Constants
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.core.utils.GsonUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.common.utils.countDownTimer
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.databinding.DialogDeviceRemindBinding
|
||||
import com.gh.gamecenter.entity.DeviceDialogEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
|
||||
@ -10,18 +10,16 @@ import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.text.HtmlCompat
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.common.util.toColor
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DialogGameOffServiceBinding
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
|
||||
// 游戏关闭下载弹窗
|
||||
class GameOffServiceDialogFragment
|
||||
// : BaseTrackableDialogFragment()
|
||||
: BaseDialogFragment() {
|
||||
class GameOffServiceDialogFragment : BaseDialogFragment() {
|
||||
|
||||
private var mDialog: GameEntity.Dialog? = null
|
||||
private var mBinding: DialogGameOffServiceBinding? = null
|
||||
@ -78,14 +76,6 @@ class GameOffServiceDialogFragment
|
||||
return super.onCreateDialog(savedInstanceState).apply { setCanceledOnTouchOutside(true) }
|
||||
}
|
||||
|
||||
// override fun getEvent(): String {
|
||||
// return "游戏下载状态按钮"
|
||||
// }
|
||||
//
|
||||
// override fun getKey(): String {
|
||||
// return "查看详情弹窗"
|
||||
// }
|
||||
|
||||
companion object {
|
||||
const val KEY_DIALOG = "dialog"
|
||||
|
||||
|
||||
@ -13,15 +13,20 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.PermissionHelper.INSTALL_PERMISSION_CODE
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper.INSTALL_PERMISSION_CODE
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.common.utils.getExtension
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import kotlin.random.Random
|
||||
|
||||
class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
|
||||
class InstallPermissionDialogFragment : BaseDialogFragment() {
|
||||
|
||||
lateinit var mView: View
|
||||
var isXapk = false
|
||||
@ -54,18 +59,15 @@ class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
|
||||
}
|
||||
|
||||
closeTv.setOnClickListener {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), "文案样式_点击以后再说")
|
||||
if (isXapk) {
|
||||
mCallBack?.invoke()
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
closeIv.setOnClickListener {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), "图标样式_点击关闭")
|
||||
dismiss()
|
||||
}
|
||||
activateTv.setOnClickListener {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), if (randomNumber == 0) "文案样式_点击立即开启" else "图标样式_点击立即开启")
|
||||
PermissionHelper.toInstallPermissionSetting(requireActivity())
|
||||
if (isXapk) {
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, requireActivity().javaClass.name)
|
||||
@ -84,10 +86,6 @@ class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEvent(): String = "安装引导弹窗"
|
||||
|
||||
override fun getKey(): String = "引导弹窗"
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun show(activity: AppCompatActivity, downloadEntity: DownloadEntity, callBack: (() -> Unit)?) {
|
||||
|
||||
@ -10,12 +10,13 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.GsonUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.util.PermissionHelper
|
||||
import com.gh.common.util.fromHtml
|
||||
import com.gh.gamecenter.core.utils.GsonUtils
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper
|
||||
import com.gh.gamecenter.common.utils.fromHtml
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.databinding.DialogNotificationHintBinding
|
||||
import com.gh.gamecenter.entity.NotificationStyleEntity
|
||||
import com.gh.gamecenter.entity.NotificationUgc
|
||||
@ -27,7 +28,7 @@ import java.io.InputStreamReader
|
||||
import kotlin.random.Random
|
||||
|
||||
// 通知权限弹窗
|
||||
class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
class NotificationHintDialogFragment : BaseDialogFragment() {
|
||||
|
||||
private var mNotificationUgc: NotificationUgc? = null
|
||||
private val mBinding: DialogNotificationHintBinding by lazy { DialogNotificationHintBinding.inflate(layoutInflater) }
|
||||
@ -68,8 +69,6 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
}
|
||||
|
||||
activateTv.setOnClickListener {
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击立即开启")
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击立即开启")
|
||||
dismissAllowingStateLoss()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
//这种方案适用于 API 26, 即8.0(含8.0)以上可以用
|
||||
@ -88,24 +87,12 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
closeIv.setOnClickListener {
|
||||
dismissAllowingStateLoss()
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击关闭")
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击关闭")
|
||||
}
|
||||
}
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
}
|
||||
|
||||
override fun getEvent(): String {
|
||||
return "推送引导弹窗"
|
||||
}
|
||||
|
||||
override fun getKey(): String {
|
||||
return "引导弹窗"
|
||||
}
|
||||
|
||||
override fun trackWithBasicDeviceInfo() = true
|
||||
|
||||
private fun getJsonFromAssets(): String? {
|
||||
val stringBuilder = StringBuilder()
|
||||
var bufferedReader: BufferedReader? = null
|
||||
|
||||
@ -15,12 +15,16 @@ import androidx.fragment.app.FragmentTransaction
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.view.CustomLinkMovementMethod
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.gamecenter.common.view.CustomLinkMovementMethod
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentPackageCheckBinding
|
||||
import com.gh.gamecenter.databinding.PackageCheckItemBinding
|
||||
import com.gh.gamecenter.entity.DetectionObjectEntity
|
||||
@ -52,7 +56,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
private var mAdapter: PackageCheckAdapter? = null
|
||||
private var mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
|
||||
var gameEntity: GameEntity? = null
|
||||
var callBack: DialogUtils.ConfirmListener? = null
|
||||
var callBack: ConfirmListener? = null
|
||||
|
||||
private val dataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
@ -318,7 +322,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun show(activity: AppCompatActivity, gameEntity: GameEntity, callBack: DialogUtils.ConfirmListener) {
|
||||
fun show(activity: AppCompatActivity, gameEntity: GameEntity, callBack: ConfirmListener) {
|
||||
val packageDialogEntity = gameEntity.packageDialog
|
||||
if (packageDialogEntity == null) {
|
||||
callBack.onConfirm()
|
||||
|
||||
@ -12,14 +12,14 @@ import android.view.*
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.common.util.fromHtml
|
||||
import com.gh.common.view.CustomLinkMovementMethod
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.fromHtml
|
||||
import com.gh.gamecenter.common.view.CustomLinkMovementMethod
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.databinding.DialogPrivacyProtocolBinding
|
||||
import com.gh.gamecenter.entity.DialogEntity
|
||||
import com.lightgame.utils.AppManager
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package com.gh.common.view
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
@ -6,12 +6,13 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.common.util.fromHtml
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.fromHtml
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.view.FixLinearLayoutManager
|
||||
import com.gh.gamecenter.databinding.DialogReserveBinding
|
||||
import com.gh.gamecenter.databinding.DialogReserveItemBinding
|
||||
import com.gh.gamecenter.entity.SimpleGameEntity
|
||||
@ -1,384 +0,0 @@
|
||||
//package com.gh.common.dialog
|
||||
//
|
||||
//import android.annotation.SuppressLint
|
||||
//import android.app.Application
|
||||
//import android.os.Bundle
|
||||
//import android.text.Html
|
||||
//import android.view.*
|
||||
//import android.view.animation.AnimationUtils
|
||||
//import android.widget.EditText
|
||||
//import android.widget.TextView
|
||||
//import androidx.lifecycle.AndroidViewModel
|
||||
//import androidx.lifecycle.MutableLiveData
|
||||
//import androidx.lifecycle.Observer
|
||||
//import butterknife.BindView
|
||||
//import butterknife.ButterKnife
|
||||
//import butterknife.OnClick
|
||||
//import com.gh.base.fragment.BaseDialogFragment
|
||||
//import com.gh.common.AppExecutor
|
||||
//import com.gh.common.constant.Config
|
||||
//import com.gh.common.history.HistoryHelper
|
||||
//import com.gh.common.repository.ReservationRepository
|
||||
//import com.gh.common.util.*
|
||||
//import com.gh.gamecenter.R
|
||||
//import com.gh.gamecenter.entity.GameEntity
|
||||
//import com.gh.gamecenter.entity.NotificationUgc
|
||||
//import com.gh.gamecenter.manager.UserManager
|
||||
//import com.gh.gamecenter.retrofit.BiResponse
|
||||
//import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
//import com.halo.assistant.HaloApp
|
||||
//import com.lightgame.utils.Utils
|
||||
//import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
//import io.reactivex.schedulers.Schedulers
|
||||
//import okhttp3.ResponseBody
|
||||
//import org.json.JSONArray
|
||||
//import org.json.JSONObject
|
||||
//
|
||||
//// 预约弹窗
|
||||
//@Deprecated("v5.6.0废弃")
|
||||
//class ReserveDialogFragment
|
||||
// : BaseDialogFragment(), KeyboardHeightObserver {
|
||||
//// : BaseTrackableDialogFragment() {
|
||||
//
|
||||
// @BindView(R.id.reserve_hint_tv)
|
||||
// lateinit var reserveHintTv: TextView
|
||||
//
|
||||
// @BindView(R.id.reserve_content_tv)
|
||||
// lateinit var reserveContentTv: TextView
|
||||
//
|
||||
// @BindView(R.id.reserve_completed_content_tv)
|
||||
// lateinit var reserveCompletedContentTv: TextView
|
||||
//
|
||||
// @BindView(R.id.mobile_et)
|
||||
// lateinit var mobileEt: EditText
|
||||
//
|
||||
// @BindView(R.id.reserve_container)
|
||||
// lateinit var reserveContainer: View
|
||||
//
|
||||
// @BindView(R.id.reserve_completed_container)
|
||||
// lateinit var reserveCompletedContainer: View
|
||||
//
|
||||
// @BindView(R.id.customizable_btn)
|
||||
// lateinit var customizableBtn: TextView
|
||||
//
|
||||
// @BindView(R.id.content_container)
|
||||
// lateinit var contentContainer: View
|
||||
//
|
||||
// @BindView(R.id.mobile_index_container)
|
||||
// lateinit var mobileIndexContainer: View
|
||||
//
|
||||
// @BindView(R.id.mobile_index_reserve)
|
||||
// lateinit var mobileIndexReserve: TextView
|
||||
//
|
||||
// @BindView(R.id.mobile_index_user)
|
||||
// lateinit var mobileIndexUser: TextView
|
||||
//
|
||||
// @BindView(R.id.mobile_et_delete)
|
||||
// lateinit var mobileEtDelete: View
|
||||
//
|
||||
// @BindView(R.id.layout_container)
|
||||
// lateinit var layoutContainer: View
|
||||
//
|
||||
// private lateinit var mViewModel: ReserveViewModel
|
||||
//
|
||||
// var successCallback: SuccessCallback? = null
|
||||
//
|
||||
// private var mGame: GameEntity? = null
|
||||
// private var mGameId: String = ""
|
||||
// private var mGameName: String = ""
|
||||
//
|
||||
// private var mKeyboardHeightProvider: KeyboardHeightProvider? = null
|
||||
//
|
||||
// override fun onCreate(savedInstanceState: Bundle?) {
|
||||
// super.onCreate(savedInstanceState)
|
||||
//
|
||||
// mGame = requireArguments().getParcelable(EntranceUtils.KEY_GAME)
|
||||
// mGameId = mGame?.id ?:""
|
||||
// mGameName = mGame?.name ?:""
|
||||
//
|
||||
// mViewModel = viewModelProvider()
|
||||
// mKeyboardHeightProvider = KeyboardHeightProvider(activity)
|
||||
// mKeyboardHeightProvider?.start()
|
||||
// }
|
||||
//
|
||||
// override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
// super.onActivityCreated(savedInstanceState)
|
||||
// dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
// }
|
||||
//
|
||||
// override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
// return inflater.inflate(R.layout.dialog_reserve_game, null)
|
||||
// }
|
||||
//
|
||||
//// override fun getEvent(): String {
|
||||
//// return "预约游戏"
|
||||
//// }
|
||||
////
|
||||
//// override fun getKey(): String {
|
||||
//// return "预约功能操作"
|
||||
//// }
|
||||
//
|
||||
// @Suppress("DEPRECATION")
|
||||
// @SuppressLint("SetTextI18n")
|
||||
// override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
// super.onViewCreated(view, savedInstanceState)
|
||||
// ButterKnife.bind(this, view)
|
||||
//
|
||||
// val reserveContent = "游戏上线,您将收到<font color='#1383EB'>免费短信</font>提醒"
|
||||
// reserveContentTv.text = Html.fromHtml(reserveContent)
|
||||
//
|
||||
//
|
||||
// mobileEt.setTextChangedListener { s, _, _, _ ->
|
||||
// mobileIndexContainer.visibility = View.GONE
|
||||
// mobileEtDelete.goneIf(s.trim().isEmpty())
|
||||
// }
|
||||
//
|
||||
// mViewModel.reservation.observeNonNull(this) {
|
||||
// if (it.success) {
|
||||
// showSuccessDialog(it.withMobile, it.boundWechat)
|
||||
// successCallback?.onSuccess()
|
||||
// HistoryHelper.insertGameEntity(mGame!!)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// mViewModel.reserveMobile.observe(viewLifecycleOwner, Observer {
|
||||
// setMobileIndexHint(it)
|
||||
// })
|
||||
//
|
||||
// dialog?.setCanceledOnTouchOutside(true)
|
||||
// }
|
||||
//
|
||||
// private fun showSuccessDialog(withMobile: Boolean, boundWechat: Boolean) {
|
||||
// reserveHintTv.text = "游戏预约成功"
|
||||
// reserveContainer.visibility = View.GONE
|
||||
// reserveCompletedContainer.visibility = View.VISIBLE
|
||||
//
|
||||
// val reservation = Config.getSettings()?.appointment
|
||||
// val dialogConfig = if (withMobile) reservation?.withMobile else reservation?.withoutMobile
|
||||
//
|
||||
// reserveCompletedContentTv.text = dialogConfig?.htmlContent?.fromHtml()
|
||||
// if (dialogConfig?.text.isNullOrEmpty()
|
||||
// || (dialogConfig?.type == "wechat_bind" && boundWechat)) {
|
||||
// customizableBtn.visibility = View.GONE
|
||||
// } else {
|
||||
// customizableBtn.text = dialogConfig?.text
|
||||
// customizableBtn.setOnClickListener {
|
||||
//// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击跳转按钮")
|
||||
// DirectUtils.directToLinkPage(
|
||||
// requireContext(),
|
||||
// dialogConfig!!.toLinkEntity(),
|
||||
// "(游戏预约)",
|
||||
// "")
|
||||
// dismissAllowingStateLoss()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun setMobileIndexHint(reserveMobile: String?) {
|
||||
// var userMobile = UserManager.getInstance().userInfoEntity?.mobile
|
||||
// if (reserveMobile == userMobile) userMobile = null
|
||||
//
|
||||
// if (!reserveMobile.isNullOrEmpty()) {
|
||||
// mobileIndexReserve.visibility = View.VISIBLE
|
||||
// mobileIndexReserve.text = reserveMobile
|
||||
// } else {
|
||||
// mobileIndexReserve.visibility = View.GONE
|
||||
// }
|
||||
//
|
||||
// if (!userMobile.isNullOrEmpty()) {
|
||||
// mobileIndexUser.visibility = View.VISIBLE
|
||||
// mobileIndexUser.text = userMobile
|
||||
// } else {
|
||||
// mobileIndexUser.visibility = View.GONE
|
||||
// }
|
||||
// mobileIndexContainer.goneIf(mobileIndexUser.visibility == View.GONE && mobileIndexReserve.visibility == View.GONE)
|
||||
// if (mobileIndexContainer.visibility ==View.VISIBLE) {
|
||||
// mobileIndexContainer.animation = AnimationUtils.loadAnimation(requireContext(), R.anim.reserve_dialog_index_anim)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @OnClick(R.id.reserve_with_mobile_btn,
|
||||
// R.id.reserve_without_mobile_btn,
|
||||
// R.id.content_container,
|
||||
// R.id.close_btn,
|
||||
// R.id.customizable_btn,
|
||||
// R.id.mobile_index_reserve,
|
||||
// R.id.mobile_index_user,
|
||||
// R.id.mobile_et_delete,
|
||||
// R.id.mobile_et,
|
||||
// R.id.layout_container)
|
||||
// fun onClick(view: View) {
|
||||
// when (view.id) {
|
||||
// R.id.reserve_without_mobile_btn -> {
|
||||
//// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击无手机号预约")
|
||||
// if (mobileIndexContainer.visibility == View.VISIBLE) {
|
||||
// mobileIndexContainer.visibility = View.GONE
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// mViewModel.reserve(gameId = mGameId, gameName = mGameName)
|
||||
// }
|
||||
//
|
||||
// R.id.reserve_with_mobile_btn -> {
|
||||
// if (mobileIndexContainer.visibility == View.VISIBLE) {
|
||||
// mobileIndexContainer.visibility = View.GONE
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// val mobile = mobileEt.text.toString()
|
||||
// if (mobile.length < 11 || !mobile.startsWith("1")) {
|
||||
// Utils.toast(context, "手机号格式错误,请检查并重新输入")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
//// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击立即预约")
|
||||
// mViewModel.reserve(gameId = mGameId, gameName = mGameName, mobile = mobile)
|
||||
// }
|
||||
//
|
||||
// R.id.close_btn -> {
|
||||
//// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击关闭")
|
||||
// dismissAllowingStateLoss()
|
||||
// AppExecutor.uiExecutor.executeWithDelay(Runnable {
|
||||
// NotificationHelper.showNotificationHintDialog(NotificationUgc.RESERVE_GAME)
|
||||
// }, 1000)
|
||||
// }
|
||||
// R.id.content_container -> {
|
||||
// mobileIndexContainer.visibility = View.GONE
|
||||
// }
|
||||
// R.id.mobile_index_reserve -> {
|
||||
// mobileEt.setText(mobileIndexReserve.text.toString())
|
||||
// mobileEt.setSelection(mobileEt.text.length)
|
||||
// mobileIndexContainer.visibility = View.GONE
|
||||
// }
|
||||
// R.id.mobile_index_user -> {
|
||||
// mobileEt.setText(mobileIndexUser.text.toString())
|
||||
// mobileEt.setSelection(mobileEt.text.length)
|
||||
// mobileIndexContainer.visibility = View.GONE
|
||||
// }
|
||||
// R.id.mobile_et_delete -> {
|
||||
// mobileEt.setText("")
|
||||
// }
|
||||
// R.id.mobile_et -> {
|
||||
// mobileIndexContainer.visibility = View.GONE
|
||||
// }
|
||||
// R.id.layout_container -> {
|
||||
// dismissAllowingStateLoss()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun onResume() {
|
||||
// super.onResume()
|
||||
// if (HaloApp.getInstance().mCacheKeyboardHeight > 0) {
|
||||
// val attributes = dialog?.window?.attributes
|
||||
// val heightPixels = requireContext().resources.displayMetrics.heightPixels
|
||||
// val mCacheKeyboardHeight = HaloApp.getInstance().mCacheKeyboardHeight
|
||||
// val statusBarHeight = DisplayUtils.getStatusBarHeight(requireContext().resources)
|
||||
// dialog?.window?.attributes?.height = heightPixels - mCacheKeyboardHeight - statusBarHeight
|
||||
// attributes?.gravity = Gravity.TOP
|
||||
// dialog?.window?.attributes = attributes
|
||||
// }
|
||||
// mKeyboardHeightProvider?.setKeyboardHeightObserver(this)
|
||||
// }
|
||||
//
|
||||
// override fun onPause() {
|
||||
// super.onPause()
|
||||
// mKeyboardHeightProvider?.setKeyboardHeightObserver(null)
|
||||
// }
|
||||
//
|
||||
// override fun onDestroy() {
|
||||
// super.onDestroy()
|
||||
// mKeyboardHeightProvider?.close()
|
||||
// }
|
||||
//
|
||||
// override fun onKeyboardHeightChanged(height: Int, orientation: Int) {
|
||||
// if (height > 0) {
|
||||
// val attributes = dialog?.window?.attributes
|
||||
// attributes?.gravity = Gravity.CENTER
|
||||
// dialog?.window?.attributes = attributes
|
||||
// HaloApp.getInstance().mCacheKeyboardHeight = height
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// companion object {
|
||||
// @JvmStatic
|
||||
// fun getInstance(gameEntity: GameEntity, successCallback: SuccessCallback) = ReserveDialogFragment().apply {
|
||||
// arguments = Bundle().apply {
|
||||
// putParcelable(EntranceUtils.KEY_GAME, gameEntity)
|
||||
// }
|
||||
// this.successCallback = successCallback
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// interface SuccessCallback {
|
||||
// fun onSuccess()
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//class ReserveViewModel(application: Application) : AndroidViewModel(application) {
|
||||
// val reservation = MutableLiveData<Reservation>()
|
||||
//
|
||||
// val reserveMobile = MutableLiveData<String>()
|
||||
//
|
||||
// init {
|
||||
// getAppointmentMobile()
|
||||
// }
|
||||
//
|
||||
// @SuppressLint("CheckResult")
|
||||
// fun reserve(gameId: String, gameName: String, mobile: String = "") {
|
||||
//
|
||||
// val requestMap = hashMapOf<String, String>()
|
||||
// requestMap["game_id"] = gameId
|
||||
// if (mobile.isNotEmpty()) {
|
||||
// requestMap["mobile"] = mobile
|
||||
// }
|
||||
//
|
||||
// RetrofitManager.getInstance().api
|
||||
// .createNewGameReservation(requestMap.createRequestBody())
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .subscribe(object : BiResponse<ResponseBody>() {
|
||||
// override fun onSuccess(data: ResponseBody) {
|
||||
// var boundWechat = false
|
||||
// tryWithDefaultCatch {
|
||||
// boundWechat = JSONObject(data.string() ?: "").getBoolean("wechat_bind")
|
||||
// }
|
||||
//
|
||||
// reservation.postValue(Reservation(success = true, withMobile = mobile.isNotEmpty(), boundWechat = boundWechat))
|
||||
// ReservationRepository.addReservationToMemoryAndRefresh(gameId)
|
||||
//
|
||||
//// MtaHelper.onEvent("预约游戏", "预约", gameName)
|
||||
// }
|
||||
//
|
||||
// override fun onFailure(exception: Exception) {
|
||||
// Utils.toast(getApplication(), exception.message)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// @SuppressLint("CheckResult")
|
||||
// private fun getAppointmentMobile() {
|
||||
// RetrofitManager.getInstance().api
|
||||
// .getAppointmentMobile(UserManager.getInstance().userId)
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .observeOn(AndroidSchedulers.mainThread())
|
||||
// .subscribe(object : BiResponse<ResponseBody>() {
|
||||
// override fun onSuccess(data: ResponseBody) {
|
||||
// var mobile: String? = null
|
||||
// tryCatchInRelease {
|
||||
// val jsonArray = JSONArray(data.string())
|
||||
// if (jsonArray.length() > 0) {
|
||||
// mobile = jsonArray.get(0).toString()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// reserveMobile.postValue(mobile)
|
||||
// }
|
||||
//
|
||||
// override fun onFailure(exception: Exception) {
|
||||
// reserveMobile.postValue(null)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// class Reservation(var success: Boolean = false, var withMobile: Boolean = false, var boundWechat: Boolean = false)
|
||||
//}
|
||||
@ -1,57 +0,0 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import com.gh.common.util.MtaHelper
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
open class TrackableDialog(context: Context,
|
||||
themeResId: Int,
|
||||
private var mEvent: String,
|
||||
private var mKey: String,
|
||||
private var mValue: String? = null,
|
||||
private var mCancelValue: String? = null,
|
||||
private var mKeyBackValue: String? = null,
|
||||
private var mLogShowEvent: Boolean = true)
|
||||
: Dialog(context, themeResId) {
|
||||
|
||||
// 区分此 dialog 是点击 dialog 外部取消的还是点击返回取消的
|
||||
private val mIsCanceledByClickOutsideOfDialog = AtomicBoolean(true)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setOnCancelListener {
|
||||
if (mIsCanceledByClickOutsideOfDialog.get()) {
|
||||
MtaHelper.onEvent(mEvent, mKey, mCancelValue ?: "点击空白")
|
||||
if (!mValue.isNullOrEmpty()) {
|
||||
MtaHelper.onEvent(mEvent, "点击空白", mValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setOnKeyListener { _, keyCode, event ->
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
super.show()
|
||||
if (mLogShowEvent) {
|
||||
MtaHelper.onEvent(mEvent, mKey, "出现弹窗")
|
||||
if (!mValue.isNullOrEmpty()) {
|
||||
MtaHelper.onEvent(mEvent, "出现弹窗", mValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.gh.common.exposure.meta.Meta
|
||||
import com.gh.common.util.GsonUtils
|
||||
import com.gh.gamecenter.common.entity.ExposureEntity
|
||||
import com.gh.gamecenter.common.exposure.meta.Meta
|
||||
import com.gh.gamecenter.core.utils.GsonUtils
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
|
||||
@ -1,90 +0,0 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Keep
|
||||
@Parcelize
|
||||
data class ExposureEntity(
|
||||
@SerializedName("game_id")
|
||||
val gameId: String? = "",
|
||||
@SerializedName("subject_id")
|
||||
val subjectId: String? = null, // 专题 id
|
||||
@SerializedName("carousel_id")
|
||||
val carouselId: String? = "", // 轮播图 id
|
||||
val gameName: String? = "",
|
||||
val gameVersion: String? = "",
|
||||
val sequence: Int? = 0,
|
||||
val outerSequence: Int? = 0,
|
||||
val platform: String? = null,
|
||||
var isMirrorData: Boolean = false,
|
||||
@SerializedName("is_web_download")
|
||||
var isWebDownload: Boolean = false,
|
||||
val downloadType: String? = null,
|
||||
val downloadCompleteType: String? = null,
|
||||
@SerializedName("display_type")
|
||||
val displayType: String? = "",
|
||||
@SerializedName("is_platform_recommend")
|
||||
val isPlatformRecommend: Boolean? = false,
|
||||
|
||||
// 外层内容 id (包括)
|
||||
// 1. "test_server_id" : "", // 开测表 ID
|
||||
// 2. "block_id" : "", // 板块 ID
|
||||
// 3. "category_id" : "", // 新分类1.0 ID
|
||||
// 4. "category_v2_id" : "", // 新分类2.0 ID
|
||||
var containerId: String? = null,
|
||||
var containerType: String? = null,
|
||||
|
||||
@SerializedName("test_server_id")
|
||||
var testServerId: String? = null,
|
||||
@SerializedName("block_id")
|
||||
var blockId: String? = null,
|
||||
@SerializedName("category_id")
|
||||
var categoryId: String? = null,
|
||||
@SerializedName("category_v2_id")
|
||||
var categoryV2Id: String? = null,
|
||||
@SerializedName("navigation_id")
|
||||
var navigationId: String? = null,
|
||||
|
||||
// 专题详情的来源页面和来源 id
|
||||
@SerializedName("source_page")
|
||||
var sourcePage: String? = null,
|
||||
@SerializedName("source_page_id")
|
||||
var sourcePageId: String? = null,
|
||||
@SerializedName("source_page_name")
|
||||
var sourcePageName: String? = null,
|
||||
|
||||
// 下载地址的 host 和 path
|
||||
var host: String? = null,
|
||||
var path: String? = null,
|
||||
|
||||
// 统计启动弹窗相关数据用的 (ugly)
|
||||
@SerializedName("dialog_id")
|
||||
var welcomeDialogId: String? = null,
|
||||
@SerializedName("link_title")
|
||||
var welcomeDialogLinkTitle: String? = null
|
||||
) : Parcelable {
|
||||
|
||||
fun setContainerInfo(id: String?, type: String?) {
|
||||
when (type) {
|
||||
TEST_SERVER_ID -> testServerId = id
|
||||
BLOCK_ID -> blockId = id
|
||||
CATEGORY_ID -> categoryId = id
|
||||
CATEGORY_V2_ID -> categoryV2Id = id
|
||||
NAVIGATION_ID -> navigationId = id
|
||||
}
|
||||
|
||||
containerId = null
|
||||
containerType = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TEST_SERVER_ID = "test_server_id"
|
||||
const val BLOCK_ID = "block_id"
|
||||
const val CATEGORY_ID = "category_id"
|
||||
const val CATEGORY_V2_ID = "category_v2_id"
|
||||
const val NAVIGATION_ID = "navigation_id"
|
||||
}
|
||||
}
|
||||
@ -4,12 +4,13 @@ import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.exposure.meta.Meta
|
||||
import com.gh.common.exposure.meta.MetaUtil
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.exposure.meta.Meta
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
import com.gh.common.exposure.time.TimeUtil
|
||||
import com.gh.common.util.getFirstElementDividedByDivider
|
||||
import com.gh.gamecenter.common.utils.getFirstElementDividedByDivider
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.common.entity.ExposureEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import com.aliyun.sls.android.producer.Log
|
||||
import com.gh.common.loghub.LoghubHelper
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.common.loghub.LoghubHelper
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import java.util.concurrent.ExecutorService
|
||||
@ -126,19 +127,4 @@ object ExposureManager {
|
||||
logTime = event.time.toLong()
|
||||
}
|
||||
|
||||
class FixedSizeLinkedHashSet<T>(var maxSize: Int) : LinkedHashSet<T>() {
|
||||
override fun add(element: T): Boolean {
|
||||
if (size == maxSize) {
|
||||
pop()
|
||||
}
|
||||
return super.add(element);
|
||||
}
|
||||
|
||||
private fun pop() {
|
||||
if (size > 0) {
|
||||
remove(iterator().next())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,7 +3,8 @@ package com.gh.common.exposure
|
||||
import android.text.TextUtils
|
||||
import com.g00fy2.versioncompare.Version
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet
|
||||
import com.gh.gamecenter.common.utils.toObject
|
||||
import com.gh.gamecenter.entity.ApkEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
@ -11,7 +12,7 @@ import com.lightgame.download.DownloadEntity
|
||||
|
||||
object ExposureUtils {
|
||||
|
||||
private val mDownloadCompleteTraceEventIdSet = ExposureManager.FixedSizeLinkedHashSet<String>(3)
|
||||
private val mDownloadCompleteTraceEventIdSet = FixedSizeLinkedHashSet<String>(3)
|
||||
|
||||
@JvmStatic
|
||||
fun logADownloadExposureEvent(
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
package com.gh.common.exposure.meta
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Keep
|
||||
@Parcelize
|
||||
data class Meta(
|
||||
val mac: String? = "",
|
||||
val jnfj: String? = "",
|
||||
val model: String? = "",
|
||||
val manufacturer: String? = "",
|
||||
val dia: String? = "",
|
||||
val android_sdk: Int? = -1,
|
||||
val android_version: String? = "",
|
||||
val network: String? = "",
|
||||
val os: String? = "",
|
||||
val gid: String? = "",
|
||||
val oaid: String? = "",
|
||||
val channel: String? = "",
|
||||
val appVersion: String? = "",
|
||||
val userId: String? = "",
|
||||
val exposureVersion: String? = "",
|
||||
val rom: String? = ""
|
||||
) : Parcelable
|
||||
@ -1,238 +0,0 @@
|
||||
package com.gh.common.exposure.meta
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.ConnectivityManager
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import android.telephony.TelephonyManager
|
||||
import android.text.TextUtils
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.walkud.rom.checker.RomIdentifier
|
||||
|
||||
object MetaUtil {
|
||||
|
||||
private val application: Application = HaloApp.getInstance().application
|
||||
private var channel = ""
|
||||
|
||||
private var m: Meta? = null
|
||||
private var imei: String? = null
|
||||
private var base64EncodedImei: String? = null
|
||||
private var androidId: String? = null
|
||||
private var base64EncodedAndroidId: String? = null
|
||||
|
||||
private var romName: String? = null
|
||||
private var romVersion: String? = null
|
||||
|
||||
fun refreshMeta() {
|
||||
|
||||
if (romName == null) {
|
||||
tryWithDefaultCatch {
|
||||
romName = RomIdentifier.getRom().name
|
||||
romVersion = RomIdentifier.getRom().versionName
|
||||
}
|
||||
}
|
||||
|
||||
m = Meta(mac = null,
|
||||
jnfj = getBase64EncodedIMEI(),
|
||||
model = getModel(),
|
||||
manufacturer = getManufacturer(),
|
||||
dia = getBase64EncodedAndroidId(),
|
||||
android_sdk = getAndroidSDK(),
|
||||
android_version = getAndroidVersion(),
|
||||
network = getNetwork(),
|
||||
os = getOS(),
|
||||
gid = HaloApp.getInstance().gid,
|
||||
oaid = HaloApp.getInstance().oaid,
|
||||
channel = getChannel(),
|
||||
appVersion = BuildConfig.VERSION_NAME,
|
||||
userId = UserManager.getInstance().userId,
|
||||
exposureVersion = BuildConfig.EXPOSURE_VERSION,
|
||||
rom = romName + "" + romVersion)
|
||||
}
|
||||
|
||||
fun getMeta(): Meta {
|
||||
if (m == null) {
|
||||
refreshMeta()
|
||||
}
|
||||
return m!!
|
||||
}
|
||||
|
||||
private fun getChannel(): String? {
|
||||
return HaloApp.getInstance().channel
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IMEI
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getIMEI(): String {
|
||||
|
||||
if (!HaloApp.isUserAcceptPrivacyPolicy(HaloApp.getInstance().application)) {
|
||||
return ""
|
||||
}
|
||||
|
||||
if (imei != null) {
|
||||
return imei ?: ""
|
||||
}
|
||||
|
||||
imei = SPUtils.getString(Constants.SP_IMEI)
|
||||
|
||||
if (!TextUtils.isEmpty(imei)) {
|
||||
return imei ?: ""
|
||||
}
|
||||
|
||||
if (application.checkCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
|
||||
return ""
|
||||
}
|
||||
|
||||
val telephonyManager = application.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 29) {
|
||||
return "".apply {
|
||||
imei = this
|
||||
SPUtils.setString(Constants.SP_IMEI, this)
|
||||
}
|
||||
} else if (Build.VERSION.SDK_INT >= 26) {
|
||||
return (telephonyManager.imei ?: "").apply {
|
||||
imei = this
|
||||
SPUtils.setString(Constants.SP_IMEI, this)
|
||||
}
|
||||
}
|
||||
|
||||
return (telephonyManager.getDeviceId() ?: "").apply {
|
||||
imei = this
|
||||
SPUtils.setString(Constants.SP_IMEI, this)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getBase64EncodedIMEI(): String {
|
||||
if (imei == null) {
|
||||
getIMEI()
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(base64EncodedImei) && imei != null) {
|
||||
try {
|
||||
base64EncodedImei = android.util.Base64.encodeToString(getIMEI().trim().toByteArray(), android.util.Base64.NO_WRAP)
|
||||
} catch (e: java.lang.Exception) {
|
||||
e.printStackTrace()
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
return base64EncodedImei ?: ""
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getBase64EncodedAndroidId(): String {
|
||||
if (androidId == null) {
|
||||
getAndroidId()
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(base64EncodedAndroidId) && androidId != null) {
|
||||
try {
|
||||
base64EncodedAndroidId = android.util.Base64.encodeToString(getAndroidId().trim().toByteArray(), android.util.Base64.NO_WRAP)
|
||||
} catch (e: java.lang.Exception) {
|
||||
e.printStackTrace()
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
return base64EncodedAndroidId ?: ""
|
||||
}
|
||||
|
||||
fun getModel(): String? {
|
||||
return Build.MODEL
|
||||
}
|
||||
|
||||
fun getManufacturer(): String? {
|
||||
return Build.MANUFACTURER
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getAndroidId(): String {
|
||||
|
||||
if (!HaloApp.isUserAcceptPrivacyPolicy(HaloApp.getInstance().application)) {
|
||||
return ""
|
||||
}
|
||||
|
||||
if (androidId != null) {
|
||||
return androidId ?: ""
|
||||
}
|
||||
|
||||
androidId = SPUtils.getString(Constants.SP_ANDROID_ID)
|
||||
|
||||
if (!TextUtils.isEmpty(androidId)) {
|
||||
return androidId ?: ""
|
||||
}
|
||||
|
||||
return try {
|
||||
Settings.Secure.getString(application.contentResolver, Settings.Secure.ANDROID_ID).apply {
|
||||
androidId = this
|
||||
SPUtils.setString(Constants.SP_ANDROID_ID, this)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
androidId = ""
|
||||
SPUtils.setString(Constants.SP_ANDROID_ID, "")
|
||||
""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getAndroidSDK(): Int? {
|
||||
return Build.VERSION.SDK_INT
|
||||
}
|
||||
|
||||
fun getAndroidVersion(): String? {
|
||||
return Build.VERSION.RELEASE
|
||||
}
|
||||
|
||||
fun getNetwork(): String? {
|
||||
|
||||
if (application.checkCallingOrSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)
|
||||
return "unknown"
|
||||
|
||||
val activeNetwork = (application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
|
||||
?: return "unknown"
|
||||
|
||||
return when (activeNetwork.type) {
|
||||
ConnectivityManager.TYPE_WIFI -> "Wifi"
|
||||
ConnectivityManager.TYPE_WIMAX -> "WifiMax"
|
||||
ConnectivityManager.TYPE_MOBILE -> {
|
||||
val telephonyManager = application.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||
if (telephonyManager.simState != TelephonyManager.SIM_STATE_READY) return "unknown"
|
||||
when (telephonyManager.networkType) {
|
||||
// Unknown
|
||||
TelephonyManager.NETWORK_TYPE_UNKNOWN -> "Cellular - Unknown"
|
||||
// Cellular Data–2G
|
||||
TelephonyManager.NETWORK_TYPE_EDGE, TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_CDMA,
|
||||
TelephonyManager.NETWORK_TYPE_IDEN, TelephonyManager.NETWORK_TYPE_1xRTT -> "Cellular - 2G"
|
||||
// Cellular Data–3G
|
||||
TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_HSPA,
|
||||
TelephonyManager.NETWORK_TYPE_HSPAP, TelephonyManager.NETWORK_TYPE_HSUPA, TelephonyManager.NETWORK_TYPE_EVDO_0,
|
||||
TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_EVDO_B -> "Cellular - 3G"
|
||||
// Cellular Data–4G
|
||||
TelephonyManager.NETWORK_TYPE_LTE -> "Cellular - 4G"
|
||||
else -> "Cellular - Unknown Generation"
|
||||
}
|
||||
|
||||
}
|
||||
else -> "unknown"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getOS(): String {
|
||||
return "android"
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,14 @@
|
||||
package com.gh.common.filter
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.common.util.debounceActionWithInterval
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.common.utils.debounceActionWithInterval
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.common.utils.toObject
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.functions.Function
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package com.gh.common.history
|
||||
|
||||
import com.gh.common.runOnIoThread
|
||||
import com.gh.common.util.clearHtmlFormatCompletely
|
||||
import com.gh.common.util.removeInsertedContent
|
||||
import com.gh.common.util.removeVideoContent
|
||||
import com.gh.common.util.tryCatchInRelease
|
||||
import com.gh.gamecenter.common.utils.clearHtmlFormatCompletely
|
||||
import com.gh.gamecenter.common.utils.removeInsertedContent
|
||||
import com.gh.gamecenter.common.utils.removeVideoContent
|
||||
import com.gh.gamecenter.common.utils.tryCatchInRelease
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.qa.entity.AnswerDetailEntity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
@ -108,7 +108,7 @@ object HistoryHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun deleteGamesCollectionEntity(gameCollectionId: String) {
|
||||
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.gamesCollectionDao().deleteGamesCollection(GamesCollectionEntity(id = gameCollectionId)) }}
|
||||
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.gamesCollectionDao().deleteGamesCollection(GamesCollectionEntity(id = gameCollectionId)) } }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
package com.gh.common.iinterface
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
interface IOffsetable {
|
||||
fun getOffset(position: Int): Int
|
||||
|
||||
fun updateOffset(position: Int, offset: Int)
|
||||
|
||||
fun resetOffset()
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.gh.common.iinterface
|
||||
|
||||
interface IScrollable {
|
||||
fun scrollToTop()
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
//package com.gh.common.im
|
||||
//
|
||||
//import android.app.Activity
|
||||
//import androidx.core.view.ViewCompat
|
||||
//import android.view.View
|
||||
//import android.view.ViewGroup
|
||||
//
|
||||
//object ImHintHelper {
|
||||
//
|
||||
// @JvmStatic
|
||||
// fun show(activity: Activity?) {
|
||||
// activity?.let {
|
||||
// var hintView = retrieveHintViewFromActivity(it)
|
||||
// if (hintView == null) {
|
||||
// hintView = ImHintView(it)
|
||||
// hintView.showDot(ImManager.shouldShowFloatingWindowDot)
|
||||
//
|
||||
// val decorView = it.window.decorView as ViewGroup
|
||||
// it.runOnUiThread {
|
||||
// decorView.addView(hintView)
|
||||
// }
|
||||
// } else {
|
||||
// hintView.showDot(ImManager.shouldShowFloatingWindowDot)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @JvmStatic
|
||||
// fun dismiss(activity: Activity?) {
|
||||
// activity?.let {
|
||||
// clearCurrent(it)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun retrieveHintViewFromActivity(activity: Activity?) : ImHintView? {
|
||||
// (activity?.window?.decorView as? ViewGroup)?.let {
|
||||
// for (i in 0..it.childCount) {
|
||||
// val childView = if (it.getChildAt(i) is ImHintView) it.getChildAt(i) as ImHintView else null
|
||||
// if (childView != null && childView.windowToken != null) {
|
||||
// return childView
|
||||
// }
|
||||
// }
|
||||
// return null
|
||||
// }
|
||||
// return null
|
||||
// }
|
||||
//
|
||||
// private fun clearCurrent(activity: Activity?) {
|
||||
// (activity?.window?.decorView as? ViewGroup)?.let {
|
||||
// for (i in 0..it.childCount) {
|
||||
// val childView = if (it.getChildAt(i) is ImHintView) it.getChildAt(i) as ImHintView else null
|
||||
// if (childView != null && childView.windowToken != null) {
|
||||
// ViewCompat.animate(childView).alpha(0f).withEndAction(getRemoveViewRunnable(childView))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun getRemoveViewRunnable(childView: View?): Runnable {
|
||||
// return Runnable {
|
||||
// childView?.let {
|
||||
// (childView.parent as? ViewGroup)?.removeView(childView)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
@ -1,45 +0,0 @@
|
||||
//package com.gh.common.im
|
||||
//
|
||||
//import android.app.Activity
|
||||
//import android.content.Context
|
||||
//import android.util.AttributeSet
|
||||
//import android.util.TypedValue
|
||||
//import android.view.View
|
||||
//import android.widget.RelativeLayout
|
||||
//import androidx.core.view.ViewCompat
|
||||
//import com.gh.common.util.DisplayUtils
|
||||
//import com.gh.gamecenter.R
|
||||
//import kotlinx.android.synthetic.main.view_im_hint.view.*
|
||||
//
|
||||
//class ImHintView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
|
||||
// : RelativeLayout(context, attrs, defStyle) {
|
||||
//
|
||||
// init {
|
||||
// inflate(context, R.layout.view_im_hint, this)
|
||||
//
|
||||
// ViewCompat.setTranslationZ(this, Integer.MAX_VALUE.toFloat() - 1)
|
||||
//
|
||||
// ivContainer.setOnClickListener {
|
||||
// if (context is Activity) {
|
||||
// ImManager.startChatActivity(context)
|
||||
// ImManager.removeNotification()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val lp = ivContainer.layoutParams as RelativeLayout.LayoutParams
|
||||
//
|
||||
// lp.setMargins(0, 0, dp2px(30f), dp2px(106f) + DisplayUtils.retrieveNavigationHeight(context))
|
||||
// }
|
||||
//
|
||||
// fun showDot(show: Boolean) {
|
||||
// if (show) {
|
||||
// unreadDot.visibility = View.VISIBLE
|
||||
// } else {
|
||||
// unreadDot.visibility = View.GONE
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private fun dp2px(dp: Float): Int {
|
||||
// return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.applicationContext.resources.displayMetrics).toInt()
|
||||
// }
|
||||
//}
|
||||
@ -1,145 +0,0 @@
|
||||
package com.gh.common.im
|
||||
|
||||
import android.app.Activity
|
||||
import com.gh.gamecenter.HelpAndFeedbackActivity
|
||||
import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.MessageActivity
|
||||
|
||||
object ImManager {
|
||||
|
||||
const val IM_KEY = "893be270-9c75-11e8-a344-212975ba32b9"
|
||||
const val SP_FLOATING_WINDOW_KEY = "IM_FLOATING_WINDOW"
|
||||
const val SP_FLOATING_WINDOW_DOT_KEY = "IM_FLOATING_WINDOW_DOT"
|
||||
|
||||
var shouldShowFloatingWindow = false
|
||||
var shouldShowFloatingWindowDot = false
|
||||
|
||||
// 记录当前用户 ID 避免重复初始化
|
||||
var currentUserId = ""
|
||||
|
||||
@JvmStatic
|
||||
fun attachIm() {
|
||||
// try {
|
||||
// if (UserManager.getInstance().userInfoEntity != null &&
|
||||
// currentUserId != UserManager.getInstance().userId) {
|
||||
// currentUserId = UserManager.getInstance().userId
|
||||
// MoorUtils.init(HaloApp.getInstance().application)
|
||||
// Utils.init(HaloApp.getInstance().application)
|
||||
// IMChatManager.getInstance().init(
|
||||
// HaloApp.getInstance().application,
|
||||
// ImReceiver.UNIQUE_BROADCAST_ACTION,
|
||||
// IM_KEY,
|
||||
// UserManager.getInstance().userInfoEntity?.name + "(" + UserManager.getInstance().userId + ")",
|
||||
// UserManager.getInstance().userId)
|
||||
//
|
||||
// shouldShowFloatingWindow = SPUtils.getBoolean(SP_FLOATING_WINDOW_KEY + UserManager.getInstance().userId)
|
||||
// shouldShowFloatingWindowDot = SPUtils.getBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId)
|
||||
// updateFloatingWindow()
|
||||
// }
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun detachIm() {
|
||||
// try {
|
||||
// IMChatManager.getInstance().quitSDk()
|
||||
// shouldShowFloatingWindow = false
|
||||
// updateFloatingWindow()
|
||||
// removeNotification()
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun startChatActivity(activity: Activity, inputContent: String? = "", requestCode: Int? = null) {
|
||||
// if (!UserManager.getInstance().userId.isNullOrEmpty()) {
|
||||
// try {
|
||||
// SPUtils.setBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId, false)
|
||||
// shouldShowFloatingWindowDot = false
|
||||
// val chatHelper = KfStartHelper(activity, UserManager.getInstance().userInfoEntity?.icon, inputContent, requestCode)
|
||||
// chatHelper.initSdkChat(
|
||||
// ImReceiver.UNIQUE_BROADCAST_ACTION,
|
||||
// IM_KEY,
|
||||
// UserManager.getInstance().userInfoEntity?.name + "(" + UserManager.getInstance().userId + ")"
|
||||
// + "[" + BuildConfig.VERSION_NAME + "]",
|
||||
// UserManager.getInstance().userId)
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showFloatingWindow() {
|
||||
updateShouldShowFloatingWindow(true)
|
||||
updateShouldShowFloatingWindowDot(true)
|
||||
updateFloatingWindow()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun dismissFloatingWindow() {
|
||||
updateShouldShowFloatingWindow(false)
|
||||
updateShouldShowFloatingWindowDot(false)
|
||||
updateFloatingWindow()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun removeNotification() {
|
||||
// val notificationManager = HaloApp.getInstance().application?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
// notificationManager.cancel(ImReceiver.NOTIFICATION_ID)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun updateFloatingWindow() {
|
||||
// try {
|
||||
// CurrentActivityHolder.getCurrentActivity()?.let {
|
||||
// if (isActivityValid(it)) {
|
||||
// if (shouldShowFloatingWindow) {
|
||||
// ImHintHelper.show(it)
|
||||
// } else {
|
||||
// ImHintHelper.dismiss(it)
|
||||
// removeNotification()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun sendFeedbackMessage(message: String) {
|
||||
// val fromToMessage = IMMessage.createTxtMessage(message)
|
||||
// runOnIoThread {
|
||||
// tryWithDefaultCatch {
|
||||
// IMChat.getInstance().sendMessage(fromToMessage, object : ChatListener {
|
||||
// override fun onProgress(p0: Int) {}
|
||||
// override fun onSuccess() {}
|
||||
// override fun onFailed() {}
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
fun updateShouldShowFloatingWindow(show: Boolean) {
|
||||
// SPUtils.setBoolean(SP_FLOATING_WINDOW_KEY + UserManager.getInstance().userId, show)
|
||||
// shouldShowFloatingWindow = show
|
||||
}
|
||||
|
||||
fun updateShouldShowFloatingWindowDot(show: Boolean) {
|
||||
// SPUtils.setBoolean(SP_FLOATING_WINDOW_DOT_KEY + UserManager.getInstance().userId, show)
|
||||
// shouldShowFloatingWindowDot = show
|
||||
}
|
||||
|
||||
private fun isActivityValid(activity: Activity): Boolean {
|
||||
return when (activity) {
|
||||
is MainActivity -> true
|
||||
is HelpAndFeedbackActivity -> true
|
||||
is MessageActivity -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
package com.gh.common.im
|
||||
|
||||
import android.app.NotificationManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
||||
class ImReceiver : BroadcastReceiver() {
|
||||
|
||||
companion object {
|
||||
const val UNIQUE_BROADCAST_ACTION = "com.gh.im"
|
||||
const val NOTIFICATION_ID: Int = 987321
|
||||
}
|
||||
|
||||
var notificationManager: NotificationManager? = null
|
||||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
// context?.doOnMainProcessOnly {
|
||||
// intent?.let {
|
||||
// if (intent.action == IMChatManager.NEW_MSG_ACTION) {
|
||||
// notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
// // 判断 ImActivity 是否在最顶端
|
||||
// if (CurrentActivityHolder.getCurrentActivity() is ChatActivity) {
|
||||
// ImManager.showFloatingWindow()
|
||||
// ImManager.updateShouldShowFloatingWindowDot(false)
|
||||
// } else {
|
||||
// val contentIntent = Intent(Utils.getApp(), ChatActivity::class.java)
|
||||
//
|
||||
// contentIntent.putExtra("PeerId", "")
|
||||
// contentIntent.putExtra("type", "peedId")
|
||||
//
|
||||
// contentIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
// val resultPendingIntent = PendingIntent.getActivity(
|
||||
// Utils.getApp(),
|
||||
// 0,
|
||||
// contentIntent,
|
||||
// PendingIntent.FLAG_UPDATE_CURRENT
|
||||
// )
|
||||
//
|
||||
// // 新的通知
|
||||
// val builder = NotificationCompat.Builder(Utils.getApp(), "Halo_IM")
|
||||
// val notification = builder.setTicker("您有新的消息")
|
||||
// .setDefaults(Notification.DEFAULT_ALL)
|
||||
// .setSmallIcon(R.drawable.ic_notification)
|
||||
// .setWhen(System.currentTimeMillis())
|
||||
// .setContentIntent(resultPendingIntent)
|
||||
// .setContentTitle("光环助手客服回复")
|
||||
// .setContentText("您有新的消息")
|
||||
// .setAutoCancel(true)
|
||||
// .build()
|
||||
//
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// val channel = NotificationChannel("Halo_IM", "Halo_IM", NotificationManager.IMPORTANCE_DEFAULT)
|
||||
// notificationManager?.createNotificationChannel(channel)
|
||||
// }
|
||||
//
|
||||
// if (notification != null) {
|
||||
// notificationManager?.notify(NOTIFICATION_ID, notification)
|
||||
// ImManager.showFloatingWindow()
|
||||
// }
|
||||
// }
|
||||
// } else if (intent.action == IMChatManager.FINISH_ACTION) {
|
||||
// ImManager.dismissFloatingWindow()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
package com.gh.common.image
|
||||
|
||||
import com.facebook.imagepipeline.common.ImageDecodeOptions
|
||||
import com.facebook.imagepipeline.decoder.ImageDecoder
|
||||
import com.facebook.imagepipeline.image.CloseableImage
|
||||
import com.facebook.imagepipeline.image.EncodedImage
|
||||
import com.facebook.imagepipeline.image.QualityInfo
|
||||
|
||||
class EmptyDecoder : ImageDecoder {
|
||||
override fun decode(
|
||||
encodedImage: EncodedImage,
|
||||
length: Int,
|
||||
qualityInfo: QualityInfo,
|
||||
options: ImageDecodeOptions
|
||||
): CloseableImage {
|
||||
return object : CloseableImage() {
|
||||
override fun close() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun getWidth(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun getHeight(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun getSizeInBytes(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun isClosed(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
package com.gh.common.json
|
||||
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
//Source: https://stackoverflow.com/questions/41861449/kotlin-dsl-for-creating-json-objects-without-creating-garbage
|
||||
|
||||
fun json(build: JsonObjectBuilder.() -> Unit): JSONObject {
|
||||
return JsonObjectBuilder().json(build)
|
||||
}
|
||||
|
||||
class JsonObjectBuilder {
|
||||
private val deque: Deque<JSONObject> = ArrayDeque()
|
||||
|
||||
fun json(build: JsonObjectBuilder.() -> Unit): JSONObject {
|
||||
deque.push(JSONObject())
|
||||
this.build()
|
||||
return deque.pop()
|
||||
}
|
||||
|
||||
infix fun <T> String.to(value: T) {
|
||||
// wrap value into json block if it is a lambda
|
||||
val wrapped = when (value) {
|
||||
is Function0<*> -> json { value.invoke() }
|
||||
is Array<*> -> JSONArray().apply { value.forEach { put(it) } }
|
||||
else -> value
|
||||
}
|
||||
|
||||
deque.peek().put(this, wrapped)
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
|
||||
@Database(entities = [LoghubEvent::class], version = 1, exportSchema = false)
|
||||
abstract class LoghubDatabase : RoomDatabase() {
|
||||
companion object {
|
||||
private const val DATABASE = "gh_loghub_database"
|
||||
|
||||
fun buildDatabase(context: Context): LoghubDatabase {
|
||||
return Room.databaseBuilder(context, LoghubDatabase::class.java, DATABASE)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun logHubEventDao(): LoghubEventDao
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.util.*
|
||||
|
||||
@Keep
|
||||
@Parcelize
|
||||
@Entity(tableName = "loghubEvent")
|
||||
data class LoghubEvent(@PrimaryKey
|
||||
val id: String = UUID.randomUUID().toString(),
|
||||
var time: String,
|
||||
var content: String,
|
||||
var logStore: String) : Parcelable
|
||||
@ -1,18 +0,0 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import androidx.room.*
|
||||
|
||||
@Dao
|
||||
interface LoghubEventDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertMany(eventList: List<LoghubEvent>)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(event: LoghubEvent)
|
||||
|
||||
@Query("SELECT * FROM LoghubEvent")
|
||||
fun getAll(): List<LoghubEvent>
|
||||
|
||||
@Delete
|
||||
fun deleteMany(eventList: List<LoghubEvent>)
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import com.aliyun.sls.android.producer.*
|
||||
import com.gh.common.util.PackageFlavorHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
/**
|
||||
* 上传阿里云日志辅助类
|
||||
*/
|
||||
object LoghubHelper {
|
||||
|
||||
private const val ACCESS_KEY_ID = "LTAIV3i0sNc4TPK1"
|
||||
private const val ACCESS_KEY_SECRET = "8dKtTPeE5WYA6ZCeuIBcIVp7eB0ir4"
|
||||
private const val ENDPOINT = "cn-qingdao.log.aliyuncs.com"
|
||||
private const val PROJECT = "ghzs"
|
||||
|
||||
private val mClientMaps by lazy { hashMapOf<String, LogProducerClient>() }
|
||||
|
||||
fun uploadLog(log: Log, logStore: String) {
|
||||
getClient(logStore)?.addLog(log)
|
||||
}
|
||||
|
||||
fun uploadLogs(logs: List<Log>, logStore: String) {
|
||||
logs.forEach {
|
||||
uploadLog(it, logStore)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getClient(logStore: String): LogProducerClient? {
|
||||
if (!mClientMaps.containsKey(logStore)) {
|
||||
mClientMaps[logStore] = createClient(logStore)
|
||||
}
|
||||
return mClientMaps[logStore]
|
||||
}
|
||||
|
||||
private fun createClient(logStore: String): LogProducerClient {
|
||||
val config = LogProducerConfig(
|
||||
HaloApp.getInstance().applicationContext,
|
||||
ENDPOINT,
|
||||
PROJECT,
|
||||
logStore,
|
||||
ACCESS_KEY_ID,
|
||||
ACCESS_KEY_SECRET
|
||||
).apply {
|
||||
// 1 开启断点续传功能, 0 关闭
|
||||
// 每次发送前会把日志保存到本地的binlog文件,只有发送成功才会删除,保证日志上传At Least Once
|
||||
setPersistent(1)
|
||||
// 持久化的文件名,需要保证文件所在的文件夹已创建。配置多个客户端时,不应设置相同文件
|
||||
setPersistentFilePath(HaloApp.getInstance().application.filesDir.absolutePath + "/${logStore}.dat")
|
||||
// 是否每次AddLog强制刷新,高可靠性场景建议打开
|
||||
setPersistentForceFlush(1)
|
||||
// 持久化文件滚动个数,建议设置成10。
|
||||
setPersistentMaxFileCount(10)
|
||||
// 每个持久化文件的大小,建议设置成1-10M
|
||||
setPersistentMaxFileSize(1024 * 1024)
|
||||
// 本地最多缓存的日志数,不建议超过1M,通常设置为65536即可
|
||||
setPersistentMaxLogCount(65536)
|
||||
|
||||
//网络连接超时时间,整数,单位秒,默认为10
|
||||
setConnectTimeoutSec(15)
|
||||
//日志发送超时时间,整数,单位秒,默认为15
|
||||
setSendTimeoutSec(15)
|
||||
//flusher线程销毁最大等待时间,整数,单位秒,默认为1
|
||||
setDestroyFlusherWaitSec(2)
|
||||
//sender线程池销毁最大等待时间,整数,单位秒,默认为1
|
||||
setDestroySenderWaitSec(2)
|
||||
//日志时间与本机时间之差,超过该大小后会根据 `drop_delay_log` 选项进行处理。
|
||||
//一般此种情况只会在设置persistent的情况下出现,即设备下线后,超过几天/数月启动,发送退出前未发出的日志
|
||||
//整数,单位秒,默认为7*24*3600,即7天
|
||||
setMaxLogDelayTime(7 * 24 * 3600)
|
||||
//对于超过 `max_log_delay_time` 日志的处理策略
|
||||
//0 不丢弃,把日志时间修改为当前时间; 1 丢弃,默认为 1 (丢弃)
|
||||
setDropDelayLog(0)
|
||||
//是否丢弃鉴权失败的日志,0 不丢弃,1丢弃
|
||||
//默认为 0,即不丢弃
|
||||
setDropUnauthorizedLog(0)
|
||||
}
|
||||
|
||||
return if (!PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
LogProducerClient(config)
|
||||
} else {
|
||||
LogProducerClient(config) { resultCode, reqId, errorMessage, logBytes, compressedBytes ->
|
||||
// resultCode 返回结果代码
|
||||
// reqId 请求id
|
||||
// errorMessage 错误信息,没有为null
|
||||
// logBytes 日志大小
|
||||
// compressedBytes 压缩后日志大小
|
||||
Utils.log(
|
||||
"LoghubHelper -> ${
|
||||
String.format(
|
||||
"%s %s %s %s %s",
|
||||
LogProducerResult.fromInt(resultCode),
|
||||
reqId,
|
||||
errorMessage,
|
||||
logBytes,
|
||||
compressedBytes
|
||||
)
|
||||
}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,110 +0,0 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import android.app.Application
|
||||
import androidx.annotation.Keep
|
||||
import com.aliyun.sls.android.producer.Log
|
||||
import com.gh.common.exposure.ExposureEntity
|
||||
import com.gh.common.exposure.meta.Meta
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import org.json.JSONObject
|
||||
import java.util.concurrent.ExecutorService
|
||||
|
||||
object LoghubUtils {
|
||||
|
||||
private const val STORE_SIZE = 100
|
||||
private lateinit var mApplication: Application
|
||||
|
||||
private val loghubEventSet by lazy { hashSetOf<LoghubEvent>() }
|
||||
private var loghubEventExecutor: ExecutorService? = null
|
||||
private val loghubEventDao by lazy { LoghubDatabase.buildDatabase(mApplication).logHubEventDao() }
|
||||
|
||||
@JvmStatic
|
||||
fun init(application: Application, executor: ExecutorService) {
|
||||
mApplication = application
|
||||
|
||||
loghubEventExecutor = executor
|
||||
loghubEventExecutor?.execute {
|
||||
tryWithDefaultCatch {
|
||||
val eventList = loghubEventDao.getAll()
|
||||
loghubEventSet.addAll(eventList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun log(logJson: JSONObject, logStore: String, forcedUpload: Boolean) {
|
||||
loghubEventExecutor?.execute {
|
||||
try {
|
||||
val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = logJson.toString(), logStore = logStore)
|
||||
loghubEventSet.add(event)
|
||||
loghubEventDao.insert(event)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
if (forcedUpload || loghubEventSet.size >= STORE_SIZE) {
|
||||
commitSavedLoghubEvents()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun log(jsonString: String, logStore: String, forcedUpload: Boolean) {
|
||||
loghubEventExecutor?.execute {
|
||||
try {
|
||||
val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = jsonString, logStore = logStore)
|
||||
loghubEventSet.add(event)
|
||||
loghubEventDao.insert(event)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
if (forcedUpload || loghubEventSet.size >= STORE_SIZE) {
|
||||
commitSavedLoghubEvents()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun commitSavedLoghubEvents() {
|
||||
loghubEventExecutor?.execute {
|
||||
// TODO 初始化 loghubHelper 去掉这个 tryCatch 块
|
||||
tryWithDefaultCatch {
|
||||
if (loghubEventSet.isEmpty()) return@execute
|
||||
|
||||
val exposureList = loghubEventSet.toList()
|
||||
|
||||
uploadEvents()
|
||||
loghubEventSet.removeAll(exposureList)
|
||||
loghubEventDao.deleteMany(exposureList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun uploadEvents() {
|
||||
for (event in loghubEventSet) {
|
||||
|
||||
val log = Log()
|
||||
// 特殊处理,以下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)
|
||||
}
|
||||
|
||||
LoghubHelper.uploadLog(log, event.logStore)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Keep
|
||||
data class SimpleLogContainerEntity(
|
||||
var event: String? = null,
|
||||
var action: String? = null,
|
||||
var meta: Meta? = null,
|
||||
var payload: ExposureEntity? = null,
|
||||
var timestamp: Long? = 0)
|
||||
@ -1,170 +0,0 @@
|
||||
package com.gh.common.notifier
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.core.view.ViewCompat
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.gamecenter.*
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
class Notifier private constructor() {
|
||||
|
||||
companion object {
|
||||
|
||||
private var activityWeakReference: WeakReference<Activity>? = null
|
||||
|
||||
private const val SP_VIEWED_NOTIFIER = "viewed_notifier"
|
||||
|
||||
/**
|
||||
* 根据内容决定是否显示 Notifier
|
||||
*/
|
||||
@JvmStatic
|
||||
fun shouldShowNotifier(content: String): Boolean {
|
||||
val viewedNotifierCollection = SPUtils.getString(SP_VIEWED_NOTIFIER)
|
||||
return !viewedNotifierCollection.contains(content)
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记相应内容的 Notifier 已经显示过了
|
||||
*/
|
||||
@JvmStatic
|
||||
fun tagNotifierAsShowed(content: String) {
|
||||
val viewedNotifierCollection = SPUtils.getString(SP_VIEWED_NOTIFIER)
|
||||
if (viewedNotifierCollection.length > 3000) {
|
||||
SPUtils.setString(SP_VIEWED_NOTIFIER, content)
|
||||
} else {
|
||||
SPUtils.setString(SP_VIEWED_NOTIFIER, viewedNotifierCollection + content)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun create(activity: Activity?): Notifier {
|
||||
if (activity == null) {
|
||||
throw IllegalArgumentException("Activity cannot be null!")
|
||||
}
|
||||
|
||||
val notifier = Notifier()
|
||||
|
||||
// Hide current NotifierView, if one is active
|
||||
clearCurrent(activity)
|
||||
|
||||
notifier.setActivity(activity)
|
||||
notifier.notifierView = NotifierView(activity)
|
||||
|
||||
return notifier
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isActivityValid(activity: Activity?): Boolean {
|
||||
if (activity == null) return false
|
||||
|
||||
return when (activity) {
|
||||
is MessageActivity -> false
|
||||
is DownloadManagerActivity -> false
|
||||
is CleanApkActivity -> false
|
||||
is SplashScreenActivity -> false
|
||||
else -> isNotExistInActivity(activity)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isNotExistInActivity(activity: Activity?): Boolean {
|
||||
if (activity == null) return false
|
||||
|
||||
(activity.window?.decorView as? ViewGroup)?.let {
|
||||
//Find all NotifierView Views in Parent layout
|
||||
for (i in 0..it.childCount) {
|
||||
val childView = if (it.getChildAt(i) is NotifierView) it.getChildAt(i) as NotifierView else null
|
||||
if (childView != null && childView.windowToken != null) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the currently showing notifierView view, if one is present
|
||||
*
|
||||
* @param activity The current Activity
|
||||
*/
|
||||
@JvmStatic
|
||||
fun clearCurrent(activity: Activity?) {
|
||||
(activity?.window?.decorView as? ViewGroup)?.let {
|
||||
//Find all NotifierView Views in Parent layout
|
||||
for (i in 0..it.childCount) {
|
||||
val childView = if (it.getChildAt(i) is NotifierView) it.getChildAt(i) as NotifierView else null
|
||||
if (childView != null && childView.windowToken != null) {
|
||||
ViewCompat.animate(childView).alpha(0f).withEndAction(getRemoveViewRunnable(childView))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun hide() {
|
||||
activityWeakReference?.get()?.let { clearCurrent(it) }
|
||||
}
|
||||
|
||||
private fun getRemoveViewRunnable(childView: NotifierView?): Runnable {
|
||||
return Runnable {
|
||||
childView?.let {
|
||||
(childView.parent as? ViewGroup)?.removeView(childView)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var notifierView: NotifierView? = null
|
||||
|
||||
private val activityDecorView: ViewGroup?
|
||||
get() {
|
||||
var decorView: ViewGroup? = null
|
||||
|
||||
activityWeakReference?.get()?.let {
|
||||
decorView = it.window.decorView as ViewGroup
|
||||
}
|
||||
|
||||
return decorView
|
||||
}
|
||||
|
||||
fun show(showVerticalTranslateAnimation: Boolean, delay: Long? = 0): NotifierView? {
|
||||
activityWeakReference?.get()?.let {
|
||||
it.runOnUiThread {
|
||||
activityDecorView?.postDelayed({
|
||||
notifierView?.showVerticalTranslateAnimation = showVerticalTranslateAnimation
|
||||
activityDecorView?.addView(notifierView)
|
||||
}, delay!!)
|
||||
}
|
||||
}
|
||||
|
||||
return notifierView
|
||||
}
|
||||
|
||||
fun setIcon(url: String?): Notifier {
|
||||
url?.let { notifierView?.setIcon(it) }
|
||||
return this
|
||||
}
|
||||
|
||||
fun setText(text: String?): Notifier {
|
||||
notifierView?.setText(text)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
fun setDuration(time: Long): Notifier {
|
||||
notifierView?.duration = time
|
||||
return this
|
||||
}
|
||||
|
||||
fun setOnClickListener(onClickListener: View.OnClickListener): Notifier {
|
||||
notifierView?.findViewById<View>(R.id.cardView)?.setOnClickListener(onClickListener)
|
||||
return this
|
||||
}
|
||||
|
||||
private fun setActivity(activity: Activity) {
|
||||
activityWeakReference = WeakReference(activity)
|
||||
}
|
||||
}
|
||||
@ -1,312 +0,0 @@
|
||||
package com.gh.common.notifier
|
||||
|
||||
import android.animation.*
|
||||
import android.content.Context
|
||||
import android.graphics.Path
|
||||
import android.text.TextUtils
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.core.view.ViewCompat
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.common.util.doOnEnd
|
||||
import com.gh.common.util.doOnStart
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
|
||||
: FrameLayout(context, attrs, defStyle) {
|
||||
|
||||
companion object {
|
||||
const val SCALE_MINI = 0.2F
|
||||
const val SCALE_DEFAULT = 1F
|
||||
|
||||
const val DEFAULT_DURATION = 500L
|
||||
}
|
||||
|
||||
var onShowListener: OnShowNotificationListener? = null
|
||||
var onHideListener: OnHideNotificationListener? = null
|
||||
|
||||
lateinit var expandAnimator: ValueAnimator
|
||||
lateinit var shrinkAnimator: ValueAnimator
|
||||
|
||||
lateinit var translateUpAnimator: ObjectAnimator
|
||||
lateinit var translateDownAnimator: ObjectAnimator
|
||||
|
||||
lateinit var translateToLeftAnimator: ObjectAnimator
|
||||
lateinit var translateToRightAnimator: ObjectAnimator
|
||||
|
||||
lateinit var zoomInAnimator: ObjectAnimator
|
||||
lateinit var zoomOutAnimator: ObjectAnimator
|
||||
|
||||
var showAnimatorSet: AnimatorSet
|
||||
var hideAnimatorSet: AnimatorSet
|
||||
|
||||
var rightToLeftPath: Path
|
||||
var leftToRightPath: Path
|
||||
|
||||
var veryRight: Float = 0F
|
||||
var veryBottom: Float = 0F
|
||||
var centerX: Float = 0F
|
||||
|
||||
var navigationHeight = 0
|
||||
|
||||
var textWidth: Int = 0
|
||||
var cardViewWidth: Int = 0
|
||||
var verticalAnimationOffset: Int = 0
|
||||
|
||||
var duration = DEFAULT_DURATION
|
||||
|
||||
var showVerticalTranslateAnimation: Boolean = true
|
||||
|
||||
private var mCardView: CardView
|
||||
private var mContentTv: TextView
|
||||
private var mIconIv: SimpleDraweeView
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.view_notifier, this)
|
||||
|
||||
ViewCompat.setTranslationZ(this, Integer.MAX_VALUE.toFloat())
|
||||
|
||||
mCardView = findViewById(R.id.cardView)
|
||||
mContentTv = findViewById(R.id.tvText)
|
||||
mIconIv = findViewById(R.id.ivIcon)
|
||||
|
||||
mCardView.scaleX = SCALE_MINI
|
||||
mCardView.scaleY = SCALE_MINI
|
||||
|
||||
verticalAnimationOffset = dp2px(100F)
|
||||
|
||||
navigationHeight = DisplayUtils.retrieveNavigationHeight(context)
|
||||
|
||||
rightToLeftPath = Path()
|
||||
leftToRightPath = Path()
|
||||
|
||||
showAnimatorSet = AnimatorSet()
|
||||
hideAnimatorSet = AnimatorSet()
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
super.onLayout(changed, left, top, right, bottom)
|
||||
|
||||
centerX = (left + right - cardViewWidth) / 2F
|
||||
|
||||
// TODO Provide method to change these absolute offset.
|
||||
val r = right - dp2px(72F).toFloat()
|
||||
val b = bottom - dp2px(145F).toFloat() - navigationHeight
|
||||
|
||||
// Only set
|
||||
if (veryRight != r || veryBottom != b) {
|
||||
veryRight = r
|
||||
veryBottom = b
|
||||
|
||||
rightToLeftPath.moveTo(r, b)
|
||||
rightToLeftPath.lineTo(centerX, b)
|
||||
|
||||
leftToRightPath.moveTo(centerX, b)
|
||||
leftToRightPath.lineTo(r, b)
|
||||
|
||||
initAnimator()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initAnimator() {
|
||||
expandAnimator = ValueAnimator.ofFloat(0F, 1F)
|
||||
expandAnimator.duration = DEFAULT_DURATION
|
||||
expandAnimator.addUpdateListener { a ->
|
||||
val progress = a?.animatedValue as Float
|
||||
mContentTv.width = (textWidth * progress).toInt()
|
||||
}
|
||||
expandAnimator.doOnEnd {
|
||||
enableSwipeToDismiss()
|
||||
shrinkAfterDelay()
|
||||
}
|
||||
|
||||
shrinkAnimator = ValueAnimator.ofFloat(1F, 0F)
|
||||
shrinkAnimator.duration = DEFAULT_DURATION
|
||||
shrinkAnimator.addUpdateListener { a ->
|
||||
val progress = a?.animatedValue as Float
|
||||
mContentTv.width = (textWidth * progress).toInt()
|
||||
}
|
||||
shrinkAnimator.doOnEnd {
|
||||
val lp = FrameLayout.LayoutParams(mCardView.layoutParams)
|
||||
lp.gravity = Gravity.NO_GRAVITY
|
||||
mCardView.layoutParams = lp
|
||||
|
||||
disableSwipeToDismiss()
|
||||
}
|
||||
|
||||
translateToLeftAnimator = ObjectAnimator.ofFloat(mCardView, "translationX", veryRight, centerX)
|
||||
translateToLeftAnimator.duration = DEFAULT_DURATION
|
||||
translateToLeftAnimator.doOnEnd {
|
||||
onShowListener?.onShow()
|
||||
|
||||
val lp = FrameLayout.LayoutParams(mCardView.layoutParams)
|
||||
lp.gravity = Gravity.CENTER_HORIZONTAL
|
||||
mCardView.layoutParams = lp
|
||||
mCardView.translationX = 0f
|
||||
|
||||
expandAnimator.start()
|
||||
}
|
||||
|
||||
translateToRightAnimator = ObjectAnimator.ofFloat(mCardView, "translationX", centerX, veryRight)
|
||||
translateToRightAnimator.duration = DEFAULT_DURATION
|
||||
|
||||
translateUpAnimator = ObjectAnimator.ofFloat(mCardView, "translationY", veryBottom + verticalAnimationOffset, veryBottom)
|
||||
translateUpAnimator.duration = DEFAULT_DURATION
|
||||
translateUpAnimator.doOnStart { mCardView.translationX = veryRight }
|
||||
|
||||
translateDownAnimator = ObjectAnimator.ofFloat(mCardView, "translationY", veryBottom, veryBottom + verticalAnimationOffset)
|
||||
translateDownAnimator.duration = DEFAULT_DURATION
|
||||
|
||||
zoomInAnimator = ObjectAnimator.ofPropertyValuesHolder(mCardView, PropertyValuesHolder.ofFloat("scaleX", SCALE_DEFAULT),
|
||||
PropertyValuesHolder.ofFloat("scaleY", SCALE_DEFAULT))
|
||||
zoomInAnimator.duration = DEFAULT_DURATION
|
||||
zoomInAnimator.doOnStart { mCardView.translationX = veryRight }
|
||||
zoomInAnimator.doOnStart { mCardView.translationY = veryBottom }
|
||||
|
||||
zoomOutAnimator = ObjectAnimator.ofPropertyValuesHolder(mCardView, PropertyValuesHolder.ofFloat("scaleX", SCALE_MINI),
|
||||
PropertyValuesHolder.ofFloat("scaleY", SCALE_MINI))
|
||||
zoomOutAnimator.duration = DEFAULT_DURATION
|
||||
zoomOutAnimator.doOnEnd { removeFromParent() }
|
||||
|
||||
if (showVerticalTranslateAnimation) {
|
||||
showAnimatorSet.play(translateUpAnimator).with(zoomInAnimator).before(translateToLeftAnimator)
|
||||
} else {
|
||||
showAnimatorSet.play(zoomInAnimator).before(translateToLeftAnimator)
|
||||
}
|
||||
showAnimatorSet.start()
|
||||
}
|
||||
|
||||
private fun enableSwipeToDismiss() {
|
||||
mCardView?.setOnTouchListener(SwipeDismissTouchListener(mCardView, object : SwipeDismissTouchListener.DismissCallbacks {
|
||||
override fun canDismiss(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDismiss(view: View) {
|
||||
removeFromParent()
|
||||
}
|
||||
|
||||
override fun onTouch(view: View, touch: Boolean) {
|
||||
// Ignore.
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
private fun disableSwipeToDismiss() {
|
||||
mCardView?.setOnTouchListener(null)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
|
||||
showAnimatorSet.cancel()
|
||||
hideAnimatorSet.cancel()
|
||||
|
||||
try {
|
||||
removeAllListeners(expandAnimator,
|
||||
shrinkAnimator,
|
||||
translateUpAnimator,
|
||||
translateDownAnimator,
|
||||
translateToLeftAnimator,
|
||||
translateToRightAnimator)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeAllListeners(vararg ts: Animator) {
|
||||
for (a in ts) {
|
||||
a.removeAllListeners()
|
||||
if (a is ValueAnimator) {
|
||||
a.removeAllUpdateListeners()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||
performClick()
|
||||
return super.onTouchEvent(event)
|
||||
}
|
||||
|
||||
private fun shrinkAfterDelay() {
|
||||
postDelayed({ shrink() }, duration)
|
||||
}
|
||||
|
||||
private fun shrink() {
|
||||
shrinkAnimator.doOnEnd { hide() }
|
||||
shrinkAnimator.start()
|
||||
}
|
||||
|
||||
private fun removeFromParent() {
|
||||
clearAnimation()
|
||||
visibility = View.GONE
|
||||
|
||||
postDelayed(object : Runnable {
|
||||
override fun run() {
|
||||
try {
|
||||
if (parent == null) {
|
||||
Log.e(javaClass.simpleName, "getParent() returning Null")
|
||||
} else {
|
||||
try {
|
||||
(parent as ViewGroup).removeView(this@NotifierView)
|
||||
|
||||
onHideListener?.onHide()
|
||||
} catch (ex: Exception) {
|
||||
Log.e(javaClass.simpleName, "Cannot remove from parent layout")
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Log.e(javaClass.simpleName, Log.getStackTraceString(ex))
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
|
||||
fun setText(text: String?) {
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
mContentTv.text = text
|
||||
mContentTv.measure(0, 0)
|
||||
textWidth = mContentTv.measuredWidth
|
||||
mContentTv.width = 0
|
||||
|
||||
mCardView.measure(0, 0)
|
||||
cardViewWidth = mCardView.measuredWidth
|
||||
}
|
||||
}
|
||||
|
||||
fun hide() {
|
||||
if (showVerticalTranslateAnimation) {
|
||||
hideAnimatorSet.play(translateDownAnimator).with(zoomOutAnimator).after(translateToRightAnimator)
|
||||
} else {
|
||||
hideAnimatorSet.play(zoomOutAnimator).after(translateToRightAnimator)
|
||||
}
|
||||
hideAnimatorSet.start()
|
||||
}
|
||||
|
||||
fun setIcon(url: String) {
|
||||
ImageUtils.display(mIconIv, url)
|
||||
}
|
||||
|
||||
private fun dp2px(dp: Float): Int {
|
||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.applicationContext.resources.displayMetrics).toInt()
|
||||
}
|
||||
|
||||
interface OnShowNotificationListener {
|
||||
fun onShow()
|
||||
}
|
||||
|
||||
interface OnHideNotificationListener {
|
||||
fun onHide()
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,238 +0,0 @@
|
||||
package com.gh.common.notifier
|
||||
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Modifications Copyright (C) 2017 David Kwon
|
||||
*/
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.animation.ValueAnimator
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import android.view.MotionEvent
|
||||
import android.view.VelocityTracker
|
||||
import android.view.View
|
||||
import android.view.ViewConfiguration
|
||||
|
||||
/**
|
||||
* A [View.OnTouchListener] that makes any [View] dismissable when the
|
||||
* user swipes (drags her finger) horizontally across the view.
|
||||
*
|
||||
* @param view The view to make dismissable.
|
||||
* @param callbacks The callback to trigger when the user has indicated that she would like to
|
||||
* dismiss this view.
|
||||
*/
|
||||
class SwipeDismissTouchListener(
|
||||
private val mView: View,
|
||||
private val mCallbacks: DismissCallbacks) : View.OnTouchListener {
|
||||
|
||||
// Cached ViewConfiguration and system-wide constant values
|
||||
private val mSlop: Int
|
||||
private val mMinFlingVelocity: Int
|
||||
private val mAnimationTime: Long
|
||||
private var mViewWidth = 1 // 1 and not 0 to prevent dividing by zero
|
||||
|
||||
// Transient properties
|
||||
private var mDownX: Float = 0.toFloat()
|
||||
private var mDownY: Float = 0.toFloat()
|
||||
private var mSwiping: Boolean = false
|
||||
private var mSwipingSlop: Int = 0
|
||||
private var mVelocityTracker: VelocityTracker? = null
|
||||
private var mTranslationX: Float = 0.toFloat()
|
||||
|
||||
init {
|
||||
val vc = ViewConfiguration.get(mView.context)
|
||||
mSlop = vc.scaledTouchSlop
|
||||
mMinFlingVelocity = vc.scaledMinimumFlingVelocity * 16
|
||||
mAnimationTime = mView.context.resources.getInteger(
|
||||
android.R.integer.config_shortAnimTime).toLong()
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB_MR1)
|
||||
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
|
||||
// offset because the view is translated during swipe
|
||||
motionEvent.offsetLocation(mTranslationX, 0f)
|
||||
|
||||
if (mViewWidth < 2) {
|
||||
mViewWidth = mView.width
|
||||
}
|
||||
|
||||
when (motionEvent.actionMasked) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
mDownX = motionEvent.rawX
|
||||
mDownY = motionEvent.rawY
|
||||
if (mCallbacks.canDismiss()) {
|
||||
mVelocityTracker = VelocityTracker.obtain()
|
||||
mVelocityTracker!!.addMovement(motionEvent)
|
||||
}
|
||||
mCallbacks.onTouch(view, true)
|
||||
return false
|
||||
}
|
||||
MotionEvent.ACTION_UP -> {
|
||||
mVelocityTracker?.run {
|
||||
val deltaX = motionEvent.rawX - mDownX
|
||||
this.addMovement(motionEvent)
|
||||
this.computeCurrentVelocity(1000)
|
||||
val velocityX = this.xVelocity
|
||||
val absVelocityX = Math.abs(velocityX)
|
||||
val absVelocityY = Math.abs(this.yVelocity)
|
||||
var dismiss = false
|
||||
var dismissRight = false
|
||||
if (Math.abs(deltaX) > mViewWidth / 2 && mSwiping) {
|
||||
dismiss = true
|
||||
dismissRight = deltaX > 0
|
||||
} else if (mMinFlingVelocity <= absVelocityX && absVelocityY < absVelocityX && mSwiping) {
|
||||
// dismiss only if flinging in the same direction as dragging
|
||||
dismiss = velocityX < 0 == deltaX < 0
|
||||
dismissRight = this.xVelocity > 0
|
||||
}
|
||||
if (dismiss) {
|
||||
// dismiss
|
||||
mView.animate()
|
||||
.translationX((if (dismissRight) mViewWidth else -mViewWidth).toFloat())
|
||||
.alpha(0f)
|
||||
.setDuration(mAnimationTime)
|
||||
.setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
performDismiss()
|
||||
}
|
||||
})
|
||||
} else if (mSwiping) {
|
||||
// cancel
|
||||
mView.animate()
|
||||
.translationX(0f)
|
||||
.alpha(1f)
|
||||
.setDuration(mAnimationTime)
|
||||
.setListener(null)
|
||||
mCallbacks.onTouch(view, false)
|
||||
}
|
||||
this.recycle()
|
||||
mVelocityTracker = null
|
||||
mTranslationX = 0f
|
||||
mDownX = 0f
|
||||
mDownY = 0f
|
||||
mSwiping = false
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_CANCEL -> {
|
||||
mVelocityTracker?.run {
|
||||
mView.animate()
|
||||
.translationX(0f)
|
||||
.alpha(1f)
|
||||
.setDuration(mAnimationTime)
|
||||
.setListener(null)
|
||||
this.recycle()
|
||||
mVelocityTracker = null
|
||||
mTranslationX = 0f
|
||||
mDownX = 0f
|
||||
mDownY = 0f
|
||||
mSwiping = false
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
mVelocityTracker?.run {
|
||||
this.addMovement(motionEvent)
|
||||
val deltaX = motionEvent.rawX - mDownX
|
||||
val deltaY = motionEvent.rawY - mDownY
|
||||
if (Math.abs(deltaX) > mSlop && Math.abs(deltaY) < Math.abs(deltaX) / 2) {
|
||||
mSwiping = true
|
||||
mSwipingSlop = if (deltaX > 0) mSlop else -mSlop
|
||||
mView.parent.requestDisallowInterceptTouchEvent(true)
|
||||
|
||||
// Cancel listview's touch
|
||||
val cancelEvent = MotionEvent.obtain(motionEvent)
|
||||
cancelEvent.action = MotionEvent.ACTION_CANCEL or (motionEvent.actionIndex shl MotionEvent.ACTION_POINTER_INDEX_SHIFT)
|
||||
mView.onTouchEvent(cancelEvent)
|
||||
cancelEvent.recycle()
|
||||
}
|
||||
|
||||
if (mSwiping) {
|
||||
mTranslationX = deltaX
|
||||
mView.translationX = deltaX - mSwipingSlop
|
||||
// TODO: use an ease-out interpolator or such
|
||||
mView.alpha = Math.max(0f, Math.min(1f,
|
||||
1f - 2f * Math.abs(deltaX) / mViewWidth))
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
view.performClick()
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
|
||||
private fun performDismiss() {
|
||||
// Animate the dismissed view to zero-height and then fire the dismiss callback.
|
||||
// This triggers layout on each animation frame; in the future we may want to do something
|
||||
// smarter and more performant.
|
||||
|
||||
val lp = mView.layoutParams
|
||||
val originalHeight = mView.height
|
||||
|
||||
val animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(mAnimationTime)
|
||||
|
||||
animator.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
mCallbacks.onDismiss(mView)
|
||||
// Reset view presentation
|
||||
mView.alpha = 1f
|
||||
mView.translationX = 0f
|
||||
lp.height = originalHeight
|
||||
mView.layoutParams = lp
|
||||
}
|
||||
})
|
||||
|
||||
animator.addUpdateListener { valueAnimator ->
|
||||
lp.height = valueAnimator.animatedValue as Int
|
||||
mView.layoutParams = lp
|
||||
}
|
||||
|
||||
animator.start()
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback interface used by [SwipeDismissTouchListener] to inform its client
|
||||
* about a successful dismissal of the view for which it was created.
|
||||
*/
|
||||
interface DismissCallbacks {
|
||||
/**
|
||||
* Called to determine whether the view can be dismissed.
|
||||
*
|
||||
* @return boolean The view can dismiss.
|
||||
*/
|
||||
fun canDismiss(): Boolean
|
||||
|
||||
/**
|
||||
* Called when the user has indicated they she would like to dismiss the view.
|
||||
*
|
||||
* @param view The originating [View]
|
||||
*/
|
||||
fun onDismiss(view: View)
|
||||
|
||||
/**
|
||||
* Called when the user touches the view or release the view.
|
||||
*
|
||||
* @param view The originating [View]
|
||||
* @param touch The view is being touched.
|
||||
*/
|
||||
fun onTouch(view: View, touch: Boolean)
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
package com.gh.common.observer
|
||||
|
||||
import android.content.Context
|
||||
import android.database.ContentObserver
|
||||
import android.media.AudioManager
|
||||
import android.os.Handler
|
||||
import com.gh.common.util.tryCatchInRelease
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
class VolumeObserver(var callback: MuteCallback? = null)
|
||||
: ContentObserver(Handler()) {
|
||||
var previousVolume: Int = 0
|
||||
|
||||
init {
|
||||
val audio = HaloApp.getInstance().application.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
// 部分设备的 audioManager getStreamVolume 内部会触发空指针 :(
|
||||
tryCatchInRelease { previousVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC) }
|
||||
}
|
||||
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
super.onChange(selfChange)
|
||||
|
||||
val audio = HaloApp.getInstance().application.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
var currentVolume = 0
|
||||
|
||||
tryCatchInRelease {
|
||||
// 部分设备(Meizu 7.1.2 M6 Note)的 audioManager getStreamVolume 内部会触发空指针 :(
|
||||
currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC)
|
||||
}
|
||||
|
||||
val delta = previousVolume - currentVolume
|
||||
|
||||
if (delta != 0) {
|
||||
if (currentVolume == 0) {
|
||||
callback?.onMute(true)
|
||||
} else {
|
||||
callback?.onMute(false)
|
||||
}
|
||||
}
|
||||
|
||||
if (delta > 0) {
|
||||
previousVolume = currentVolume
|
||||
} else if (delta < 0) {
|
||||
previousVolume = currentVolume
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface MuteCallback {
|
||||
fun onMute(isMute: Boolean)
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.util.ActivationHelper
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IActivationProvider
|
||||
|
||||
@Route(path = RouteConsts.provider.activation, name = "ActivationHelper暴露服务")
|
||||
interface ActivationProviderImpl : IActivationProvider {
|
||||
override fun init(context: Context?) {
|
||||
|
||||
}
|
||||
|
||||
override fun sendActivationInfo() {
|
||||
ActivationHelper.sendActivationInfo()
|
||||
}
|
||||
}
|
||||
51
app/src/main/java/com/gh/common/provider/AppProviderImpl.kt
Normal file
51
app/src/main/java/com/gh/common/provider/AppProviderImpl.kt
Normal file
@ -0,0 +1,51 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IAppProvider
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Route(path = RouteConsts.provider.app, name = "Application暴露服务")
|
||||
class AppProviderImpl : IAppProvider {
|
||||
override fun init(context: Context?) {
|
||||
|
||||
}
|
||||
|
||||
override fun getAppName(): String {
|
||||
return HaloApp.getInstance().getString(R.string.app_name)
|
||||
}
|
||||
|
||||
override fun getGid(): String {
|
||||
return HaloApp.getInstance().gid ?: ""
|
||||
}
|
||||
|
||||
override fun getOaid(): String {
|
||||
return HaloApp.getInstance().oaid ?: ""
|
||||
}
|
||||
|
||||
override fun getChannel(): String {
|
||||
return HaloApp.getInstance().channel ?: ""
|
||||
}
|
||||
|
||||
override fun getUserAgent(): String {
|
||||
return HaloApp.getInstance().userAgent ?: ""
|
||||
}
|
||||
|
||||
override fun getServerUserMark(): String {
|
||||
return HaloApp.getInstance().serverUserMark ?: ""
|
||||
}
|
||||
|
||||
override fun getDeviceRamSize(): Long {
|
||||
return HaloApp.getInstance().deviceRamSize
|
||||
}
|
||||
|
||||
override fun getTemporaryLocalDeviceId(): String {
|
||||
return HaloApp.getInstance().temporaryLocalDeviceId ?: ""
|
||||
}
|
||||
|
||||
override fun isUserAcceptPrivacyPolicy(context: Context): Boolean {
|
||||
return HaloApp.isUserAcceptPrivacyPolicy(context)
|
||||
}
|
||||
}
|
||||
34
app/src/main/java/com/gh/common/provider/BuildConfigImpl.kt
Normal file
34
app/src/main/java/com/gh/common/provider/BuildConfigImpl.kt
Normal file
@ -0,0 +1,34 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IBuildConfigProvider
|
||||
|
||||
@Route(path = RouteConsts.provider.buildConfig, name = "BuildConfig暴露服务")
|
||||
class BuildConfigImpl : IBuildConfigProvider {
|
||||
override fun init(context: Context?) {
|
||||
|
||||
}
|
||||
|
||||
override fun getApplicationId(): String = BuildConfig.APPLICATION_ID
|
||||
|
||||
override fun getVersionName(): String = BuildConfig.VERSION_NAME
|
||||
|
||||
override fun getExposureVersion(): String = BuildConfig.EXPOSURE_VERSION
|
||||
|
||||
override fun isDebug(): Boolean = BuildConfig.DEBUG
|
||||
|
||||
override fun getBuildTime(): Long = BuildConfig.BUILD_TIME
|
||||
|
||||
override fun getApiHost(): String = BuildConfig.API_HOST
|
||||
|
||||
override fun getDevApiHost(): String = BuildConfig.DEV_API_HOST
|
||||
|
||||
override fun getNewApiHost(): String = BuildConfig.NEW_API_HOST
|
||||
|
||||
override fun getNewDevApiHost(): String = BuildConfig.NEW_DEV_API_HOST
|
||||
|
||||
override fun getIsNightModeOn(): Boolean = BuildConfig.IS_NIGHT_MODE_ON
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.ICheckLoginProvider
|
||||
|
||||
@Route(path = RouteConsts.provider.checkLogin, name = "CheckLoginUtils暴露服务")
|
||||
class CheckLoginProviderImpl : ICheckLoginProvider {
|
||||
override fun checkLogin(context: Context, entrance: String, action: (() -> Unit)?) {
|
||||
CheckLoginUtils.checkLogin(context, entrance, action)
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IConfigProvider
|
||||
|
||||
@Route(path = RouteConsts.provider.config, name = "Config暴露服务")
|
||||
class ConfigProviderImpl : IConfigProvider {
|
||||
override fun getTencentAppId(): String {
|
||||
return Config.TENCENT_APPID
|
||||
}
|
||||
|
||||
override fun getWechatAppId(): String {
|
||||
return Config.WECHAT_APPID
|
||||
}
|
||||
|
||||
override fun getUploadLimitSize(): Long {
|
||||
return Config.getSettings()?.image?.uploadLimitSize ?: 0L
|
||||
}
|
||||
|
||||
override fun getSize(): Int {
|
||||
return Config.getSettings()?.image?.size ?: 0
|
||||
}
|
||||
|
||||
override fun getRatio(): Int {
|
||||
return Config.getSettings()?.image?.ratio ?: 0
|
||||
}
|
||||
|
||||
override fun getQuality(): Int {
|
||||
return Config.getSettings()?.image?.quality ?: 0
|
||||
}
|
||||
|
||||
override fun getGif(): String {
|
||||
return Config.getSettings()?.image?.oss?.gif ?: ""
|
||||
}
|
||||
|
||||
override fun getJpeg(): String {
|
||||
return Config.getSettings()?.image?.oss?.jpeg ?: ""
|
||||
}
|
||||
|
||||
override fun getWebp(): String {
|
||||
return Config.getSettings()?.image?.oss?.webp ?: ""
|
||||
}
|
||||
|
||||
override fun getGitThumb(): String {
|
||||
return Config.getSettings()?.image?.oss?.gitThumb ?: ""
|
||||
}
|
||||
|
||||
override fun getGifWaterMark(): String {
|
||||
return Config.getSettings()?.image?.oss?.gifWaterMark ?: ""
|
||||
}
|
||||
|
||||
override fun getQQ(): String {
|
||||
return Config.getSettings()?.support?.qq ?: ""
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.DefaultUrlHandler
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IDefaultUrlHandlerProvider
|
||||
|
||||
@Route(path = RouteConsts.provider.defaultUrlHandler, name = "DefaultUrlHandler暴露服务")
|
||||
class DefaultUrlHandlerProviderImpl : IDefaultUrlHandlerProvider {
|
||||
|
||||
override fun interceptUrl(context: Context, url: String, entrance: String):Boolean {
|
||||
return DefaultUrlHandler.interceptUrl(context, url, entrance)
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.gamecenter.common.callback.CancelListener
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IDialogUtilsProvider
|
||||
|
||||
@Route(path = RouteConsts.provider.dialogUtils, name = "DialogUtils暴露服务")
|
||||
class DialogUtilsProviderImpl : IDialogUtilsProvider {
|
||||
override fun showRegulationTestDialog(context: Context, confirm: () -> Unit, cancel: () -> Unit) {
|
||||
DialogUtils.showRegulationTestDialog(context, object : ConfirmListener {
|
||||
override fun onConfirm() {
|
||||
confirm.invoke()
|
||||
}
|
||||
}, object :CancelListener{
|
||||
override fun onCancel() {
|
||||
cancel.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IDirectProvider
|
||||
|
||||
@Route(path = RouteConsts.provider.directUtils, name = "DirectUtils暴露服务")
|
||||
class DirectProviderImpl : IDirectProvider {
|
||||
|
||||
override fun directToWebView(context: Context, url: String, entrance: String?) {
|
||||
DirectUtils.directToWebView(context, url, entrance)
|
||||
}
|
||||
|
||||
override fun directToRegulationTestPage(context: Context) {
|
||||
DirectUtils.directToRegulationTestPage(context)
|
||||
}
|
||||
|
||||
override fun directToQqConversation(context: Context, qq: String) {
|
||||
DirectUtils.directToQqConversation(context, qq)
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IDownloadManagerProvider
|
||||
import com.lightgame.download.DownloadEntity
|
||||
|
||||
@Route(path = RouteConsts.provider.downloadManager, name = "DownloadManager暴露服务")
|
||||
class DownloadManagerProviderImpl : IDownloadManagerProvider {
|
||||
|
||||
override fun getDownloadEntityByUrl(url: String): DownloadEntity? {
|
||||
return DownloadManager.getInstance().getDownloadEntityByUrl(url)
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user