diff --git a/app/build.gradle b/app/build.gradle index c9ab5428e5..f643f9c11c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -57,7 +57,11 @@ android { ndk { // 如果不添加 `arm64` 调用系统的 PackageManager 的方法读取安装包信息的时候会出现 native 层闪退,草 - abiFilters "armeabi-v7a", "arm64-v8a", "x86" + // 添加了 `arm64` 以后部分 5.0 的设备会报用错 so 的问题, + // couldn't find DSO to load: libimagepipeline.so caused by: dlopen failed: "/data/data/com.gh.gamecenter/lib-main/libimagepipeline.so" is 64-bit instead of 32-bit result: 0 + // 以 OPPO R7PLUS 为例,明明设备是骁龙 615,ARMv8-64 bit 的设备却不支持 arm64 的 abi + // 惊了 + abiFilters "armeabi-v7a", "x86" } renderscriptTargetApi 18 diff --git a/app/src/main/java/com/gh/common/constant/Constants.java b/app/src/main/java/com/gh/common/constant/Constants.java index 1439b344fe..d88fe7798d 100644 --- a/app/src/main/java/com/gh/common/constant/Constants.java +++ b/app/src/main/java/com/gh/common/constant/Constants.java @@ -76,6 +76,9 @@ public class Constants { 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"; // 骨架图配置 @@ -210,6 +213,9 @@ public class Constants { // 新分类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_CONTENT_VIDEO_OPTION = "content_video_option"; 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 0fd890b775..c2eb189505 100644 --- a/app/src/main/java/com/gh/common/dialog/CertificationDialog.kt +++ b/app/src/main/java/com/gh/common/dialog/CertificationDialog.kt @@ -19,12 +19,11 @@ import com.gh.common.avoidcallback.Callback import com.gh.common.constant.Constants import com.gh.common.util.* import com.gh.gamecenter.R -import com.gh.gamecenter.UserInfoEditActivity +import com.gh.gamecenter.ShellActivity import com.gh.gamecenter.entity.AuthDialogEntity import com.gh.gamecenter.entity.AuthDialogLevel import com.gh.gamecenter.entity.GameEntity import com.gh.gamecenter.manager.UserManager -import com.gh.gamecenter.user.UserViewModel import com.google.gson.reflect.TypeToken import com.halo.assistant.fragment.user.UserInfoEditFragment import com.lightgame.utils.AppManager @@ -130,7 +129,7 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi val currentActivity = AppManager.getInstance().currentActivity() ?: return AvoidOnResultManager.getInstance(currentActivity as AppCompatActivity) - .startForResult(UserInfoEditActivity.getIntent(context, UserViewModel.TYPE_ID_CARD), object : Callback { + .startForResult(ShellActivity.getIntent(context, ShellActivity.Type.REAL_NAME_INFO, null), object : Callback { override fun onActivityResult(resultCode: Int, data: Intent?) { if (resultCode == Activity.RESULT_OK && data != null) { val isAuthSuccess = data.getBooleanExtra(UserInfoEditFragment.AUTH_SUCCESS, false) diff --git a/app/src/main/java/com/gh/common/dialog/NotificationHintDialogFragment.kt b/app/src/main/java/com/gh/common/dialog/NotificationHintDialogFragment.kt index c5667d02e1..9201a62d1c 100644 --- a/app/src/main/java/com/gh/common/dialog/NotificationHintDialogFragment.kt +++ b/app/src/main/java/com/gh/common/dialog/NotificationHintDialogFragment.kt @@ -1,6 +1,7 @@ package com.gh.common.dialog import android.annotation.SuppressLint +import android.content.ActivityNotFoundException import android.content.Intent import android.os.Build import android.os.Bundle @@ -73,7 +74,11 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() { val intent = Intent() intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS intent.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID) - startActivity(intent) + try { + startActivity(intent) + } catch (e: ActivityNotFoundException) { + PermissionHelper.toPermissionSetting(requireActivity()) + } } else { PermissionHelper.toPermissionSetting(requireActivity()) } 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 a4acfab466..c7aa2b056a 100644 --- a/app/src/main/java/com/gh/common/util/DataUtils.java +++ b/app/src/main/java/com/gh/common/util/DataUtils.java @@ -194,7 +194,7 @@ public class DataUtils { * 获取应用 gid 绑定的实名信息 */ @SuppressLint("CheckResult") - private static void getDeviceCertification(String gid) { + public static void getDeviceCertification(String gid) { RetrofitManager.getInstance(HaloApp.getInstance()) .getApi() .getCertification() diff --git a/app/src/main/java/com/gh/common/util/DetailDownloadUtils.java b/app/src/main/java/com/gh/common/util/DetailDownloadUtils.java index d2e3cad046..2ffe52d506 100644 --- a/app/src/main/java/com/gh/common/util/DetailDownloadUtils.java +++ b/app/src/main/java/com/gh/common/util/DetailDownloadUtils.java @@ -88,6 +88,8 @@ public class DetailDownloadUtils { viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.PLUGIN); } else if (viewHolder.context.getString(R.string.launch).equals(status)) { viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.LAUNCH_OR_OPEN); + } else if (viewHolder.context.getString(R.string.install).equals(status)) { + viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.INSTALL_NORMAL); } else { viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.NORMAL); } @@ -101,6 +103,8 @@ public class DetailDownloadUtils { downloadText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord); } else if (viewHolder.context.getString(R.string.attempt).equals(status)) { downloadText = status + getDownloadSizeText(viewHolder); + } else if (viewHolder.context.getString(R.string.install).equals(status)) { + downloadText = viewHolder.context.getString(R.string.install); } else { downloadText = status + (TextUtils.isEmpty(downloadAddWord) ? "" : downloadAddWord) + getDownloadSizeText(viewHolder); } diff --git a/app/src/main/java/com/gh/common/util/DirectUtils.kt b/app/src/main/java/com/gh/common/util/DirectUtils.kt index c90bfd057b..4d69ca035b 100644 --- a/app/src/main/java/com/gh/common/util/DirectUtils.kt +++ b/app/src/main/java/com/gh/common/util/DirectUtils.kt @@ -60,7 +60,6 @@ import com.gh.gamecenter.servers.GameServersActivity import com.gh.gamecenter.subject.SubjectActivity import com.gh.gamecenter.suggest.SuggestType import com.gh.gamecenter.tag.TagsActivity -import com.gh.gamecenter.user.UserViewModel import com.gh.gamecenter.video.data.VideoDataActivity import com.gh.gamecenter.video.detail.VideoDetailActivity import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel @@ -290,7 +289,7 @@ object DirectUtils { } "authentication" -> { - context.startActivity(UserInfoEditActivity.getIntent(context, UserViewModel.TYPE_ID_CARD)) + context.startActivity(ShellActivity.getIntent(context, ShellActivity.Type.REAL_NAME_INFO, null)) } "user_background" -> { @@ -505,9 +504,9 @@ object DirectUtils { @JvmStatic fun directToHomeActivity( context: Context, - userId: String?, - type: String = "", - position: Int, + userId: String? = "", + type: String? = "", + position: Int? = 0, entrance: String? = null, path: String? = null ) { @@ -519,7 +518,7 @@ object DirectUtils { bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path)) bundle.putString(KEY_PATH, path) bundle.putString(KEY_TYPE, UserHistoryViewModel.TYPE.fromValue(type).value) - bundle.putInt(KEY_POSITION, position) + bundle.putInt(KEY_POSITION, position ?: 0) jumpActivity(context, bundle) } 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 9b3194e05a..6e0b3b0aea 100644 --- a/app/src/main/java/com/gh/common/util/DownloadObserver.kt +++ b/app/src/main/java/com/gh/common/util/DownloadObserver.kt @@ -3,7 +3,6 @@ package com.gh.common.util import android.os.Build import android.preference.PreferenceManager import com.gh.base.BaseActivity -import com.gh.base.CurrentActivityHolder import com.gh.common.constant.Constants import com.gh.common.exposure.ExposureUtils import com.gh.common.exposure.meta.MetaUtil @@ -13,10 +12,7 @@ import com.gh.common.util.EnergyTaskHelper.postEnergyTask import com.gh.common.xapk.XapkInstaller import com.gh.download.DownloadDataHelper import com.gh.download.DownloadManager -import com.gh.gamecenter.BuildConfig -import com.gh.gamecenter.R -import com.gh.gamecenter.SuggestionActivity -import com.gh.gamecenter.UserInfoEditActivity +import com.gh.gamecenter.* import com.gh.gamecenter.entity.GameEntity import com.gh.gamecenter.entity.SimpleGameEntity import com.gh.gamecenter.entity.SimulatorEntity @@ -26,7 +22,6 @@ import com.gh.gamecenter.retrofit.Response import com.gh.gamecenter.retrofit.RetrofitManager import com.gh.gamecenter.setting.GameDownloadSettingFragment.Companion.AUTO_INSTALL_SP_KEY import com.gh.gamecenter.suggest.SuggestType -import com.gh.gamecenter.user.UserViewModel import com.halo.assistant.HaloApp import com.lightgame.download.DataWatcher import com.lightgame.download.DownloadEntity @@ -104,59 +99,15 @@ object DownloadObserver { DownloadDataHelper.uploadRedirectEvent(downloadEntity) } else if (DownloadStatus.unqualified == downloadEntity.status) { // 未成年 - val currentActivity = CurrentActivityHolder.getCurrentActivity() - if (currentActivity == null) { - ToastUtils.toast("为保护未成年身心健康成长,根据相关政策要求,该游戏不对未成年人开放下载") - } else { - NewLogUtils.logCertificationHintDialogTrigger(true) - DialogHelper.showDialog( - currentActivity, - title = "实名提示", - content = "为保护未成年身心健康成长,根据相关政策要求,该游戏不对未成年人开放下载", - confirmText = "知道了", - cancelText = "", - confirmClickCallback = { -// NewLogUtils.logCertificationHintDialogTrigger(true) - } - ) - } - DownloadManager.getInstance(HaloApp.getInstance()).addInvisiblePendingTask(downloadEntity) + RealNameHelper.showRealNameUnqualifiedDialog(downloadEntity) // 删除任务 downloadEntity.status = DownloadStatus.cancel downloadManager.cancel(downloadEntity.url) } else if (DownloadStatus.uncertificated == downloadEntity.status) { // 未实名 - NewLogUtils.logCertificationTrigger(downloadEntity.gameId, downloadEntity.name) + RealNameHelper.showRealNameUncertificatedDialog(downloadEntity) - val currentActivity = CurrentActivityHolder.getCurrentActivity() - if (currentActivity == null) { - ToastUtils.toast("为保护未成年身心健康成长,根据相关政策要求,该游戏不对未成年人开放下载") - } else { - NewLogUtils.logCertificationHintDialogAppearance() - DialogHelper.showDialog( - currentActivity, - title = "实名提示", - content = "为保护未成年身心健康成长,根据相关政策要求,该游戏不对未成年人开放下载\n" + - "如需下载,请前往实名认证", - confirmText = "前往实名认证", - cancelText = "取消", - confirmClickCallback = { - currentActivity.startActivity( - UserInfoEditActivity.getIntent( - currentActivity, - UserViewModel.TYPE_ID_CARD, - true - ) - ) - NewLogUtils.logCertificationHintDialogOptionsClicked("前往实名认证") - }, - cancelClickCallback = { - NewLogUtils.logCertificationHintDialogOptionsClicked("取消") - } - ) - } - DownloadManager.getInstance(HaloApp.getInstance()).addInvisiblePendingTask(downloadEntity) // 删除任务 downloadEntity.status = DownloadStatus.cancel downloadManager.cancel(downloadEntity.url) diff --git a/app/src/main/java/com/gh/common/util/ErrorHelper.kt b/app/src/main/java/com/gh/common/util/ErrorHelper.kt index 5eb6d4e9ba..2a9ed4927c 100644 --- a/app/src/main/java/com/gh/common/util/ErrorHelper.kt +++ b/app/src/main/java/com/gh/common/util/ErrorHelper.kt @@ -136,6 +136,7 @@ object ErrorHelper { 400001 -> Utils.toast(context, "字数超过500或者未填写原因") 403102 -> Utils.toast(context, "你已经举报过该内容了哦") 403115 -> Utils.toast(context, "请求太频繁了,稍微休息一下") + 403119 -> Utils.toast(context, "不能重复修改实名") 403020 -> if (showHighPriorityHint) { DialogHelper.showDialog( diff --git a/app/src/main/java/com/gh/common/util/LoginHelper.kt b/app/src/main/java/com/gh/common/util/LoginHelper.kt index 9dc9806805..07e9585186 100644 --- a/app/src/main/java/com/gh/common/util/LoginHelper.kt +++ b/app/src/main/java/com/gh/common/util/LoginHelper.kt @@ -3,6 +3,7 @@ package com.gh.common.util import android.app.Activity import android.content.Intent import com.gh.common.constant.Config +import com.gh.common.constant.Constants import com.gh.gamecenter.R import com.gh.gamecenter.user.LoginTag import com.halo.assistant.HaloApp @@ -169,6 +170,15 @@ object LoginHelper { // 微博登录 @JvmStatic fun loginWithWeibo(loginCallback: LoginCallback, context: Activity) { + + tryWithDefaultCatch { + if (SPUtils.getBoolean(Constants.SP_USER_NEED_WEIBO_X86_SO)) { + SentryHelper.onEvent( + "weibo_sdk_login_error", + "exception_digest", "no_x86_so"); + } + } + mWBAPI = WBAPIFactory.createWBAPI(context) //初始化微博分享 mLoginCallback = WeakReference(loginCallback) mWBAPI.registerApp( 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 3a23b350d1..67e8d4cbae 100644 --- a/app/src/main/java/com/gh/common/util/PackageInstaller.kt +++ b/app/src/main/java/com/gh/common/util/PackageInstaller.kt @@ -1,5 +1,6 @@ package com.gh.common.util +import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.content.Intent @@ -7,16 +8,23 @@ import android.net.Uri import android.os.Build import androidx.appcompat.app.AppCompatActivity import androidx.core.content.FileProvider +import com.gh.base.CurrentActivityHolder import com.gh.common.constant.Constants import com.gh.common.dialog.InstallPermissionDialogFragment import com.gh.common.xapk.XapkInstaller +import com.gh.download.DownloadManager import com.gh.download.server.BrowserInstallHelper import com.gh.gamecenter.BuildConfig +import com.gh.gamecenter.retrofit.BiResponse +import com.gh.gamecenter.retrofit.RetrofitManager import com.halo.assistant.HaloApp import com.lightgame.download.DownloadEntity import com.lightgame.download.FileUtils -import com.lightgame.utils.AppManager import com.lightgame.utils.Utils +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers +import okhttp3.ResponseBody +import retrofit2.HttpException import java.io.File object PackageInstaller { @@ -41,7 +49,7 @@ object PackageInstaller { val pkgPath = downloadEntity.path val isXapk = XapkInstaller.XAPK_EXTENSION_NAME == pkgPath.getExtension() - val currentActivity = AppManager.getInstance().currentActivity() ?: return + val currentActivity = CurrentActivityHolder.getCurrentActivity() ?: return // TODO 此处可能遇到 activity 是 WXEntryActivity // TODO 当 activity 全部出栈,但是应用还在下载游戏,下载完会唤不起安装! @@ -71,16 +79,27 @@ object PackageInstaller { try { // 判断是否需要使用浏览器来进行安装 if (BrowserInstallHelper.isUseBrowserToInstallEnabled() - && BrowserInstallHelper.shouldUseBrowserToInstall()) { + && BrowserInstallHelper.shouldUseBrowserToInstall() + ) { BrowserInstallHelper.downloadFile(pkgPath) return } if (PackageUtils.isCanLaunchSetup(context, pkgPath)) { + val app = HaloApp.getInstance() + HaloApp.put(Constants.LAST_INSTALL_GAME, pkgPath) - val installIntent = getInstallIntent(context, pkgPath) - context.startActivity(installIntent) + val downloadEntity = + DownloadManager.getInstance(app).allDownloadEntity.firstOrNull { + it.path == pkgPath + } +// if (downloadEntity != null) { +// showCertificateDialogIfNeededBeforeInstall(app, downloadEntity, pkgPath) +// } else { + val installIntent = getInstallIntent(context, pkgPath) + context.startActivity(installIntent) +// } } else { if (isPluggin) { DialogHelper.showPluginDialog(context) { @@ -98,6 +117,49 @@ object PackageInstaller { } } + @SuppressLint("CheckResult") + fun showCertificateDialogIfNeededBeforeInstall(context: Context, downloadEntity: DownloadEntity, pkgPath: String) { + val isOverwrite = LunchType.UPDATE.name == SPUtils.getString(Constants.SP_INSTALL_TYPE) + val hashMap = hashMapOf(Pair("url", downloadEntity.url), Pair("overwrite", isOverwrite)) + RetrofitManager.getInstance(context).api.postCertificationCheck(hashMap.toRequestBody()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: ResponseBody) { + val installIntent = getInstallIntent(context, pkgPath) + context.startActivity(installIntent) + } + + override fun onFailure(exception: Exception) { + super.onFailure(exception) + + if (exception is HttpException) { + val resultString = + (exception as HttpException).response().errorBody() + ?.string() + // 未实名 + when { + resultString?.contains("403117") == true -> { + RealNameHelper.showRealNameUncertificatedDialog( + downloadEntity + ) + } + resultString?.contains("403118") == true -> { + RealNameHelper.showRealNameUnqualifiedDialog( + downloadEntity + ) + } + resultString?.contains("400004") == true -> { + ToastUtils.toast("安装服务异常,缺少参数") + } + } + } else { + ToastUtils.toast("安装服务异常,${exception.localizedMessage}请稍候再试") + } + } + }) + } + /** * 获取启动安装意图 * @@ -107,11 +169,12 @@ object PackageInstaller { @JvmStatic fun getInstallIntent(context: Context, path: String): Intent { var uri = Uri.fromFile(File(path)) - val installIntent = if (BrowserInstallHelper.isUseBrowserToInstallEnabledWithPackageMatched()) { - Intent(Intent.ACTION_INSTALL_PACKAGE) - } else { - Intent(Intent.ACTION_VIEW) - } + val installIntent = + if (BrowserInstallHelper.isUseBrowserToInstallEnabledWithPackageMatched()) { + Intent(Intent.ACTION_INSTALL_PACKAGE) + } else { + Intent(Intent.ACTION_VIEW) + } if ("smartisan" == Build.MANUFACTURER) { installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } @@ -129,7 +192,8 @@ object PackageInstaller { } installIntent.setDataAndType(uri, "application/vnd.android.package-archive") } - InstallUtils.getInstance(context).addInstall(PackageUtils.getPackageNameByPath(context, path)) + InstallUtils.getInstance(context) + .addInstall(PackageUtils.getPackageNameByPath(context, path)) return installIntent } @@ -163,7 +227,10 @@ object PackageInstaller { @JvmStatic fun getDownloadPathWithId(id: String, format: String?): String { - return FileUtils.getDownloadPath(HaloApp.getInstance().application, id + "." + getFileSuffixByFormat(format)) + return FileUtils.getDownloadPath( + HaloApp.getInstance().application, + id + "." + getFileSuffixByFormat(format) + ) } private fun getFileSuffixByFormat(format: String?): String { diff --git a/app/src/main/java/com/gh/common/util/RealNameHelper.kt b/app/src/main/java/com/gh/common/util/RealNameHelper.kt index 52778ce87f..b15d4e0bc9 100644 --- a/app/src/main/java/com/gh/common/util/RealNameHelper.kt +++ b/app/src/main/java/com/gh/common/util/RealNameHelper.kt @@ -1,17 +1,104 @@ package com.gh.common.util import android.content.Context -import com.gh.gamecenter.UserInfoEditActivity +import com.gh.base.CurrentActivityHolder +import com.gh.download.DownloadManager +import com.gh.gamecenter.ShellActivity import com.gh.gamecenter.entity.GameEntity -import com.gh.gamecenter.manager.UserManager -import com.gh.gamecenter.user.UserViewModel -import java.util.* +import com.halo.assistant.HaloApp +import com.lightgame.download.DownloadEntity +import com.lightgame.download.DownloadStatus object RealNameHelper { + var pendingInstallPkgPath = "" + @JvmStatic fun checkIfAuth(context: Context, gameEntity: GameEntity, callback: EmptyCallback) { callback.onCallback() } + /** + * 弹未成年人不能下载游戏弹窗 + */ + fun showRealNameUnqualifiedDialog(downloadEntity: DownloadEntity) { + + val contentText = if (downloadEntity.status == DownloadStatus.done) { + "为保护未成年身心健康成长\n" + "根据相关政策要求,该游戏不对未成年人开放" + } else { + "为保护未成年身心健康成长\n" + "根据相关政策要求,该游戏不对未成年人开放下载" + } + + val currentActivity = CurrentActivityHolder.getCurrentActivity() + if (currentActivity == null) { + ToastUtils.toast("为保护未成年身心健康成长,根据相关政策要求,该游戏不对未成年人开放") + } else { + NewLogUtils.logCertificationHintDialogTrigger(true) + DialogHelper.showDialog( + currentActivity, + title = "实名提示", + content = contentText, + confirmText = "知道了", + cancelText = "", + confirmClickCallback = { +// NewLogUtils.logCertificationHintDialogTrigger(true) + } + ) + } + if (downloadEntity.status != DownloadStatus.done) { + DownloadManager.getInstance(HaloApp.getInstance()) + .addInvisiblePendingTask(downloadEntity) + } + } + + /** + * 弹需要实名弹窗 + */ + fun showRealNameUncertificatedDialog(downloadEntity: DownloadEntity) { + NewLogUtils.logCertificationTrigger(downloadEntity.gameId, downloadEntity.name) + + val contentText = if (downloadEntity.status == DownloadStatus.done) { + "为保护未成年身心健康成长\n" + "根据相关政策要求,该游戏不对未成年人开放\n" + "如需完成安装,请前往实名认证" + } else { + "为保护未成年身心健康成长\n" + "根据相关政策要求,该游戏不对未成年人开放下载\n" + "如需下载,请前往实名认证" + } + + val currentActivity = CurrentActivityHolder.getCurrentActivity() + if (currentActivity == null) { + ToastUtils.toast("为保护未成年身心健康成长,根据相关政策要求,该游戏不对未成年人开放") + } else { + NewLogUtils.logCertificationHintDialogAppearance() + DialogHelper.showDialog( + currentActivity, + title = "实名提示", + content = contentText, + confirmText = "前往实名认证", + cancelText = "取消", + confirmClickCallback = { + currentActivity.startActivity( + ShellActivity.getIntent( + currentActivity, + ShellActivity.Type.REAL_NAME_INFO + ).apply { + putExtra(EntranceUtils.KEY_IS_FORCED_TO_CERTICIFICE, true) + } + ) + if (downloadEntity.status == DownloadStatus.done) { + pendingInstallPkgPath = downloadEntity.path + } + NewLogUtils.logCertificationHintDialogOptionsClicked("前往实名认证") + }, + cancelClickCallback = { + NewLogUtils.logCertificationHintDialogOptionsClicked("取消") + } + ) + } + + if (downloadEntity.status != DownloadStatus.done) { + DownloadManager.getInstance(HaloApp.getInstance()) + .addInvisiblePendingTask(downloadEntity) + } + + } + } \ No newline at end of file diff --git a/app/src/main/java/com/gh/download/DownloadManager.java b/app/src/main/java/com/gh/download/DownloadManager.java index 01d7d9bd3f..6428240fe1 100644 --- a/app/src/main/java/com/gh/download/DownloadManager.java +++ b/app/src/main/java/com/gh/download/DownloadManager.java @@ -27,6 +27,7 @@ import com.gh.common.util.DialogUtils; import com.gh.common.util.ExtensionsKt; import com.gh.common.util.GsonUtils; import com.gh.common.util.HomePluggableHelper; +import com.gh.common.util.LunchType; import com.gh.common.util.NetworkUtils; import com.gh.common.util.PackageInstaller; import com.gh.common.util.PackageUtils; @@ -118,7 +119,7 @@ public class DownloadManager implements DownloadStatusListener { downloadingMap.put(entity.getUrl(), entity); - DownloadWorkManager.addWorker(); +// DownloadWorkManager.addWorker(); } @Override @@ -142,7 +143,7 @@ public class DownloadManager implements DownloadStatusListener { mDownloadedGameIdAndPackageNameDao.add(entity.getGameId() + entity.getPackageName()); if (downloadingMap.isEmpty()) { - DownloadWorkManager.cancelWorker(); +// DownloadWorkManager.cancelWorker(); } } @@ -1041,6 +1042,7 @@ public class DownloadManager implements DownloadStatusListener { ArrayList updates = PackageRepository.INSTANCE.getGameUpdate(); for (GameUpdateEntity update : updates) { + if (update == null) continue; String mark = update.getId() + update.getPackageName(); if (!mUpdateMarks.contains(mark)) { mUpdateMarks.add(mark); @@ -1124,6 +1126,13 @@ public class DownloadManager implements DownloadStatusListener { * 更新下载请求头的相关信息 */ public static void updateDownloadMetaMap() { + String isOverwrite; + if (LunchType.UPDATE.name().equals(SPUtils.getString(Constants.SP_INSTALL_TYPE))) { + isOverwrite = "true"; + } else { + isOverwrite = "false"; + } + HashMap map = new HashMap<>(); map.put(HttpDnsManager.APP_VERSION, BuildConfig.VERSION_NAME); map.put(HttpDnsManager.CHANNEL, HaloApp.getInstance().getChannel()); @@ -1132,6 +1141,7 @@ public class DownloadManager implements DownloadStatusListener { map.put(HttpDnsManager.USER_ID, UserManager.getInstance().getUserId()); map.put(HttpDnsManager.IMEI, MetaUtil.getBase64EncodedIMEI()); map.put(HttpDnsManager.TOKEN, UserManager.getInstance().getToken()); + map.put(HttpDnsManager.IS_OVERWRITE, isOverwrite); HttpDnsManager.metaMap = map; } diff --git a/app/src/main/java/com/gh/download/DownloadWorkManager.kt b/app/src/main/java/com/gh/download/DownloadWorkManager.kt index cd734214b3..18ff96b85a 100644 --- a/app/src/main/java/com/gh/download/DownloadWorkManager.kt +++ b/app/src/main/java/com/gh/download/DownloadWorkManager.kt @@ -29,7 +29,7 @@ object DownloadWorkManager { @JvmStatic fun cancelWorker() { - tryWithDefaultCatch { WorkManager.getInstance().cancelAllWorkByTag(TAG_DOWNLOAD) } +// tryWithDefaultCatch { WorkManager.getInstance().cancelAllWorkByTag(TAG_DOWNLOAD) } } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/ImageViewerActivity.kt b/app/src/main/java/com/gh/gamecenter/ImageViewerActivity.kt index 2b2d0f3b67..3867ae5b3a 100644 --- a/app/src/main/java/com/gh/gamecenter/ImageViewerActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/ImageViewerActivity.kt @@ -128,13 +128,19 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener { mUrlList = ArrayList() mUrlList?.add(image) } else { - mUrlList = it.getStringArrayList(KEY_URL_LIST) + mUrlList = it.getStringArrayList(KEY_URL_LIST) ?: arrayListOf() mInitialPosition = it.getInt(KEY_CURRENT, 0) } mShowSaveBtn = it.getBoolean(KEY_SHOW_SAVE) mUseEnterAndExitAnimation = it.getBoolean(KEY_USE_ENTER_AND_EXIT_ANIMATION) mAnswerEntity = it.getParcelable(AnswerEntity::class.java.name) } + + if (mUrlList?.isEmpty() == true) { + ToastUtils.toast("无法查看大图") + finish() + } + mSavePicBtn.visibleIf(mShowSaveBtn) mArticleDetailBtn.visibleIf(mAnswerEntity != null) mIndicatorMask.goneIf(mUrlList?.size == 1) diff --git a/app/src/main/java/com/gh/gamecenter/MainActivity.java b/app/src/main/java/com/gh/gamecenter/MainActivity.java index 1abf13aeee..8e7cde52bf 100644 --- a/app/src/main/java/com/gh/gamecenter/MainActivity.java +++ b/app/src/main/java/com/gh/gamecenter/MainActivity.java @@ -222,6 +222,11 @@ public class MainActivity extends BaseActivity { getPluginUpdate(); mSp.edit().putBoolean("isNewFirstLaunchV" + PackageUtils.getGhVersionName(), false).apply(); + // 记录曾安装过的版本 + 渠道 + SPUtils.setString("installedVersionV" + PackageUtils.getGhVersionName(), HaloApp.getInstance().getChannel()); + + SPUtils.setString(Constants.SP_INSTALL_TYPE, lunchType.name()); + checkDevice(); // 根据设备信息判断用户是否是新用户 } @@ -1033,9 +1038,7 @@ public class MainActivity extends BaseActivity { // 所以 x86 的 AS 模拟器/ Genymotion 会初始化失败,但实测部分硬性需要提供 x86 SO 的模拟器 (如雷电) 却又能正常使用 // 这里加个简单日志,看看到底有没有(有多少)真实设备出现初始化失败的问题 if (!BuildConfig.DEBUG) { - SentryHelper.INSTANCE.onEvent( - "weibo_sdk_init_error", - "exception_digest", e.getLocalizedMessage()); + SPUtils.setBoolean(Constants.SP_USER_NEED_WEIBO_X86_SO, true); e.printStackTrace(); } } diff --git a/app/src/main/java/com/gh/gamecenter/ShellActivity.kt b/app/src/main/java/com/gh/gamecenter/ShellActivity.kt index e78f1c75dd..2484e64853 100644 --- a/app/src/main/java/com/gh/gamecenter/ShellActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/ShellActivity.kt @@ -9,6 +9,7 @@ import com.gh.base.fragment.BaseFragment import com.gh.common.util.EntranceUtils import com.gh.gamecenter.amway.AmwaySuccessFragment import com.halo.assistant.fragment.SwitchInstallMethodFragment +import com.halo.assistant.fragment.user.RealNameInfoFragment /** * ShellActivity 用来包裹那些几乎没有交互且运营也不会想要知道页面访问量的静态 fragment (如安利墙的评论提交成功页面) @@ -30,6 +31,7 @@ class ShellActivity : ToolBarActivity() { when (intentType) { Type.AMWAY_SUCCESS -> startFragment(AmwaySuccessFragment().with(bundle)) Type.SWITCH_INSTALL_METHOD -> startFragment(SwitchInstallMethodFragment()) + Type.REAL_NAME_INFO -> startFragment(RealNameInfoFragment().with(bundle)) } } @@ -54,7 +56,8 @@ class ShellActivity : ToolBarActivity() { enum class Type(val value: String) { AMWAY_SUCCESS("amway_success"), - SWITCH_INSTALL_METHOD("switch_install_method"); + SWITCH_INSTALL_METHOD("switch_install_method"), + REAL_NAME_INFO("real_name_info"); companion object { fun fromString(typeString: String): Type { 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 a30e95d50b..d2140c0f1b 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/ListAdapter.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListAdapter.java @@ -52,42 +52,51 @@ public abstract class ListAdapter extends BaseRecyclerAdapter { ArrayList updateDataCopy = new ArrayList<>(updateData); ListExecutor.getWorkerExecutor().execute(() -> { - DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() { - @Override - public int getOldListSize() { - return mEntityList == null ? 0 : mEntityList.size(); - } + try { + DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() { + @Override + public int getOldListSize() { + return mEntityList == null ? 0 : mEntityList.size(); + } - @Override - public int getNewListSize() { - return updateDataCopy.size(); - } + @Override + public int getNewListSize() { + return updateDataCopy.size(); + } - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - if (oldItemPosition >= mEntityList.size()) return false; - if (newItemPosition >= updateDataCopy.size()) return false; + @Override + public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + if (oldItemPosition >= mEntityList.size()) return false; + if (newItemPosition >= updateDataCopy.size()) return false; - DataType oldItem = ExtensionsKt.safelyGetInRelease(mEntityList, oldItemPosition); - DataType newItem = ExtensionsKt.safelyGetInRelease(updateDataCopy, newItemPosition); - return ListAdapter.this.areItemsTheSame(oldItem, newItem); - } + DataType oldItem = ExtensionsKt.safelyGetInRelease(mEntityList, oldItemPosition); + DataType newItem = ExtensionsKt.safelyGetInRelease(updateDataCopy, newItemPosition); + return ListAdapter.this.areItemsTheSame(oldItem, newItem); + } - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - if (oldItemPosition >= mEntityList.size()) return false; - if (newItemPosition >= updateDataCopy.size()) return false; + @Override + public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { + if (oldItemPosition >= mEntityList.size()) return false; + if (newItemPosition >= updateDataCopy.size()) return false; - DataType oldItem = ExtensionsKt.safelyGetInRelease(mEntityList, oldItemPosition); - DataType newItem = ExtensionsKt.safelyGetInRelease(updateDataCopy, newItemPosition); - return ListAdapter.this.areContentsTheSame(oldItem, newItem); - } - }); + DataType oldItem = ExtensionsKt.safelyGetInRelease(mEntityList, oldItemPosition); + DataType newItem = ExtensionsKt.safelyGetInRelease(updateDataCopy, newItemPosition); + return ListAdapter.this.areContentsTheSame(oldItem, newItem); + } + }); - ListExecutor.getUiExecutor().execute(() -> { - mEntityList = new ArrayList<>(updateDataCopy); - diffResult.dispatchUpdatesTo(ListAdapter.this); - }); + ListExecutor.getUiExecutor().execute(() -> { + mEntityList = new ArrayList<>(updateDataCopy); + diffResult.dispatchUpdatesTo(ListAdapter.this); + }); + } catch (ArrayIndexOutOfBoundsException exception) { + // 新旧数据比较的时候数组越界了(大概是别处修改了数据源 :( ),直接 notifyDataSetChanged + ListExecutor.getUiExecutor().execute(() -> { + exception.printStackTrace(); + mEntityList = new ArrayList<>(updateData); + notifyDataSetChanged(); + }); + } }); } diff --git a/app/src/main/java/com/gh/gamecenter/download/UpdatableGameAdapter.kt b/app/src/main/java/com/gh/gamecenter/download/UpdatableGameAdapter.kt index ad953d615c..4045f0e31d 100644 --- a/app/src/main/java/com/gh/gamecenter/download/UpdatableGameAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/download/UpdatableGameAdapter.kt @@ -11,6 +11,7 @@ import androidx.core.content.ContextCompat import androidx.core.view.setPadding import androidx.fragment.app.FragmentActivity import androidx.recyclerview.widget.RecyclerView +import com.gh.base.CurrentActivityHolder import com.gh.common.exposure.ExposureEvent import com.gh.common.exposure.ExposureEvent.Companion.createEvent import com.gh.common.exposure.ExposureSource @@ -338,7 +339,9 @@ class UpdatableGameAdapter(private var mViewModel: UpdatableGameViewModel) : updateBtn.setOnClickListener { val str: String = updateBtn.text.toString() if ("更新" == str || str.contains("化")) { - (updateBtn.context as FragmentActivity).checkStoragePermissionBeforeAction { + // 这里用 CurrentActivity 不用 view.context 的原因是 + // view.context 在 5.0 以下设备会使用 TintContextWrapper 包一层导致类型转换异常 + (CurrentActivityHolder.getCurrentActivity() as? FragmentActivity)?.checkStoragePermissionBeforeAction { DialogUtils.checkDownload( updateBtn.context, update.size diff --git a/app/src/main/java/com/gh/gamecenter/download/UpdatableGameFragment.kt b/app/src/main/java/com/gh/gamecenter/download/UpdatableGameFragment.kt index 7dfab6da2f..b6bbb42da5 100644 --- a/app/src/main/java/com/gh/gamecenter/download/UpdatableGameFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/download/UpdatableGameFragment.kt @@ -1,13 +1,13 @@ package com.gh.gamecenter.download import android.view.View -import androidx.recyclerview.widget.LinearLayoutManager import com.gh.base.fragment.LazyFragment import com.gh.common.exposure.ExposureListener import com.gh.common.util.EntranceUtils import com.gh.common.util.goneIf import com.gh.common.util.observeNonNull import com.gh.common.util.viewModelProvider +import com.gh.common.view.FixLinearLayoutManager import com.gh.gamecenter.MainActivity import com.gh.gamecenter.R import com.gh.gamecenter.databinding.FragmentGameUpdatableBinding @@ -59,7 +59,7 @@ class UpdatableGameFragment : LazyFragment() { noDataContainer.reuseNodataSkipTvBtn.setOnClickListener { MainActivity.skipToMainActivity(activity, MainWrapperFragment.INDEX_HOME) } - recyclerView.layoutManager = LinearLayoutManager(requireContext()) + recyclerView.layoutManager = FixLinearLayoutManager(requireContext()) recyclerView.adapter = mAdapter.also { recyclerView.addOnScrollListener(ExposureListener(this@UpdatableGameFragment, it)) } diff --git a/app/src/main/java/com/gh/gamecenter/download/UpdatableGameViewModel.kt b/app/src/main/java/com/gh/gamecenter/download/UpdatableGameViewModel.kt index cf0dc15cc1..ec5971b472 100644 --- a/app/src/main/java/com/gh/gamecenter/download/UpdatableGameViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/download/UpdatableGameViewModel.kt @@ -64,6 +64,8 @@ class UpdatableGameViewModel( mRawUpdatableList.clear() for (update in updatableList) { + // 有闪退日志说这个 update 实体可能为空,实在看不原因 :( + if (update == null) continue // 筛选仅下载管理出现的插件化更新 if (update.isShowPlugin(PluginLocation.only_index)) { val platform = @@ -534,7 +536,8 @@ class UpdatableGameViewModel( * 全部更新 (版本匹配的我的版本) */ fun updateAllMatchedVersionValidUpdate() { - for (update in mCachedMatchedVersionValidUpdateList) { + val updateList = ArrayList(mCachedMatchedVersionValidUpdateList) + for (update in updateList) { update(update, false) } } diff --git a/app/src/main/java/com/gh/gamecenter/entity/IdCardEntity.kt b/app/src/main/java/com/gh/gamecenter/entity/IdCardEntity.kt index 61bec2d6e7..d36427fd57 100644 --- a/app/src/main/java/com/gh/gamecenter/entity/IdCardEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/entity/IdCardEntity.kt @@ -5,5 +5,6 @@ import androidx.room.Entity @Entity data class IdCardEntity( var id: String? = null, - var name: String? = null + var name: String? = null, + var revise: Boolean? = false, ) \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/forum/moderator/ApplyModeratorFragment.kt b/app/src/main/java/com/gh/gamecenter/forum/moderator/ApplyModeratorFragment.kt index 9ddc3dc55b..7e8e9936d4 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/moderator/ApplyModeratorFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/moderator/ApplyModeratorFragment.kt @@ -13,14 +13,13 @@ import com.gh.common.avoidcallback.Callback import com.gh.common.dialog.ApplyModeratorDialogFragment import com.gh.common.util.* import com.gh.gamecenter.R -import com.gh.gamecenter.UserInfoEditActivity +import com.gh.gamecenter.ShellActivity import com.gh.gamecenter.databinding.FragmentApplyModeratorBinding import com.gh.gamecenter.entity.ApplyModeratorStatusEntity import com.gh.gamecenter.entity.ApplyModeratorTaskEntity import com.gh.gamecenter.forum.detail.ForumDetailActivity import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.normal.NormalFragment -import com.gh.gamecenter.user.UserViewModel import com.lightgame.utils.AppManager import com.lightgame.utils.Utils @@ -102,13 +101,10 @@ class ApplyModeratorFragment : NormalFragment() { val currentActivity = AppManager.getInstance().currentActivity() AvoidOnResultManager.getInstance(currentActivity as AppCompatActivity) .startForResult( - UserInfoEditActivity.getIntent( - context, - UserViewModel.TYPE_ID_CARD - ), object : + ShellActivity.getIntent(requireContext(), ShellActivity.Type.REAL_NAME_INFO, null), object : Callback { override fun onActivityResult(resultCode: Int, data: Intent?) { - + Utils.log(resultCode) } }) } diff --git a/app/src/main/java/com/gh/gamecenter/game/horizontal/GameHorizontalSlideAdapter.kt b/app/src/main/java/com/gh/gamecenter/game/horizontal/GameHorizontalSlideAdapter.kt index d8c2644ba3..f33fd72764 100644 --- a/app/src/main/java/com/gh/gamecenter/game/horizontal/GameHorizontalSlideAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/game/horizontal/GameHorizontalSlideAdapter.kt @@ -5,6 +5,7 @@ import android.view.ViewGroup import com.gh.common.exposure.ExposureEvent import com.gh.common.util.StringUtils import com.gh.common.util.dip2px +import com.gh.common.util.safelyGetInRelease import com.gh.gamecenter.GameDetailActivity import com.gh.gamecenter.R import com.gh.gamecenter.databinding.GameHorizontalItemBinding @@ -62,7 +63,7 @@ class GameHorizontalSlideAdapter(context: Context, } holder.setRemarkView(mSubjectEntity, gameEntity) holder.itemView.setOnClickListener { - val exposureEvent = exposureEventList?.get(position) + val exposureEvent = exposureEventList?.safelyGetInRelease(position) if (exposureEvent != null) { GameDetailActivity.startGameDetailActivity(mContext, gameEntity, StringUtils.buildString("(游戏-专题:", mSubjectEntity.name, "-列表[", (position + 1).toString(), "])"), exposureEvent) diff --git a/app/src/main/java/com/gh/gamecenter/game/rank/RankAdapter.kt b/app/src/main/java/com/gh/gamecenter/game/rank/RankAdapter.kt index f58da9dfda..2a15b60d22 100644 --- a/app/src/main/java/com/gh/gamecenter/game/rank/RankAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/game/rank/RankAdapter.kt @@ -20,7 +20,7 @@ import com.gh.gamecenter.entity.TagStyleEntity import com.gh.gamecenter.eventbus.EBDownloadStatus import com.lightgame.adapter.BaseRecyclerAdapter import com.lightgame.download.DownloadEntity -import java.util.HashMap +import java.util.* class RankAdapter( context: Context, @@ -148,7 +148,7 @@ class RankAdapter( } val entrance = "(专题合集-排行榜:$columnName)" - val exposureEvent = exposureEventList?.get(exposureOffset + position) + val exposureEvent = exposureEventList?.safelyGetInRelease(exposureOffset + position) root.setOnClickListener { if (exposureEvent != null) { GameDetailActivity.startGameDetailActivity( diff --git a/app/src/main/java/com/gh/gamecenter/game/upload/GameResourcePolicyDialogFragment.kt b/app/src/main/java/com/gh/gamecenter/game/upload/GameResourcePolicyDialogFragment.kt index e670db7d1c..56a3fc162d 100644 --- a/app/src/main/java/com/gh/gamecenter/game/upload/GameResourcePolicyDialogFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/game/upload/GameResourcePolicyDialogFragment.kt @@ -5,12 +5,15 @@ import android.content.DialogInterface import android.os.Build import android.os.Bundle import android.view.* -import android.webkit.* +import android.webkit.WebSettings +import android.webkit.WebView +import android.webkit.WebViewClient import android.widget.TextView import com.gh.base.fragment.BaseDialogFragment import com.gh.common.DefaultJsApi import com.gh.common.util.MtaHelper import com.gh.common.util.dip2px +import com.gh.common.util.tryWithDefaultCatch import com.gh.common.view.dsbridge.DWebView import com.gh.gamecenter.BuildConfig import com.gh.gamecenter.R @@ -37,7 +40,9 @@ class GameResourcePolicyDialogFragment : BaseDialogFragment() { } // 避免提示网页有害信息不能访问 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - settings?.safeBrowsingEnabled = false + tryWithDefaultCatch { + settings?.safeBrowsingEnabled = false + } } DWebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG || "internal" == BuildConfig.FLAVOR) 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 b08dbd8f1b..5f8d3c82b7 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt @@ -18,13 +18,12 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentStatePagerAdapter import androidx.lifecycle.Observer -import androidx.viewpager.widget.PagerAdapter import butterknife.BindView import butterknife.OnClick import com.ethanhua.skeleton.Skeleton import com.ethanhua.skeleton.ViewSkeletonScreen +import com.gh.base.adapter.FragmentAdapter import com.gh.base.fragment.BaseFragment_TabLayout import com.gh.common.constant.Config import com.gh.common.constant.Constants @@ -765,20 +764,7 @@ class GameDetailFragment : NormalFragment() { mTabContainer.goneIf(tabTitleList.size == 1) mToolbarGapView.goneIf(tabTitleList.size == 1) -// mViewPager.adapter = FragmentAdapter(childFragmentManager, fragmentsList, tabTitleList) - mViewPager.adapter = object : FragmentStatePagerAdapter(childFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { - override fun getItem(position: Int) = fragmentsList[position] - - override fun getCount() = fragmentsList.size - - override fun getItemPosition(`object`: Any) = PagerAdapter.POSITION_NONE - - override fun getPageTitle(position: Int): CharSequence? { - return if (tabTitleList.size > position) { - tabTitleList[position] - } else super.getPageTitle(position) - } - } + mViewPager.adapter = FragmentAdapter(childFragmentManager, fragmentsList, tabTitleList) mViewPager.doOnPageSelected { logTabClick(it) } @@ -1447,7 +1433,7 @@ class GameDetailFragment : NormalFragment() { && System.currentTimeMillis() - mTabClickEvent.first < 300 ) { val fragment = fragmentsList[mViewPager.currentItem] - if (fragment is IScrollable) { + if (fragment is IScrollable && fragment.isAdded) { fragment.scrollToTop() } } else { diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescFragment.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescFragment.kt index b0b6a38668..81aafd62b8 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescFragment.kt @@ -224,7 +224,9 @@ class DescFragment : BaseFragment(), IScrollable { } override fun scrollToTop() { - mRecyclerView.scrollToPosition(0) + if (::mRecyclerView.isInitialized) { + mRecyclerView.scrollToPosition(0) + } } } \ No newline at end of file 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 280c5ac63b..5f3ffd3df4 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 @@ -1,7 +1,6 @@ package com.gh.gamecenter.gamedetail.fuli import android.content.Intent -import android.os.Bundle import android.view.View import androidx.core.content.ContextCompat import androidx.lifecycle.Observer @@ -9,7 +8,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.ethanhua.skeleton.Skeleton import com.ethanhua.skeleton.ViewSkeletonScreen -import com.gh.base.fragment.BaseFragment +import com.gh.base.fragment.LazyFragment import com.gh.common.iinterface.IScrollable import com.gh.common.util.* import com.gh.gamecenter.LibaoDetailActivity @@ -29,7 +28,7 @@ import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode -class FuLiFragment : BaseFragment(), IScrollable { +class FuLiFragment : LazyFragment(), IScrollable { private val mRecyclerView by bindView(R.id.fm_fuli_rv) @@ -45,24 +44,21 @@ class FuLiFragment : BaseFragment(), IScrollable { private var isCanShowKaiFuHint: Boolean = false private var shouldScroolToLibao: Boolean = false - private var indexHeight = 0 - private lateinit var mViewSkeletonScreen: ViewSkeletonScreen override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - val detailEntity = mFuLiViewModel?.unifiedGameDetail?.game if (requestCode == GAME_DETAIL_LIBAO_REQUEST) { mAdapter!!.notifyDataSetChanged() } } - override fun getLayoutId(): Int { + override fun getRealLayoutId(): Int { return R.layout.fragment_fuli } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + override fun onFragmentFirstVisible() { + super.onFragmentFirstVisible() val gameEntity = arguments?.getParcelable(GameEntity.TAG) as? GameEntity val gameDetailFactory = GameDetailViewModel.Factory(HaloApp.getInstance().application, gameEntity?.id, gameEntity) @@ -99,8 +95,25 @@ class FuLiFragment : BaseFragment(), IScrollable { } } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onFragmentResume() { + super.onFragmentResume() + startPageTime = System.currentTimeMillis() + } + + override fun onFragmentPause() { + super.onFragmentPause() + + val stayTime = (System.currentTimeMillis() - startPageTime) / 1000 + NewLogUtils.logGameDetailTabOrCommentDetailPause( + "jump_game_detail_special_area_tab", + stayTime, + mGameDetailViewModel?.game?.id ?: "", + mGameDetailViewModel?.game?.gameType ?: "" + ) + } + + override fun initRealView() { + super.initRealView() mViewSkeletonScreen = Skeleton.bind(game_detail_skeleton).shimmer(false).load(R.layout.fragment_gamedongtai_skeleton).show() mAdapter = FuLiAdapter(requireContext(), this, mFuLiViewModel, mEntrance) @@ -176,8 +189,7 @@ class FuLiFragment : BaseFragment(), IScrollable { } } - - override fun onListClick(view: View?, position: Int, data: LIST) { + override fun onListClick(view: View?, position: Int, data: Any?) { when (view?.id) { R.id.gamedetail_libao_item -> { val liBao = data as LibaoEntity @@ -200,14 +212,4 @@ class FuLiFragment : BaseFragment(), IScrollable { mRecyclerView.scrollToPosition(0) } - override fun onPause() { - super.onPause() - val stayTime = (System.currentTimeMillis() - startPageTime) / 1000 - NewLogUtils.logGameDetailTabOrCommentDetailPause( - "jump_game_detail_special_area_tab", - stayTime, - mGameDetailViewModel?.game?.id ?: "", - mGameDetailViewModel?.game?.gameType ?: "" - ) - } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingFragment.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingFragment.kt index 59517ae6ad..ae8feb32d6 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingFragment.kt @@ -2,7 +2,6 @@ package com.gh.gamecenter.gamedetail.rating import android.app.Activity import android.content.Intent -import android.os.Bundle import android.text.method.LinkMovementMethod import android.view.View import android.widget.ProgressBar @@ -17,7 +16,7 @@ import com.gh.common.util.* import com.gh.common.view.VerticalItemDecoration import com.gh.gamecenter.R import com.gh.gamecenter.WebActivity -import com.gh.gamecenter.baselist.ListFragment +import com.gh.gamecenter.baselist.LazyListFragment import com.gh.gamecenter.baselist.LoadStatus import com.gh.gamecenter.baselist.LoadType import com.gh.gamecenter.entity.GameEntity @@ -32,7 +31,7 @@ import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode -class RatingFragment : ListFragment(), IScrollable { +class RatingFragment : LazyListFragment(), IScrollable { private var mAdapter: RatingAdapter? = null @@ -40,9 +39,9 @@ class RatingFragment : ListFragment(), IScrollab private var mRatingType: RatingViewModel.RatingType? = null - override fun getLayoutId(): Int { + override fun getRealLayoutId(): Int { return if (mRatingType == RatingViewModel.RatingType.RATING) { - super.getLayoutId() + R.layout.fragment_list_base } else { R.layout.fragment_list_fold_rating } @@ -83,10 +82,31 @@ class RatingFragment : ListFragment(), IScrollab return false } - override fun onCreate(savedInstanceState: Bundle?) { + override fun onFragmentResume() { + super.onFragmentResume() + + startPageTime = System.currentTimeMillis() + } + + override fun onFragmentPause() { + super.onFragmentPause() + + val game = arguments?.getParcelable(GameEntity.TAG) + val stayTime = (System.currentTimeMillis() - startPageTime) / 1000 + NewLogUtils.logGameDetailTabOrCommentDetailPause( + "jump_game_detail_comment_tab", + stayTime, + game?.id ?: "", + game?.gameType ?: "" + ) + } + + override fun onFragmentFirstVisible() { mRatingType = arguments?.getSerializable(EntranceUtils.KEY_LOCATION) as? RatingViewModel.RatingType - ?: RatingViewModel.RatingType.RATING - super.onCreate(savedInstanceState) + ?: RatingViewModel.RatingType.RATING + + super.onFragmentFirstVisible() + mSkipGameComment = arguments?.getBoolean(EntranceUtils.KEY_SKIP_GAME_COMMENT) mListRv.setPadding(20F.dip2px(), 0, 20F.dip2px(), 0) mListRefresh?.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.transparent)) @@ -97,8 +117,9 @@ class RatingFragment : ListFragment(), IScrollab }) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun initRealView() { + super.initRealView() + if (mRatingType == RatingViewModel.RatingType.FOLD_RATING) { val foldRatingReasonTv = requireView().findViewById(R.id.foldRatingReasonTv) val text = "折叠原因:因违反《光环助手评论规则》被管理员折叠" @@ -189,18 +210,6 @@ class RatingFragment : ListFragment(), IScrollab mListRv?.scrollToPosition(0) } - override fun onPause() { - super.onPause() - val game = arguments?.getParcelable(GameEntity.TAG) - val stayTime = (System.currentTimeMillis() - startPageTime) / 1000 - NewLogUtils.logGameDetailTabOrCommentDetailPause( - "jump_game_detail_comment_tab", - stayTime, - game?.id ?: "", - game?.gameType ?: "" - ) - } - companion object { @BindingAdapter("setRatingScore") @JvmStatic diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/edit/RatingEditActivity.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/edit/RatingEditActivity.kt index 3dd8194f26..2016d02f86 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/edit/RatingEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/edit/RatingEditActivity.kt @@ -150,7 +150,9 @@ class RatingEditActivity : ToolBarActivity(), KeyboardHeightObserver { } // 避免提示网页有害信息不能访问 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - settings.safeBrowsingEnabled = false + tryWithDefaultCatch { + settings.safeBrowsingEnabled = false + } } DWebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG || "internal" == BuildConfig.FLAVOR) diff --git a/app/src/main/java/com/gh/gamecenter/home/slide/HomeSlideListViewHolder.kt b/app/src/main/java/com/gh/gamecenter/home/slide/HomeSlideListViewHolder.kt index 0ee49dc962..94e584ac07 100644 --- a/app/src/main/java/com/gh/gamecenter/home/slide/HomeSlideListViewHolder.kt +++ b/app/src/main/java/com/gh/gamecenter/home/slide/HomeSlideListViewHolder.kt @@ -13,6 +13,7 @@ import com.gh.base.BaseRecyclerViewHolder import com.gh.common.exposure.ExposureSource import com.gh.common.util.MtaHelper import com.gh.common.util.hexStringToIntColor +import com.gh.common.util.safelyGetInRelease import com.gh.common.util.throwExceptionInDebug import com.gh.common.view.DrawableView import com.gh.common.view.FixLinearLayoutManager @@ -139,8 +140,8 @@ class HomeSlideListViewHolder( val nextPosition = adapter.getActualPosition(position + 1) val currentColor = - slideList[currentPosition].placeholderColor.hexStringToIntColor() - val nextColor = slideList[nextPosition].placeholderColor.hexStringToIntColor() + slideList.safelyGetInRelease(currentPosition)?.placeholderColor?.hexStringToIntColor() ?: Color.WHITE + val nextColor = slideList.safelyGetInRelease(nextPosition)?.placeholderColor?.hexStringToIntColor() ?: currentColor val colorInBetween = ColorUtils.blendARGB(currentColor, nextColor, positionOffset) diff --git a/app/src/main/java/com/gh/gamecenter/manager/UpdateManager.java b/app/src/main/java/com/gh/gamecenter/manager/UpdateManager.java index f914863adc..bd03b0ba80 100644 --- a/app/src/main/java/com/gh/gamecenter/manager/UpdateManager.java +++ b/app/src/main/java/com/gh/gamecenter/manager/UpdateManager.java @@ -1,5 +1,6 @@ package com.gh.gamecenter.manager; +import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.SharedPreferences; @@ -18,6 +19,7 @@ import android.widget.TextView; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.app.NotificationManagerCompat; +import com.gh.base.CurrentActivityHolder; import com.gh.common.AppExecutor; import com.gh.common.constant.Constants; import com.gh.common.exposure.ExposureEvent; @@ -64,6 +66,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import retrofit2.HttpException; +// 吐了,这个祖传的类,代码写得不是一般的糟糕,还不敢随便改 : ( /** * Created by LGT on 2016/12/8. * 助手更新 工具类 @@ -76,6 +79,7 @@ public class UpdateManager { private final static String ONCE_ONLY_SECOND_OPEN = "ONCE_ONLY_SECOND_OPEN"; private Context mContext; + private Context mApplicationContext; private SharedPreferences mSp; @@ -140,7 +144,7 @@ public class UpdateManager { } if (DownloadStatus.done.equals(downloadEntity.getStatus())) { - DownloadManager.getInstance(mContext).cancel(downloadEntity.getUrl(), false, true); + DownloadManager.getInstance(mApplicationContext).cancel(downloadEntity.getUrl(), false, true); if (downloadDialog != null) { try { downloadDialog.dismiss(); @@ -152,13 +156,13 @@ public class UpdateManager { AppExecutor.getUiExecutor().executeWithDelay(() -> exitApp(), 1000); } } else if (DownloadStatus.neterror.equals(downloadEntity.getStatus())) { - Utils.toast(mContext, "网络错误,请稍后重试"); + Utils.toast(mApplicationContext, "网络错误,请稍后重试"); } else if (DownloadStatus.timeout.equals(downloadEntity.getStatus())) { - Utils.toast(mContext, "请求超时,请稍后重试"); + Utils.toast(mApplicationContext, "请求超时,请稍后重试"); } else if (DownloadStatus.notfound.equals(downloadEntity.getStatus())) { - Utils.toast(mContext, "下载链接异常,请稍后重试"); + Utils.toast(mApplicationContext, "下载链接异常,请稍后重试"); } else if (DownloadStatus.hijack.equals(downloadEntity.getStatus())) { - Utils.toast(mContext, "网络劫持,请稍后重试"); + Utils.toast(mApplicationContext, "网络劫持,请稍后重试"); } } else { if (downloadEntity.getSize() != lastUpdateFileSize) { @@ -186,7 +190,8 @@ public class UpdateManager { private UpdateManager(Context context) { mContext = context; - mSp = PreferenceManager.getDefaultSharedPreferences(mContext); + mApplicationContext = context.getApplicationContext(); + mSp = PreferenceManager.getDefaultSharedPreferences(mApplicationContext); this.isShowDownload = false; this.isChecking = false; @@ -209,7 +214,7 @@ public class UpdateManager { loadingDialog = DialogUtils.showWaitDialog(mContext, "检查更新中..."); } String channel = HaloApp.getInstance().getChannel(); - RetrofitManager.getInstance(mContext).getApi().getUpdate(PackageUtils.getGhVersionName(), PackageUtils.getGhVersionCode(), channel) + RetrofitManager.getInstance(mApplicationContext).getApi().getUpdate(PackageUtils.getGhVersionName(), PackageUtils.getGhVersionCode(), channel) .map(appEntity -> { boolean isShowUpdateDialog = false; @@ -261,7 +266,7 @@ public class UpdateManager { if (!appEntity.isForce() && isAutoCheck && !isUpdateFileDownloaded(response) - && NetworkUtils.isWifiConnected(mContext)) { + && NetworkUtils.isWifiConnected(mApplicationContext)) { createUpdate(response, true); } else { showUpdateDialog(response); @@ -273,7 +278,7 @@ public class UpdateManager { handler.sendMessage(message); } } else if (!isAutoCheck) { - Utils.toast(mContext, "已是最新版本"); + Utils.toast(mApplicationContext, "已是最新版本"); if (handler != null) { handler.sendEmptyMessage(1); } @@ -293,11 +298,11 @@ public class UpdateManager { handler.sendEmptyMessage(1); } if (e != null && (e.code() == 304 || e.code() == 404)) { - Utils.toast(mContext, "您的光环助手已是最新版本"); + Utils.toast(mApplicationContext, "您的光环助手已是最新版本"); return; } - Utils.toast(mContext, "检查更新失败"); + Utils.toast(mApplicationContext, "检查更新失败"); } invokeDismissCallback(); @@ -307,7 +312,9 @@ public class UpdateManager { // 显示助手有更新提示框 private void showUpdateDialog(final String md5) { - updateDialog = new Dialog(mContext); + Context context = getValidContext(); + + updateDialog = new Dialog(context); updateDialog.setOnDismissListener(dialog -> { invokeDismissCallback(); }); @@ -316,7 +323,8 @@ public class UpdateManager { window.setBackgroundDrawableResource(android.R.color.transparent); } - View view = View.inflate(mContext, R.layout.app_update_hint_dialog, null); + View view = View.inflate(context, R.layout.app_update_hint_dialog, null); + cancelUpdateTextView = view.findViewById(R.id.cancel); downloadedHintView = view.findViewById(R.id.downloadedHint); confirmTextView = view.findViewById(R.id.confirm); @@ -331,7 +339,7 @@ public class UpdateManager { R.color.theme_font, false, () -> { - DirectUtils.directToExternalBrowser(mContext, appEntity.getSpareLink()); + DirectUtils.directToExternalBrowser(context, appEntity.getSpareLink()); return null; }) .build(); @@ -340,7 +348,7 @@ public class UpdateManager { externalTextTv.setVisibility(View.VISIBLE); } - if (NetworkUtils.isWifiConnected(mContext)) { + if (NetworkUtils.isWifiConnected(context)) { if (!isUpdateFileDownloaded(md5)) { updateUpdateDialogView(false); createUpdate(md5, true); @@ -376,11 +384,11 @@ public class UpdateManager { } else if (isUpdateFileDownloaded(md5) && !appEntity.isForce()) { updateDialog.dismiss(); } - String path = FileUtils.getDownloadPath(mContext, "光环助手V" + appEntity.getVersion() + "_" + md5 + ".apk"); + String path = FileUtils.getDownloadPath(context, "光环助手V" + appEntity.getVersion() + "_" + md5 + ".apk"); // 产品不接受显示下载完成文案从立即更新变为立即安装,所以文案为立即更新时一律不执行安装 if (isUpdateFileDownloaded(md5) && confirmTextView.getText() != "立即更新") { - DataLogUtils.uploadUpgradeLog(mContext, "install"); //上传更新安装数据 - PackageInstaller.install(mContext, false, path); + DataLogUtils.uploadUpgradeLog(context, "install"); //上传更新安装数据 + PackageInstaller.install(context, false, path); } else { MtaHelper.onEvent("软件更新", "下载开始"); @@ -396,20 +404,22 @@ public class UpdateManager { updateDialog.setContentView(view); updateDialog.show(); - DataLogUtils.uploadUpgradeLog(mContext, "notice"); //上传更新通知弹窗数据 + DataLogUtils.uploadUpgradeLog(context, "notice"); //上传更新通知弹窗数据 } private void exitApp() { - NotificationManagerCompat.from(HaloApp.getInstance().getApplication()).cancelAll(); + NotificationManagerCompat.from(mApplicationContext).cancelAll(); AppManager.getInstance().finishAllActivity(); } private void showDownloadDialog(String md5) { - if (NetworkUtils.isMobileConnected(mContext)) { - Utils.toast(mContext, "当前使用移动数据进行下载"); + Context context = getValidContext(); + + if (NetworkUtils.isMobileConnected(context)) { + Utils.toast(context, "当前使用移动数据进行下载"); } - downloadDialog = new Dialog(mContext); + downloadDialog = new Dialog(context); downloadDialog.setOnDismissListener(dialog -> { invokeDismissCallback(); }); @@ -418,7 +428,7 @@ public class UpdateManager { window.setBackgroundDrawableResource(android.R.color.transparent); } - View view = View.inflate(mContext, R.layout.app_updating_dialog, null); + View view = View.inflate(context, R.layout.app_updating_dialog, null); app_pb_progress = view.findViewById(R.id.progress); appProgressSize = view.findViewById(R.id.size); @@ -428,7 +438,7 @@ public class UpdateManager { appProgressFilling = view.findViewById(R.id.progress_filling); view.findViewById(R.id.app_tv_cancel).setOnClickListener(v -> { - DownloadManager.getInstance(mContext).cancel(appEntity.getUrl()); + DownloadManager.getInstance(context).cancel(appEntity.getUrl()); if (appEntity.isForce()) { exitApp(); } else { @@ -437,11 +447,11 @@ public class UpdateManager { }); downloadDialog.setOnDismissListener(dialog -> { - DownloadManager.getInstance(mContext).removeObserver(dataWatcher); + DownloadManager.getInstance(context).removeObserver(dataWatcher); isShowDownload = false; }); - int dialogWidth = mContext.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(60); + int dialogWidth = context.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(60); downloadDialog.setCanceledOnTouchOutside(false); downloadDialog.setCancelable(false); downloadDialog.closeOptionsMenu(); @@ -456,20 +466,20 @@ public class UpdateManager { } private void createUpdate(String md5, boolean isSilentUpdate) { - DownloadManager.getInstance(mContext).addObserver(dataWatcher); + DownloadManager.getInstance(mApplicationContext).addObserver(dataWatcher); boolean shouldCancelPreviousDownload = true; // 是否应该取消旧更新任务 // 在部分设备上取消正在进行中的旧下载任务再创建新下载任务有机率造成新下载任务依然带有 "静默更新" 标签导致无法唤起安装 // 所以这里对当前静默更新任务正在进行中的时候就不用删旧任务,直接改 meta 标签 if (!isSilentUpdate - && DownloadManager.getInstance(mContext).isTaskDownloading(appEntity.getUrl())) { + && DownloadManager.getInstance(mApplicationContext).isTaskDownloading(appEntity.getUrl())) { try { DownloadEntity entity = DataChanger.INSTANCE.getDownloadEntries().get(appEntity.getUrl()); if (entity != null) { ExtensionsKt.addMetaExtra(entity, Constants.EXTRA_DOWNLOAD_TYPE, "不再是静默更新"); - DownloadManager.getInstance(mContext).updateDownloadEntity(entity); - DownloadManager.getInstance(mContext).resume(entity, false); + DownloadManager.getInstance(mApplicationContext).updateDownloadEntity(entity); + DownloadManager.getInstance(mApplicationContext).resume(entity, false); shouldCancelPreviousDownload = false; } @@ -482,7 +492,7 @@ public class UpdateManager { // 预下载完成或者还没进行预下载的都进这里,先删掉旧的下载文件再进行下载 if (shouldCancelPreviousDownload) { - String path = FileUtils.getDownloadPath(mContext, "光环助手V" + appEntity.getVersion() + "_" + md5 + ".apk"); + String path = FileUtils.getDownloadPath(mApplicationContext, "光环助手V" + appEntity.getVersion() + "_" + md5 + ".apk"); File file = new File(path); if (file.exists() && file.delete()) { Utils.log(file.getName() + " file delete success."); @@ -506,18 +516,34 @@ public class UpdateManager { ExtensionsKt.addMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE, Constants.SILENT_UPDATE); } - downloadEntity.setPackageName(mContext.getPackageName()); - DownloadManager.getInstance(mContext).cancel(appEntity.getUrl(), true, true); - DownloadManager.getInstance(mContext).pauseAll(); + downloadEntity.setPackageName(mApplicationContext.getPackageName()); + DownloadManager.getInstance(mApplicationContext).cancel(appEntity.getUrl(), true, true); + DownloadManager.getInstance(mApplicationContext).pauseAll(); AppExecutor.getUiExecutor().executeWithDelay(() -> { - DownloadManager.getInstance(mContext).add(downloadEntity); + DownloadManager.getInstance(mApplicationContext).add(downloadEntity); }, 200); } } + /** + * 尽量获取有效的 activity context + */ + private Context getValidContext() { + Context context = mContext; + + Activity currentActivity = CurrentActivityHolder.getCurrentActivity(); + if (currentActivity != null + && mContext != currentActivity + && !currentActivity.isFinishing()) { + context = currentActivity; + } + + return context; + } + private boolean isUpdateFileDownloaded(String md5) { - String path = FileUtils.getDownloadPath(mContext, "光环助手V" + appEntity.getVersion() + "_" + md5 + ".apk"); + String path = FileUtils.getDownloadPath(mApplicationContext, "光环助手V" + appEntity.getVersion() + "_" + md5 + ".apk"); File file = new File(path); return file.exists() && file.length() == SPUtils.getLong(Constants.LAST_GHZS_UPDATE_FILE_SIZE, 0); 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 89e0ff45af..f907168bdb 100644 --- a/app/src/main/java/com/gh/gamecenter/packagehelper/PackageRepository.kt +++ b/app/src/main/java/com/gh/gamecenter/packagehelper/PackageRepository.kt @@ -82,7 +82,7 @@ object PackageRepository { mInstalledPkgList.addAll(list) notifyInstallPkgData() - loadInstalledGameDigestAndNotifyData(list, true) + loadInstalledGameDigestAndNotifyData(list) loadGhzsUpdate() } } @@ -345,10 +345,13 @@ object PackageRepository { fun uninstalledGame(pkgName: String) { // TODO 检查为什么会有两个相同的包名添加到 mInstalledPkgList 里 mInstalledPkgList.removeAll { it == pkgName } - val iterator = currentVersionList.iterator() - while (iterator.hasNext()) { - if (iterator.next().packageName == pkgName) { - iterator.remove() + // 尝试从临时的当前版本列表里移除已卸载的条目 + tryCatchInRelease { + val iterator = currentVersionList.iterator() + while (iterator.hasNext()) { + if (iterator.next().packageName == pkgName) { + iterator.remove() + } } } notifyInstallPkgData() diff --git a/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt b/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt index 56768c49c9..316bdfac35 100644 --- a/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt @@ -201,7 +201,7 @@ class PersonalFunctionAdapter(val context: Context, val groupName: String, var m } } "实名认证" -> { - context.startActivity(UserInfoEditActivity.getIntent(context, UserViewModel.TYPE_ID_CARD)) + context.startActivity(ShellActivity.getIntent(context, ShellActivity.Type.REAL_NAME_INFO, null)) } "微信提醒" -> { MtaHelper.onEvent("我的光环", "设置微信提醒") diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentFragment.kt index 5d8ece9ff1..13dff479ff 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentFragment.kt @@ -413,6 +413,7 @@ open class NewCommentFragment : ListFragment override fun onClick(view: View) { when (view.id) { R.id.answer_comment_send_btn -> if (!ClickUtils.isFastDoubleClick(R.id.answer_comment_send_btn, 5000)) { + Util_System_Keyboard.hideSoftKeyboard(requireActivity()) ifLogin(getLoginEntrance()) { showRegulationTestDialogIfNeeded { postComment() diff --git a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java index b57d93d3ea..1b8236d4e0 100644 --- a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java +++ b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java @@ -170,6 +170,12 @@ public interface ApiService { @POST("certification") Single postCertification(@Body RequestBody body); + /** + * 检查实名认证接口 + */ + @POST("./certification:check") + Single postCertificationCheck(@Body RequestBody body); + /** * 获取新闻详情 */ diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt index 40bc10f496..869b10ccd3 100644 --- a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt @@ -424,7 +424,7 @@ class SearchGameIndexAdapter(context: Context, for (key in positionAndPackageMap.keys) { if (key.contains(download.packageName) && key.contains(download.gameId)) { val position = positionAndPackageMap[key] - if (position != null && mEntityList != null && mEntityList[position].game != null && position < mEntityList.size) { + if (position != null && mEntityList != null && position < mEntityList.size && mEntityList[position].game != null) { mEntityList[position].game!!.getEntryMap()[download.platform] = download notifyItemChanged(position) } @@ -436,7 +436,7 @@ class SearchGameIndexAdapter(context: Context, for (key in positionAndPackageMap.keys) { if (key.contains(status.packageName) && key.contains(status.gameId)) { val position = positionAndPackageMap[key] - if (position != null && mEntityList != null && mEntityList[position].game != null && position < mEntityList.size) { + if (position != null && mEntityList != null && position < mEntityList.size && mEntityList[position].game != null) { mEntityList[position].game!!.getEntryMap().remove(status.platform) notifyItemChanged(position) } diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt index 4f59e00976..c05ef5efbb 100644 --- a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt @@ -442,7 +442,7 @@ class SearchGameResultAdapter(context: Context, for (key in positionAndPackageMap.keys) { if (key.contains(download.packageName) && key.contains(download.gameId)) { val position = positionAndPackageMap[key] - if (position != null && mEntityList != null && mEntityList[position].game != null && position < mEntityList.size) { + if (position != null && mEntityList != null && position < mEntityList.size && mEntityList[position].game != null) { mEntityList[position].game!!.getEntryMap()[download.platform] = download notifyItemChanged(position) } @@ -454,7 +454,7 @@ class SearchGameResultAdapter(context: Context, for (key in positionAndPackageMap.keys) { if (key.contains(status.packageName) && key.contains(status.gameId)) { val position = positionAndPackageMap[key] - if (position != null && mEntityList != null && mEntityList[position].game != null && position < mEntityList.size) { + if (position != null && mEntityList != null && position < mEntityList.size && mEntityList[position].game != null) { mEntityList[position].game!!.getEntryMap().remove(status.platform) notifyItemChanged(position) } diff --git a/app/src/main/java/com/gh/gamecenter/user/UserRepository.java b/app/src/main/java/com/gh/gamecenter/user/UserRepository.java index 2540b3b8d5..1c6673c81e 100644 --- a/app/src/main/java/com/gh/gamecenter/user/UserRepository.java +++ b/app/src/main/java/com/gh/gamecenter/user/UserRepository.java @@ -8,6 +8,7 @@ import android.preference.PreferenceManager; import android.text.TextUtils; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.lifecycle.LiveData; import androidx.lifecycle.MediatorLiveData; @@ -152,6 +153,8 @@ public class UserRepository { // 通知页面更新 EventBus.getDefault().post(new EBReuse(PersonalFragment.LOGOUT_TAG)); + + DataUtils.getDeviceCertification(HaloApp.getInstance().getGid()); } public LiveData> getLoginUserInfo() { @@ -568,13 +571,22 @@ public class UserRepository { } } - private void cacheAndNotifyUserInfo(UserInfoEntity userInfoEntity, boolean isEditUserInfo) { + public void cacheAndNotifyUserInfo(UserInfoEntity userInfoEntity, boolean isEditUserInfo) { setUserManagerData(null, userInfoEntity); mCacheUserInfoEntity = userInfoEntity; mLoginObsResponseUserInfo.postValue(new ApiResponse<>(userInfoEntity)); - if (isEditUserInfo) mEditObsResponseUserInfo.postValue(new ApiResponse<>(userInfoEntity)); + if (isEditUserInfo) { + mEditObsResponseUserInfo.postValue(new ApiResponse<>(userInfoEntity)); + } else { + DataUtils.getDeviceCertification(HaloApp.getInstance().getGid()); + } + } + + @Nullable + public UserInfoEntity getCacheUserInfoEntity() { + return mCacheUserInfoEntity; } private void cacheAndNotifyLoginToken(LoginTokenEntity loginTokenEntity) { diff --git a/app/src/main/java/com/halo/assistant/fragment/user/RealNameInfoFragment.kt b/app/src/main/java/com/halo/assistant/fragment/user/RealNameInfoFragment.kt new file mode 100644 index 0000000000..b000aca5e4 --- /dev/null +++ b/app/src/main/java/com/halo/assistant/fragment/user/RealNameInfoFragment.kt @@ -0,0 +1,194 @@ +package com.halo.assistant.fragment.user + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import android.text.InputType +import android.text.TextUtils +import android.view.View +import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.widget.doOnTextChanged +import androidx.fragment.app.viewModels +import com.gh.common.util.* +import com.gh.common.view.CustomLinkMovementMethod +import com.gh.gamecenter.R +import com.gh.gamecenter.ShellActivity +import com.gh.gamecenter.databinding.FragmentRealNameBinding +import com.gh.gamecenter.normal.NormalFragment +import org.json.JSONObject + +class RealNameInfoFragment : NormalFragment() { + + private var mIsForcedToCertificate: Boolean = false + private val mViewModel: RealNameInfoViewModel by viewModels() + + private val mBinding: FragmentRealNameBinding by lazy { + FragmentRealNameBinding.inflate( + layoutInflater + ) + } + + override fun getLayoutId(): Int = 0 + override fun getInflatedLayout(): View = mBinding.root + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + mIsForcedToCertificate = + arguments?.getBoolean(EntranceUtils.KEY_IS_FORCED_TO_CERTICIFICE) ?: false + + mBinding.toolbar.normalTitle.text = "实名认证" + mBinding.toolbar.normalToolbar.setNavigationOnClickListener { requireActivity().finish() } + + if (mIsForcedToCertificate || !isRealNameInfoExist()) { + initEditingView() + mViewModel.certificateResultLiveData.observeNonNull(viewLifecycleOwner) { + requireActivity().setResult( + Activity.RESULT_OK, + Intent().putExtra(UserInfoEditFragment.AUTH_SUCCESS, true) + ) + requireActivity().finish() + } + } else { + initDisplayOnlyView() + } + } + + private fun isRealNameInfoExist(): Boolean { + val userInfoEntity = mViewModel.getUserInfo() + return if (userInfoEntity != null) { + val idCard = userInfoEntity.idCard + if (idCard != null && !TextUtils.isEmpty(idCard.name)) { + true + } else { + NewLogUtils.logCertificationTriggerType(mIsForcedToCertificate) + false + } + } else { + NewLogUtils.logCertificationTriggerType(mIsForcedToCertificate) + false + } + } + + private fun initEditingView() { + val bodyString = + "为响应《国家新闻出版署关于防止未成年沉迷网络游戏的通知》,请认真填写您的身份信息。您提供的证件信息将受到严格保护,仅用于用户实名制认证,不会用作其他用途,请放心填写。前往了解更多信息>>" + mBinding.bodyTv.text = + SpanBuilder(bodyString) + .click( + bodyString.length - "前往了解更多信息>>".length, + bodyString.length, + R.color.theme_font + ) { + DirectUtils.directToWebView( + requireContext(), + "https://resource.ghzs.com/page/privacy_policies/Identity_information.html", + "(实名认证)" + ) + } + .build() + mBinding.bodyTv.movementMethod = CustomLinkMovementMethod.getInstance() + + val hintString = "特别说明:由于部分用户之前的实名信息不正确或认证失败,可能需要重新认证,请提交真实的信息进行认证即可。部分游戏仅对成年用户进行开放" + mBinding.hintTv.text = + SpanBuilder(hintString) + .bold(0, 5) + .build() + + mBinding.nameEt.filters = arrayOf(TextHelper.getFilter(20, "最多20个字")) + mBinding.idCardEt.filters = arrayOf(TextHelper.getFilter(18, "身份证号码最长18位")) + + mBinding.nameEt.doOnTextChanged { _, _, _, _ -> + updateSubmitBtn() + } + mBinding.idCardEt.doOnTextChanged { _, _, _, _ -> + updateSubmitBtn() + } + } + + private fun initDisplayOnlyView() { + val userInfoEntity = mViewModel.getUserInfo() + + mBinding.badgeContainer.visibility = View.VISIBLE + mBinding.run { + val set = ConstraintSet() + set.run { + clone(infoContainer) + clear(R.id.nameTv, ConstraintSet.TOP) + connect( + R.id.nameTv, + ConstraintSet.TOP, + R.id.badgeContainer, + ConstraintSet.BOTTOM, + 14F.dip2px() + ) + applyTo(infoContainer) + } + } + mBinding.submitBtn.visibility = View.GONE + mBinding.reEditInfoBtn.visibleIf(userInfoEntity?.idCard?.revise == false) + mBinding.nameEt.inputType = InputType.TYPE_NULL + mBinding.idCardEt.inputType = InputType.TYPE_NULL + + val idCard = userInfoEntity?.idCard + val sb = StringBuilder(idCard?.name?.substring(0, 1) ?: "") + for (i in 0 until idCard?.name!!.length - 1) { + sb.append("*") + } + mBinding.nameEt.setText(sb.toString()) + mBinding.idCardEt.setText( + idCard.id?.replace( + "(\\d)\\d{16}([0-9,x-y])".toRegex(), + "$1****************$2" + ) + ) + + mBinding.reEditInfoBtn.setOnClickListener { + startActivity( + ShellActivity.getIntent(requireContext(), ShellActivity.Type.REAL_NAME_INFO).apply { + putExtra(EntranceUtils.KEY_IS_FORCED_TO_CERTICIFICE, true) + } + ) + requireActivity().finish() + } + } + + private fun updateSubmitBtn() { + val validationPair = + isInputValid(mBinding.nameEt.text.toString(), mBinding.idCardEt.text.toString()) + + mBinding.submitBtn.isEnabled = validationPair.first + if (validationPair.first) { + mBinding.submitBtn.background = R.drawable.button_round_2496ff.toDrawable() + mBinding.submitBtn.setOnClickListener { + val o = JSONObject() + o.put("id", mBinding.idCardEt.text.toString()) + o.put("name", mBinding.nameEt.text.toString()) + mViewModel.postCertification(o.toString(), mIsForcedToCertificate) + } + } else { + mBinding.submitBtn.background = R.drawable.button_round_2496ff_alpha_40.toDrawable() + } + mBinding.errorHintTv.text = validationPair.second + } + + private fun isInputValid(name: String, idCard: String): Pair { + if (TextUtils.isEmpty(name)) { + return Pair(false, "请输入姓名") + } + if (TextUtils.isEmpty(idCard)) { + return Pair(false, "请输入身份证号码") + } + if (idCard.length < 18) { + return Pair(false, "必须使用18位的身份证号码") + } + val idCardRegex = + Regex("^[1-9]\\d{5}([1-9]\\d{3})(0\\d|1[0-2])([0-2]\\d|3[0-1])\\d{3}[\\dXx]$") + if (!idCard.matches(idCardRegex)) { + return Pair(false, "身份证无效,请重新输入") + } + + return Pair(true, "") + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/halo/assistant/fragment/user/RealNameInfoViewModel.kt b/app/src/main/java/com/halo/assistant/fragment/user/RealNameInfoViewModel.kt new file mode 100644 index 0000000000..02098f9ddc --- /dev/null +++ b/app/src/main/java/com/halo/assistant/fragment/user/RealNameInfoViewModel.kt @@ -0,0 +1,120 @@ +package com.halo.assistant.fragment.user + +import android.annotation.SuppressLint +import android.app.Application +import android.text.TextUtils +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.MutableLiveData +import com.gh.common.constant.Constants +import com.gh.common.util.* +import com.gh.common.util.GsonUtils.fromJson +import com.gh.common.util.GsonUtils.toJson +import com.gh.download.DownloadManager +import com.gh.gamecenter.entity.IdCardEntity +import com.gh.gamecenter.entity.UserInfoEntity +import com.gh.gamecenter.manager.UserManager +import com.gh.gamecenter.retrofit.BiResponse +import com.gh.gamecenter.retrofit.RetrofitManager +import com.gh.gamecenter.user.UserRepository +import com.halo.assistant.HaloApp +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers +import okhttp3.MediaType +import okhttp3.RequestBody +import okhttp3.ResponseBody +import org.json.JSONObject +import retrofit2.HttpException + +class RealNameInfoViewModel(application: Application) : AndroidViewModel(application) { + + val certificateResultLiveData = MutableLiveData() + + fun getUserInfo(): UserInfoEntity? { + var userInfoEntity = UserManager.getInstance().userInfoEntity + val certificationOnlyInfoEntity: UserInfoEntity? + val deviceCertificationInfoString = + SPUtils.getString(Constants.SP_DEVICE_CERTIFICATION_PREFIX + HaloApp.getInstance().gid) + if (!TextUtils.isEmpty(deviceCertificationInfoString)) { + certificationOnlyInfoEntity = deviceCertificationInfoString.toObject() + if (userInfoEntity?.idCard == null && certificationOnlyInfoEntity != null) { + userInfoEntity = certificationOnlyInfoEntity + } + + userInfoEntity?.idCard?.revise = certificationOnlyInfoEntity?.idCard?.revise + } + + return userInfoEntity + } + + @SuppressLint("CheckResult") + fun postCertification(content: String, isForced: Boolean) { + val userInfoEntity = UserInfoEntity() + val idCardEntity = fromJson(content, IdCardEntity::class.java) + userInfoEntity.idCard = idCardEntity + val body = RequestBody.create( + MediaType.parse("application/json"), toJson(userInfoEntity) + ) + RetrofitManager.getInstance(HaloApp.getInstance()).api.postCertification(body) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : BiResponse() { + override fun onFailure(exception: Exception) { + ErrorHelper.handleError( + HaloApp.getInstance(), + (exception as? HttpException)?.response()?.errorBody()?.string() + ) + NewLogUtils.logCertificationResult(isForced, 0) + } + + override fun onSuccess(data: ResponseBody?) { + val cachedUserInfo = + UserRepository.getInstance(getApplication()).cacheUserInfoEntity + + // 登录状态下更新实名认证信息 + if (cachedUserInfo != null) { + cachedUserInfo.idCard = content.toObject() + UserRepository.getInstance(getApplication()) + .cacheAndNotifyUserInfo(cachedUserInfo, true) + } + + tryWithDefaultCatch { + val `object` = JSONObject(data?.string() ?: "") + val isUnQualified = `object`.getBoolean("minor") + var qualifyInt = 1 + if (!isUnQualified) { + qualifyInt = 2 + } + NewLogUtils.logCertificationResult(isForced, qualifyInt) + } + + DataUtils.getDeviceCertification(HaloApp.getInstance().gid) + + certificateResultLiveData.postValue(true) + + // 安装因为实名延迟的游戏 + resumeInstallationIfNeeded() + // 重启因为实名认证而处于等待中的任务 + DownloadManager.getInstance(HaloApp.getInstance()) + .resumeAllInvisiblePendingTask() + } + }) + } + + /** + * 安装因为实名延迟的游戏 + */ + private fun resumeInstallationIfNeeded() { + val pendingInstallation = RealNameHelper.pendingInstallPkgPath + if (pendingInstallation.isNotEmpty()) { + val pendingDownloadEntity = + DownloadManager.getInstance(HaloApp.getInstance()).allDownloadEntity.firstOrNull { + it.path == pendingInstallation + } + + PackageInstaller.install(HaloApp.getInstance(), pendingDownloadEntity) + RealNameHelper.pendingInstallPkgPath = "" + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/halo/assistant/fragment/user/UserInfoFragment.java b/app/src/main/java/com/halo/assistant/fragment/user/UserInfoFragment.java index 5631c8b2d8..6c4d2dedc2 100644 --- a/app/src/main/java/com/halo/assistant/fragment/user/UserInfoFragment.java +++ b/app/src/main/java/com/halo/assistant/fragment/user/UserInfoFragment.java @@ -11,9 +11,9 @@ import com.gh.common.util.ImageUtils; import com.gh.common.util.MtaHelper; import com.gh.gamecenter.R; import com.gh.gamecenter.SelectUserIconActivity; +import com.gh.gamecenter.ShellActivity; import com.gh.gamecenter.UserInfoEditActivity; import com.gh.gamecenter.UserRegionActivity; -import com.gh.gamecenter.WebActivity; import com.gh.gamecenter.entity.IdCardEntity; import com.gh.gamecenter.entity.UserInfoEntity; import com.gh.gamecenter.normal.NormalFragment; @@ -159,7 +159,7 @@ public class UserInfoFragment extends NormalFragment { break; case R.id.userinfo_verify_rl: MtaHelper.onEvent("个人主页详情", "个人中心", "实名认证"); - startActivity(UserInfoEditActivity.getIntent(getContext(), UserViewModel.TYPE_ID_CARD)); + startActivity(ShellActivity.getIntent(getContext(), ShellActivity.Type.REAL_NAME_INFO, null)); break; case R.id.userinfo_introduce_rl: MtaHelper.onEvent("个人主页详情", "个人中心", "个性签名"); diff --git a/app/src/main/res/drawable-xhdpi/bg_userinfo_verified_success.9.png b/app/src/main/res/drawable-xhdpi/bg_userinfo_verified_success.9.png index 4994be456b..a8401fa3fd 100644 Binary files a/app/src/main/res/drawable-xhdpi/bg_userinfo_verified_success.9.png and b/app/src/main/res/drawable-xhdpi/bg_userinfo_verified_success.9.png differ diff --git a/app/src/main/res/drawable/button_round_2496ff_alpha_40.xml b/app/src/main/res/drawable/button_round_2496ff_alpha_40.xml new file mode 100644 index 0000000000..b461c34da3 --- /dev/null +++ b/app/src/main/res/drawable/button_round_2496ff_alpha_40.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_real_name.xml b/app/src/main/res/layout/fragment_real_name.xml new file mode 100644 index 0000000000..370b4d21d8 --- /dev/null +++ b/app/src/main/res/layout/fragment_real_name.xml @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dependencies.gradle b/dependencies.gradle index 08c265ec46..f821f19150 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -99,7 +99,7 @@ ext { skeleton = "1.1.3" shimmerlayout = "2.1.0" mta = "6.7.9" - romChecker = "1.0.2" + romChecker = "1.0.3" oss = "2.9.2" toolargetool = "0.3.0" chart = "3.1.0"