diff --git a/app/src/main/java/com/gh/common/dialog/CertificationDialog.kt b/app/src/main/java/com/gh/common/dialog/CertificationDialog.kt index a6294551dc..a2f4e07d51 100644 --- a/app/src/main/java/com/gh/common/dialog/CertificationDialog.kt +++ b/app/src/main/java/com/gh/common/dialog/CertificationDialog.kt @@ -118,7 +118,9 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi //跳转登录页面 private fun gotoLoginPage() { - CheckLoginUtils.checkLogin(AppManager.getInstance().currentActivity() as AppCompatActivity, + val currentActivity = AppManager.getInstance().currentActivity() ?: return + + CheckLoginUtils.checkLogin(currentActivity as AppCompatActivity, null, true, "实名认证弹窗") { if (UserManager.getInstance().isAuth) { listener.onConfirm() @@ -129,7 +131,9 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi //跳转实名认证页面 private fun gotoAuthPage() { - AvoidOnResultManager.getInstance(AppManager.getInstance().currentActivity() as AppCompatActivity) + val currentActivity = AppManager.getInstance().currentActivity() ?: return + + AvoidOnResultManager.getInstance(currentActivity as AppCompatActivity) .startForResult(UserInfoEditActivity.getIntent(context, UserViewModel.TYPE_ID_CARD), object : Callback { override fun onActivityResult(resultCode: Int, data: Intent?) { if (resultCode == Activity.RESULT_OK && data != null) { diff --git a/app/src/main/java/com/gh/common/observer/VolumeObserver.kt b/app/src/main/java/com/gh/common/observer/VolumeObserver.kt index 434c10a623..89f2a4204e 100644 --- a/app/src/main/java/com/gh/common/observer/VolumeObserver.kt +++ b/app/src/main/java/com/gh/common/observer/VolumeObserver.kt @@ -20,7 +20,12 @@ class VolumeObserver(var context: Context, handler: Handler, var callback: MuteC super.onChange(selfChange) val audio = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager - val currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC) + var currentVolume = 0 + + tryCatchInRelease { + // 部分设备(Meizu 7.1.2 M6 Note)的 audioManager getStreamVolume 内部会触发空指针 :( + currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC) + } val delta = previousVolume - currentVolume diff --git a/app/src/main/java/com/gh/common/simulator/SimulatorGameManager.kt b/app/src/main/java/com/gh/common/simulator/SimulatorGameManager.kt index 2dfb1e8c59..638fd660ca 100644 --- a/app/src/main/java/com/gh/common/simulator/SimulatorGameManager.kt +++ b/app/src/main/java/com/gh/common/simulator/SimulatorGameManager.kt @@ -33,7 +33,7 @@ object SimulatorGameManager { @JvmStatic fun deleteLocalGames(names: List) { - val downloadEntityList = DownloadDao.getInstance(HaloApp.getInstance().application).all + val downloadEntityList = DownloadManager.getInstance(HaloApp.getInstance().application).allDownloadEntity names.forEach { name -> val downloadEntity = downloadEntityList.find { it.name == name } if (downloadEntity != null) { @@ -48,7 +48,7 @@ object SimulatorGameManager { @JvmStatic fun deleteLocalGame(name: String) { - val downloadEntityList = DownloadDao.getInstance(HaloApp.getInstance().application).all + val downloadEntityList = DownloadManager.getInstance(HaloApp.getInstance().application).allDownloadEntity val downloadEntity = downloadEntityList.find { it.name == name } if (downloadEntity != null) { val file = File(downloadEntity.path) diff --git a/app/src/main/java/com/gh/common/util/DataUtils.java b/app/src/main/java/com/gh/common/util/DataUtils.java index 84858b35c4..93c1609953 100644 --- a/app/src/main/java/com/gh/common/util/DataUtils.java +++ b/app/src/main/java/com/gh/common/util/DataUtils.java @@ -42,6 +42,15 @@ public class DataUtils { } SentryAndroid.init(context, options -> { + // Sentry 疯狂报 ANR (很大一部分还是莫名奇妙的 ANR)严重影响到其它闪退日志的收集 + // 这里将它局限到只有官网渠道的包才统计 ANR + if ("GH_206".equals(channel)) { + options.setAnrEnabled(true); + options.setAnrTimeoutIntervalMillis(6000); + } else { + options.setAnrEnabled(false); + } + options.setDebug(BuildConfig.DEBUG); options.setEnableSessionTracking(true); options.setEnvironment(BuildConfig.FLAVOR); @@ -57,10 +66,6 @@ public class DataUtils { }); Sentry.configureScope(scope -> { - User user = new User(); - user.setId(HaloApp.getInstance().getGid()); - scope.setUser(user); - if (BuildConfig.BUILD_TIME != 0L) { scope.setTag("alias", "内测版" + BuildConfig.VERSION_NAME); } else { diff --git a/app/src/main/java/com/gh/common/util/DownloadObserver.kt b/app/src/main/java/com/gh/common/util/DownloadObserver.kt index ea58d52340..88b51ed987 100644 --- a/app/src/main/java/com/gh/common/util/DownloadObserver.kt +++ b/app/src/main/java/com/gh/common/util/DownloadObserver.kt @@ -76,9 +76,10 @@ object DownloadObserver { // MtaHelper.onEventWithBasicDeviceInfo("下载失败弹窗", // "游戏", downloadEntity.name, // "平台", downloadEntity.platform) + val currentActivity = AppManager.getInstance().currentActivity() ?: return - DialogUtils.showAlertDialog(AppManager.getInstance().currentActivity(), "下载失败", "下载链接已失效,建议提交反馈", "立即反馈", "取消", { - SuggestionActivity.startSuggestionActivity(AppManager.getInstance().currentActivity(), + DialogUtils.showAlertDialog(currentActivity, "下载失败", "下载链接已失效,建议提交反馈", "立即反馈", "取消", { + SuggestionActivity.startSuggestionActivity(currentActivity, SuggestType.gameQuestion, "notfound", StringUtils.buildString(downloadEntity.name, ",问题反馈:下载链接失效"), SimpleGameEntity(gameId, downloadEntity.name, "")) @@ -141,7 +142,9 @@ object DownloadObserver { if (gameEntity?.simulator != null) { val isInstalled = PackageUtils.isInstalledFromAllPackage(HaloApp.getInstance().application, gameEntity.simulator!!.apk!!.packageName) if (!isInstalled) { - SimulatorDownloadManager.getInstance().showDownloadDialog(AppManager.getInstance().currentActivity(), gameEntity.simulator, + val currentActivity = AppManager.getInstance().currentActivity() ?: return + + SimulatorDownloadManager.getInstance().showDownloadDialog(currentActivity, gameEntity.simulator, SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name ?: "", null) } diff --git a/app/src/main/java/com/gh/common/util/GameUtils.java b/app/src/main/java/com/gh/common/util/GameUtils.java index c729270bdd..73b8dffb6c 100644 --- a/app/src/main/java/com/gh/common/util/GameUtils.java +++ b/app/src/main/java/com/gh/common/util/GameUtils.java @@ -78,6 +78,9 @@ public class GameUtils { int pluginCount = 0; // 可插件化数量 int updateCount = 0; // 可更新数量 int installCount = 0; // 已安装数量 + + boolean isRelatedEmulatorInstalled = false; // 若该游戏是模拟器游戏时其对应的模拟器是否已经安装 + DownloadEntity downloadEntity; Object gh_id; apkFor: @@ -123,20 +126,26 @@ public class GameUtils { boolean isInstalled = PackageUtils.isInstalledFromAllPackage(context, gameEntity.getSimulator().getApk().getPackageName()); if (isInstalled) { installCount++; + isRelatedEmulatorInstalled = true; } else { doneCount++; } } } } - if (installCount != 0) { + + if (isRelatedEmulatorInstalled && doneCount != 0) { return context.getString(R.string.launch); + } + + if (doneCount != 0) { + return context.getString(R.string.install); } else if (pluginCount != 0 && !SimulatorGameManager.isSimulatorGame(gameEntity)) { return context.getString(R.string.pluggable); } else if (updateCount != 0 && !SimulatorGameManager.isSimulatorGame(gameEntity)) { return context.getString(R.string.update); - } else if (doneCount != 0) { - return context.getString(R.string.install); + } else if (installCount != 0) { + return context.getString(R.string.launch); } else if (gameEntity.getVersionNumber().contains("无版号") && Config.isGameDomeSwitchOpen() && !SimulatorGameManager.isSimulatorGame(gameEntity)) { return context.getString(R.string.attempt); } else { diff --git a/app/src/main/java/com/gh/common/util/PackageInstaller.kt b/app/src/main/java/com/gh/common/util/PackageInstaller.kt index e59488d77c..5db42fc727 100644 --- a/app/src/main/java/com/gh/common/util/PackageInstaller.kt +++ b/app/src/main/java/com/gh/common/util/PackageInstaller.kt @@ -41,7 +41,10 @@ object PackageInstaller { fun install(context: Context, downloadEntity: DownloadEntity, showUnzipToast: Boolean) { val pkgPath = downloadEntity.path val isXapk = XapkInstaller.XAPK_EXTENSION_NAME == pkgPath.getExtension() - InstallPermissionDialogFragment.show(AppManager.getInstance().currentActivity() as AppCompatActivity, downloadEntity) { + + val currentActivity = AppManager.getInstance().currentActivity() ?: return + + InstallPermissionDialogFragment.show(currentActivity as AppCompatActivity, downloadEntity) { // 取消状态栏下载完成的通知,若存在 downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES" DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity) diff --git a/app/src/main/java/com/gh/common/util/PackageUtils.java b/app/src/main/java/com/gh/common/util/PackageUtils.java index 791c8b2eb5..9b18c5d367 100644 --- a/app/src/main/java/com/gh/common/util/PackageUtils.java +++ b/app/src/main/java/com/gh/common/util/PackageUtils.java @@ -183,11 +183,13 @@ public class PackageUtils { return null; } + // TODO 找一个更好的办法来比较签名并且不触发 ANR public static boolean compareSignatureBetweenInstalledAppWithApk(Context context, String packageName, String apkFilePath) { try { + // 据 Sentry 统计,刚上架一个周末的包里对这个方法有 700+ 次调用,然后其中一部分会造成 ANR Signature sig = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures[0]; - // Fuck HUAWEI, 华为系统调用 getPackageArchiveInfo 获取魔羯 apk 的签名时会耗时超过5秒造成 ANR,没有找到解决方法 + // 调用 getPackageArchiveInfo 获取较大的 apk 的签名时会耗时超过5秒造成 ANR,没有找到解决方法 // 如果可以的话尽量避免调用 getPackageArchiveInfo 方法 Signature releaseSig = context.getPackageManager().getPackageArchiveInfo(apkFilePath, PackageManager.GET_SIGNATURES).signatures[0]; return sig.hashCode() == releaseSig.hashCode(); diff --git a/app/src/main/java/com/gh/common/view/dsbridge/DWebView.java b/app/src/main/java/com/gh/common/view/dsbridge/DWebView.java index 797e41c3e5..a9c303ae97 100644 --- a/app/src/main/java/com/gh/common/view/dsbridge/DWebView.java +++ b/app/src/main/java/com/gh/common/view/dsbridge/DWebView.java @@ -420,7 +420,7 @@ public class DWebView extends WebView { e.printStackTrace(); try { super.loadUrl("javascript:" + script); - } catch (Exception ignored){ + } catch (Exception ignored) { } } @@ -1029,4 +1029,19 @@ public class DWebView extends WebView { mainHandler.post(runnable); } + @Override + public void setOverScrollMode(int mode) { + try { + super.setOverScrollMode(mode); + } catch (Throwable e) { + String trace = Log.getStackTraceString(e); + if (trace.contains("android.content.pm.PackageManager$NameNotFoundException") + || trace.contains("java.lang.RuntimeException: Cannot load WebView") + || trace.contains("android.webkit.WebViewFactory$MissingWebViewPackageException: Failed to load WebView provider: No WebView installed")) { + e.printStackTrace(); + } else { + throw e; + } + } + } } diff --git a/app/src/main/java/com/gh/download/DownloadManager.java b/app/src/main/java/com/gh/download/DownloadManager.java index 9ed07f5a5a..ba7d0d624b 100644 --- a/app/src/main/java/com/gh/download/DownloadManager.java +++ b/app/src/main/java/com/gh/download/DownloadManager.java @@ -543,7 +543,7 @@ public class DownloadManager implements DownloadStatusListener { } public List getAllSimulatorDownloadEntity() { - List downloadEntityList = mDownloadDao.getAll(); + List downloadEntityList = getAllDownloadEntity(); ArrayList filteredDownloadEntityList = new ArrayList<>(); for (DownloadEntity downloadEntity : downloadEntityList) { if (ExtensionsKt.isSimulatorGame(downloadEntity) && downloadEntity.getStatus() == DownloadStatus.done) { @@ -560,7 +560,7 @@ public class DownloadManager implements DownloadStatusListener { if (CommonDebug.IS_DEBUG) { CommonDebug.logMethodName(this); } - List all = mDownloadDao.getAll(); + List all = getAllDownloadEntity(); return filterSilentDownloadTask(all); } diff --git a/app/src/main/java/com/gh/download/PackageObserver.kt b/app/src/main/java/com/gh/download/PackageObserver.kt index 1ef2fedc79..0538ba56ab 100644 --- a/app/src/main/java/com/gh/download/PackageObserver.kt +++ b/app/src/main/java/com/gh/download/PackageObserver.kt @@ -7,6 +7,7 @@ import android.preference.PreferenceManager import android.text.TextUtils import com.gh.common.constant.Constants import com.gh.common.loghub.LoghubUtils +import com.gh.common.runOnIoThread import com.gh.common.util.* import com.gh.gamecenter.entity.GameDigestEntity import com.gh.gamecenter.eventbus.EBPackage @@ -106,7 +107,8 @@ object PackageObserver { } }) } - postNewlyInstalledApp(gameId, packageName) + + runOnIoThread { postNewlyInstalledApp(gameId, packageName) } } if ("卸载" == busFour.type) { diff --git a/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java b/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java index 6ddb9be05c..380cebd9bd 100644 --- a/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java +++ b/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java @@ -300,7 +300,7 @@ public class SplashScreenActivity extends BaseActivity { finish(); } - private void uploadTeaAndGdtData(){ + private void uploadTeaAndGdtData() { // 在可能获取了相关权限后才初始化SDK/发送激活数据 // TeaHelper.init(getApplication(), HaloApp.getInstance().getChannel()); try { @@ -422,25 +422,25 @@ public class SplashScreenActivity extends BaseActivity { // 检查下载文件夹下是否有旧版本的光环助手的包,有则删除 @SuppressWarnings("ResultOfMethodCallIgnored") private void deleteOutdatedUpdatePackage() { - File folder = new File(FileUtils.getDownloadDir(this) + File.separator); - if (folder.isDirectory()) { - for (File file : folder.listFiles()) { - if (!file.isDirectory() && file.getName().startsWith("光环助手V")) { - String name = file.getName(); - int index = name.indexOf("_"); - if (index != -1) { - try { + try { + File folder = new File(FileUtils.getDownloadDir(this) + File.separator); + if (folder.isDirectory()) { + for (File file : folder.listFiles()) { + if (!file.isDirectory() && file.getName().startsWith("光环助手V")) { + String name = file.getName(); + int index = name.indexOf("_"); + if (index != -1) { String versionString = name.substring(name.indexOf("V") + 1, index); Version currentVersion = new Version(PackageUtils.getVersionName()); if (currentVersion.isHigherThan(versionString) || currentVersion.isEqual(versionString)) { file.delete(); } - } catch (Exception exception) { - exception.printStackTrace(); } } } } + } catch (Exception e) { + e.printStackTrace(); } } diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListAdapter.java b/app/src/main/java/com/gh/gamecenter/baselist/ListAdapter.java index 23705689d5..4dc9a36498 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/ListAdapter.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListAdapter.java @@ -20,6 +20,7 @@ public abstract class ListAdapter extends BaseRecyclerAdapter { public static final int FOOTER_ITEM_COUNT = 1; public static final int TOP_ITEM_COUNT = 1; + // TODO mEntityList 适配多线程读写 protected List mEntityList = new ArrayList<>(); protected boolean mIsOver; diff --git a/app/src/main/java/com/gh/gamecenter/catalog/SpecialCatalogAdapter.kt b/app/src/main/java/com/gh/gamecenter/catalog/SpecialCatalogAdapter.kt index 385cc629e3..4f0c8050bb 100644 --- a/app/src/main/java/com/gh/gamecenter/catalog/SpecialCatalogAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/catalog/SpecialCatalogAdapter.kt @@ -14,6 +14,7 @@ import com.gh.common.exposure.ExposureEvent import com.gh.common.exposure.ExposureSource import com.gh.common.exposure.IExposable import com.gh.common.util.DirectUtils +import com.gh.common.util.dip2px import com.gh.gamecenter.R import com.gh.gamecenter.adapter.viewholder.FooterViewHolder import com.gh.gamecenter.baselist.ListAdapter @@ -100,6 +101,11 @@ class SpecialCatalogAdapter(context: Context, private val mCatalogViewModel: Cat is CatalogImageItemHolder -> { val imageEntity = mEntityList[position].bigImage!! holder.binding.run { + image.layoutParams = image.layoutParams.apply { + val imageWidth = mContext.resources.displayMetrics.widthPixels - (80F + 16F + 16F).dip2px() + height = imageWidth * 9 / 16 + } + entity = imageEntity.image var exposureEvent: ExposureEvent? = null diff --git a/app/src/main/java/com/gh/gamecenter/download/GameDownloadFragment.java b/app/src/main/java/com/gh/gamecenter/download/GameDownloadFragment.java index aed802de92..09775a2d6b 100644 --- a/app/src/main/java/com/gh/gamecenter/download/GameDownloadFragment.java +++ b/app/src/main/java/com/gh/gamecenter/download/GameDownloadFragment.java @@ -79,6 +79,9 @@ public class GameDownloadFragment extends BaseFragment implements View.OnClickLi @Nullable Integer location = adapter.getLocation(downloadEntity.getUrl()); String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS); if (location != null && XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) { + + if (location > adapter.getDoneList().size()) return; + adapter.getDoneList().set(location, downloadEntity); adapter.notifyItemChanged(location + 1); return; diff --git a/app/src/main/java/com/gh/gamecenter/energy/CommodityAdapter.kt b/app/src/main/java/com/gh/gamecenter/energy/CommodityAdapter.kt index 2a54498422..f0fe4dd70e 100644 --- a/app/src/main/java/com/gh/gamecenter/energy/CommodityAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/energy/CommodityAdapter.kt @@ -58,7 +58,10 @@ class CommodityAdapter(context: Context): ListAdapter(context) executePendingBindings() commodity.tag?.run { - if (id.isNotBlank()) tagContainer.addView(getTagView(this)) + if (id.isNotBlank()) { + tagContainer.removeAllViews() + tagContainer.addView(getTagView(this)) + } } originEnergy.paint.flags = Paint.STRIKE_THRU_TEXT_FLAG diff --git a/app/src/main/java/com/gh/gamecenter/energy/CommodityFragment.kt b/app/src/main/java/com/gh/gamecenter/energy/CommodityFragment.kt index 84ef6b44a8..032bf57425 100644 --- a/app/src/main/java/com/gh/gamecenter/energy/CommodityFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/energy/CommodityFragment.kt @@ -100,13 +100,17 @@ class CommodityFragment : ListFragment() { } fun refreshPage(size: SubjectSettingEntity.Size) { - mListViewModel.sortSize = size - onRefresh() + if (size != mListViewModel.sortSize) { + mListViewModel.sortSize = size + onRefresh() + } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - mListRefresh?.isNestedScrollingEnabled = false + if (mEntrance == "光能中心") { + mListRefresh?.isNestedScrollingEnabled = false + } } override fun onLoadDone() { @@ -114,6 +118,17 @@ class CommodityFragment : ListFragment() { mListRefresh?.isEnabled = false } + override fun onLoadEmpty() { + super.onLoadEmpty() + // RecyclerView 被隐藏的话会导致不能 AppBar 不能滑动 + mListRv.visibility = View.VISIBLE + } + + override fun onLoadError() { + super.onLoadError() + mListRv.visibility = View.VISIBLE + } + fun setNestedScrollingEnabled(enable: Boolean) { mListRv.isNestedScrollingEnabled = enable } diff --git a/app/src/main/java/com/gh/gamecenter/energy/EnergyCenterFragment.kt b/app/src/main/java/com/gh/gamecenter/energy/EnergyCenterFragment.kt index 26976ef61b..2b24190ade 100644 --- a/app/src/main/java/com/gh/gamecenter/energy/EnergyCenterFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/energy/EnergyCenterFragment.kt @@ -1,6 +1,8 @@ package com.gh.gamecenter.energy +import android.os.Build import android.os.Bundle +import android.util.DisplayMetrics import android.view.LayoutInflater import android.view.View import android.widget.CheckedTextView @@ -88,7 +90,12 @@ class EnergyCenterFragment : BaseLazyFragment() { } mBinding.run { - val screenHeight = resources.displayMetrics.heightPixels + val screenHeight = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) + resources.displayMetrics.heightPixels + else + DisplayMetrics() + .apply { requireActivity().windowManager.defaultDisplay.getRealMetrics(this) } + .heightPixels val behavior = BottomSheetBehavior.from(bottomSheet) val toolbarHeight = screenHeight - DisplayUtils.getStatusBarHeight(resources) - 48F.dip2px() behavior.peekHeight = screenHeight - 312F.dip2px() @@ -105,8 +112,7 @@ class EnergyCenterFragment : BaseLazyFragment() { } } - override fun onSlide(bottomSheet: View, slideOffset: Float) { - } + override fun onSlide(bottomSheet: View, slideOffset: Float) {} }) } } @@ -182,13 +188,13 @@ class EnergyCenterFragment : BaseLazyFragment() { } } - @OnClick(R.id.backIv, R.id.EnergyRecord, R.id.lotteryCenter, R.id.signSwitch, R.id.signBubble, + @OnClick(R.id.backIv, R.id.energyRecord, R.id.lotteryCenter, R.id.signSwitch, R.id.signBubble, R.id.oneDay, R.id.twoDay, R.id.threeDay, R.id.fourDay, R.id.fiveDay, R.id.sixDay, R.id.sevenDay) fun onViewClicked(v: View) { when (v.id) { R.id.backIv -> requireActivity().finish() - R.id.EnergyRecord -> { + R.id.energyRecord -> { ifLogin("光能中心-光能记录") { DirectUtils.directToEnergyRecord(requireContext()) } diff --git a/app/src/main/java/com/gh/gamecenter/energy/EnergyHouseFragment.kt b/app/src/main/java/com/gh/gamecenter/energy/EnergyHouseFragment.kt index 99b24e8813..ef8b6e4a3f 100644 --- a/app/src/main/java/com/gh/gamecenter/energy/EnergyHouseFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/energy/EnergyHouseFragment.kt @@ -19,6 +19,7 @@ import com.gh.gamecenter.databinding.FragmentEnergyHouseBinding import com.gh.gamecenter.entity.CommodityCategoryEntity import com.gh.gamecenter.entity.SubjectSettingEntity import com.gh.gamecenter.entity.TaskEntity +import com.gh.gamecenter.entity.UserInfoEntity import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.personalhome.UserHomeViewModel import com.gh.gamecenter.user.UserViewModel @@ -34,12 +35,14 @@ class EnergyHouseFragment: BaseLazyFragment() { private lateinit var mUserHomeViewModel: UserHomeViewModel private lateinit var mEnergyHouseViewModel: EnergyHouseViewModel private lateinit var mCommodityCategories: List + private var mUserInfo: UserInfoEntity? = null private val mTitleList = ArrayList() private val mFragments = ArrayList() - private val mTasks = ArrayList() + private var mTasks = ArrayList() private val mRollUserNames = ArrayList() private val mRollCommodityNames = ArrayList() - private var currentSizeIndex = 0 + private var mCurrentSizeIndex = 0 + private var mCurrentSize = SubjectSettingEntity.Size() override fun getLayoutId() = 0 @@ -70,9 +73,9 @@ class EnergyHouseFragment: BaseLazyFragment() { mUserViewModel.loginObsUserinfo.observeNonNull(viewLifecycleOwner) { if (it.data != null) { mBinding.run { - val userInfo = it.data - userIcon.display(userInfo.iconBorder?.url, userInfo.icon ?: "") - userName.text = userInfo.name + mUserInfo = it.data + userIcon.display(mUserInfo?.iconBorder?.url, mUserInfo?.icon ?: "") + userName.text = mUserInfo?.name } mUserHomeViewModel.userId = UserManager.getInstance().userId mUserHomeViewModel.getUserEnergy() @@ -101,12 +104,20 @@ class EnergyHouseFragment: BaseLazyFragment() { mEnergyHouseViewModel.noviceTasks.observeNonNull(viewLifecycleOwner) { mTasks.clear() - mTasks.addAll(it) - mEnergyHouseViewModel.getDailyTasks() + if (it.size > 4) { + mTasks.addAll(it.subList(0, 5)) + initTaskView() + } else { + mTasks.addAll(it) + mEnergyHouseViewModel.getDailyTasks() + } } mEnergyHouseViewModel.dailyTasks.observeNonNull(viewLifecycleOwner) { mTasks.addAll(it) + if (mTasks.size > 4) { + mTasks = ArrayList(mTasks.subList(0, 5)) + } initTaskView() } @@ -203,6 +214,10 @@ class EnergyHouseFragment: BaseLazyFragment() { updateTabStyle(tab, true) } }) + + viewpager.doOnPageSelected { + (mFragments[it] as CommodityFragment).refreshPage(mCurrentSize) + } } initSize() @@ -244,10 +259,11 @@ class EnergyHouseFragment: BaseLazyFragment() { val tv = item.findViewById(R.id.size_tv) tv.text = size.text item.setOnClickListener { - if (currentSizeIndex != index) { + if (mCurrentSizeIndex != index) { changeSizeBg(index) (mFragments[mBinding.viewpager.currentItem] as CommodityFragment).refreshPage(size) - currentSizeIndex = index + mCurrentSizeIndex = index + mCurrentSize = size } } } @@ -269,12 +285,18 @@ class EnergyHouseFragment: BaseLazyFragment() { } - @OnClick(R.id.backIv, R.id.EnergyRecord, R.id.energyOrder) + @OnClick(R.id.backIv, R.id.userEnergy, R.id.energyRecord, R.id.energyOrder) fun onViewClicked(v: View) { when (v.id) { R.id.backIv -> requireActivity().finish() - R.id.EnergyRecord -> { + R.id.userEnergy -> { + mUserInfo?.run { + DialogUtils.showEnergyDialog(requireContext(), name, mBinding.userEnergy.text.toString()) + } + } + + R.id.energyRecord -> { ifLogin("光能屋-光能记录") { DirectUtils.directToEnergyRecord(requireContext(), 1) } diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt index 03f0394af4..555cef87bc 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt @@ -212,7 +212,7 @@ class GameDetailFragment : NormalFragment() { if (mGameEntity != null && mGameEntity!!.getApk().size == 1) { val url = mGameEntity!!.getApk()[0].url if (downloadEntity.url == url) { - if ("pause" != DownloadManager.getInstance(context).getStatus(downloadEntity.url).status) { + if ("pause" != DownloadManager.getInstance(context).getStatus(downloadEntity.url)?.status) { mDownloadEntity = downloadEntity DetailDownloadUtils.detailInvalidate(detailViewHolder) } @@ -291,8 +291,8 @@ class GameDetailFragment : NormalFragment() { mMaxWidth = resources.displayMetrics.widthPixels - DisplayUtils.dip2px(40f) - val args = arguments - mAutoDownload = args!!.getBoolean(EntranceUtils.KEY_AUTO_DOWNLOAD) + val args = arguments ?: Bundle() + mAutoDownload = args.getBoolean(EntranceUtils.KEY_AUTO_DOWNLOAD) mTraceEvent = args.getParcelable(EntranceUtils.KEY_TRACE_EVENT) mSkipGameComment = args.getBoolean(EntranceUtils.KEY_SKIP_GAME_COMMENT) mDestinationTab = args.getInt(EntranceUtils.KEY_TARGET, -1) diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/fuli/FuLiFragment.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/fuli/FuLiFragment.kt index 2651df7570..750009a006 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/fuli/FuLiFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/fuli/FuLiFragment.kt @@ -86,8 +86,8 @@ class FuLiFragment : BaseFragment(), IScrollable { mAdapter?.itemList = it.data mAdapter?.notifyDataSetChanged() } else { - containerRl.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.white)) - noDataImg.visibility = View.VISIBLE + containerRl?.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.white)) + noDataImg?.visibility = View.VISIBLE } }) diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/video/TopVideoView.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/video/TopVideoView.kt index 17a732c418..3e55400dca 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/video/TopVideoView.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/video/TopVideoView.kt @@ -84,7 +84,7 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS clearFullscreenLayout() } - errorBtn.setOnClickListener { + errorBtn?.setOnClickListener { debounceActionWithInterval(errorBtn.id, 1000) { if (!com.shuyu.gsyvideoplayer.utils.NetworkUtils.isAvailable(mContext)) { Utils.toast(context, "网络异常,请检查手机网络状态") diff --git a/app/src/main/java/com/gh/gamecenter/packagehelper/PackageRepository.kt b/app/src/main/java/com/gh/gamecenter/packagehelper/PackageRepository.kt index 79e8d30ede..4af1b9b0a3 100644 --- a/app/src/main/java/com/gh/gamecenter/packagehelper/PackageRepository.kt +++ b/app/src/main/java/com/gh/gamecenter/packagehelper/PackageRepository.kt @@ -61,7 +61,7 @@ object PackageRepository { val gameUpdateLiveData = MutableLiveData>() val gameInstalledLiveData = MutableLiveData>() - val gameInstalled = ArrayList() + val gameInstalled = Collections.synchronizedList(ArrayList()) val gameUpdate = ArrayList() init { @@ -190,7 +190,7 @@ object PackageRepository { * * @param list 已安装的游戏包名集合 */ - private fun loadInstalledGameDigestAndNotifyData(list: ArrayList) { + private fun loadInstalledGameDigestAndNotifyData(list: ArrayList, onWorkerThreadOnly: Boolean = false) { var isNotifyUpdate = false val latch = ObservableUtil.latch(list.size, { if (isNotifyUpdate || gameUpdateLiveData.value == null) notifyGameUpdateData() @@ -199,33 +199,39 @@ object PackageRepository { for (pkgName in list) { val filterQuery = UrlFilterUtils.getFilterQuery("package", pkgName) - mSensitiveApi.loadGameDataByPackageName(filterQuery) + + var observable = mSensitiveApi.loadGameDataByPackageName(filterQuery) .map(RegionSettingHelper.filterGame) .map(ApkActiveUtils.filterMapperList) .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : Response>() { - override fun onResponse(response: List?) { - if (response != null) { - val gh_id = PackageUtils.getMetaData(HaloApp.getInstance().application, pkgName, "gh_id") - for (game in response) { - if (gh_id == null || gh_id == game.id) { - gameInstalled.add(GameInstall.transformGameInstall(game, pkgName)) - val isCanPluggable = checkGamePlugin(game, pkgName) - val isCanUpdate = checkGameUpdate(game) - if (!isNotifyUpdate && isCanUpdate || isCanPluggable) { - isNotifyUpdate = true - } - } + + if (!onWorkerThreadOnly) { + // 这里面的代码(根据包名获取签名?)或许是造成安装完成后的 ANR 和 startForegroundService did not then call startForeground 的原因 + // 为了避免影响其它地方,这里只处理安装完成后的调用 + observable = observable.observeOn(AndroidSchedulers.mainThread()) + } + observable.subscribe(object : Response>() { + override fun onResponse(response: List?) { + if (response != null) { + val gh_id = PackageUtils.getMetaData(HaloApp.getInstance().application, pkgName, "gh_id") + for (game in response) { + if (gh_id == null || gh_id == game.id) { + gameInstalled.add(GameInstall.transformGameInstall(game, pkgName)) + val isCanPluggable = checkGamePlugin(game, pkgName) + val isCanUpdate = checkGameUpdate(game) + if (!isNotifyUpdate && isCanUpdate || isCanPluggable) { + isNotifyUpdate = true } } - latch.countDown() } + } + latch.countDown() + } - override fun onFailure(e: HttpException?) { - latch.countDown() - } - }) + override fun onFailure(e: HttpException?) { + latch.countDown() + } + }) } } @@ -303,7 +309,7 @@ object PackageRepository { val list = ArrayList() list.add(pkgName) - loadInstalledGameDigestAndNotifyData(list) + loadInstalledGameDigestAndNotifyData(list, true) } /** diff --git a/app/src/main/java/com/gh/gamecenter/personalhome/border/AvatarBorderFragment.kt b/app/src/main/java/com/gh/gamecenter/personalhome/border/AvatarBorderFragment.kt index f32a3241f5..925703445e 100644 --- a/app/src/main/java/com/gh/gamecenter/personalhome/border/AvatarBorderFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/personalhome/border/AvatarBorderFragment.kt @@ -48,14 +48,14 @@ class AvatarBorderFragment : BaseFragment_TabLayout() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mUserViewModel = viewModelProvider(UserViewModel.Factory(HaloApp.getInstance().application)) - mUserViewModel.loginObsUserinfo.observe(this, Observer { + mUserViewModel.loginObsUserinfo.observeNonNull(this) { if (it.data.background?.url.isNullOrEmpty()) { ImageUtils.display(mBinding.forumBackground, R.drawable.bg_avatar_border) } else { ImageUtils.display(mBinding.forumBackground, it.data.background?.url) } mBinding.userAvatar.display(it.data.iconBorder?.url, it.data.icon ?: "") - }) + } mUserViewModel.editObsUserinfo.observe(this, Observer { mBinding.userAvatar.displayAvatar(it.data.icon ?: "") }) diff --git a/app/src/main/java/com/gh/gamecenter/receiver/InstallAndUninstallReceiver.java b/app/src/main/java/com/gh/gamecenter/receiver/InstallAndUninstallReceiver.java index 1682ff06fd..d44b15daf1 100644 --- a/app/src/main/java/com/gh/gamecenter/receiver/InstallAndUninstallReceiver.java +++ b/app/src/main/java/com/gh/gamecenter/receiver/InstallAndUninstallReceiver.java @@ -4,6 +4,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import com.gh.common.AppExecutor; import com.gh.common.util.DataUtils; import com.gh.common.util.ExtensionsKt; import com.gh.common.util.InstallUtils; @@ -38,7 +39,14 @@ public class InstallAndUninstallReceiver extends BroadcastReceiver { String versionName = PackageUtils.getVersionByPackage(packageName); EBPackage installEb = new EBPackage("安装", packageName, versionName); EventBus.getDefault().post(installEb); - PackageObserver.onPackageChanged(installEb); + if (PackageUtils.isAppOnForeground(context)) { + PackageObserver.onPackageChanged(installEb); + } else { + // 处于后台运行的时候尝试延迟 1 秒再触发 onPackageChanged (猜测是引起 ANR 的原因) + AppExecutor.getUiExecutor().executeWithDelay(() -> { + PackageObserver.onPackageChanged(installEb); + }, 1000); + } } // 接收卸载广播 diff --git a/app/src/main/java/com/gh/gamecenter/security/BindPhoneFragment.kt b/app/src/main/java/com/gh/gamecenter/security/BindPhoneFragment.kt index 7533878b40..802c290086 100644 --- a/app/src/main/java/com/gh/gamecenter/security/BindPhoneFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/security/BindPhoneFragment.kt @@ -120,7 +120,7 @@ class BindPhoneFragment : NormalFragment() { // 如果当前登录方式是手机号登录,也要更新loginType UserManager.getInstance().loginTokenEntity?.apply { - if (loginType.length == 11) loginType = phoneNum + if (loginType?.length == 11) loginType = phoneNum } requireActivity().finish() @@ -186,7 +186,7 @@ class BindPhoneFragment : NormalFragment() { } @OnClick(R.id.bind_phone_skip, R.id.bind_phone_captcha, R.id.bind_phone_btn) - override fun onClick(v : View) { + override fun onClick(v: View) { // 防止快速点击 if (ClickUtils.isFastDoubleClick()) return diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt index 6498e74956..cf6fc07687 100644 --- a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt @@ -122,7 +122,7 @@ class SimulatorGameFragment : NormalFragment() { MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击${mTypeAliasList[it]}") if (mCurrentPage != it) { - (mFragmentsList[mCurrentPage] as SimulatorGameListFragment).resetPage() + (mFragmentsList.safelyGetInRelease(mCurrentPage) as? SimulatorGameListFragment)?.resetPage() mCurrentPage = it } } diff --git a/app/src/main/java/com/gh/gamecenter/video/detail/VideoDetailContainerFragment.kt b/app/src/main/java/com/gh/gamecenter/video/detail/VideoDetailContainerFragment.kt index 02f3abd295..222926712c 100644 --- a/app/src/main/java/com/gh/gamecenter/video/detail/VideoDetailContainerFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/video/detail/VideoDetailContainerFragment.kt @@ -218,6 +218,7 @@ class VideoDetailContainerFragment : BaseLazyFragment(), OnBackPressedListener { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) val (itemHeight, distance) = getDistance() + if (itemHeight <= 0) return val offsetY = distance % itemHeight val alpha = 1 - offsetY.toFloat() / itemHeight val homeVideoFragment = this@VideoDetailContainerFragment.parentFragment as? HomeVideoFragment @@ -242,7 +243,7 @@ class VideoDetailContainerFragment : BaseLazyFragment(), OnBackPressedListener { } override fun onPageRelease(isNext: Boolean, position: Int) { - val video = mViewModel.videoList.value?.get(position) + val video = mViewModel.videoList.value?.safelyGetInRelease(position) video?.let { ExoCacheManager.cancel(video.url) diff --git a/app/src/main/java/com/gh/gamecenter/video/detail/VideoDetailContainerViewModel.kt b/app/src/main/java/com/gh/gamecenter/video/detail/VideoDetailContainerViewModel.kt index 817710427a..047bee0d94 100644 --- a/app/src/main/java/com/gh/gamecenter/video/detail/VideoDetailContainerViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/video/detail/VideoDetailContainerViewModel.kt @@ -453,8 +453,10 @@ class VideoDetailContainerViewModel(application: Application) : AndroidViewModel } fun shareVideoStatistics(videoEntity: VideoEntity?) { + if (videoEntity == null) return + RetrofitManager.getInstance(getApplication()) - .api.shareVideoStatistics(videoEntity!!.id) + .api.shareVideoStatistics(videoEntity.id) .subscribeOn(Schedulers.io()) .subscribe(object : BiResponse() { override fun onSuccess(data: JsonObject) { diff --git a/app/src/main/res/layout/catalog_subject_game_item.xml b/app/src/main/res/layout/catalog_subject_game_item.xml index f40e40942e..2b6ec63019 100644 --- a/app/src/main/res/layout/catalog_subject_game_item.xml +++ b/app/src/main/res/layout/catalog_subject_game_item.xml @@ -28,8 +28,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:singleLine="true" - android:ellipsize="marquee" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" + android:maxLines="2" + android:ellipsize="end" android:marqueeRepeatLimit="marquee_forever" android:gravity="center" android:includeFontPadding="false" diff --git a/app/src/main/res/layout/fragment_commodity_list.xml b/app/src/main/res/layout/fragment_commodity_list.xml index 855ca2a04e..f279bc102e 100644 --- a/app/src/main/res/layout/fragment_commodity_list.xml +++ b/app/src/main/res/layout/fragment_commodity_list.xml @@ -11,7 +11,7 @@ + android:layout_height="match_parent" /> diff --git a/app/src/main/res/layout/fragment_energy_center.xml b/app/src/main/res/layout/fragment_energy_center.xml index d24454d1b5..dd6fb3b737 100644 --- a/app/src/main/res/layout/fragment_energy_center.xml +++ b/app/src/main/res/layout/fragment_energy_center.xml @@ -71,7 +71,7 @@ + android:src="@drawable/ic_energy_center_sign_normal" /> + android:src="@drawable/ic_energy_center_sign_normal" /> + app:layout_constraintTop_toBottomOf="@+id/energyRecord" />