Compare commits

...

16 Commits

Author SHA1 Message Date
8c0773aab2 fix:模拟器下载流程修复20221027测试反馈 https://git.shanqu.cc/pm/halo/halo-app-issues/-/issues/2125 2022-10-28 14:35:36 +08:00
e596de766a Merge remote-tracking branch 'origin/dev' into feature-issues2125 2022-10-27 14:36:36 +08:00
12c3605db8 fix:规范修改 2022-10-27 11:44:37 +08:00
4201d0abd3 fix:规范修改 2022-10-27 11:30:40 +08:00
3a0daea1fb fix:修改 2022-10-27 11:18:22 +08:00
17e4923c98 fix修改私有变量命名规范 2022-10-27 10:39:37 +08:00
1a2c90cfb0 fix:合并冲突 2022-10-27 10:37:46 +08:00
06c084a1ec feat:模拟器游戏埋点 2022-10-26 16:29:53 +08:00
930fc88183 merge 2022-10-26 11:30:14 +08:00
e8dec7d101 Merge remote-tracking branch 'origin/dev' into feature-issues2125 2022-10-26 11:20:46 +08:00
28fcd20186 fix:模拟器下载流程修改 2022-10-26 11:06:20 +08:00
d8483686d2 Merge remote-tracking branch 'origin/dev' into feature-issues2125
# Conflicts:
#	app/src/main/java/com/gh/common/util/NewFlatLogUtils.kt
2022-10-25 17:40:55 +08:00
cb67b4f01e Merge branch 'dev' into 'feature-issues2125'
# Conflicts:
#   app/src/main/java/com/gh/common/util/NewFlatLogUtils.kt
2022-10-25 09:31:16 +00:00
236ecb9f4f fix:解决冲突 2022-10-25 17:26:46 +08:00
877335f47b fix:解决冲突 2022-10-25 17:21:07 +08:00
676b81b649 feat: 模拟器下载流程调整 https://git.shanqu.cc/pm/halo/halo-app-issues/-/issues/2125 2022-10-25 17:03:41 +08:00
32 changed files with 806 additions and 119 deletions

View File

@ -0,0 +1,35 @@
package com.gh.common.chain
import android.content.Context
import com.gh.common.simulator.NewSimulatorGameManager
import com.gh.common.simulator.SimulatorGameManager
import com.gh.gamecenter.entity.GameEntity
class UpdateNewSimulatorHandler: ChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity) {
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
if (NewSimulatorGameManager.shouldShowUpdateNewSimulatorAlert(context)) {
NewSimulatorGameManager.showUpdateNewsSimulator(context) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
} else {
processEndCallback?.invoke(null)
}
}
}
else{
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
}
}
}
else{
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity)
}
}
}
}

View File

