package com.gh.base; import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE; import android.content.Intent; 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.Window; import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; 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.common.util.ToastUtils; 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/ButterKnife/Share/GlobalDialog/Permissions) *

* 需要工具栏的页面请继承{@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; public long startPageTime = 0; protected final Handler mBaseHandler = new BaseHandler(this); protected static class BaseHandler extends Handler { private final WeakReference 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) { 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, ""); } } } } @Override protected void onResume() { super.onResume(); startPageTime = System.currentTimeMillis(); } @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; }); } else { tv.setOnLongClickListener(v -> { SPUtils.setBoolean("dokit_enabled", true); ToastUtils.toast("重启应用后即可启用辅助工具"); return true; }); } screenRootView.addView(view); screenRootView.addView(ll); 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 (BuildConfig.DEBUG) { 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); } else { NightModeUtils.INSTANCE.setSystemMode(true); } NightModeUtils.INSTANCE.initNightMode(); }, () -> { if (NightModeUtils.INSTANCE.getSystemMode()) { NightModeUtils.INSTANCE.setNightMode(true); } else { NightModeUtils.INSTANCE.setNightMode(!NightModeUtils.INSTANCE.getNightMode()); } 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 perms) { } @Override public void onPermissionsGranted(int requestCode, List 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 getBusinessId() { return null; } @Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); 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); } } }