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 6cddd0a856..1d0677a9a9 100644 --- a/app/src/main/java/com/gh/common/util/DirectUtils.kt +++ b/app/src/main/java/com/gh/common/util/DirectUtils.kt @@ -341,7 +341,7 @@ object DirectUtils { "feedback" -> directToFeedback(context, linkEntity.name, linkEntity.text, false, "", entrance) - "qa", "Q&A" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "") + "qa", "qa_content", "Q&A" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "") "qa_collection", "Q&A合集" -> directToQaCollection( context, linkEntity.text 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 dcbb211d35..e36bfd1a7f 100644 --- a/app/src/main/java/com/gh/common/util/PackageInstaller.kt +++ b/app/src/main/java/com/gh/common/util/PackageInstaller.kt @@ -4,12 +4,9 @@ import android.app.Activity import android.app.PendingIntent import android.content.Context import android.content.Intent -import android.content.pm.PackageInstaller.SessionCallback import android.net.Uri import android.os.Build -import android.util.Log import android.view.View -import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.core.content.FileProvider import com.gh.common.dialog.InstallPermissionDialogFragment @@ -21,7 +18,6 @@ import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.utils.DialogHelper import com.gh.gamecenter.common.utils.getExtension import com.gh.gamecenter.common.utils.getMetaExtra -import com.gh.gamecenter.core.AppExecutor import com.gh.gamecenter.core.utils.CurrentActivityHolder import com.gh.gamecenter.core.utils.MD5Utils import com.gh.gamecenter.core.utils.ToastUtils diff --git a/app/src/main/java/com/gh/common/xapk/XapkInstaller.kt b/app/src/main/java/com/gh/common/xapk/XapkInstaller.kt index 256eafa937..be924ae831 100644 --- a/app/src/main/java/com/gh/common/xapk/XapkInstaller.kt +++ b/app/src/main/java/com/gh/common/xapk/XapkInstaller.kt @@ -2,13 +2,15 @@ package com.gh.common.xapk import android.annotation.SuppressLint import android.content.Context +import android.content.Intent import android.os.Build +import android.provider.Settings +import com.gh.common.constant.Config import com.gh.common.util.* import com.gh.download.DownloadDataHelper import com.gh.download.DownloadManager -import com.gh.gamecenter.common.utils.debugOnly -import com.gh.gamecenter.common.utils.getExtension -import com.gh.gamecenter.common.utils.throwExceptionInDebug +import com.gh.gamecenter.common.constant.Constants +import com.gh.gamecenter.common.utils.* import com.gh.gamecenter.core.AppExecutor import com.gh.gamecenter.core.utils.SentryHelper import com.gh.gamecenter.xapk.XApkUnZipper @@ -51,6 +53,9 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory { const val XAPK_DATA_EXTENSION_NAME = "obb" const val PACKAGE_EXTENSION_NAME = "apk" + private const val GUIDE_TYPE_MIUI_OPTIMIZATION = "miui_optimization" + private const val MIUI_OPTIMIZATION_WARNING_DIALOG_ENTRANCE = "MIUI优化关闭提示弹窗" + private var mContext = HaloApp.getInstance().application.applicationContext private val mXApkUnZipper = XApkUnZipper(this) @@ -69,6 +74,30 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory { val filePath = downloadEntity.path if (XAPK_EXTENSION_NAME == filePath.getExtension()) { + if (MiuiUtils.isMiui() && !MiuiUtils.isMiuiOptimizationDisabled() && downloadEntity.format == Constants.XAPK_APKS_FORMAT) {// 小米手机开启miui以后,需要引导用户关闭miui优化 + DialogHelper.showMiuiOptimizationWarning( + context, + onHintClick = { + val guides = Config.getNewApiSettingsEntity()?.install + val miuiOptimizationGuide = guides?.guides?.findLast { + it.type == GUIDE_TYPE_MIUI_OPTIMIZATION + } + if (miuiOptimizationGuide != null) { + DirectUtils.directToLinkPage( + context, + miuiOptimizationGuide.link, + MIUI_OPTIMIZATION_WARNING_DIALOG_ENTRANCE, + "" + ) + } + }, + onConfirmClick = { + context.startActivity(Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)) + } + ) + return + } + unzipXapkFile(downloadEntity) if (showUnzipToast) { Utils.toast(mContext, "解压过程请勿退出光环助手!") @@ -227,7 +256,9 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory { if (sessionId != -1) { val sessionInfo = installer.getSessionInfo(sessionId) // 表示用户点击了安装弹窗外部区域 - if (sessionInfo != null && sessionInfo.progress <= 0.8F) { + if (sessionInfo == null) { + pendingSessionInfo.updateStatus(XapkPendingSessionInfo.STATUS_INSTALL_CANCELED) + } else if (sessionInfo.progress <= 0.8F) { AppExecutor.ioExecutor.execute { installer.abandonSession(sessionInfo.sessionId) } @@ -278,12 +309,13 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory { ) : IPackageInstaller { override fun install(context: Context) { - val downloadEntity = mDownloadEntityMap[xApkFile.file.path] ?: return val applicationContext = context.applicationContext + val downloadEntity = mDownloadEntityMap[xApkFile.file.path] ?: return + mPendingSessionInfoMap[downloadEntity.path] = XapkPendingSessionInfo(downloadEntity.path, sessionId) AppExecutor.ioExecutor.execute {// 有可能卡顿造成anr - NDataChanger.notifyDataChanged(downloadEntity) PackageInstaller.installMultiple(applicationContext, downloadEntity.path, sessionId) + NDataChanger.notifyDataChanged(downloadEntity) } } } @@ -309,7 +341,6 @@ enum class XapkUnzipStatus(status: String) { UNZIPPING("unzipping"), SUCCESS("success"), CANCEL("cancel"), - INSTALLING("installing"), INSTALLED("installed"), FAILURE("failure"); } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/MainActivity.java b/app/src/main/java/com/gh/gamecenter/MainActivity.java index 4fe79c552a..e9d49d13b2 100644 --- a/app/src/main/java/com/gh/gamecenter/MainActivity.java +++ b/app/src/main/java/com/gh/gamecenter/MainActivity.java @@ -198,7 +198,6 @@ public class MainActivity extends BaseActivity { protected void onCreate(Bundle savedInstanceState) { showAd = getIntent().getBooleanExtra(SHOW_AD, false) && savedInstanceState == null; - HaloApp.getInstance().initFresco(); HaloApp.getInstance().isAlreadyUpAndRunning = true; super.onCreate(savedInstanceState); diff --git a/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.kt b/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.kt index 21ae49c7b8..f9cf6cf817 100644 --- a/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.kt @@ -297,19 +297,7 @@ class SplashScreenActivity : BaseActivity() { private fun doFlavorInit() { HaloApp.getInstance().flavorProvider.init(HaloApp.getInstance(), this, PkgHelper.getActivateRatio()) - val whiteListChannel = arrayListOf( - "GH_206", - "KS-GHZS-KY1", - "KS-GHZS-MC1", - "GDT_GHZS_MC1", - "T11-GH-APPDY-ZC01", - "T7-GH-APPDY-KY03", - "T8-GH-APPUX-KY04", - "T1-GHZS-MC01", - "T4-GHZS-MC03" - ) - - if (whiteListChannel.contains(HaloApp.getInstance().channel) || PackageFlavorHelper.IS_TEST_FLAVOR) { + if (HaloApp.getInstance().channel == "GH_206" || PackageFlavorHelper.IS_TEST_FLAVOR) { SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel) } } diff --git a/app/src/main/java/com/gh/gamecenter/entity/NewApiSettingsEntity.kt b/app/src/main/java/com/gh/gamecenter/entity/NewApiSettingsEntity.kt index f6baef26aa..3f5dfeb510 100644 --- a/app/src/main/java/com/gh/gamecenter/entity/NewApiSettingsEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/entity/NewApiSettingsEntity.kt @@ -1,5 +1,6 @@ package com.gh.gamecenter.entity +import com.gh.gamecenter.common.entity.LinkEntity import com.gh.gamecenter.feature.entity.SimulatorEntity import com.google.gson.annotations.SerializedName @@ -29,7 +30,9 @@ class NewApiSettingsEntity( // VPN 配置 class Install( @SerializedName("vpn_required") - val vpnRequired: VpnSetting? = null + val vpnRequired: VpnSetting? = null, + @SerializedName("guides") + val guides: List? = null ) class VpnSetting( @@ -38,4 +41,9 @@ class NewApiSettingsEntity( @SerializedName("packages") val vpnMatchedPackagesName: HashSet ) + + class Guide( + val type: String, + val link: LinkEntity + ) } \ No newline at end of file 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 ded4d38c98..95bf119cf7 100644 --- a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt @@ -534,8 +534,7 @@ class SearchGameIndexAdapter( if (key.contains(download.packageName) && key.contains(download.gameId)) { val position = positionAndPackageMap[key] if (position != null && mEntityList != null && position < mEntityList.size && mEntityList[position].game != null) { - mEntityList[position].game!!.getEntryMap()[download.platform] = download - notifyItemChanged(position) + DownloadItemUtils.processDate(mEntityList[position].game!!, download, this, position) } } } diff --git a/app/src/main/java/com/gh/gamecenter/servers/gametest2/GameServerTestV2ListFragment.kt b/app/src/main/java/com/gh/gamecenter/servers/gametest2/GameServerTestV2ListFragment.kt index 8a7b33dd42..253e2f52c2 100644 --- a/app/src/main/java/com/gh/gamecenter/servers/gametest2/GameServerTestV2ListFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/servers/gametest2/GameServerTestV2ListFragment.kt @@ -102,6 +102,7 @@ class GameServerTestV2ListFragment : } override fun initSkeletonScreen() { + if (mBinding?.skeleton == null) return mSkeletonScreen = Skeleton.bind(mBinding?.skeleton) .shimmer(true) .angle(Constants.SHIMMER_ANGLE) diff --git a/app/src/main/java/com/gh/vspace/VArchiveHelper.kt b/app/src/main/java/com/gh/vspace/VArchiveHelper.kt index d15a0cb6bb..926245ca51 100644 --- a/app/src/main/java/com/gh/vspace/VArchiveHelper.kt +++ b/app/src/main/java/com/gh/vspace/VArchiveHelper.kt @@ -150,7 +150,7 @@ object VArchiveHelper { if (isSuccess) { val vGameEntity = VHelper.getVGameSnapshot(packageName = packageName) runOnIoThread { - val fileMd5 = MD5Utils.calculateMD5(mLatestArchiveFile) + val fileMd5 = MD5Utils.calculateMD5(mLatestArchiveFile) ?: return@runOnIoThread val vArchiveEntity = VArchiveEntity( id = fileMd5, gameId = vGameEntity?.downloadEntity?.gameId ?: "", diff --git a/app/src/main/java/com/gh/vspace/VHelper.kt b/app/src/main/java/com/gh/vspace/VHelper.kt index 483866651d..8fb35ebe3e 100644 --- a/app/src/main/java/com/gh/vspace/VHelper.kt +++ b/app/src/main/java/com/gh/vspace/VHelper.kt @@ -959,11 +959,21 @@ object VHelper { location: String? = null) { Utils.log(LOG_TAG, "检测是需要安装还是启动 ${downloadEntity.gameId}") + if (downloadEntity.name.isNullOrEmpty()) { + SentryHelper.onEvent( + "V_GAME_DOWNLOAD_ENTITY_NAME_EMPTY", + "game_id", + downloadEntity.gameId, + "location", + location + ) + } + installOrLaunch( context, downloadEntity.packageName, downloadEntity.gameId, - downloadEntity.name, + downloadEntity.name ?: "", downloadEntity.getGameCategory(), downloadEntity.getMetaExtra(KEY_BIT), location diff --git a/app/src/main/java/com/gh/vspace/VSpace32DialogFragment.kt b/app/src/main/java/com/gh/vspace/VSpace32DialogFragment.kt index 90ccbc2c38..7a3529978a 100644 --- a/app/src/main/java/com/gh/vspace/VSpace32DialogFragment.kt +++ b/app/src/main/java/com/gh/vspace/VSpace32DialogFragment.kt @@ -46,6 +46,7 @@ class VSpace32DialogFragment : BaseDraggableDialogFragment() { private val mBinding by lazy { DialogVspace32Binding.inflate(layoutInflater) } private var mIsLogInstallShow = false private var mIsLogAutoInstallClick = false + private var mIsClickDownloadThisTime = false // 是否本次弹出Dialog点击的下载按钮 private val mDataWatcher = object : DataWatcher() { override fun onDataChanged(downloadEntity: DownloadEntity) { if (downloadEntity.url == mDownloadUrl && isAdded) { @@ -146,6 +147,8 @@ class VSpace32DialogFragment : BaseDraggableDialogFragment() { downloadType ).toJson() + mIsClickDownloadThisTime = true + AppExecutor.uiExecutor.executeWithDelay({ DownloadManager.getInstance().cancel(mDownloadUrl) DownloadManager.getInstance().add(downloadEntity) @@ -221,7 +224,7 @@ class VSpace32DialogFragment : BaseDraggableDialogFragment() { val isVSpace32DownloadOnly = downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.VSPACE_32_DOWNLOAD_ONLY val isAutoInstall = SPUtils.getBoolean(Constants.SP_AUTO_INSTALL, true) - if (!isVSpace32DownloadOnly && isAutoInstall && !mIsLogAutoInstallClick) { + if (!isVSpace32DownloadOnly && isAutoInstall && !mIsLogAutoInstallClick && mIsClickDownloadThisTime) { NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_click") SensorsBridge.trackEvent("HaloFunExpandInstallButtonClick") mIsLogAutoInstallClick = true diff --git a/app/src/main/java/com/gh/vspace/VSpaceDialogFragment.kt b/app/src/main/java/com/gh/vspace/VSpaceDialogFragment.kt index f9f01fe182..98cd61955d 100644 --- a/app/src/main/java/com/gh/vspace/VSpaceDialogFragment.kt +++ b/app/src/main/java/com/gh/vspace/VSpaceDialogFragment.kt @@ -59,6 +59,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { private val mBinding by lazy { DialogVspaceBinding.inflate(layoutInflater) } private var mIsLogInstallShow = false private var mIsLogAutoInstallClick = false + private var mIsClickDownloadThisTime = false // 是否本次弹出Dialog点击的下载按钮 private val mDataWatcher = object : DataWatcher() { override fun onDataChanged(downloadEntity: DownloadEntity) { if (((mAppEntity64 != null && downloadEntity.url == mDownloadUrl64) || (mAppEntity64 == null && downloadEntity.url == mDownloadUrl32)) && isAdded) { @@ -159,6 +160,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity32, "开始") } + mIsClickDownloadThisTime = true AppExecutor.uiExecutor.executeWithDelay({ if (downloadEntity64 != null) { DownloadManager.getInstance().cancel(mDownloadUrl64) @@ -238,7 +240,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { // 需要下载的 32 位组件是否与已安装的 32 位组件版本一致 val is32BitVersionMatched = - mAppEntity32 == null + (mAppEntity32 == null || mBit != "32") || mAppEntity32?.version == PackageUtils.getVersionNameByPackageName(VHelper.VSPACE_32BIT_PACKAGENAME) if (is64BitVersionMatched && is32BitVersionMatched) { @@ -318,8 +320,14 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { mIsLogInstallShow = true } - if (SPUtils.getBoolean(Constants.SP_AUTO_INSTALL, true) && !mIsLogAutoInstallClick) { - SensorsBridge.trackEvent("HaloFunInstallButtonClick", "space_schema_type", vSpaceType) + if (SPUtils.getBoolean( + Constants.SP_AUTO_INSTALL, + true + ) && !mIsLogAutoInstallClick && mIsClickDownloadThisTime + ) { + downloadBtn.postDelayed({ + SensorsBridge.trackEvent("HaloFunInstallButtonClick", "space_schema_type", vSpaceType) + }, SENSORS_LOG_DELAY) mIsLogAutoInstallClick = true } @@ -359,6 +367,8 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() { const val KEY_AUTO_DOWNLOAD = "auto_download" const val KEY_IS_UPDATE = "is_update" + const val SENSORS_LOG_DELAY = 1000L + @JvmStatic fun showDownloadDialog( context: Context?, diff --git a/app/src/main/java/com/halo/assistant/HaloApp.java b/app/src/main/java/com/halo/assistant/HaloApp.java index ebe6c14499..ccf0e0ba67 100644 --- a/app/src/main/java/com/halo/assistant/HaloApp.java +++ b/app/src/main/java/com/halo/assistant/HaloApp.java @@ -227,12 +227,12 @@ public class HaloApp extends MultiDexApplication { PlayerFactory.setPlayManager(Exo2PlayerManager.class); CacheFactory.setCacheManager(ExoPlayerCacheManager.class); + initFresco(); + AppExecutor.getIoExecutor().execute(() -> { initDataHelper(); ExtensionsKt.doOnMainProcessOnly(this, () -> Tracker.init(this)); - initFresco(); - deviceRamSize = DeviceUtils.getTotalRamSizeOfDevice(this); mChannel = mFlavorProvider.getChannelStr(this); diff --git a/module_common/src/main/java/com/gh/gamecenter/common/utils/DialogHelper.kt b/module_common/src/main/java/com/gh/gamecenter/common/utils/DialogHelper.kt index afc1a36bd1..de114f24f7 100644 --- a/module_common/src/main/java/com/gh/gamecenter/common/utils/DialogHelper.kt +++ b/module_common/src/main/java/com/gh/gamecenter/common/utils/DialogHelper.kt @@ -4,15 +4,22 @@ import android.app.Activity import android.app.Dialog import android.content.Context import android.graphics.Color +import android.graphics.Paint +import android.graphics.Typeface import android.graphics.drawable.ColorDrawable import android.os.Build import android.text.Html +import android.text.Spannable +import android.text.SpannableStringBuilder +import android.text.style.StyleSpan import android.view.* import androidx.annotation.DrawableRes +import androidx.core.content.ContextCompat import com.alibaba.android.arouter.launcher.ARouter import com.gh.gamecenter.common.R import com.gh.gamecenter.common.base.TrackableDialog import com.gh.gamecenter.common.callback.ConfirmListener +import com.gh.gamecenter.common.constant.Config import com.gh.gamecenter.common.constant.RouteConsts import com.gh.gamecenter.common.databinding.DialogAlertDefaultBinding import com.gh.gamecenter.common.databinding.DialogGuideBinding @@ -622,18 +629,6 @@ object DialogHelper { ) } - /** - * @param context may be is application context - * @return activity context - */ - fun checkDialogContext(context: Context?): Context? { - if (context == null) { - throw NullPointerException("dialog context is null") - } - return context as? Activity ?: AppManager.getInstance().currentActivity() - - // currentActivity 是否存在 isDestroyed 的情况? - } @JvmStatic fun showUnsupportedFeatureDialog(context: Context) { @@ -655,6 +650,49 @@ object DialogHelper { ) } + fun showMiuiOptimizationWarning( + context: Context, + onHintClick: () -> Unit, + onConfirmClick: () -> Unit, + ) { + showDialog( + context = context, + title = context.getString(R.string.miui_optimization_warning_dialog_title), + content = SpannableStringBuilder( + context.getString(R.string.miui_optimization_warning_dialog_content) + ).apply { + setSpan(StyleSpan(Typeface.BOLD), 10, 15, Spannable.SPAN_INCLUSIVE_INCLUSIVE) + }, + confirmText = context.getString(R.string.miui_optimizaition_warning_dialog_confirm), + cancelText = context.getString(R.string.miui_optimizaition_warning_dialog_cancel), + confirmClickCallback = onConfirmClick, + extraConfig = Config(), + uiModificationCallback = { + it.hintTv.text = context.getString(R.string.miui_optimizaition_warning_dialog_hint) + it.hintTv.visibility = View.VISIBLE + it.hintTv.paint.flags = Paint.UNDERLINE_TEXT_FLAG + it.hintTv.paint.isAntiAlias = true + it.hintTv.setTextColor(ContextCompat.getColor(context, R.color.theme_font)) + it.hintTv.setOnClickListener { + onHintClick.invoke() + } + } + ) + } + + /** + * @param context may be is application context + * @return activity context + */ + fun checkDialogContext(context: Context?): Context? { + if (context == null) { + throw NullPointerException("dialog context is null") + } + return context as? Activity ?: AppManager.getInstance().currentActivity() + + // currentActivity 是否存在 isDestroyed 的情况? + } + class Config( val hint: String = "", val showCloseIcon: Boolean = false, diff --git a/module_common/src/main/java/com/gh/gamecenter/common/utils/MiuiUtils.java b/module_common/src/main/java/com/gh/gamecenter/common/utils/MiuiUtils.java new file mode 100644 index 0000000000..6a22914488 --- /dev/null +++ b/module_common/src/main/java/com/gh/gamecenter/common/utils/MiuiUtils.java @@ -0,0 +1,91 @@ +package com.gh.gamecenter.common.utils; + +import android.annotation.SuppressLint; +import android.os.Build; +import android.text.TextUtils; + +import java.util.Objects; + +public class MiuiUtils { + + public static boolean isMiui() { + return !TextUtils.isEmpty(SystemUtils.getSystemProperty("ro.miui.ui.version.name")); + } + + public static String getMiuiVersionName() { + String versionName = SystemUtils.getSystemProperty("ro.miui.ui.version.name"); + return !TextUtils.isEmpty(versionName) ? versionName : "???"; + } + + public static int getMiuiVersionCode() { + try { + return Integer.parseInt(Objects.requireNonNull(SystemUtils.getSystemProperty("ro.miui.ui.version.code"))); + } catch (Exception e) { + return -1; + } + } + + public static String getActualMiuiVersion() { + return Build.VERSION.INCREMENTAL; + } + + private static int[] parseVersionIntoParts(String version) { + try { + String[] versionParts = version.split("\\."); + int[] intVersionParts = new int[versionParts.length]; + + for (int i = 0; i < versionParts.length; i++) + intVersionParts[i] = Integer.parseInt(versionParts[i]); + + return intVersionParts; + } catch (Exception e) { + return new int[]{-1}; + } + } + + /** + * @return 0 if versions are equal, values less than 0 if ver1 is lower than ver2, value more than 0 if ver1 is higher than ver2 + */ + private static int compareVersions(String version1, String version2) { + if (version1.equals(version2)) + return 0; + + int[] version1Parts = parseVersionIntoParts(version1); + int[] version2Parts = parseVersionIntoParts(version2); + + for (int i = 0; i < version2Parts.length; i++) { + if (i >= version1Parts.length) + return -1; + + if (version1Parts[i] < version2Parts[i]) + return -1; + + if (version1Parts[i] > version2Parts[i]) + return 1; + } + + return 1; + } + + public static boolean isActualMiuiVersionAtLeast(String targetVer) { + return compareVersions(getActualMiuiVersion(), targetVer) >= 0; + } + + @SuppressLint("PrivateApi") + public static boolean isMiuiOptimizationDisabled() { + if ("0".equals(SystemUtils.getSystemProperty("persist.sys.miui_optimization"))) + return true; + + try { + return (boolean) Class.forName("android.miui.AppOpsUtils") + .getDeclaredMethod("isXOptMode") + .invoke(null); + } catch (Exception e) { + return false; + } + } + + public static boolean isFixedMiui() { + return isActualMiuiVersionAtLeast("20.2.20") || isMiuiOptimizationDisabled(); + } +} diff --git a/module_common/src/main/java/com/gh/gamecenter/common/utils/SystemUtils.kt b/module_common/src/main/java/com/gh/gamecenter/common/utils/SystemUtils.kt new file mode 100644 index 0000000000..295918799f --- /dev/null +++ b/module_common/src/main/java/com/gh/gamecenter/common/utils/SystemUtils.kt @@ -0,0 +1,19 @@ +package com.gh.gamecenter.common.utils + +import android.annotation.SuppressLint + + +object SystemUtils { + @SuppressLint("PrivateApi") + @JvmStatic + fun getSystemProperty(key: String?): String? { + return try { + Class.forName("android.os.SystemProperties") + .getDeclaredMethod("get", String::class.java) + .invoke(null, key) as String + } catch (e: Exception) { + null + } + } + +} \ No newline at end of file diff --git a/module_common/src/main/res/values/strings.xml b/module_common/src/main/res/values/strings.xml index 1fc022df9a..ecb6bb43ae 100644 --- a/module_common/src/main/res/values/strings.xml +++ b/module_common/src/main/res/values/strings.xml @@ -74,4 +74,9 @@ 当前版本不支持该功能,\n建议您升级到最新版本体验哦 体验升级 取消 + 温馨提示 + 安装该游戏需要关闭MIUI优化,否则将无法解压安装\n注意:MIUI优化关闭后可能会导致手机系统不稳定,以及无法使用MIUI提供的服务。你可以在游戏安装完成后重新开启 + 立即关闭 + 以后再说 + ]]> \ No newline at end of file