@ -22,6 +22,7 @@ import com.gh.gamecenter.entity.NewSettingsEntity;
import com.gh.gamecenter.entity.NewsEntity; import com.gh.gamecenter.entity.NewsEntity;
import com.gh.gamecenter.entity.SettingsEntity; import com.gh.gamecenter.entity.SettingsEntity;
import com.gh.gamecenter.common.eventbus.EBReuse; import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.entity.SimulatorEntity;
import com.gh.gamecenter.entity.VSetting; import com.gh.gamecenter.entity.VSetting;
import com.gh.gamecenter.common.retrofit.BiResponse; import com.gh.gamecenter.common.retrofit.BiResponse;
import com.gh.gamecenter.common.retrofit.Response; import com.gh.gamecenter.common.retrofit.Response;
@ -65,6 +66,7 @@ public class Config {
private static NewSettingsEntity mNewSettingsEntity; private static NewSettingsEntity mNewSettingsEntity;
private static NewSettingsEntity.NightMode mNightModeSetting; private static NewSettingsEntity.NightMode mNightModeSetting;
private static SimulatorEntity mNewSimulatorEntity;
private static VSetting mVSetting; private static VSetting mVSetting;
private static GameGuidePopupEntity mGameGuidePopupEntity; private static GameGuidePopupEntity mGameGuidePopupEntity;
private static SharedPreferences mDefaultSharedPreferences; private static SharedPreferences mDefaultSharedPreferences;
@ -220,6 +222,18 @@ public class Config {
return mSettingsEntity; return mSettingsEntity;
} }
//新模拟器
@Nullable
public static SimulatorEntity getNewSimulatorEntitySetting() {
if (mNewSimulatorEntity != null) {
return mNewSimulatorEntity;
} else if (mNewSettingsEntity != null && mNewSettingsEntity.getSimulator() != null) {
return mNewSettingsEntity.getSimulator();
} else {
return null;
}
}
@Nullable @Nullable
public static NewSettingsEntity.NightMode getNightModeSetting() { public static NewSettingsEntity.NightMode getNightModeSetting() {
if (mNightModeSetting != null) { if (mNightModeSetting != null) {
@ -370,7 +384,7 @@ public class Config {
}); });
} }
if (mNightModeSetting == null) { if (mNightModeSetting == null && mNewSimulatorEntity == null) {
RetrofitManager.getInstance() RetrofitManager.getInstance()
.getNewApi().getNewSettings(PackageUtils.getGhVersionName(), channel) .getNewApi().getNewSettings(PackageUtils.getGhVersionName(), channel)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -379,6 +393,7 @@ public class Config {
@Override @Override
public void onSuccess(NewSettingsEntity data) { public void onSuccess(NewSettingsEntity data) {
mNightModeSetting = data.getNightMode(); mNightModeSetting = data.getNightMode();
mNewSimulatorEntity = data.getSimulator();
if (HaloApp.getInstance().isNewForThisVersion && mNightModeSetting != null && mNightModeSetting.getInstall()) { if (HaloApp.getInstance().isNewForThisVersion && mNightModeSetting != null && mNightModeSetting.getInstall()) {
DarkModeUtils.INSTANCE.updateFollowSystemDarkModeToSp(true); DarkModeUtils.INSTANCE.updateFollowSystemDarkModeToSp(true);
DarkModeUtils.INSTANCE.updateAppDarkModeStatusToSp(true); DarkModeUtils.INSTANCE.updateAppDarkModeStatusToSp(true);
@ -386,6 +401,7 @@ public class Config {
} }
if (mNewSettingsEntity != null) { if (mNewSettingsEntity != null) {
mNewSettingsEntity.setSimulator(mNewSimulatorEntity);
mNewSettingsEntity.setNightMode(mNightModeSetting); mNewSettingsEntity.setNightMode(mNightModeSetting);
SPUtils.setString(Constants.SP_NEW_SETTINGS, GsonUtils.toJson(data)); SPUtils.setString(Constants.SP_NEW_SETTINGS, GsonUtils.toJson(data));
} }

View File

@ -0,0 +1,165 @@
package com.gh.common.simulator
import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.view.Gravity
import androidx.core.content.FileProvider
import com.g00fy2.versioncompare.Version
import com.gh.common.constant.Config
import com.gh.common.util.DownloadItemUtils
import com.gh.common.util.LogUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.GameEntity
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.utils.AppManager
import io.reactivex.Single
import java.io.ByteArrayOutputStream
import java.io.File
object NewSimulatorGameManager {
private const val KEY_GAME_ICON = "GAME_ICON"
private const val KEY_GAME_ID = "GAME_ID"
private const val KEY_GAME_NAME = "GAME_NAME"
private const val KEY_GAME_PACKAGE_NAME = "GAME_PACKAGE_NAME"
private const val KEY_GAME_PACKAGE_PATH = "GAME_PACKAGE_PATH"
private const val KEY_GAME_PACKAGE_LAST_MODIFICATION = "GAME_PACKAGE_LAST_MODIFICATION"
private const val KEY_GAME_PACKAGE_EXTENSION = "GAME_PACKAGE_EXTENSION"
private const val KEY_GAME_PACKAGE_SDCARD_PATH = "GAME_PACKAGE_SDCARD_PATH" // boolean 是否sdcard文件路径
private const val KEY_GAME_EMU_SYSTEM = "GAME_EMU_SYSTEM"
private const val KEY_EMU_ID = "EMU_ID"
private const val KEY_EMU_NAME = "EMU_NAME"
private const val KEY_USE_DEBUG_API = "USE_DEBUG_API"
private const val KEY_META = "META"
// private const val GH_RETRO_EMU_APP_PACKAGE_NAME = "com.gh.retroemu"
private const val GH_RETRO_EMU_APP_LAUNCHER_ACTIVITY_NAME = "com.gh.retroemu.ui.SplashActivity"
private const val NEW_SIMULATOR_SHOW_ALERT_TAG = "-news-simulator-show-alert"
/**
* 后台模拟器管理上传新版本模拟器(显示状态),且检测用户有安装旧版本模拟器 每日弹出一次更新弹框
*/
@JvmStatic
fun shouldShowUpdateNewSimulatorAlert(context: Context): Boolean {
val isUploadNewsSimulator = Config.getNewSimulatorEntitySetting()?.active ?: false
val isInstallOld = SimulatorGameManager.isOldSimulatorInstalled(context)
val showAlertTag = SPUtils.getString(NEW_SIMULATOR_SHOW_ALERT_TAG, "")
val todayIsShow = showAlertTag == TimeUtils.getToday()//当天是否弹出过一次
val isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(context)
return (isUploadNewsSimulator && !todayIsShow && isInstallOld && !isInstalledNewSimulator)
}
/**
* 弹出更新弹框
*/
@JvmStatic
fun showUpdateNewsSimulator(context: Context, callback: EmptyCallback? = null){
NewFlatLogUtils.logSimulatorUpdateAlertShow()
DialogHelper.showDialog(
context,
"更新提示",
"光环助手近期对模拟器进行升级,优化游戏体验!\n但更新后可能会导致原先的游戏存档数据无法使用(可在模拟器管理中安装新版本模拟器)",
"更新",
"取消",
confirmClickCallback = {
NewFlatLogUtils.logSimulatorUpdateAlertClick("更新")
val simulator = Config.getNewSimulatorEntitySetting()
if (simulator != null) {
SimulatorDownloadManager.getInstance().showDownloadingDialog(context, simulator)
}
},
cancelClickCallback = {
callback?.onCallback()
NewFlatLogUtils.logSimulatorUpdateAlertClick("取消")
},
uiModificationCallback = { binding ->
binding.contentTv.gravity = Gravity.START
binding.contentTv.setTextColor(R.color.text_subtitle.toColor(context))
},
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
)
SPUtils.setString(NEW_SIMULATOR_SHOW_ALERT_TAG, TimeUtils.getToday())
}
/**
* 通过模拟器启动游戏
*/
@SuppressLint("CheckResult")
@JvmStatic
fun launchGameViaSimulator(downloadEntity: DownloadEntity, gameEntity: GameEntity) {
val newSimulator = Config.getNewSimulatorEntitySetting() ?: return
val gameIcon = gameEntity.icon ?: gameEntity.rawIcon ?: ""
Single.just(ImageUtils.getCachedUrl(gameIcon))
.flatMap {
SimulatorGameManager.getBitmapFormCache(it)
}.map {
BitmapUtils.compressBitmap(it, 100)
}.map {
val baos = ByteArrayOutputStream()
it.compress(Bitmap.CompressFormat.WEBP, 90, baos)
baos.toByteArray()
}
.compose(singleToMain())
.subscribe({
val gamePackageFileUri = FileProvider.getUriForFile(
HaloApp.getInstance(),
BuildConfig.APPLICATION_ID,
File(downloadEntity.path)
)
HaloApp.getInstance().grantUriPermission(
SimulatorGameManager.NEW_SIMULATOR_PACKAGE_NAME,
gamePackageFileUri,
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION // 冗余,以备不时之需
)
val intent = Intent()
intent.setClassName(SimulatorGameManager.NEW_SIMULATOR_PACKAGE_NAME, GH_RETRO_EMU_APP_LAUNCHER_ACTIVITY_NAME)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.data = gamePackageFileUri
gameEntity.getApk().safelyGetInRelease(0)?.let { apk ->
intent.putExtra(KEY_GAME_PACKAGE_NAME, apk.packageName)
intent.putExtra(KEY_GAME_PACKAGE_EXTENSION, apk.format)
}
intent.putExtra(KEY_GAME_NAME, downloadEntity.name)
intent.putExtra(KEY_GAME_ICON, it)
intent.putExtra(KEY_GAME_PACKAGE_PATH, downloadEntity.path) // 游戏包文件路径,冗余参数)
intent.putExtra(KEY_GAME_PACKAGE_SDCARD_PATH, true)
intent.putExtra(KEY_GAME_PACKAGE_LAST_MODIFICATION, File(downloadEntity.path).lastModified()) // 游戏包文件修改时间
intent.putExtra(KEY_GAME_EMU_SYSTEM, gameEntity.simulatorType) // 模拟器类型
intent.putExtra(KEY_GAME_ID, gameEntity.id)
// TODO 补充光环模拟器的游戏 id
intent.putExtra(KEY_EMU_ID, newSimulator.apk?.id) // 光环模拟器.apk gameId
intent.putExtra(KEY_EMU_NAME, "光环模拟器") // 光环模拟器.apk name
intent.putExtra(KEY_USE_DEBUG_API, EnvHelper.isDevEnv) // // 游戏来源是否为dev后台 (是否来源于测试环境)
intent.putExtra(KEY_META, LogUtils.getMetaObject().toString())
try {
AppManager.getInstance().recentActiveActivity?.startActivity(intent)
} catch (e: ActivityNotFoundException) {
ToastUtils.showToast("模拟器安装错误")
}
SimulatorGameManager.recordPlaySimulatorGames(gameEntity.id)
}, {
ToastUtils.showToast("跳转失败")
})
}
}

View File

@ -10,6 +10,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import com.g00fy2.versioncompare.Version import com.g00fy2.versioncompare.Version
import com.gh.common.util.LogUtils import com.gh.common.util.LogUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.PackageInstaller import com.gh.common.util.PackageInstaller
import com.gh.common.util.PackageUtils import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager import com.gh.download.DownloadManager
@ -137,8 +138,6 @@ class SimulatorDownloadManager private constructor() {
cancelCallback: (() -> Unit)? = null cancelCallback: (() -> Unit)? = null
) { ) {
if (context == null) return if (context == null) return
mContextRef = WeakReference(context)
this.simulatorLocation = location this.simulatorLocation = location
this.simulator = simulator this.simulator = simulator
this.gameId = gameId this.gameId = gameId
@ -152,20 +151,30 @@ class SimulatorDownloadManager private constructor() {
return return
} }
val isInstalled = PackageUtils.isInstalledFromAllPackage(context, simulator?.apk?.packageName) val isInstalled = PackageUtils.isInstalledFromAllPackage(context, simulator?.apk?.packageName)
val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator?.apk?.packageName) // val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator?.apk?.packageName)
val shouldShowUpdate = Version(simulator?.apk?.version).isHigherThan(versionFromInstalledApp) val shouldShowUpdate = PackageUtils.isInstalledApkMatchedMd5(simulator?.apk?.packageName, simulator?.apk?.md5)
val showAlertTag = SPUtils.getString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, "") //当天是否弹过
val todayIsShow = showAlertTag == TimeUtils.getToday()
downloadType = if (shouldShowUpdate && isInstalled) "update" else "download"
if (downloadType == "update" && todayIsShow && location != SimulatorLocation.SIMULATOR_MANAGE){
return
}
if (downloadType == "download" && isInstalled){
return
}
val title = if (shouldShowUpdate && isInstalled) "更新模拟器" else "安装模拟器" val title = if (shouldShowUpdate && isInstalled) "更新模拟器" else "安装模拟器"
val message = if (shouldShowUpdate && isInstalled) "检测到模拟器存在更高版本,是否前往更新" else "模拟器游戏需要先下载安装对应的模拟器,才可以运行" val message = if (shouldShowUpdate && isInstalled) "检测到模拟器存在更高版本,是否前往更新" else "模拟器游戏需要先下载安装对应的模拟器,才可以运行"
val positiveText = val positiveText =
if (shouldShowUpdate && isInstalled) "更新(${simulator?.apk?.size}" else "下载(${simulator?.apk?.size}" if (shouldShowUpdate && isInstalled) "更新(${simulator?.apk?.size}" else "下载(${simulator?.apk?.size}"
val negativeText = if (shouldShowUpdate && isInstalled) "下次再说" else "取消" val negativeText = if (shouldShowUpdate && isInstalled) "下次再说" else "取消"
downloadType = if (shouldShowUpdate && isInstalled) "update" else "download"
val trackableEntity = TrackableEntity( val trackableEntity = TrackableEntity(
"模拟器下载", "模拟器下载",
key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗", key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗",
logShowEvent = true logShowEvent = true
) )
if (shouldShowUpdate && isInstalled) {
NewFlatLogUtils.logSimulatorUpdateAlertShow()
}
DialogHelper.showDialog( DialogHelper.showDialog(
context, context,
title, title,
@ -176,11 +185,13 @@ class SimulatorDownloadManager private constructor() {
cancelClickCallback = { cancelClickCallback = {
if (shouldShowUpdate && isInstalled) { if (shouldShowUpdate && isInstalled) {
cancelCallback?.invoke() cancelCallback?.invoke()
NewFlatLogUtils.logSimulatorUpdateAlertClick("取消")
MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说") MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说")
} }
}, },
confirmClickCallback = { confirmClickCallback = {
showDownloadingDialog(context, simulator) showDownloadingDialog(context, simulator)
NewFlatLogUtils.logSimulatorUpdateAlertClick("更新")
MtaHelper.onEvent( MtaHelper.onEvent(
trackableEntity.event, trackableEntity.event,
trackableEntity.key, trackableEntity.key,
@ -190,11 +201,15 @@ class SimulatorDownloadManager private constructor() {
mtaEvent = trackableEntity.event, mtaKey = trackableEntity.key, mtaEvent = trackableEntity.event, mtaKey = trackableEntity.key,
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true) extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
) )
if (downloadType == "update" && location != SimulatorLocation.SIMULATOR_MANAGE) {
SPUtils.setString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, TimeUtils.getToday())
}
} }
}) })
} }
private fun showDownloadingDialog(context: Context, simulator: SimulatorEntity?) { fun showDownloadingDialog(context: Context, simulator: SimulatorEntity?) {
mContextRef = WeakReference(context)
val msg = FileUtils.isCanDownload(context, simulator?.apk?.size) val msg = FileUtils.isCanDownload(context, simulator?.apk?.size)
if (!msg.isNullOrEmpty()) { if (!msg.isNullOrEmpty()) {
Utils.toast(context, msg) Utils.toast(context, msg)

View File

@ -2,11 +2,12 @@ package com.gh.common.simulator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
import android.text.TextUtils import android.text.TextUtils
import com.g00fy2.versioncompare.Version import com.gh.common.constant.Config
import com.gh.common.util.ApkActiveUtils import com.gh.common.util.ApkActiveUtils
import com.gh.common.util.LogUtils import com.gh.common.util.LogUtils
import com.gh.common.util.PackageUtils import com.gh.common.util.PackageUtils
@ -17,6 +18,8 @@ import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.EmptyResponse import com.gh.gamecenter.common.retrofit.EmptyResponse
import com.gh.gamecenter.common.retrofit.Response import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.* import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.core.utils.ToastUtils import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.core.utils.UrlFilterUtils import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.entity.GameEntity import com.gh.gamecenter.entity.GameEntity
@ -36,13 +39,48 @@ import okhttp3.ResponseBody
import org.json.JSONArray import org.json.JSONArray
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
import java.util.*
object SimulatorGameManager { object SimulatorGameManager {
private val gamePath by lazy { FileUtils.getDownloadPath(HaloApp.getInstance().application, "emulator_game") } private val mGamePath by lazy { FileUtils.getDownloadPath(HaloApp.getInstance().application, "emulator_game") }
const val SIMULATOR_UPDATE_SHOW_ALERT_TAG = "simulator-update-show-alert"
private val mSimulatorPackageNames by lazy {
listOf(
"com.gh.fbnemu",
"com.gh.mame4droid",
"com.gh.nesemu",
"com.gh.ppsspp",
"com.gh.gbaemu",
"com.gh.gbcemu",
"com.gh.snes9xplus"
)
}
const val NEW_SIMULATOR_PACKAGE_NAME = "com.gh.retroemu" //新版本模拟器包名
@JvmStatic @JvmStatic
fun getPathByType(type: String) = "${gamePath}/${type}" //是否安装了新模拟器
fun isNewSimulatorInstalled(context: Context?): Boolean {
return PackageUtils.isInstalledFromAllPackage(context, NEW_SIMULATOR_PACKAGE_NAME)
}
@JvmStatic
//是否安装了旧模拟器
fun isOldSimulatorInstalled(context: Context?): Boolean {
for (packageName in mSimulatorPackageNames) {
if (PackageUtils.isInstalledFromAllPackage(context, packageName)) {
return true
}
}
return false
}
@JvmStatic
fun getPathByType(type: String) = "${mGamePath}/${type}"
@JvmStatic @JvmStatic
fun deleteLocalGames(names: List<String>) { fun deleteLocalGames(names: List<String>) {
@ -90,16 +128,33 @@ object SimulatorGameManager {
@JvmStatic @JvmStatic
fun launchSimulatorGame(downloadEntity: DownloadEntity, gameEntity: GameEntity) { fun launchSimulatorGame(downloadEntity: DownloadEntity, gameEntity: GameEntity) {
val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(gameEntity.simulator?.apk?.packageName) val isInstalledNewSimulator = isNewSimulatorInstalled(HaloApp.getInstance().application)
val shouldShowUpdate = Version(gameEntity.simulator?.apk?.version).isHigherThan(versionFromInstalledApp) var packageName = gameEntity.simulator?.apk?.packageName
var simulator = gameEntity.simulator
if (isInstalledNewSimulator) {
packageName = NEW_SIMULATOR_PACKAGE_NAME
if (Config.getNewSimulatorEntitySetting() == null) {
return
}
simulator = Config.getNewSimulatorEntitySetting()
}
// val version = simulator?.apk?.version
// val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(packageName)
val shouldShowUpdate = PackageUtils.isInstalledApkMatchedMd5(packageName, simulator?.apk?.md5)
updateSimulatorConfigFile(gameId = gameEntity.id) updateSimulatorConfigFile(gameId = gameEntity.id)
if (shouldShowUpdate) { if (shouldShowUpdate) {
SimulatorDownloadManager.getInstance().showDownloadDialog( val showAlertTag = SPUtils.getString(SIMULATOR_UPDATE_SHOW_ALERT_TAG, "")
AppManager.getInstance().recentActiveActivity, gameEntity.simulator, val todayIsShow = showAlertTag == TimeUtils.getToday() //当天是否弹过
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name if (!todayIsShow) {
?: "" SimulatorDownloadManager.getInstance().showDownloadDialog(
) { AppManager.getInstance().recentActiveActivity, simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name
?: ""
) {
jumpToSimulator(downloadEntity, gameEntity)
}
} else {
jumpToSimulator(downloadEntity, gameEntity) jumpToSimulator(downloadEntity, gameEntity)
} }
} else { } else {
@ -109,6 +164,11 @@ object SimulatorGameManager {
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
private fun jumpToSimulator(downloadEntity: DownloadEntity, gameEntity: GameEntity) { private fun jumpToSimulator(downloadEntity: DownloadEntity, gameEntity: GameEntity) {
val isInstalledNewSimulator = isNewSimulatorInstalled(HaloApp.getInstance().application)
if (isInstalledNewSimulator){
NewSimulatorGameManager.launchGameViaSimulator(downloadEntity,gameEntity)
return
}
val gameIcon = gameEntity.icon ?: gameEntity.rawIcon ?: "" val gameIcon = gameEntity.icon ?: gameEntity.rawIcon ?: ""
Single.just(ImageUtils.getCachedUrl(gameIcon)) Single.just(ImageUtils.getCachedUrl(gameIcon))
.flatMap { .flatMap {
@ -152,7 +212,7 @@ object SimulatorGameManager {
}) })
} }
private fun getBitmapFormCache(url: String): Single<Bitmap> { fun getBitmapFormCache(url: String): Single<Bitmap> {
return Single.create { return Single.create {
ImageUtils.getBitmap(url, object : BiCallback<Bitmap, Boolean> { ImageUtils.getBitmap(url, object : BiCallback<Bitmap, Boolean> {
override fun onFirst(first: Bitmap) { override fun onFirst(first: Bitmap) {

View File

@ -248,7 +248,8 @@ public class DetailDownloadUtils {
case done: case done:
if (SimulatorGameManager.isSimulatorGame(viewHolder.gameEntity)) { if (SimulatorGameManager.isSimulatorGame(viewHolder.gameEntity)) {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(viewHolder.context, viewHolder.gameEntity.getSimulator().getApk().getPackageName()); boolean isInstalled = PackageUtils.isInstalledFromAllPackage(viewHolder.context, viewHolder.gameEntity.getSimulator().getApk().getPackageName());
if (isInstalled) { boolean isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(viewHolder.context);
if (isInstalled || isInstalledNewSimulator) {
viewHolder.mDownloadPb.setText(R.string.launch); viewHolder.mDownloadPb.setText(R.string.launch);
viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN); viewHolder.mDownloadPb.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
} else { } else {

View File

@ -14,6 +14,7 @@ import com.gh.common.exposure.ExposureEvent
import com.gh.common.filter.RegionSettingHelper import com.gh.common.filter.RegionSettingHelper
import com.gh.common.history.HistoryHelper import com.gh.common.history.HistoryHelper
import com.gh.common.repository.ReservationRepository import com.gh.common.repository.ReservationRepository
import com.gh.common.simulator.NewSimulatorGameManager
import com.gh.common.simulator.SimulatorDownloadManager import com.gh.common.simulator.SimulatorDownloadManager
import com.gh.common.simulator.SimulatorGameManager import com.gh.common.simulator.SimulatorGameManager
import com.gh.common.view.DownloadButton import com.gh.common.view.DownloadButton
@ -769,6 +770,7 @@ object DownloadItemUtils {
val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return
if (str == context.getString(R.string.download)) { if (str == context.getString(R.string.download)) {
ChainBuilder().apply { ChainBuilder().apply {
addHandler(UpdateNewSimulatorHandler())
addHandler(GamePermissionHandler()) addHandler(GamePermissionHandler())
addHandler(BrowserInstallHandler()) addHandler(BrowserInstallHandler())
addHandler(PackageCheckHandler()) addHandler(PackageCheckHandler())
@ -839,9 +841,15 @@ object DownloadItemUtils {
if (gameEntity.simulator != null) { if (gameEntity.simulator != null) {
val isInstalled = val isInstalled =
PackageUtils.isInstalledFromAllPackage(context, gameEntity.simulator!!.apk!!.packageName) PackageUtils.isInstalledFromAllPackage(context, gameEntity.simulator!!.apk!!.packageName)
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(gameEntity) && !isInstalled) { val isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(context)
val isInstalledOldSimulator = SimulatorGameManager.isOldSimulatorInstalled(context)
var simulator = gameEntity.simulator
if (!isInstalledOldSimulator) {
simulator = Config.getNewSimulatorEntitySetting()
}
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(gameEntity) && !isInstalled && !isInstalledNewSimulator) {
SimulatorDownloadManager.getInstance().showDownloadDialog( SimulatorDownloadManager.getInstance().showDownloadDialog(
context, gameEntity.simulator, context, simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name!!, null SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name!!, null
) )
return return
@ -855,9 +863,12 @@ object DownloadItemUtils {
} }
} else if (str == context.getString(R.string.launch)) { } else if (str == context.getString(R.string.launch)) {
EnergyBridge.postEnergyTask("play_game", gameEntity.id, gameEntity.getApk()[0].packageName) EnergyBridge.postEnergyTask("play_game", gameEntity.id, gameEntity.getApk()[0].packageName)
//启动模拟器游戏 //启动模拟器游戏
if (SimulatorGameManager.isSimulatorGame(gameEntity)) { if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
if (NewSimulatorGameManager.shouldShowUpdateNewSimulatorAlert(context)) {
NewSimulatorGameManager.showUpdateNewsSimulator(context, null)
return
}
val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk()[0].url) val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk()[0].url)
if (downloadEntity != null) { if (downloadEntity != null) {
val file = File(downloadEntity.path) val file = File(downloadEntity.path)
@ -865,6 +876,7 @@ object DownloadItemUtils {
download(context, gameEntity, downloadBtn, entrance, location, false, traceEvent) download(context, gameEntity, downloadBtn, entrance, location, false, traceEvent)
return return
} }
NewFlatLogUtils.logSimulatorGameCardClick("启动")
SimulatorGameManager.launchSimulatorGame(downloadEntity, gameEntity) SimulatorGameManager.launchSimulatorGame(downloadEntity, gameEntity)
} }
return return

View File

@ -1,6 +1,7 @@
package com.gh.common.util package com.gh.common.util
import android.preference.PreferenceManager import android.preference.PreferenceManager
import com.gh.common.constant.Config
import com.gh.common.exposure.ExposureUtils import com.gh.common.exposure.ExposureUtils
import com.gh.common.simulator.SimulatorDownloadManager import com.gh.common.simulator.SimulatorDownloadManager
import com.gh.common.simulator.SimulatorGameManager import com.gh.common.simulator.SimulatorGameManager
@ -239,20 +240,23 @@ object DownloadObserver {
val simulatorJson = downloadEntity.getMetaExtra(Constants.SIMULATOR) val simulatorJson = downloadEntity.getMetaExtra(Constants.SIMULATOR)
val gameName = downloadEntity.getMetaExtra(Constants.GAME_NAME) val gameName = downloadEntity.getMetaExtra(Constants.GAME_NAME)
if (simulatorJson.isEmpty()) return if (simulatorJson.isEmpty()) return
val simulator = GsonUtils.fromJson(simulatorJson, SimulatorEntity::class.java) var simulator = GsonUtils.fromJson(simulatorJson, SimulatorEntity::class.java)
val isInstalled = PackageUtils.isInstalledFromAllPackage( val isInstalled = PackageUtils.isInstalledFromAllPackage(HaloApp.getInstance().application, simulator.apk?.packageName)
HaloApp.getInstance().application, val isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(HaloApp.getInstance().application)
simulator.apk?.packageName val isInstalledOldSimulator = SimulatorGameManager.isOldSimulatorInstalled(HaloApp.getInstance().application)
) // if (!isInstalled && !isInstalledNewSimulator) {
if (!isInstalled) { val currentActivity = AppManager.getInstance().currentActivity()
val currentActivity = AppManager.getInstance().currentActivity() ?: return
?: return if (!isInstalledOldSimulator || isInstalledNewSimulator) { //如果没有安装任一旧的模拟器 或者下载了新模拟器 则使用新版本模拟器
Config.getNewSimulatorEntitySetting().let {
SimulatorDownloadManager.getInstance().showDownloadDialog( simulator = it!!
currentActivity, simulator, }
SimulatorDownloadManager.SimulatorLocation.LAUNCH, downloadEntity.gameId, gameName, null
)
} }
SimulatorDownloadManager.getInstance().showDownloadDialog(
currentActivity, simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, downloadEntity.gameId, gameName, null
)
// }
SimulatorGameManager.recordDownloadSimulatorGame(downloadEntity.gameId, simulator.type) SimulatorGameManager.recordDownloadSimulatorGame(downloadEntity.gameId, simulator.type)
SimulatorGameManager.postPlayedGame(downloadEntity.gameId, downloadEntity.packageName) SimulatorGameManager.postPlayedGame(downloadEntity.gameId, downloadEntity.packageName)
} else { } else {

View File

@ -89,7 +89,7 @@ public class GameUtils {
int installCount = 0; // 已安装数量 int installCount = 0; // 已安装数量
boolean isRelatedEmulatorInstalled = false; // 若该游戏是模拟器游戏时其对应的模拟器是否已经安装 boolean isRelatedEmulatorInstalled = false; // 若该游戏是模拟器游戏时其对应的模拟器是否已经安装
boolean isInstalledNewSimulator = false;// 是否安装新模拟器
DownloadEntity downloadEntity = null; DownloadEntity downloadEntity = null;
Object gh_id; Object gh_id;
apkFor: apkFor:
@ -138,6 +138,7 @@ public class GameUtils {
} }
} }
if (SimulatorGameManager.isSimulatorGame(gameEntity)) { if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(context);
DownloadEntity simulatorDownloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apkEntity.getUrl()); DownloadEntity simulatorDownloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apkEntity.getUrl());
if (simulatorDownloadEntity != null && gameEntity.getSimulator() != null) { if (simulatorDownloadEntity != null && gameEntity.getSimulator() != null) {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(context, gameEntity.getSimulator().getApk().getPackageName()); boolean isInstalled = PackageUtils.isInstalledFromAllPackage(context, gameEntity.getSimulator().getApk().getPackageName());
@ -150,8 +151,7 @@ public class GameUtils {
} }
} }
} }
if ((isRelatedEmulatorInstalled || isInstalledNewSimulator) && doneCount != 0) {
if (isRelatedEmulatorInstalled && doneCount != 0) {
return context.getString(R.string.launch); return context.getString(R.string.launch);
} }

View File

@ -607,4 +607,129 @@ object NewFlatLogUtils {
} }
log(json, "event", false) log(json, "event", false)
} }
//模拟器更新弹窗展示事件
@JvmStatic
fun logSimulatorUpdateAlertShow() {
val json = json {
"event" to "simulator_update_pop_show"
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//模拟器更新弹窗按钮点击事件
@JvmStatic
fun logSimulatorUpdateAlertClick(buttonText: String) {
val json = json {
"event" to "simulator_update_pop_click"
"button_type" to buttonText
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//模拟器游戏页面展示事件
@JvmStatic
fun logSimulatorGamePageShow() {
val json = json {
"event" to "simulator_game_page_show"
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//模拟器游戏类型Tab展示事件
@JvmStatic
fun logSimulatorGamePageTabClick(tabName: String) {
val json = json {
"event" to "simulator_game_tag_show"
"tab_name" to tabName
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//模拟器游戏卡片点击事件
@JvmStatic
fun logSimulatorGameCardClick(buttonText: String) {
val json = json {
"event" to "simulator_game_card_click"
"button_type" to buttonText
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//模拟器游戏合集点击事件
@JvmStatic
fun logSimulatorGameCollectionClick() {
val json = json {
"event" to "simulator_game_collection_click"
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//游戏删除提示弹窗展示事件
@JvmStatic
fun logSimulatorGameDeleteAlertShow() {
val json = json {
"event" to "simulator_delete_game_pop_show"
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//游戏删除提示弹窗点击事件
@JvmStatic
fun logSimulatorGameDeleteAlertClick(buttonText: String) {
val json = json {
"event" to "simulator_delete_game_pop_click"
"button_type" to buttonText
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//模拟器管理页面展示事件
@JvmStatic
fun logSimulatorManagerClick() {
val json = json {
"event" to "simulator_manger_page_show"
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//模拟器列表相关点击事件
fun logSimulatorListClick(buttonText: String, simulatorType: String) {
val json = json {
"event" to "simulator_list_click"
"button_type" to buttonText
"simulator_name" to simulatorType
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//模拟器卸载提示弹窗展示事件
fun logSimulatorUninstallAlertShow(simulatorType: String) {
val json = json {
"event" to "simulator_uninstall_pop_show"
"simulator_name" to simulatorType
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
//模拟器卸载提示弹窗展示事件
fun logSimulatorUninstallAlertClick(buttonText: String) {
val json = json {
"event" to "simulator_uninstall_pop_click"
"button_type" to buttonText
parseAndPutMeta().invoke(this)
}
log(json, "event", false)
}
} }

View File

@ -28,6 +28,8 @@ import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.common.constant.Constants; import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.utils.ExtensionsKt; import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.PackageFlavorHelper; import com.gh.gamecenter.common.utils.PackageFlavorHelper;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.core.utils.MD5Utils;
import com.gh.gamecenter.core.utils.SentryHelper; import com.gh.gamecenter.core.utils.SentryHelper;
import com.gh.gamecenter.entity.ApkEntity; import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity; import com.gh.gamecenter.entity.GameEntity;
@ -55,6 +57,7 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -72,6 +75,36 @@ public class PackageUtils {
private static final String TAG = "PackageUtils"; private static final String TAG = "PackageUtils";
public static String getInstallPackageInfoSourceDir(String packageName) {
try {
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).applicationInfo.sourceDir;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据packageName和模拟器apk文件的MD5去判断目标文件是否需要更新
*
* @param packageName 包名
* @param MD5Str 文件MD5
*/
public static boolean isInstalledApkMatchedMd5(String packageName, String MD5Str) {
if (MD5Str == null){
Utils.log("MD5Str is null");
return false;
}
String path = getInstallPackageInfoSourceDir(packageName);
if (path == null){
Utils.log("File path null");
return false;
}
File file = new File(path);
return !(MD5Str.equals(MD5Utils.calculateMD5(file)));
}
/* /*
* 判断是否可以更新只判断gh_version的大小 * 判断是否可以更新只判断gh_version的大小
*/ */

View File

@ -21,14 +21,17 @@ import com.gh.common.chain.DownloadDialogHelperHandler;
import com.gh.common.chain.GamePermissionHandler; import com.gh.common.chain.GamePermissionHandler;
import com.gh.common.chain.OverseaDownloadHandler; import com.gh.common.chain.OverseaDownloadHandler;
import com.gh.common.chain.PackageCheckHandler; import com.gh.common.chain.PackageCheckHandler;
import com.gh.common.chain.UpdateNewSimulatorHandler;
import com.gh.common.chain.ValidateVSpaceHandler; import com.gh.common.chain.ValidateVSpaceHandler;
import com.gh.common.chain.VersionNumberHandler; import com.gh.common.chain.VersionNumberHandler;
import com.gh.common.constant.Config;
import com.gh.common.dialog.DeviceRemindDialog; import com.gh.common.dialog.DeviceRemindDialog;
import com.gh.common.dialog.GameOffServiceDialogFragment; import com.gh.common.dialog.GameOffServiceDialogFragment;
import com.gh.common.exposure.ExposureEvent; import com.gh.common.exposure.ExposureEvent;
import com.gh.common.filter.RegionSetting; import com.gh.common.filter.RegionSetting;
import com.gh.common.filter.RegionSettingHelper; import com.gh.common.filter.RegionSettingHelper;
import com.gh.common.history.HistoryHelper; import com.gh.common.history.HistoryHelper;
import com.gh.common.simulator.NewSimulatorGameManager;
import com.gh.common.simulator.SimulatorDownloadManager; import com.gh.common.simulator.SimulatorDownloadManager;
import com.gh.common.simulator.SimulatorGameManager; import com.gh.common.simulator.SimulatorGameManager;
import com.gh.common.util.CheckLoginUtils; import com.gh.common.util.CheckLoginUtils;
@ -58,6 +61,7 @@ import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity; import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.common.entity.LinkEntity; import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.eventbus.EBReuse; import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.entity.SimulatorEntity;
import com.gh.gamecenter.eventbus.EBScroll; import com.gh.gamecenter.eventbus.EBScroll;
import com.gh.gamecenter.gamedetail.GameDetailFragment; import com.gh.gamecenter.gamedetail.GameDetailFragment;
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment; import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment;
@ -216,7 +220,10 @@ public class DetailViewHolder {
DataLogUtils.uploadGameLog(mViewHolder.context, mGameEntity.getId(), mGameEntity.getName(), mEntrance); DataLogUtils.uploadGameLog(mViewHolder.context, mGameEntity.getId(), mGameEntity.getName(), mEntrance);
} }
case PLUGIN: case PLUGIN:
ChainBuilder builder = new ChainBuilder(); ChainBuilder builder = new ChainBuilder();
builder.addHandler(new UpdateNewSimulatorHandler());
builder.addHandler(new ValidateVSpaceHandler()); builder.addHandler(new ValidateVSpaceHandler());
builder.addHandler(new GamePermissionHandler()); builder.addHandler(new GamePermissionHandler());
builder.addHandler(new CheckStoragePermissionHandler()); builder.addHandler(new CheckStoragePermissionHandler());
@ -262,6 +269,10 @@ public class DetailViewHolder {
if (mGameEntity.getApk().size() == 1) { if (mGameEntity.getApk().size() == 1) {
//启动模拟器游戏 //启动模拟器游戏
if (SimulatorGameManager.isSimulatorGame(mGameEntity)) { if (SimulatorGameManager.isSimulatorGame(mGameEntity)) {
if (NewSimulatorGameManager.shouldShowUpdateNewSimulatorAlert(mViewHolder.context)){
NewSimulatorGameManager.showUpdateNewsSimulator(mViewHolder.context, null);
return;
}
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(mGameEntity.getApk().get(0).getUrl()); DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(mGameEntity.getApk().get(0).getUrl());
if (downloadEntity != null) { if (downloadEntity != null) {
File file = new File(downloadEntity.getPath()); File file = new File(downloadEntity.getPath());
@ -301,8 +312,17 @@ public class DetailViewHolder {
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apk.getUrl()); DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(apk.getUrl());
if (mGameEntity.getSimulator() != null) { if (mGameEntity.getSimulator() != null) {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(mViewHolder.context, mGameEntity.getSimulator().getApk().getPackageName()); boolean isInstalled = PackageUtils.isInstalledFromAllPackage(mViewHolder.context, mGameEntity.getSimulator().getApk().getPackageName());
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(mGameEntity) && !isInstalled) { boolean isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(mViewHolder.context);
SimulatorDownloadManager.getInstance().showDownloadDialog(mViewHolder.context, mGameEntity.getSimulator(), boolean isInstalledOldSimulator = SimulatorGameManager.isOldSimulatorInstalled(mViewHolder.context);
SimulatorEntity simulator = mGameEntity.getSimulator();
if (!isInstalledOldSimulator){
if (Config.getNewSimulatorEntitySetting() != null){
simulator = Config.getNewSimulatorEntitySetting();
}
}
if (downloadEntity != null && SimulatorGameManager.isSimulatorGame(mGameEntity) && !isInstalled && !isInstalledNewSimulator) {
SimulatorDownloadManager.getInstance().showDownloadDialog(mViewHolder.context, simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, mGameEntity.getId(), mGameEntity.getName(), null); SimulatorDownloadManager.SimulatorLocation.LAUNCH, mGameEntity.getId(), mGameEntity.getName(), null);
return; return;
} }

View File

@ -14,6 +14,8 @@ import kotlinx.parcelize.Parcelize
data class ApkEntity( data class ApkEntity(
@SerializedName("package") @SerializedName("package")
var packageName: String = "", var packageName: String = "",
@SerializedName("_id")
var id: String = "",
var size: String? = null, var size: String? = null,
var url: String? = null, var url: String? = null,
private var platform: String? = null, private var platform: String? = null,

View File

@ -7,6 +7,7 @@ data class NewSettingsEntity(
var installModel: InstallModel? = null, var installModel: InstallModel? = null,
@SerializedName("night_mode") @SerializedName("night_mode")
var nightMode: NightMode? = null, var nightMode: NightMode? = null,
var simulator: SimulatorEntity? = null
) { ) {
data class InstallModel( data class InstallModel(
var status: String = "", var status: String = "",

View File

@ -147,6 +147,7 @@ class HaloPersonalRecommendAdapter(val context: Context) : BaseRecyclerAdapter<R
} }
} }
"模拟器游戏" -> { "模拟器游戏" -> {
NewFlatLogUtils.logSimulatorGamePageShow()
mContext.startActivity(SimulatorGameActivity.getIntent(mContext)) mContext.startActivity(SimulatorGameActivity.getIntent(mContext))
} }
"收货信息" -> { "收货信息" -> {

View File

@ -65,6 +65,7 @@ class SimulatorGameFragment : ToolbarFragment() {
if (menuItem.itemId == R.id.menu_simulator_manager) { if (menuItem.itemId == R.id.menu_simulator_manager) {
startActivity(SimulatorManagementActivity.getIntent(requireContext())) startActivity(SimulatorManagementActivity.getIntent(requireContext()))
MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击模拟器管理") MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击模拟器管理")
NewFlatLogUtils.logSimulatorManagerClick()
} }
} }
@ -142,6 +143,7 @@ class SimulatorGameFragment : ToolbarFragment() {
} }
doOnPageSelected { doOnPageSelected {
MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击${mTypeAliasList[it]}") MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击${mTypeAliasList[it]}")
NewFlatLogUtils.logSimulatorGamePageTabClick(mTypeAliasList[it])
// mCurrentPage < mFragmentsList.size 是为了防止数组越界 // mCurrentPage < mFragmentsList.size 是为了防止数组越界
if (mCurrentPage != it && mCurrentPage < mFragmentsList.size) { if (mCurrentPage != it && mCurrentPage < mFragmentsList.size) {
(mFragmentsList.safelyGetInRelease(mCurrentPage) as? SimulatorGameListFragment)?.resetPage() (mFragmentsList.safelyGetInRelease(mCurrentPage) as? SimulatorGameListFragment)?.resetPage()

View File

@ -122,15 +122,10 @@ class SimulatorGameListAdapter(
holder.binding.btnSimulator.run { holder.binding.btnSimulator.run {
if (PackageUtils.isInstalledFromAllPackage(context, simulator.apk?.packageName)) { if (PackageUtils.isInstalledFromAllPackage(context, simulator.apk?.packageName)) {
val versionFromInstalledApp = // val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator.apk?.packageName)
PackageUtils.getVersionNameByPackageName(simulator.apk?.packageName) val shouldShowUpdate = PackageUtils.isInstalledApkMatchedMd5(simulator.apk?.packageName, simulator.apk?.md5)
val shouldShowUpdate = Version(simulator.apk?.version).isHigherThan(versionFromInstalledApp) text = if (shouldShowUpdate) "更新模拟器" else ""
text = if (shouldShowUpdate) "更新模拟器" else "卸载模拟器" setTextColor(if (shouldShowUpdate) R.color.theme.toColor(mContext) else R.color.text_subtitleDesc.toColor(mContext))
setTextColor(
if (shouldShowUpdate) R.color.theme.toColor(mContext) else R.color.text_subtitleDesc.toColor(
mContext
)
)
setOnClickListener { setOnClickListener {
if (shouldShowUpdate) { if (shouldShowUpdate) {
SimulatorDownloadManager.getInstance().showDownloadDialog( SimulatorDownloadManager.getInstance().showDownloadDialog(
@ -139,25 +134,22 @@ class SimulatorGameListAdapter(
SimulatorDownloadManager.SimulatorLocation.SIMULATOR_GAME SimulatorDownloadManager.SimulatorLocation.SIMULATOR_GAME
) )
MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击${simulator.typeAlias}+更新模拟器") MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击${simulator.typeAlias}+更新模拟器")
} else {
DialogHelper.showDialog(
mContext,
"卸载模拟器",
"即将卸载模拟器,是否确定卸载?",
"确定",
"取消",
confirmClickCallback = {
PackageInstaller.uninstallForPackageName(
mContext,
simulator.apk?.packageName ?: ""
)
},
uiModificationCallback = { binding ->
binding.contentTv.setTextColor(R.color.text_title.toColor(mContext))
},
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
)
} }
// else {
// DialogHelper.showDialog(
// mContext,
// "卸载模拟器",
// "即将卸载模拟器,是否确定卸载?",
// "确定",
// "取消",
// confirmClickCallback = {
// PackageInstaller.uninstallForPackageName(mContext, simulator.apk?.packageName ?: "")
// },
// uiModificationCallback = { binding ->
// binding.contentTv.setTextColor(R.color.text_title.toColor(mContext))
// },
// extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true))
// }
} }
} else { } else {
if (simulator.active) { if (simulator.active) {
@ -267,14 +259,19 @@ class SimulatorGameListAdapter(
DialogUtils.showShortCutPermissionDialog(mContext) DialogUtils.showShortCutPermissionDialog(mContext)
createShortcut(gameEntity) createShortcut(gameEntity)
MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击${gameName}+添加到桌面") MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击${gameName}+添加到桌面")
NewFlatLogUtils.logSimulatorGameCardClick("添加到桌面")
}
"游戏详情" -> {
NewFlatLogUtils.logSimulatorGameCardClick("游戏详情")
GameDetailActivity.startGameDetailActivity(
mContext,
gameEntity.id,
"(${mEntrance})"
)
} }
"游戏详情" -> GameDetailActivity.startGameDetailActivity(
mContext,
gameEntity.id,
"(${mEntrance})"
)
"删除游戏" -> { "删除游戏" -> {
MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击${gameName}+删除游戏") MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击${gameName}+删除游戏")
NewFlatLogUtils.logSimulatorGameCardClick("删除游戏")
showDeleteSingleGameDialog(gameEntity) showDeleteSingleGameDialog(gameEntity)
} }
} }
@ -412,7 +409,9 @@ class SimulatorGameListAdapter(
} }
private fun showDeleteSingleGameDialog(gameEntity: GameEntity) { private fun showDeleteSingleGameDialog(gameEntity: GameEntity) {
NewFlatLogUtils.logSimulatorGameDeleteAlertShow()
DialogHelper.showDialog(mContext, "删除游戏", "即将删除游戏记录和本地文件,是否确定删除", "确定", "取消", { DialogHelper.showDialog(mContext, "删除游戏", "即将删除游戏记录和本地文件,是否确定删除", "确定", "取消", {
NewFlatLogUtils.logSimulatorGameDeleteAlertClick("确定")
val isNetworkConnected = NetworkUtils.isNetworkConnected(mContext) val isNetworkConnected = NetworkUtils.isNetworkConnected(mContext)
SimulatorGameManager.deleteLocalGame(gameEntity.name ?: "") SimulatorGameManager.deleteLocalGame(gameEntity.name ?: "")
if (isNetworkConnected) { if (isNetworkConnected) {
@ -434,7 +433,7 @@ class SimulatorGameListAdapter(
fragment.onLoadRefresh() fragment.onLoadRefresh()
} }
} }
}, extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)) }, cancelClickCallback = { NewFlatLogUtils.logSimulatorGameDeleteAlertClick("取消") }, extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true))
} }
fun resetPageFromFragment() { fun resetPageFromFragment() {

View File

@ -2,6 +2,9 @@ package com.gh.gamecenter.simulatorgame
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import com.gh.common.util.AdHelper
import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.download.DownloadManager import com.gh.download.DownloadManager
import com.gh.gamecenter.common.constant.EntranceConsts import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.safelyGetInRelease import com.gh.gamecenter.common.utils.safelyGetInRelease
@ -10,6 +13,9 @@ import com.gh.gamecenter.common.utils.viewModelProviderFromParent
import com.gh.gamecenter.core.AppExecutor import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.common.baselist.ListFragment import com.gh.gamecenter.common.baselist.ListFragment
import com.gh.gamecenter.common.baselist.LoadType import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.databinding.FragmentForumContentSearchListBinding
import com.gh.gamecenter.databinding.FragmentSimulatorGameListBinding
import com.gh.gamecenter.entity.GameEntity import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.SimulatorEntity import com.gh.gamecenter.entity.SimulatorEntity
import com.gh.gamecenter.game.GameAndPosition import com.gh.gamecenter.game.GameAndPosition
@ -23,6 +29,7 @@ class SimulatorGameListFragment : ListFragment<GameEntity, SimulatorGameListView
private var mAdapter: SimulatorGameListAdapter? = null private var mAdapter: SimulatorGameListAdapter? = null
private var mHaveLoad = false private var mHaveLoad = false
private lateinit var mSimulatorGameViewModel: SimulatorGameViewModel private lateinit var mSimulatorGameViewModel: SimulatorGameViewModel
private var mBinding: FragmentSimulatorGameListBinding? = null
private val dataWatcher = object : DataWatcher() { private val dataWatcher = object : DataWatcher() {
override fun onDataChanged(downloadEntity: DownloadEntity) { override fun onDataChanged(downloadEntity: DownloadEntity) {
@ -41,6 +48,12 @@ class SimulatorGameListFragment : ListFragment<GameEntity, SimulatorGameListView
} }
} }
override fun getLayoutId() = 0
override fun getInflatedLayout() =
FragmentSimulatorGameListBinding.inflate(layoutInflater).apply { mBinding = this }.root
private fun getGameEntityByPackage(packageName: String): List<GameAndPosition> { private fun getGameEntityByPackage(packageName: String): List<GameAndPosition> {
val positionList = ArrayList<GameAndPosition>() val positionList = ArrayList<GameAndPosition>()
val positionMap = mListViewModel.positionAndPackageMap val positionMap = mListViewModel.positionAndPackageMap
@ -76,6 +89,17 @@ class SimulatorGameListFragment : ListFragment<GameEntity, SimulatorGameListView
} }
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
mSimulatorGameViewModel = viewModelProviderFromParent() mSimulatorGameViewModel = viewModelProviderFromParent()
mBinding?.run {
AdHelper.getAdForLocation(AdHelper.LOCATION_SIMULATOR_GAME)?.let { ad ->
simulatorGameLayout.run {
setOnClickListener {
MtaHelper.onEvent("广告位统计", "模拟器游戏", ad.title)
NewFlatLogUtils.logSimulatorGameCollectionClick()
DirectUtils.directToLinkPage(requireContext(), ad.toLinkEntity(), "(模拟器游戏-广告位)", "")
}
}
}
}
} }
override fun provideListAdapter() = mAdapter override fun provideListAdapter() = mAdapter

View File

@ -57,21 +57,17 @@ class SimulatorManagementAdapter(
var shouldShowUpdate = false var shouldShowUpdate = false
if (isInstalled) { if (isInstalled) {
val versionFromInstalledApp = // val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator.apk?.packageName)
PackageUtils.getVersionNameByPackageName(simulator.apk?.packageName) shouldShowUpdate = PackageUtils.isInstalledApkMatchedMd5(simulator.apk?.packageName, simulator.apk?.md5)
shouldShowUpdate = Version(simulator.apk?.version).isHigherThan(versionFromInstalledApp) text = if (shouldShowUpdate) "更新" else "卸载"
text = if (shouldShowUpdate) "更新" else "已安装" setTextColor(if (shouldShowUpdate) R.color.theme.toColor(mContext) else R.color.text_subtitleDesc.toColor(mContext))
setTextColor(
if (shouldShowUpdate) R.color.theme.toColor(mContext) else R.color.text_subtitleDesc.toColor(
mContext
)
)
} else { } else {
text = "安装" text = "安装"
setTextColor(R.color.theme.toColor(mContext)) setTextColor(R.color.theme.toColor(mContext))
} }
setOnClickListener { setOnClickListener {
NewFlatLogUtils.logSimulatorListClick(text.toString(), simulator.type)
if (isInstalled) { if (isInstalled) {
if (shouldShowUpdate) { if (shouldShowUpdate) {
SimulatorDownloadManager.getInstance().showDownloadDialog( SimulatorDownloadManager.getInstance().showDownloadDialog(
@ -127,13 +123,46 @@ class SimulatorManagementAdapter(
holder.itemView.setOnClickListener { holder.itemView.setOnClickListener {
if (isInstalled && !mShowSelectFlag) { if (isInstalled && !mShowSelectFlag) {
showUnInstallWindow(position) // showUnInstallWindow(position)
showUnInstallSimulatorAlert(position)
} }
} }
} }
} }
} }
private fun showUnInstallSimulatorAlert(position: Int = -1){
val simulator = mEntityList[position]
NewFlatLogUtils.logSimulatorUninstallAlertShow(simulator.type)
DialogHelper.showDialog(
mContext,
"提示",
"卸载模拟器可能会导致对应游戏的本地存档数据丢失,请确认后操作",
"再等等",
"卸载",
confirmClickCallback = { NewFlatLogUtils.logSimulatorUninstallAlertClick("再等等") },
cancelClickCallback = {
unInstallSimulator()
NewFlatLogUtils.logSimulatorUninstallAlertClick("卸载")
},
uiModificationCallback = { binding ->
binding.cancelTv.setTextColor(R.color.theme_red.toColor(mContext))
binding.confirmTv.setTextColor(R.color.text_subtitle.toColor(mContext))
binding.contentTv.setTextColor(R.color.text_subtitle.toColor(mContext))
},
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true))
if (!mShowSelectFlag) mSingleSelectFlag = true
if (!mShowSelectFlag) {
if (mSingleSelectFlag) {
mSingleSelectedPosition = position
}
if (mSingleSelectedPosition != -1) {
notifyItemChanged(mSingleSelectedPosition)
}
}
}
private fun showUnInstallWindow(position: Int = -1) { private fun showUnInstallWindow(position: Int = -1) {
if (mPopWindow != null && mPopWindow!!.isShowing) { if (mPopWindow != null && mPopWindow!!.isShowing) {
if (!mShowSelectFlag) mSingleSelectFlag = false if (!mShowSelectFlag) mSingleSelectFlag = false
@ -158,13 +187,15 @@ class SimulatorManagementAdapter(
} else { } else {
DialogHelper.showDialog( DialogHelper.showDialog(
mContext, mContext,
"卸载模拟器", "提示",
"即将卸载模拟器,是否确定卸载?", "卸载模拟器可能会导致对应游戏的本地存档数据丢失,请确认后操作",
"确定", "再等等",
"取消", "卸载",
confirmClickCallback = { unInstallSimulator() }, cancelClickCallback = { unInstallSimulator() },
uiModificationCallback = { binding -> uiModificationCallback = { binding ->
binding.contentTv.setTextColor(R.color.text_title.toColor(mContext)) binding.cancelTv.setTextColor(R.color.theme_red.toColor(mContext))
binding.confirmTv.setTextColor(R.color.text_subtitle.toColor(mContext))
binding.contentTv.setTextColor(R.color.text_subtitle.toColor(mContext))
}, },
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true) extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
) )

View File

@ -51,14 +51,14 @@ class SimulatorManagementFragment : ListFragment<SimulatorEntity, SimulatorManag
override fun onMenuItemClick(menuItem: MenuItem) { override fun onMenuItemClick(menuItem: MenuItem) {
super.onMenuItemClick(menuItem) super.onMenuItemClick(menuItem)
if (menuItem.itemId == R.id.menu_simulator_uninstall) { if (menuItem.itemId == R.id.menu_simulator_uninstall) {
val unInstallIv = menuItem.actionView?.findViewById<ImageView>(R.id.unInstallIv) val unInstallTv = menuItem.actionView?.findViewById<TextView>(R.id.unInstallTv)
val completeTv = menuItem.actionView?.findViewById<TextView>(R.id.completeTv) val completeTv = menuItem.actionView?.findViewById<TextView>(R.id.completeTv)
val showFlag = unInstallIv?.visibility == View.VISIBLE val showFlag = unInstallTv?.visibility == View.VISIBLE
if (showFlag) { if (showFlag) {
unInstallIv?.visibility = View.GONE unInstallTv?.visibility = View.GONE
completeTv?.visibility = View.VISIBLE completeTv?.visibility = View.VISIBLE
} else { } else {
unInstallIv?.visibility = View.VISIBLE unInstallTv?.visibility = View.VISIBLE
completeTv?.visibility = View.GONE completeTv?.visibility = View.GONE
} }
mAdapter?.showUnInstallWindowAndSelectIv(showFlag) mAdapter?.showUnInstallWindowAndSelectIv(showFlag)

View File

@ -3,6 +3,8 @@ package com.gh.gamecenter.simulatorgame
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Application import android.app.Application
import android.content.pm.PackageManager import android.content.pm.PackageManager
import com.gh.common.constant.Config
import com.gh.common.simulator.SimulatorGameManager
import com.gh.gamecenter.common.utils.NetworkUtils import com.gh.gamecenter.common.utils.NetworkUtils
import com.gh.common.util.PackageUtils import com.gh.common.util.PackageUtils
import com.gh.gamecenter.common.baselist.ListViewModel import com.gh.gamecenter.common.baselist.ListViewModel
@ -32,14 +34,23 @@ class SimulatorManagementViewModel(application: Application) :
override fun provideDataSingle(page: Int): Single<List<SimulatorEntity>> { override fun provideDataSingle(page: Int): Single<List<SimulatorEntity>> {
val isNetworkConnected = NetworkUtils.isNetworkConnected(HaloApp.getInstance()) val isNetworkConnected = NetworkUtils.isNetworkConnected(HaloApp.getInstance())
val isInstalledOldSimulator = SimulatorGameManager.isOldSimulatorInstalled(HaloApp.getInstance())//有没有安装旧版本模拟器
val newSimulator = Config.getNewSimulatorEntitySetting()
var newSimulatorActive = false
if (newSimulator != null) {
newSimulatorActive = newSimulator.active
}
return if (isNetworkConnected) { return if (isNetworkConnected) {
mApi.simulators if (isInstalledOldSimulator || !newSimulatorActive) {
mApi.simulators
} else {
getNewsSimulator()
}
} else { } else {
getAllSimulator() getAllSimulator()
} }
} }
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
fun getAllSimulator(): Single<List<SimulatorEntity>> { fun getAllSimulator(): Single<List<SimulatorEntity>> {
return Single.create<List<SimulatorEntity>> { emitter -> return Single.create<List<SimulatorEntity>> { emitter ->
@ -63,4 +74,16 @@ class SimulatorManagementViewModel(application: Application) :
} }
//获取新模拟器
private fun getNewsSimulator(): Single<List<SimulatorEntity>> {
return Single.create { emitter ->
val newSimulatorList = ArrayList<SimulatorEntity>()
val simulator = Config.getNewSimulatorEntitySetting()
if (simulator != null) {
newSimulatorList.add(simulator)
}
emitter.onSuccess(newSimulatorList)
}
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android = "http://schemas.android.com/apk/res/android"
android:shape = "rectangle" >
<corners android:radius = "7dp" />
<solid android:color = "@color/divider" />
</shape >

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="0dp" android:bottom="-1dp" android:left="-1dp" android:right="-1dp" >
<shape>
<solid android:color="@color/background_white" />
<stroke
android:width="0.5dp"
android:color="@color/divider" />
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:background="@color/background">
<LinearLayout
android:id="@+id/simulatorGameLayout"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:background="@drawable/bg_top_border"
android:gravity="center">
<LinearLayout
android:id="@+id/simulatorGameSubLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:id="@+id/simulatorGameTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="模拟器游戏合集"
android:textColor="@color/text_subtitleDesc"
android:textSize="13sp" />
<LinearLayout
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_marginStart="8dp"
android:background="@drawable/bg_eeeeee_corner_7"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_go_simulator_game" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id = "@+id/list_refresh"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:layout_above="@id/simulatorGameLayout">
<androidx.recyclerview.widget.RecyclerView
android:id = "@+id/list_rv"
android:layout_width = "match_parent"
android:layout_height = "match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout >
<include
android:id="@+id/reuse_ll_loading"
layout = "@layout/reuse_loading"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_centerInParent = "true" />
<include
android:id="@+id/reuse_no_connection"
layout = "@layout/reuse_no_connection" />
<include
android:id="@+id/reuse_none_data"
layout = "@layout/reuse_none_data" />
<include
android:id="@+id/reuse_data_exception"
layout="@layout/reuse_data_exception" />
</RelativeLayout >

View File

@ -80,6 +80,7 @@
android:singleLine="true" android:singleLine="true"
android:textColor="@color/text_subtitle" android:textColor="@color/text_subtitle"
android:textSize="@dimen/tag_text_size" android:textSize="@dimen/tag_text_size"
tools:visibility="visible"
android:visibility="gone" android:visibility="gone"
app:layout_goneMarginStart="0dp" app:layout_goneMarginStart="0dp"
app:layout_constraintBottom_toBottomOf="@+id/game_name" app:layout_constraintBottom_toBottomOf="@+id/game_name"
@ -90,18 +91,18 @@
<TextView <TextView
android:id="@+id/recent_played_tag" android:id="@+id/recent_played_tag"
android:layout_width="44dp" android:layout_width="48dp"
android:layout_height="13dp" android:layout_height="14dp"
android:layout_marginLeft="4dp" android:layout_marginLeft="4dp"
android:background="@drawable/button_round_1affa142" android:background="@drawable/button_round_1affa142"
android:gravity="center" android:gravity="center"
android:text="近期玩过" android:text="近期玩过"
android:textColor="@color/text_F8A142" android:textColor="@color/theme_yellow"
android:textSize="9sp" android:textSize="10sp"
tools:visibility="visible"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/game_name" app:layout_constraintBottom_toBottomOf="@+id/game_name"
app:layout_constraintLeft_toRightOf="@+id/game_name" app:layout_constraintLeft_toRightOf="@+id/gameSubtitleTv"
app:layout_constraintRight_toLeftOf="@+id/game_kaifu_type"
app:layout_constraintTop_toTopOf="@+id/game_name" /> app:layout_constraintTop_toTopOf="@+id/game_name" />
<TextView <TextView

View File

@ -13,18 +13,20 @@
android:paddingRight="16dp" android:paddingRight="16dp"
android:orientation="horizontal"> android:orientation="horizontal">
<ImageView <TextView
android:id="@+id/unInstallIv" android:id="@+id/unInstallTv"
android:layout_width="20dp" android:layout_width="wrap_content"
android:layout_height="20dp" android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_simulator_uninstall" /> android:textColor="@color/text_subtitle"
android:textSize="14sp"
android:text="管理" />
<TextView <TextView
android:visibility="gone" android:visibility="gone"
android:id="@+id/completeTv" android:id="@+id/completeTv"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/theme_font" android:textColor="@color/text_subtitle"
android:textSize="14sp" android:textSize="14sp"
android:text="完成" /> android:text="完成" />
</LinearLayout> </LinearLayout>

View File

@ -2,29 +2,31 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="36dp" android:layout_height="40dp"
android:background="@color/F4F5F6"> android:background="@color/F4F5F6">
<TextView <TextView
android:id="@+id/btn_manager" android:id="@+id/btn_manager"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center"
android:paddingLeft="16dp" android:paddingLeft="16dp"
android:paddingRight="16dp" android:paddingRight="16dp"
android:gravity="center" android:text="管理"
android:textColor="@color/theme" android:textColor="@color/text_title"
android:textSize="12sp" android:textSize="14sp" />
android:text="管理" />
<TextView <TextView
android:id="@+id/btn_simulator" android:id="@+id/btn_simulator"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:gravity="center" android:gravity="center"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="@color/theme" android:textColor="@color/theme"
android:textSize="12sp" android:textSize="12sp"
android:visibility="gone"
tools:visibility="visible"
tools:text="安装模拟器" /> tools:text="安装模拟器" />
</RelativeLayout> </RelativeLayout>

View File

@ -13,11 +13,17 @@ private fun getJsonByAssets(fileName: String): String{
val mocks: Map<RequestFilter, MockResponse> = mapOf( val mocks: Map<RequestFilter, MockResponse> = mapOf(
RequestFilter("/v5d5d0/home/union") to MockResponse().apply { // RequestFilter("/v5d5d0/home/union") to MockResponse().apply {
// setResponseCode(200)
// setBody(
// getJsonByAssets("home_union.json")
// )
// },
RequestFilter("/settings") to MockResponse().apply {
setResponseCode(200) setResponseCode(200)
setBody( setBody(
getJsonByAssets("home_union.json") getJsonByAssets("new_simulator.json")
) )
} },
) )

View File

@ -128,6 +128,7 @@ public class MD5Utils {
String output = bigInt.toString(16); String output = bigInt.toString(16);
// Fill to 32 chars // Fill to 32 chars
output = String.format("%32s", output).replace(' ', '0'); output = String.format("%32s", output).replace(' ', '0');
Utils.log("MD5:::", output);
return output; return output;
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Unable to process file for MD5", e); throw new RuntimeException("Unable to process file for MD5", e);

View File

@ -22,6 +22,20 @@ object TimeUtils {
return formatter.format(date) return formatter.format(date)
} }
/**
* 获取昨天日期
*/
@JvmStatic
fun getYesterday(): String {
var date = Date()
val calendar = GregorianCalendar()
calendar.time = date
calendar.add(GregorianCalendar.DATE, -1)
date = calendar.time
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
return formatter.format(date)
}
@JvmStatic @JvmStatic
fun getFormatTime(time: Long, pattern: String = "yyyy-MM-dd"): String { fun getFormatTime(time: Long, pattern: String = "yyyy-MM-dd"): String {
val f = SimpleDateFormat(pattern, Locale.CHINA) val f = SimpleDateFormat(pattern, Locale.CHINA)