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.SettingsEntity;
import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.entity.SimulatorEntity;
import com.gh.gamecenter.entity.VSetting;
import com.gh.gamecenter.common.retrofit.BiResponse;
import com.gh.gamecenter.common.retrofit.Response;
@ -65,6 +66,7 @@ public class Config {
private static NewSettingsEntity mNewSettingsEntity;
private static NewSettingsEntity.NightMode mNightModeSetting;
private static SimulatorEntity mNewSimulatorEntity;
private static VSetting mVSetting;
private static GameGuidePopupEntity mGameGuidePopupEntity;
private static SharedPreferences mDefaultSharedPreferences;
@ -220,6 +222,18 @@ public class Config {
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
public static NewSettingsEntity.NightMode getNightModeSetting() {
if (mNightModeSetting != null) {
@ -370,7 +384,7 @@ public class Config {
});
}
if (mNightModeSetting == null) {
if (mNightModeSetting == null && mNewSimulatorEntity == null) {
RetrofitManager.getInstance()
.getNewApi().getNewSettings(PackageUtils.getGhVersionName(), channel)
.subscribeOn(Schedulers.io())
@ -379,6 +393,7 @@ public class Config {
@Override
public void onSuccess(NewSettingsEntity data) {
mNightModeSetting = data.getNightMode();
mNewSimulatorEntity = data.getSimulator();
if (HaloApp.getInstance().isNewForThisVersion && mNightModeSetting != null && mNightModeSetting.getInstall()) {
DarkModeUtils.INSTANCE.updateFollowSystemDarkModeToSp(true);
DarkModeUtils.INSTANCE.updateAppDarkModeStatusToSp(true);
@ -386,6 +401,7 @@ public class Config {
}
if (mNewSettingsEntity != null) {
mNewSettingsEntity.setSimulator(mNewSimulatorEntity);
mNewSettingsEntity.setNightMode(mNightModeSetting);
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 com.g00fy2.versioncompare.Version
import com.gh.common.util.LogUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.PackageInstaller
import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager
@ -137,8 +138,6 @@ class SimulatorDownloadManager private constructor() {
cancelCallback: (() -> Unit)? = null
) {
if (context == null) return
mContextRef = WeakReference(context)
this.simulatorLocation = location
this.simulator = simulator
this.gameId = gameId
@ -152,20 +151,30 @@ class SimulatorDownloadManager private constructor() {
return
}
val isInstalled = PackageUtils.isInstalledFromAllPackage(context, simulator?.apk?.packageName)
val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator?.apk?.packageName)
val shouldShowUpdate = Version(simulator?.apk?.version).isHigherThan(versionFromInstalledApp)
// val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator?.apk?.packageName)
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 message = if (shouldShowUpdate && isInstalled) "检测到模拟器存在更高版本,是否前往更新" else "模拟器游戏需要先下载安装对应的模拟器,才可以运行"
val positiveText =
if (shouldShowUpdate && isInstalled) "更新(${simulator?.apk?.size}" else "下载(${simulator?.apk?.size}"
val negativeText = if (shouldShowUpdate && isInstalled) "下次再说" else "取消"
downloadType = if (shouldShowUpdate && isInstalled) "update" else "download"
val trackableEntity = TrackableEntity(
"模拟器下载",
key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗",
logShowEvent = true
)
if (shouldShowUpdate && isInstalled) {
NewFlatLogUtils.logSimulatorUpdateAlertShow()
}
DialogHelper.showDialog(
context,
title,
@ -176,11 +185,13 @@ class SimulatorDownloadManager private constructor() {
cancelClickCallback = {
if (shouldShowUpdate && isInstalled) {
cancelCallback?.invoke()
NewFlatLogUtils.logSimulatorUpdateAlertClick("取消")
MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说")
}
},
confirmClickCallback = {
showDownloadingDialog(context, simulator)
NewFlatLogUtils.logSimulatorUpdateAlertClick("更新")
MtaHelper.onEvent(
trackableEntity.event,
trackableEntity.key,
@ -190,11 +201,15 @@ class SimulatorDownloadManager private constructor() {
mtaEvent = trackableEntity.event, mtaKey = trackableEntity.key,
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)
if (!msg.isNullOrEmpty()) {
Utils.toast(context, msg)

View File

@ -2,11 +2,12 @@ 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.net.Uri
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.LogUtils
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.Response
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.UrlFilterUtils
import com.gh.gamecenter.entity.GameEntity
@ -36,13 +39,48 @@ import okhttp3.ResponseBody
import org.json.JSONArray
import java.io.ByteArrayOutputStream
import java.io.File
import java.util.*
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
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
fun deleteLocalGames(names: List<String>) {
@ -90,16 +128,33 @@ object SimulatorGameManager {
@JvmStatic
fun launchSimulatorGame(downloadEntity: DownloadEntity, gameEntity: GameEntity) {
val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(gameEntity.simulator?.apk?.packageName)
val shouldShowUpdate = Version(gameEntity.simulator?.apk?.version).isHigherThan(versionFromInstalledApp)
val isInstalledNewSimulator = isNewSimulatorInstalled(HaloApp.getInstance().application)
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)
if (shouldShowUpdate) {
SimulatorDownloadManager.getInstance().showDownloadDialog(
AppManager.getInstance().recentActiveActivity, gameEntity.simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name
?: ""
) {
val showAlertTag = SPUtils.getString(SIMULATOR_UPDATE_SHOW_ALERT_TAG, "")
val todayIsShow = showAlertTag == TimeUtils.getToday() //当天是否弹过
if (!todayIsShow) {
SimulatorDownloadManager.getInstance().showDownloadDialog(
AppManager.getInstance().recentActiveActivity, simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, gameEntity.id, gameEntity.name
?: ""
) {
jumpToSimulator(downloadEntity, gameEntity)
}
} else {
jumpToSimulator(downloadEntity, gameEntity)
}
} else {
@ -109,6 +164,11 @@ object SimulatorGameManager {
@SuppressLint("CheckResult")
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 ?: ""
Single.just(ImageUtils.getCachedUrl(gameIcon))
.flatMap {
@ -152,7 +212,7 @@ object SimulatorGameManager {
})
}
private fun getBitmapFormCache(url: String): Single<Bitmap> {
fun getBitmapFormCache(url: String): Single<Bitmap> {
return Single.create {
ImageUtils.getBitmap(url, object : BiCallback<Bitmap, Boolean> {
override fun onFirst(first: Bitmap) {

View File

@ -248,7 +248,8 @@ public class DetailDownloadUtils {
case done:
if (SimulatorGameManager.isSimulatorGame(viewHolder.gameEntity)) {
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.setButtonStyle(DownloadButton.ButtonStyle.LAUNCH_OR_OPEN);
} else {

View File

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

View File

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

View File

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

View File

@ -607,4 +607,129 @@ object NewFlatLogUtils {
}
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.utils.ExtensionsKt;
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.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity;
@ -55,6 +57,7 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
@ -72,6 +75,36 @@ public class 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的大小
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,9 @@ package com.gh.gamecenter.simulatorgame
import android.os.Bundle
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.gamecenter.common.constant.EntranceConsts
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.common.baselist.ListFragment
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.SimulatorEntity
import com.gh.gamecenter.game.GameAndPosition
@ -23,6 +29,7 @@ class SimulatorGameListFragment : ListFragment<GameEntity, SimulatorGameListView
private var mAdapter: SimulatorGameListAdapter? = null
private var mHaveLoad = false
private lateinit var mSimulatorGameViewModel: SimulatorGameViewModel
private var mBinding: FragmentSimulatorGameListBinding? = null
private val dataWatcher = object : DataWatcher() {
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> {
val positionList = ArrayList<GameAndPosition>()
val positionMap = mListViewModel.positionAndPackageMap
@ -76,6 +89,17 @@ class SimulatorGameListFragment : ListFragment<GameEntity, SimulatorGameListView
}
super.onCreate(savedInstanceState)
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

View File

@ -57,21 +57,17 @@ class SimulatorManagementAdapter(
var shouldShowUpdate = false
if (isInstalled) {
val versionFromInstalledApp =
PackageUtils.getVersionNameByPackageName(simulator.apk?.packageName)
shouldShowUpdate = Version(simulator.apk?.version).isHigherThan(versionFromInstalledApp)
text = if (shouldShowUpdate) "更新" else "已安装"
setTextColor(
if (shouldShowUpdate) R.color.theme.toColor(mContext) else R.color.text_subtitleDesc.toColor(
mContext
)
)
// val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator.apk?.packageName)
shouldShowUpdate = PackageUtils.isInstalledApkMatchedMd5(simulator.apk?.packageName, simulator.apk?.md5)
text = if (shouldShowUpdate) "更新" else "卸载"
setTextColor(if (shouldShowUpdate) R.color.theme.toColor(mContext) else R.color.text_subtitleDesc.toColor(mContext))
} else {
text = "安装"
setTextColor(R.color.theme.toColor(mContext))
}
setOnClickListener {
NewFlatLogUtils.logSimulatorListClick(text.toString(), simulator.type)
if (isInstalled) {
if (shouldShowUpdate) {
SimulatorDownloadManager.getInstance().showDownloadDialog(
@ -127,13 +123,46 @@ class SimulatorManagementAdapter(
holder.itemView.setOnClickListener {
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) {
if (mPopWindow != null && mPopWindow!!.isShowing) {
if (!mShowSelectFlag) mSingleSelectFlag = false
@ -158,13 +187,15 @@ class SimulatorManagementAdapter(
} else {
DialogHelper.showDialog(
mContext,
"卸载模拟器",
"即将卸载模拟器,是否确定卸载?",
"确定",
"取消",
confirmClickCallback = { unInstallSimulator() },
"提示",
"卸载模拟器可能会导致对应游戏的本地存档数据丢失,请确认后操作",
"再等等",
"卸载",
cancelClickCallback = { unInstallSimulator() },
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)
)

View File

@ -51,14 +51,14 @@ class SimulatorManagementFragment : ListFragment<SimulatorEntity, SimulatorManag
override fun onMenuItemClick(menuItem: MenuItem) {
super.onMenuItemClick(menuItem)
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 showFlag = unInstallIv?.visibility == View.VISIBLE
val showFlag = unInstallTv?.visibility == View.VISIBLE
if (showFlag) {
unInstallIv?.visibility = View.GONE
unInstallTv?.visibility = View.GONE
completeTv?.visibility = View.VISIBLE
} else {
unInstallIv?.visibility = View.VISIBLE
unInstallTv?.visibility = View.VISIBLE
completeTv?.visibility = View.GONE
}
mAdapter?.showUnInstallWindowAndSelectIv(showFlag)

View File

@ -3,6 +3,8 @@ package com.gh.gamecenter.simulatorgame
import android.annotation.SuppressLint
import android.app.Application
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.common.util.PackageUtils
import com.gh.gamecenter.common.baselist.ListViewModel
@ -32,14 +34,23 @@ class SimulatorManagementViewModel(application: Application) :
override fun provideDataSingle(page: Int): Single<List<SimulatorEntity>> {
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) {
mApi.simulators
if (isInstalledOldSimulator || !newSimulatorActive) {
mApi.simulators
} else {
getNewsSimulator()
}
} else {
getAllSimulator()
}
}
@SuppressLint("CheckResult")
fun getAllSimulator(): Single<List<SimulatorEntity>> {
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:textColor="@color/text_subtitle"
android:textSize="@dimen/tag_text_size"
tools:visibility="visible"
android:visibility="gone"
app:layout_goneMarginStart="0dp"
app:layout_constraintBottom_toBottomOf="@+id/game_name"
@ -90,18 +91,18 @@
<TextView
android:id="@+id/recent_played_tag"
android:layout_width="44dp"
android:layout_height="13dp"
android:layout_width="48dp"
android:layout_height="14dp"
android:layout_marginLeft="4dp"
android:background="@drawable/button_round_1affa142"
android:gravity="center"
android:text="近期玩过"
android:textColor="@color/text_F8A142"
android:textSize="9sp"
android:textColor="@color/theme_yellow"
android:textSize="10sp"
tools:visibility="visible"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/game_name"
app:layout_constraintLeft_toRightOf="@+id/game_name"
app:layout_constraintRight_toLeftOf="@+id/game_kaifu_type"
app:layout_constraintLeft_toRightOf="@+id/gameSubtitleTv"
app:layout_constraintTop_toTopOf="@+id/game_name" />
<TextView

View File

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

View File

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

View File

@ -13,11 +13,17 @@ private fun getJsonByAssets(fileName: String): String{
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)
setBody(
getJsonByAssets("home_union.json")
getJsonByAssets("new_simulator.json")
)
}
},
)

View File

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

View File

@ -22,6 +22,20 @@ object TimeUtils {
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
fun getFormatTime(time: Long, pattern: String = "yyyy-MM-dd"): String {
val f = SimpleDateFormat(pattern, Locale.CHINA)