Compare commits
69 Commits
feature-GH
...
v5.29.0-93
| Author | SHA1 | Date | |
|---|---|---|---|
| 3a15f9af33 | |||
| 6920d682b2 | |||
| b0493502e4 | |||
| 723202d4ce | |||
| 6e0628b478 | |||
| 7f14555886 | |||
| c2477d2a3f | |||
| 8ff4945cfa | |||
| fcc65fdbfe | |||
| d4b0ecce98 | |||
| 848ca0b5c6 | |||
| 4f0c81420e | |||
| 0c437d32bd | |||
| 25d9771a3c | |||
| 668b54ac6d | |||
| 92b0f8fe73 | |||
| f689dfce07 | |||
| 42d5d46e53 | |||
| cdccc35703 | |||
| d3e2fea019 | |||
| f343841233 | |||
| f62083eff2 | |||
| 8594e998c2 | |||
| 6865706b0f | |||
| bfb8b46ce8 | |||
| b6d8ca4d84 | |||
| 455e1f0432 | |||
| ba27c09096 | |||
| 15276cc4b3 | |||
| 130a7cdf2a | |||
| 164ec0c368 | |||
| 756bc66f26 | |||
| e589bce5c6 | |||
| 991bd22511 | |||
| df1ab5221d | |||
| 70916fd0f7 | |||
| 226d6c4f2c | |||
| 896adc9d36 | |||
| 0e33abebdd | |||
| c8ed126605 | |||
| b510a329b6 | |||
| 2de1ba4e1d | |||
| e4a0f0e68b | |||
| c064f9d3a6 | |||
| 759401d9ae | |||
| e56209d15e | |||
| c466ff1f21 | |||
| e09cf299f0 | |||
| 25352ba609 | |||
| 3cd065cb6e | |||
| 5a483bb5db | |||
| 3b380c6fe3 | |||
| 919a98ffe6 | |||
| eff84218a8 | |||
| 7c9c363422 | |||
| add6448f44 | |||
| efccfaaa7f | |||
| a61057ae10 | |||
| 9472cafe48 | |||
| be83e1a2b4 | |||
| e48d7745b4 | |||
| 8b1a38214c | |||
| 2acde0af00 | |||
| daab20424e | |||
| 63f2adade2 | |||
| 201c1207f9 | |||
| 75d86b5a91 | |||
| f30d647936 | |||
| c7dd449899 |
@ -11,6 +11,9 @@ android {
|
||||
|
||||
String CONFIG_ID = ""
|
||||
String FIRST_LAUNCH = ""
|
||||
String SDK_VERSION = ""
|
||||
String SDK_APP_ID = ""
|
||||
String SDK_APP_NAME = ""
|
||||
int ACTIVATE_REPORTING_RATIO = 100
|
||||
|
||||
buildFeatures {
|
||||
@ -79,6 +82,11 @@ android {
|
||||
// 推广用的配置 id
|
||||
buildConfigField "String", "CONFIG_ID", "\"${CONFIG_ID}\""
|
||||
|
||||
// 推广用的 SDK 版本 (仅记录使用)
|
||||
buildConfigField "String", "SDK_VERSION", "\"${SDK_VERSION}\""
|
||||
buildConfigField "String", "SDK_APP_ID", "\"${SDK_APP_ID}\""
|
||||
buildConfigField "String", "SDK_APP_NAME", "\"${SDK_APP_NAME}\""
|
||||
|
||||
// 首次启动的跳转配置
|
||||
buildConfigField "String", "FIRST_LAUNCH", "\"${FIRST_LAUNCH}\""
|
||||
|
||||
@ -206,17 +214,11 @@ android {
|
||||
kuaishou {
|
||||
dimension "env"
|
||||
|
||||
String KUAI_SHOU_APP_ID = ""
|
||||
String KUAI_SHOU_APP_NAME = ""
|
||||
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
|
||||
buildConfigField "String", "KUAI_SHOU_APP_ID", "\"${KUAI_SHOU_APP_ID}\""
|
||||
buildConfigField "String", "KUAI_SHOU_APP_NAME", "\"${KUAI_SHOU_APP_NAME}\""
|
||||
}
|
||||
|
||||
gdt {
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
-keep class com.gh.gamecenter.db.info.* {*;}
|
||||
-keep class com.gh.gamecenter.entity.** {<fields>;}
|
||||
-keep class com.gh.gamecenter.qa.entity.** {<fields>;}
|
||||
-keep class com.gh.download.DownloadDataSimpleEntity {<fields>;}
|
||||
-keep class com.gh.gamecenter.floatingwindow.FloatingWindowEntity {<fields>;}
|
||||
-keep class com.gh.gamecenter.BR
|
||||
-keep class com.gh.gamecenter.retrofit.* {*;}
|
||||
|
||||
@ -5,8 +5,8 @@ import com.kwai.monitor.log.TurboAgent
|
||||
import com.kwai.monitor.log.TurboConfig
|
||||
|
||||
object KuaishouHelper {
|
||||
private val mAppId by lazy { BuildConfig.KUAI_SHOU_APP_ID.ifEmpty { "81537" } }
|
||||
private val mAppName by lazy { BuildConfig.KUAI_SHOU_APP_NAME.ifEmpty { "guanghuanzhushou_1" } }
|
||||
private val mAppId by lazy { BuildConfig.SDK_APP_ID.ifEmpty { "81537" } }
|
||||
private val mAppName by lazy { BuildConfig.SDK_APP_NAME.ifEmpty { "guanghuanzhushou_1" } }
|
||||
|
||||
@JvmStatic
|
||||
fun init(context: Context, channel: String) {
|
||||
|
||||
@ -3,10 +3,13 @@ package com.gh.gamecenter.provider
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.KuaishouHelper
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.kwai.monitor.payload.TurboHelper
|
||||
|
||||
@ -44,6 +47,11 @@ class FlavorProviderImp : IFlavorProvider {
|
||||
|
||||
override fun logCoreEvent() {
|
||||
logEvent("EVENT_KEY_PATH_OPTIMIZATION")
|
||||
if (BuildConfig.ACTIVATE_REPORTING_RATIO == 1) {
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast("关键行为 EVENT_KEY_PATH_OPTIMIZATION")
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@ -830,8 +830,9 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
<activity
|
||||
android:name="com.gh.common.xapk.XapkInstallReceiver"
|
||||
android:theme="@style/Theme.Transparent"
|
||||
android:exported="false" />
|
||||
|
||||
<receiver
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
package com.gh.common.chain
|
||||
|
||||
import android.content.Context
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
|
||||
class AutoSwitchAssistantInstallHandler : ChainHandler() {
|
||||
|
||||
override fun handleRequest(context: Context, gameEntity: GameEntity) {
|
||||
if (BrowserInstallHelper.isUseBrowserToInstallEnabled()
|
||||
&& BrowserInstallHelper.shouldUseBrowserToInstall()
|
||||
&& gameEntity.isSplitXApk()) {
|
||||
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint))
|
||||
}
|
||||
if (hasNext()) {
|
||||
getNext()?.handleRequest(context, gameEntity)
|
||||
} else {
|
||||
processEndCallback?.invoke(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.databind;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
@ -19,7 +20,6 @@ import androidx.core.content.ContextCompat;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.common.chain.AutoSwitchAssistantInstallHandler;
|
||||
import com.gh.common.chain.BrowserInstallHandler;
|
||||
import com.gh.common.chain.CertificationHandler;
|
||||
import com.gh.common.chain.ChainBuilder;
|
||||
@ -52,6 +52,7 @@ import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.download.server.BrowserInstallHelper;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
@ -66,6 +67,7 @@ import com.gh.gamecenter.common.view.DrawableView;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.gamecenter.core.utils.NumberUtils;
|
||||
import com.gh.gamecenter.core.utils.ToastUtils;
|
||||
import com.gh.gamecenter.databinding.KaifuDetailItemRowBinding;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.CommunityVideoEntity;
|
||||
@ -414,7 +416,7 @@ public class BindingAdapters {
|
||||
builder.addHandler(new CheckDownloadHandler());
|
||||
|
||||
builder.setProcessEndCallback(o -> {
|
||||
download(progressBar, gameEntity, traceEvent, (boolean) o, entrance, location);
|
||||
download(v.getContext(), progressBar, gameEntity, traceEvent, (boolean) o, entrance, location);
|
||||
return null;
|
||||
});
|
||||
final ChainHandler chainHandler = builder.buildHandlerChain();
|
||||
@ -452,7 +454,7 @@ public class BindingAdapters {
|
||||
if (downloadEntity != null) {
|
||||
File file = new File(downloadEntity.getPath());
|
||||
if (!file.exists()) {
|
||||
download(progressBar, gameEntity, traceEvent, false, entrance, location);
|
||||
download(v.getContext(), progressBar, gameEntity, traceEvent, false, entrance, location);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -678,12 +680,16 @@ public class BindingAdapters {
|
||||
|
||||
|
||||
// 开始下载
|
||||
private static void download(DownloadButton progressBar,
|
||||
private static void download(Context context,
|
||||
DownloadButton progressBar,
|
||||
GameEntity gameEntity,
|
||||
ExposureEvent traceEvent,
|
||||
boolean isSubscribe,
|
||||
String entrance,
|
||||
String location) {
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint));
|
||||
}
|
||||
String str = progressBar.getText().toString();
|
||||
String method;
|
||||
if (str.contains("更新")) {
|
||||
|
||||
@ -47,7 +47,7 @@ object ExposureManager {
|
||||
fun log(eventList: List<ExposureEvent>) {
|
||||
AppExecutor.logExecutor.execute {
|
||||
for (event in eventList) {
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
if (event != null && !exposureCache.contains(event.id)) {
|
||||
exposureSet.add(event)
|
||||
exposureCache.add(event.id)
|
||||
} else {
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IAppProvider
|
||||
@ -70,6 +71,10 @@ class AppProviderImpl : IAppProvider {
|
||||
return HaloApp.getInstance().flavorProvider
|
||||
}
|
||||
|
||||
override fun getFlavor(): String {
|
||||
return BuildConfig.FLAVOR
|
||||
}
|
||||
|
||||
override fun getIsBrandNewInstall(): Boolean {
|
||||
return HaloApp.getInstance().isBrandNewInstall
|
||||
}
|
||||
|
||||
@ -341,7 +341,7 @@ object DirectUtils {
|
||||
|
||||
"feedback" -> directToFeedback(context, linkEntity.name, linkEntity.text, false, "", entrance)
|
||||
|
||||
"qa", "Q&A" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "")
|
||||
"qa", "qa_content", "Q&A" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "")
|
||||
|
||||
"qa_collection", "Q&A合集" -> directToQaCollection(
|
||||
context, linkEntity.text
|
||||
|
||||
@ -31,6 +31,7 @@ import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation
|
||||
@ -1014,10 +1015,13 @@ object DownloadItemUtils {
|
||||
isSubscribe,
|
||||
traceEvent
|
||||
)
|
||||
ToastUtils.toast(gameEntity.name + "已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint))
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
Utils.toast(context, gameEntity.name + "已加入下载队列")
|
||||
if (downloadBtn is DownloadButton) {
|
||||
downloadBtn.text = "0%"
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
|
||||
@ -1041,10 +1045,13 @@ object DownloadItemUtils {
|
||||
val msg = FileUtils.isCanDownload(context, gameEntity.getApk()[0].size ?: "")
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DownloadManager.createDownload(context, gameEntity, "插件化", entrance, location, isSubscribe, traceEvent)
|
||||
ToastUtils.toast(gameEntity.name + "已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint))
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
Utils.toast(context, gameEntity.name + "已加入下载队列")
|
||||
if (downloadBtn is DownloadButton) {
|
||||
downloadBtn.setText(R.string.downloading)
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN
|
||||
|
||||
@ -39,8 +39,11 @@ object DownloadObserver {
|
||||
// TODO 修复因为更改内存对象造成的双重下载完成事件问题,具体触发代码见 DownloadDao.updateSnapshotList
|
||||
private var mDoneDebouncePair: Pair<String, Long>? = null
|
||||
|
||||
private const val TAG = "DownloadObserver"
|
||||
private const val CORE_EVENT_DOWNLOAD_COMPLETE_LOGGED = "CORE_EVENT_DOWNLOAD_COMPLETE_LOGGED"
|
||||
|
||||
private val mRetryableHashMap = hashMapOf<String, Boolean>()
|
||||
|
||||
// 如果在WIFI状态下,下载自动暂停,则再重试一遍
|
||||
@JvmStatic
|
||||
fun initObserver() {
|
||||
@ -70,28 +73,34 @@ object DownloadObserver {
|
||||
|
||||
val currentActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
|
||||
DialogHelper.showDialog(currentActivity, "下载失败", "下载链接已失效,建议提交反馈", "立即反馈", "取消", {
|
||||
HelpAndFeedbackBridge.startSuggestionActivity(
|
||||
currentActivity,
|
||||
SuggestType.gameQuestion, "notfound",
|
||||
StringUtils.buildString(downloadEntity.name, ",问题反馈:下载链接失效"),
|
||||
SimpleGameEntity(gameId, downloadEntity.name, "")
|
||||
)
|
||||
}, extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true))
|
||||
DialogHelper.showDialog(
|
||||
currentActivity,
|
||||
"下载失败",
|
||||
"下载链接已失效,建议提交反馈",
|
||||
"立即反馈",
|
||||
"取消",
|
||||
{
|
||||
HelpAndFeedbackBridge.startSuggestionActivity(
|
||||
currentActivity,
|
||||
SuggestType.gameQuestion, "notfound",
|
||||
StringUtils.buildString(downloadEntity.name, ",问题反馈:下载链接失效"),
|
||||
SimpleGameEntity(gameId, downloadEntity.name, "")
|
||||
)
|
||||
},
|
||||
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
return
|
||||
} else if (DownloadStatus.neterror == downloadEntity.status
|
||||
|| DownloadStatus.timeout == downloadEntity.status
|
||||
|| DownloadStatus.diskioerror == downloadEntity.status
|
||||
|| DownloadStatus.diskisfull == downloadEntity.status) {
|
||||
if (downloadEntity.meta[Constants.MARK_RETRY_DOWNLOAD].isNullOrEmpty()
|
||||
|| DownloadStatus.diskisfull == downloadEntity.status
|
||||
) {
|
||||
if (mRetryableHashMap[downloadEntity.url] == true
|
||||
&& NetworkUtils.isWifiConnected(HaloApp.getInstance().application)
|
||||
) {
|
||||
downloadEntity.meta[Constants.MARK_RETRY_DOWNLOAD] = downloadEntity.progress.toString()
|
||||
downloadManager.updateDownloadEntity(downloadEntity)
|
||||
downloadManager.resumeDownload(downloadEntity.url)
|
||||
debugOnly {
|
||||
Utils.log("DownloadObserver", "下载重试->" + downloadEntity.toJson())
|
||||
}
|
||||
mRetryableHashMap[downloadEntity.url] = false
|
||||
Utils.log(TAG, "下载重试->" + downloadEntity.toJson())
|
||||
} else {
|
||||
if (DownloadStatus.diskisfull == downloadEntity.status) {
|
||||
ToastUtils.toast("磁盘已满,请清理空间后重试下载")
|
||||
@ -102,13 +111,10 @@ object DownloadObserver {
|
||||
}
|
||||
|
||||
DataLogUtils.uploadNeterrorLog(mApplication, downloadEntity)
|
||||
|
||||
debugOnly {
|
||||
Utils.log("DownloadObserver", "下载自动暂停->" + downloadEntity.toJson())
|
||||
}
|
||||
Utils.log(TAG, "下载自动暂停->" + downloadEntity.toJson())
|
||||
}
|
||||
} else if (DownloadStatus.redirected == downloadEntity.status) {
|
||||
debugOnly { Utils.log("重定向完毕") }
|
||||
Utils.log(TAG, "重定向完毕")
|
||||
DownloadDataHelper.uploadRedirectEvent(downloadEntity)
|
||||
} else if (DownloadStatus.unqualified == downloadEntity.status) {
|
||||
// 未成年
|
||||
@ -153,40 +159,35 @@ object DownloadObserver {
|
||||
if (DownloadStatus.done == downloadEntity.status) {
|
||||
if (mDoneDebouncePair?.first != downloadEntity.url) {
|
||||
mDoneDebouncePair = Pair(downloadEntity.url, System.currentTimeMillis())
|
||||
performDownloadCompleteAction(downloadEntity, gameId, downloadManager)
|
||||
performDownloadCompleteAction(downloadEntity, downloadManager)
|
||||
} else {
|
||||
if (mDoneDebouncePair?.second == 0L
|
||||
|| System.currentTimeMillis() - (mDoneDebouncePair?.second ?: 0) > 500
|
||||
) {
|
||||
performDownloadCompleteAction(downloadEntity, gameId, downloadManager)
|
||||
performDownloadCompleteAction(downloadEntity, downloadManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadEntity.status == DownloadStatus.done) {
|
||||
mRetryableHashMap.remove(downloadEntity.url)
|
||||
|
||||
EventBus.getDefault().post(EBDownloadStatus("done", "", "", "", downloadEntity.packageName, ""))
|
||||
}
|
||||
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
|
||||
// 如果已下载大小发生变化,表示成功恢复下载,则重置重试标记
|
||||
if (downloadEntity.status == DownloadStatus.downloading &&
|
||||
downloadEntity.progress.toString() != downloadEntity.meta[Constants.MARK_RETRY_DOWNLOAD]
|
||||
) {
|
||||
downloadEntity.meta[Constants.MARK_RETRY_DOWNLOAD] = ""
|
||||
downloadManager.updateDownloadEntity(downloadEntity)
|
||||
if (downloadEntity.status == DownloadStatus.downloading) {
|
||||
mRetryableHashMap[downloadEntity.url] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加观察者
|
||||
DownloadManager.getInstance().addObserver(dataWatcher)
|
||||
|
||||
}
|
||||
|
||||
private fun performDownloadCompleteAction(
|
||||
downloadEntity: DownloadEntity,
|
||||
gameId: String,
|
||||
downloadManager: DownloadManager
|
||||
) {
|
||||
if (downloadEntity.name.contains(mApplication.getString(R.string.app_name))) {
|
||||
@ -221,10 +222,12 @@ object DownloadObserver {
|
||||
downloadEntity.pluginDesc
|
||||
)
|
||||
)
|
||||
|
||||
downloadEntity.isPlugin -> Utils.toast(
|
||||
mApplication,
|
||||
downloadEntity.name + " - " + platform + " - 下载完成"
|
||||
)
|
||||
|
||||
else -> {
|
||||
if (!downloadEntity.isVGame()) {
|
||||
Utils.toast(mApplication, downloadEntity.name + " - 下载完成")
|
||||
@ -242,15 +245,10 @@ object DownloadObserver {
|
||||
val gameName = downloadEntity.getMetaExtra(Constants.GAME_NAME)
|
||||
if (simulatorJson.isEmpty()) return
|
||||
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
|
||||
val newSimulator = Config.getNewSimulatorEntitySetting()
|
||||
@ -261,7 +259,6 @@ object DownloadObserver {
|
||||
currentActivity, simulator,
|
||||
SimulatorDownloadManager.SimulatorLocation.LAUNCH, downloadEntity.gameId, gameName, null
|
||||
)
|
||||
// }
|
||||
SimulatorGameManager.recordDownloadSimulatorGame(downloadEntity.gameId, simulator.type)
|
||||
SimulatorGameManager.postPlayedGame(downloadEntity.gameId, downloadEntity.packageName)
|
||||
} else {
|
||||
|
||||
@ -27,6 +27,7 @@ import com.gh.gamecenter.common.utils.DialogHelper
|
||||
import com.gh.gamecenter.common.utils.observableToMain
|
||||
import com.gh.gamecenter.common.utils.singleToMain
|
||||
import com.gh.gamecenter.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.EmptyCallback
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
@ -183,10 +184,13 @@ object GameActivityDownloadHelper {
|
||||
str != context.getString(R.string.install) &&
|
||||
str != context.getString(R.string.launch)
|
||||
) {
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint))
|
||||
}
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
} else {
|
||||
when {
|
||||
str == context.getString(R.string.download) || str == context.getString(R.string.attempt) -> {
|
||||
@ -208,10 +212,13 @@ object GameActivityDownloadHelper {
|
||||
handleUpdateStatus(context, gameEntity, apk, entrance, location, traceEvent)
|
||||
}
|
||||
else -> {
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint))
|
||||
}
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -430,10 +437,13 @@ object GameActivityDownloadHelper {
|
||||
R.string.download
|
||||
), entrance, location, isSubscribe, traceEvent
|
||||
)
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint))
|
||||
}
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
} else {
|
||||
ToastUtils.toast(msg)
|
||||
}
|
||||
@ -452,10 +462,13 @@ object GameActivityDownloadHelper {
|
||||
val msg = FileUtils.isCanDownload(context, apk.size)
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DownloadManager.createDownload(context, apk, gameEntity, "插件化", entrance, location, isSubscribe, traceEvent)
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint))
|
||||
}
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
} else {
|
||||
ToastUtils.toast(msg)
|
||||
}
|
||||
@ -495,10 +508,13 @@ object GameActivityDownloadHelper {
|
||||
traceEvent: ExposureEvent?
|
||||
) {
|
||||
DownloadManager.createDownload(context, apk, gameEntity, "更新", entrance, location, isSubscribe, traceEvent)
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint))
|
||||
}
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
if (BrowserInstallHelper.shouldAutoSwitchAssistantInstall(gameEntity)) {
|
||||
val toast = context.getString(R.string.unsupported_browser_install_hint)
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast(toast)
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
|
||||
@ -161,14 +161,13 @@ object PackageInstaller {
|
||||
}
|
||||
|
||||
val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
|
||||
} else {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
PendingIntent.FLAG_CANCEL_CURRENT
|
||||
}
|
||||
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, flags)
|
||||
val pendingIntent = PendingIntent.getActivity(context, sessionId, intent, flags)
|
||||
// 提交数据流并执行安装
|
||||
session.commit(pendingIntent.intentSender)
|
||||
session.close()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,30 +1,35 @@
|
||||
package com.gh.common.xapk
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.content.pm.PackageInstaller.SessionInfo
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.RequiresApi
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
class XapkInstallReceiver : BroadcastReceiver() {
|
||||
class XapkInstallReceiver : Activity() {
|
||||
|
||||
companion object {
|
||||
const val KEY_PACKAGE_PATH = "package_path"
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
overridePendingTransition(0, 0)
|
||||
handleIntent(this, intent)
|
||||
|
||||
}
|
||||
|
||||
private fun handleIntent(context: Context, intent: Intent) {
|
||||
when (intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)) {
|
||||
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
|
||||
val installIntent = intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT)
|
||||
if (installIntent != null) {
|
||||
val installPackagePath = intent.getStringExtra(KEY_PACKAGE_PATH)
|
||||
val installSessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1)
|
||||
XapkInstaller.onPendingUserAction(installPackagePath!!, installSessionId)
|
||||
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
context.startActivity(installIntent)
|
||||
updatePendingSessionInfoStatus(intent, XapkPendingSessionInfo.STATUS_PENDING_USER_ACTION)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
PackageInstaller.STATUS_FAILURE,
|
||||
@ -34,11 +39,21 @@ class XapkInstallReceiver : BroadcastReceiver() {
|
||||
PackageInstaller.STATUS_FAILURE_INCOMPATIBLE,
|
||||
PackageInstaller.STATUS_FAILURE_INVALID,
|
||||
PackageInstaller.STATUS_FAILURE_STORAGE -> {
|
||||
val installPackagePath = intent.getStringExtra(KEY_PACKAGE_PATH)
|
||||
if (!installPackagePath.isNullOrEmpty()) {
|
||||
XapkInstaller.onInstallCanceled(installPackagePath)
|
||||
}
|
||||
updatePendingSessionInfoStatus(intent, XapkPendingSessionInfo.STATUS_INSTALL_CANCELED)
|
||||
finish()
|
||||
}
|
||||
else -> {
|
||||
updatePendingSessionInfoStatus(intent, XapkPendingSessionInfo.STATUS_INSTALL_SUCCESS)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePendingSessionInfoStatus(intent: Intent, status: Int) {
|
||||
val installPackagePath = intent.getStringExtra(KEY_PACKAGE_PATH)
|
||||
if (!installPackagePath.isNullOrEmpty()) {
|
||||
val pendingSessionInfo = XapkInstaller.getPendingSessionInfo(installPackagePath)
|
||||
pendingSessionInfo?.updateStatus(status)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,14 +2,19 @@ package com.gh.common.xapk
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadDataHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.utils.debugOnly
|
||||
import com.gh.gamecenter.common.utils.getExtension
|
||||
import com.gh.gamecenter.common.utils.throwExceptionInDebug
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.SentryHelper
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.xapk.XApkUnZipper
|
||||
import com.gh.gamecenter.xapk.core.XApkFile
|
||||
import com.gh.gamecenter.xapk.core.XApkUnZipCallback
|
||||
@ -50,6 +55,9 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
const val XAPK_DATA_EXTENSION_NAME = "obb"
|
||||
const val PACKAGE_EXTENSION_NAME = "apk"
|
||||
|
||||
private const val GUIDE_TYPE_MIUI_OPTIMIZATION = "miui_optimization"
|
||||
private const val MIUI_OPTIMIZATION_WARNING_DIALOG_ENTRANCE = "MIUI优化关闭提示弹窗"
|
||||
|
||||
private var mContext = HaloApp.getInstance().application.applicationContext
|
||||
|
||||
private val mXApkUnZipper = XApkUnZipper(this)
|
||||
@ -59,9 +67,7 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
|
||||
private val mDownloadEntityMap = Collections.synchronizedMap(HashMap<String, DownloadEntity>())
|
||||
|
||||
private val mInstallingPath = Collections.synchronizedList(mutableListOf<String>())
|
||||
|
||||
private val mPendingSessionIdMap = Collections.synchronizedMap(HashMap<String, Int>())
|
||||
private val mPendingSessionInfoMap = HashMap<String, XapkPendingSessionInfo>()
|
||||
|
||||
// 按并行解压
|
||||
@JvmStatic
|
||||
@ -70,6 +76,35 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
|
||||
val filePath = downloadEntity.path
|
||||
if (XAPK_EXTENSION_NAME == filePath.getExtension()) {
|
||||
if (MiuiUtils.isMiui() && !MiuiUtils.isMiuiOptimizationDisabled() && downloadEntity.format == Constants.XAPK_APKS_FORMAT) {// 小米手机开启miui以后,需要引导用户关闭miui优化
|
||||
DialogHelper.showMiuiOptimizationWarning(
|
||||
context,
|
||||
onHintClick = {
|
||||
val guides = Config.getNewApiSettingsEntity()?.install
|
||||
val miuiOptimizationGuide = guides?.guides?.findLast {
|
||||
it.type == GUIDE_TYPE_MIUI_OPTIMIZATION
|
||||
}
|
||||
if (miuiOptimizationGuide != null) {
|
||||
DirectUtils.directToLinkPage(
|
||||
context,
|
||||
miuiOptimizationGuide.link,
|
||||
MIUI_OPTIMIZATION_WARNING_DIALOG_ENTRANCE,
|
||||
""
|
||||
)
|
||||
}
|
||||
},
|
||||
onConfirmClick = {
|
||||
if (SystemUtils.isDevelopmentSettingsEnabled(context)) {
|
||||
context.startActivity(Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS))
|
||||
it.dismiss()
|
||||
} else {
|
||||
ToastUtils.showToast(context.getString(R.string.miui_open_adb_hint))
|
||||
}
|
||||
}
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
unzipXapkFile(downloadEntity)
|
||||
if (showUnzipToast) {
|
||||
Utils.toast(mContext, "解压过程请勿退出光环助手!")
|
||||
@ -99,7 +134,11 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
val downloadEntity = mDownloadEntityMap[apk.file.path] ?: return
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = String.format("%.2f", progress * 100)
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.UNZIPPING.name
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
|
||||
AppExecutor.ioExecutor.execute {
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onProgress->$progress")
|
||||
}
|
||||
@ -110,43 +149,40 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "100.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.SUCCESS.name
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk解压成功")
|
||||
AppExecutor.ioExecutor.execute {
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk解压成功")
|
||||
}
|
||||
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onSuccess->${downloadEntity.path}")
|
||||
}
|
||||
|
||||
if (!mInstallingPath.contains(downloadEntity.path)) {
|
||||
mInstallingPath.add(downloadEntity.path)
|
||||
}
|
||||
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
|
||||
XapkInstallerLooper.add(downloadEntity.path, installer)
|
||||
XapkInstallerLooper.install(mContext)
|
||||
installer.install(mContext)
|
||||
}
|
||||
|
||||
override fun onError(apk: XApkFile, exception: Throwable) {
|
||||
val downloadEntity = mDownloadEntityMap[apk.file.path] ?: return
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.FAILURE.name
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
|
||||
// 仅官网渠道上报 XAPK 异常信息
|
||||
if (HaloApp.getInstance().channel == "GH_206") {
|
||||
SentryHelper.onEvent(
|
||||
"XAPK_UNZIP_ERROR",
|
||||
"gameName", downloadEntity.name,
|
||||
"errorDigest", exception.localizedMessage
|
||||
)
|
||||
AppExecutor.ioExecutor.execute {
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
// 仅官网渠道上报 XAPK 异常信息
|
||||
if (HaloApp.getInstance().channel == "GH_206") {
|
||||
SentryHelper.onEvent(
|
||||
"XAPK_UNZIP_ERROR",
|
||||
"gameName", downloadEntity.name,
|
||||
"errorDigest", exception.localizedMessage
|
||||
)
|
||||
}
|
||||
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk解压失败")
|
||||
}
|
||||
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk解压失败")
|
||||
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onFailure->$exception")
|
||||
}
|
||||
@ -156,8 +192,10 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
val downloadEntity = mDownloadEntityMap.remove(apk.file.path) ?: return
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "0.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.CANCEL.name
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
AppExecutor.ioExecutor.execute {
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNext(apk: XApkFile, fileName: String) {
|
||||
@ -166,11 +204,9 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
}
|
||||
}
|
||||
|
||||
fun isInstalling(packagePath: String): Boolean = mInstallingPath.contains(packagePath)
|
||||
fun getPendingSessionInfo(packagePath: String): XapkPendingSessionInfo? = mPendingSessionInfoMap[packagePath]
|
||||
|
||||
fun onPendingUserAction(packagePath: String, sessionId: Int) {
|
||||
mPendingSessionIdMap[packagePath] = sessionId
|
||||
}
|
||||
fun isInstalling(packagePath: String): Boolean = mPendingSessionInfoMap.containsKey(packagePath)
|
||||
|
||||
/**
|
||||
* 通知XAPK安装完成
|
||||
@ -178,41 +214,32 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
fun onInstalled(packagePath: String) {
|
||||
val downloadEntity = mDownloadEntityMap.remove(packagePath) ?: return
|
||||
|
||||
mPendingSessionIdMap.remove(packagePath)
|
||||
mInstallingPath.remove(packagePath)
|
||||
mPendingSessionInfoMap.remove(packagePath)
|
||||
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "100.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.INSTALLED.name
|
||||
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk安装成功")
|
||||
|
||||
XapkInstallerLooper.remove(downloadEntity.path)
|
||||
XapkInstallerLooper.install(mContext)
|
||||
AppExecutor.ioExecutor.execute {
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk安装成功")
|
||||
}
|
||||
}
|
||||
|
||||
fun onInstallCanceled(packagePath: String) {
|
||||
|
||||
val downloadEntity = mDownloadEntityMap.remove(packagePath) ?: return
|
||||
|
||||
mPendingSessionIdMap.remove(packagePath)
|
||||
|
||||
mInstallingPath.remove(packagePath)
|
||||
mPendingSessionInfoMap.remove(packagePath)
|
||||
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "0.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.CANCEL.name
|
||||
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk安装取消")
|
||||
|
||||
XapkInstallerLooper.remove(downloadEntity.path)
|
||||
XapkInstallerLooper.install(mContext)
|
||||
AppExecutor.ioExecutor.execute {
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
DownloadDataHelper.uploadDownloadStatusEvent(downloadEntity, "xapk安装取消")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -220,29 +247,48 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
* 1. 用户触碰安装弹窗(原生Android系统)区域外导致安装取消
|
||||
*/
|
||||
fun updateCurrentInstallStatus() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || mPendingSessionIdMap.isEmpty()) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || mPendingSessionInfoMap.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val installer = mContext.packageManager.packageInstaller
|
||||
val updateList = mutableListOf<XapkPendingSessionInfo>()
|
||||
|
||||
for (pendingSessionEntry in mPendingSessionIdMap) {
|
||||
val sessionInfo = installer.getSessionInfo(pendingSessionEntry.value)
|
||||
for (pendingSessionInfoEntry in mPendingSessionInfoMap) {
|
||||
|
||||
// 1. 用户点击了取消按钮时,sessionInfo为空
|
||||
// 2. 用户点击了确定按钮时,sessionInfo的progress大于0.8
|
||||
if (sessionInfo == null || sessionInfo.progress > 0.8F) {
|
||||
continue
|
||||
val pendingSessionInfo = pendingSessionInfoEntry.value
|
||||
|
||||
if (pendingSessionInfo.getStatus() == XapkPendingSessionInfo.STATUS_PENDING_USER_ACTION) {// 用户触摸安装弹窗外部区域取消安装后,更新安装状态
|
||||
val installer = mContext.packageManager.packageInstaller
|
||||
val sessionId = pendingSessionInfo.sessionId
|
||||
if (sessionId != -1) {
|
||||
val sessionInfo = installer.getSessionInfo(sessionId)
|
||||
// 表示用户点击了安装弹窗外部区域
|
||||
if (sessionInfo == null) {
|
||||
pendingSessionInfo.updateStatus(XapkPendingSessionInfo.STATUS_INSTALL_CANCELED)
|
||||
} else if (sessionInfo.progress <= 0.8F) {
|
||||
AppExecutor.ioExecutor.execute {
|
||||
installer.abandonSession(sessionInfo.sessionId)
|
||||
}
|
||||
pendingSessionInfo.updateStatus(XapkPendingSessionInfo.STATUS_INSTALL_CANCELED)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
installer.abandonSession(sessionInfo.sessionId)
|
||||
val installStatus = pendingSessionInfo.getStatus()
|
||||
if (installStatus == XapkPendingSessionInfo.STATUS_INSTALL_CANCELED
|
||||
|| installStatus == XapkPendingSessionInfo.STATUS_INSTALL_SUCCESS
|
||||
) {
|
||||
updateList.add(pendingSessionInfo)
|
||||
}
|
||||
}
|
||||
|
||||
val downloadEntity = mDownloadEntityMap[pendingSessionEntry.key] ?: return
|
||||
|
||||
if (!PackageUtils.isInstalled(mContext, downloadEntity.packageName)) {
|
||||
onInstallCanceled(downloadEntity.path)
|
||||
} else {
|
||||
for (pendingSessionInfo in updateList) {
|
||||
val downloadEntity = mDownloadEntityMap[pendingSessionInfo.path] ?: continue
|
||||
val installStatus = pendingSessionInfo.getStatus()
|
||||
if (installStatus == XapkPendingSessionInfo.STATUS_INSTALL_SUCCESS) {
|
||||
onInstalled(downloadEntity.path)
|
||||
} else if (installStatus == XapkPendingSessionInfo.STATUS_INSTALL_CANCELED) {
|
||||
onInstallCanceled(downloadEntity.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -268,9 +314,16 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
private val xApkFile: XApkFile,
|
||||
private val sessionId: Int,
|
||||
) : IPackageInstaller {
|
||||
|
||||
override fun install(context: Context) {
|
||||
val applicationContext = context.applicationContext
|
||||
val downloadEntity = mDownloadEntityMap[xApkFile.file.path] ?: return
|
||||
PackageInstaller.installMultiple(context, downloadEntity.path, sessionId)
|
||||
|
||||
mPendingSessionInfoMap[downloadEntity.path] = XapkPendingSessionInfo(downloadEntity.path, sessionId)
|
||||
AppExecutor.ioExecutor.execute {// 有可能卡顿造成anr
|
||||
PackageInstaller.installMultiple(applicationContext, downloadEntity.path, sessionId)
|
||||
NDataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,6 +331,7 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
private val xApkFile: XApkFile,
|
||||
private val file: File
|
||||
) : IPackageInstaller {
|
||||
|
||||
override fun install(context: Context) {
|
||||
val downloadEntity = mDownloadEntityMap[xApkFile.file.path] ?: return
|
||||
PackageInstaller.install(
|
||||
@ -288,49 +342,12 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* XAPK安装每次只能执行一个安装流程,因此添加一个安装队列
|
||||
*/
|
||||
private object XapkInstallerLooper {
|
||||
|
||||
private val packagePathList = mutableListOf<String>()
|
||||
|
||||
private val installerList = mutableListOf<IPackageInstaller>()
|
||||
|
||||
fun add(packagePath: String, installer: IPackageInstaller) {
|
||||
if (packagePathList.contains(packagePath)) {
|
||||
return
|
||||
}
|
||||
packagePathList.add(packagePath)
|
||||
installerList.add(installer)
|
||||
}
|
||||
|
||||
fun install(context: Context) {
|
||||
if (installerList.isEmpty()) {
|
||||
return
|
||||
}
|
||||
installerList.first().install(context)
|
||||
}
|
||||
|
||||
fun remove(packagePath: String) {
|
||||
if (!packagePathList.contains(packagePath)) {
|
||||
return
|
||||
}
|
||||
val index = packagePathList.indexOf(packagePath)
|
||||
if (index != -1) {
|
||||
packagePathList.removeAt(index)
|
||||
installerList.removeAt(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class XapkUnzipStatus(status: String) {
|
||||
UNZIPPING("unzipping"),
|
||||
SUCCESS("success"),
|
||||
CANCEL("cancel"),
|
||||
INSTALLING("installing"),
|
||||
INSTALLED("installed"),
|
||||
FAILURE("failure");
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.gh.common.xapk
|
||||
|
||||
class XapkPendingSessionInfo(
|
||||
val path: String,
|
||||
val sessionId: Int = -1
|
||||
) {
|
||||
companion object {
|
||||
const val STATUS_INIT = -1
|
||||
const val STATUS_PENDING_USER_ACTION = 0
|
||||
const val STATUS_INSTALL_SUCCESS = 1
|
||||
const val STATUS_INSTALL_CANCELED = 2
|
||||
}
|
||||
|
||||
private var status = STATUS_INIT
|
||||
|
||||
internal fun updateStatus(status: Int) {
|
||||
this.status = status
|
||||
}
|
||||
|
||||
fun getStatus(): Int = status
|
||||
}
|
||||
@ -23,9 +23,6 @@ import org.json.JSONObject
|
||||
object DownloadDataHelper {
|
||||
private const val TAG = "DownloadDataHelper"
|
||||
|
||||
private const val DOWNLOAD_SPEED_TIME = "download_speed_time"
|
||||
private const val DOWNLOAD_SPEED_SIZE = "download_speed_size"
|
||||
|
||||
const val DOWNLOAD_RESUME_WAY = "download_resume_way"
|
||||
const val DOWNLOAD_RESUME_MANUAL = "manual"
|
||||
const val DOWNLOAD_RESUME_AUTO = "auto"
|
||||
@ -34,8 +31,6 @@ object DownloadDataHelper {
|
||||
const val DOWNLOAD_CANCEL_MANUAL = "manual"
|
||||
const val DOWNLOAD_CANCEL_AUTO = "auto"
|
||||
|
||||
const val DOWNLOAD_FIRST_START = "download_first_start"
|
||||
|
||||
const val DOWNLOAD_THREAD_SIZE = "download_thread_size" // 线程数量,0为传统单线程模式; 1为多线程的单线程; >1为多线程的实际线程数量
|
||||
|
||||
private val mDownloadSpeedMap = HashMap<String, MutableList<Long>>()
|
||||
@ -140,26 +135,28 @@ object DownloadDataHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun uploadDownloadEvent(downloadEntity: DownloadEntity) {
|
||||
val downloadSimpleEntity = DownloadDataSimpleHelper.getDownloadDataSimpleEntity(downloadEntity.url)
|
||||
|
||||
if (downloadEntity.status != DownloadStatus.downloading) {
|
||||
uploadDownloadStatusEvent(downloadEntity)
|
||||
}
|
||||
|
||||
if (downloadEntity.status == DownloadStatus.downloading) {
|
||||
val startupTime = downloadEntity.meta[DownloadEntity.DOWNLOAD_STARTUP_TIME_KEY]
|
||||
val startupTime =
|
||||
downloadSimpleEntity?.downloadStartUpTime
|
||||
if (startupTime != null) {
|
||||
uploadDownloadStartupTimeEvent(downloadEntity, startupTime.toInt())
|
||||
downloadEntity.meta.remove(DownloadEntity.DOWNLOAD_STARTUP_TIME_KEY)
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
uploadDownloadStartupTimeEvent(downloadEntity, startupTime)
|
||||
DownloadDataSimpleHelper.updateDownloadDataSimpleEntity(downloadEntity.url, downloadStartUpTime = null)
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadEntity.status == DownloadStatus.downloading || downloadEntity.status == DownloadStatus.done) {
|
||||
val time = downloadEntity.meta[DOWNLOAD_SPEED_TIME]
|
||||
val size = downloadEntity.meta[DOWNLOAD_SPEED_SIZE]
|
||||
val time = downloadSimpleEntity?.downloadSpeedTime
|
||||
val size = downloadSimpleEntity?.downloadSpeedSize
|
||||
if (downloadEntity.speed == 0L || time == null || size == null) {
|
||||
downloadEntity.meta[DOWNLOAD_SPEED_TIME] = System.currentTimeMillis().toString()
|
||||
downloadEntity.meta[DOWNLOAD_SPEED_SIZE] = downloadEntity.progress.toString()
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
val currentTime = System.currentTimeMillis()
|
||||
val currentProgress = downloadEntity.progress
|
||||
DownloadDataSimpleHelper.updateDownloadDataSimpleEntity(downloadEntity.url, downloadSpeedTime = currentTime, downloadSpeedSize = currentProgress)
|
||||
} else {
|
||||
val offset = System.currentTimeMillis() - time.toLong()
|
||||
if (offset > 5000) {
|
||||
@ -180,15 +177,15 @@ object DownloadDataHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
downloadEntity.meta[DOWNLOAD_SPEED_TIME] = System.currentTimeMillis().toString()
|
||||
downloadEntity.meta[DOWNLOAD_SPEED_SIZE] = downloadEntity.progress.toString()
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
val currentTime = System.currentTimeMillis()
|
||||
val currentProgress = downloadEntity.progress
|
||||
DownloadDataSimpleHelper.updateDownloadDataSimpleEntity(downloadEntity.url, downloadSpeedTime = currentTime, downloadSpeedSize = currentProgress)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun uploadDownloadStartupTimeEvent(downloadEntity: DownloadEntity, startupTime: Int) {
|
||||
private fun uploadDownloadStartupTimeEvent(downloadEntity: DownloadEntity, startupTime: Long) {
|
||||
val jsonObject = JSONObject()
|
||||
|
||||
try {
|
||||
@ -280,7 +277,7 @@ object DownloadDataHelper {
|
||||
}
|
||||
payloadObject.put("completed_size", downloadEntity.progress / 1024 / 1024)
|
||||
if (downloadEntity.status == DownloadStatus.resume) {
|
||||
if (downloadEntity.meta[DOWNLOAD_FIRST_START] == "YES") {
|
||||
if (DownloadDataSimpleHelper.getDownloadDataSimpleEntity(downloadEntity.url)?.isFirstTimeDownload == true) {
|
||||
payloadObject.put("is_first_start", true)
|
||||
} else {
|
||||
payloadObject.put("is_first_start", false)
|
||||
@ -288,8 +285,7 @@ object DownloadDataHelper {
|
||||
}
|
||||
|
||||
if (downloadEntity.status == DownloadStatus.resume || downloadEntity.status == DownloadStatus.add) {
|
||||
downloadEntity.meta[DOWNLOAD_FIRST_START] = "NO"
|
||||
DownloadManager.getInstance().updateDownloadEntity(downloadEntity)
|
||||
DownloadDataSimpleHelper.updateDownloadSimpleEntityFirstTimeDownload(downloadEntity.url, false)
|
||||
}
|
||||
jsonObject.put("payload", payloadObject)
|
||||
} catch (e: Exception) {
|
||||
@ -342,7 +338,7 @@ object DownloadDataHelper {
|
||||
/**
|
||||
* 分片检测下载进度,每隔15秒内记录一次,60秒上传一次
|
||||
*
|
||||
* 请见:https://gitlab.ghzs.com/stats/stats-issues/-/issues/188#note_66919
|
||||
* 请见:https://git.shanqu.cc/stats/stats-issues/-/issues/188#note_66919
|
||||
*/
|
||||
fun uploadDownloadHeartbeat(upload: Boolean) {
|
||||
val allDownloadEntity = DownloadManager.getInstance().allDownloadEntity
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
package com.gh.download
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import com.gh.gamecenter.common.HaloApp
|
||||
import com.gh.gamecenter.common.utils.toJsonIgnoredNull
|
||||
import com.gh.gamecenter.common.utils.toObject
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
|
||||
/**
|
||||
* 用来简单保存/获取下载时一些额外信息的辅助类,避免下载时反复修改原始下载实体的糟糕操作
|
||||
* 使用 SP 来实现,只适用于相对较为低频的调用
|
||||
*/
|
||||
object DownloadDataSimpleHelper {
|
||||
|
||||
private val mSp: SharedPreferences by lazy {
|
||||
HaloApp.getInstance().getSharedPreferences("DownloadDataSimpleDao", Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
fun getDownloadDataSimpleEntity(url: String): DownloadDataSimpleEntity? {
|
||||
return mSp.getString(url, "")?.toObject()
|
||||
}
|
||||
|
||||
fun updateDownloadDataSimpleEntity(
|
||||
url: String,
|
||||
downloadStartUpTime: Long? = null,
|
||||
downloadSpeedTime: Long? = null,
|
||||
downloadSpeedSize: Long? = null,
|
||||
) {
|
||||
val entity = getDownloadDataSimpleEntity(url) ?: DownloadDataSimpleEntity()
|
||||
entity.downloadStartUpTime = downloadStartUpTime
|
||||
|
||||
entity.downloadSpeedTime = downloadSpeedTime
|
||||
entity.downloadSpeedSize = downloadSpeedSize
|
||||
|
||||
SPUtils.setString(mSp, url, entity.toJsonIgnoredNull())
|
||||
}
|
||||
|
||||
fun updateDownloadSimpleEntityFirstTimeDownload(url: String, isFirstTimeDownload: Boolean) {
|
||||
val entity = getDownloadDataSimpleEntity(url) ?: DownloadDataSimpleEntity()
|
||||
|
||||
entity.isFirstTimeDownload = isFirstTimeDownload
|
||||
|
||||
SPUtils.setString(mSp, url, entity.toJsonIgnoredNull())
|
||||
}
|
||||
|
||||
fun removeDownloadSimpleEntity(url: String) {
|
||||
SPUtils.remove(mSp, url)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class DownloadDataSimpleEntity(
|
||||
var downloadStartUpTime: Long? = null,
|
||||
|
||||
var downloadSpeedTime: Long? = null,
|
||||
var downloadSpeedSize: Long? = null,
|
||||
|
||||
var isFirstTimeDownload: Boolean? = true
|
||||
)
|
||||
@ -834,6 +834,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
*/
|
||||
public void cancel(String url, boolean isDeleteFile, boolean automatic, boolean cancelSilently) {
|
||||
DownloadEntity entry = mDownloadDao.getSnapshot(url);
|
||||
DownloadDataSimpleHelper.INSTANCE.removeDownloadSimpleEntity(url);
|
||||
if (entry != null) {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
NDownloadBridge.INSTANCE.cancel(url);
|
||||
@ -996,8 +997,11 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
}
|
||||
|
||||
if (status == DownloadStatus.add || status == DownloadStatus.subscribe) {
|
||||
if (downloadEntity.getMeta().get(DownloadDataHelper.DOWNLOAD_FIRST_START) == null) {
|
||||
downloadEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_FIRST_START, "YES");
|
||||
DownloadDataSimpleEntity simpleEntity =
|
||||
DownloadDataSimpleHelper.INSTANCE.getDownloadDataSimpleEntity(downloadEntity.getUrl());
|
||||
|
||||
if (simpleEntity == null || simpleEntity.isFirstTimeDownload() == null) {
|
||||
DownloadDataSimpleHelper.INSTANCE.updateDownloadSimpleEntityFirstTimeDownload(downloadEntity.getUrl(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1237,7 +1241,10 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
/**
|
||||
* 更新数据库中的下载实体
|
||||
*
|
||||
* @deprecated 随意更新数据库可能会出现意想不到的情况,建议不要随意调用
|
||||
*/
|
||||
@Deprecated()
|
||||
public void updateDownloadEntity(DownloadEntity downloadEntity) {
|
||||
mDownloadDao.update(downloadEntity, false);
|
||||
}
|
||||
|
||||
@ -111,8 +111,7 @@ object PackageObserver {
|
||||
runOnIoThread { FileUtils.deleteFile(mDownloadEntity.path) }
|
||||
}
|
||||
|
||||
if (mDownloadEntity.format == Constants.XAPK_FORMAT
|
||||
|| mDownloadEntity.format == Constants.XAPK_APKS_FORMAT) {
|
||||
if (mDownloadEntity.format == Constants.XAPK_FORMAT) {
|
||||
XapkInstaller.onInstalled(mDownloadEntity.path)
|
||||
}
|
||||
|
||||
|
||||
@ -55,23 +55,21 @@ object DownloadMessageHandler : InnerDownloadListener {
|
||||
* @param status 下载状态
|
||||
*/
|
||||
override fun onStatusChanged(id: String, status: DownloadStatus) {
|
||||
val entity = findEntity(id)
|
||||
val entity = findEntity(id) ?: return
|
||||
|
||||
if (entity != null) {
|
||||
entity.status = status
|
||||
entity.status = status
|
||||
|
||||
if (status == DownloadStatus.COMPLETED) {
|
||||
SimpleDownloadManager.resumeQueuedTask()
|
||||
}
|
||||
if (status == DownloadStatus.COMPLETED) {
|
||||
SimpleDownloadManager.resumeQueuedTask()
|
||||
}
|
||||
|
||||
ExecutorProvider.getInstance().backgroundExecutor.execute {
|
||||
updateDownloadToDatabase(entity)
|
||||
updateDownloadList()
|
||||
}
|
||||
ExecutorProvider.getInstance().backgroundExecutor.execute {
|
||||
updateDownloadToDatabase(entity)
|
||||
updateDownloadList()
|
||||
}
|
||||
|
||||
for (listener in mGlobalStatusChangedListenerList) {
|
||||
listener.invoke(entity!!, status)
|
||||
listener.invoke(entity, status)
|
||||
}
|
||||
|
||||
val listenerList = mListenerMap[id] ?: return
|
||||
|
||||
@ -198,7 +198,6 @@ public class MainActivity extends BaseActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
showAd = getIntent().getBooleanExtra(SHOW_AD, false) && savedInstanceState == null;
|
||||
|
||||
HaloApp.getInstance().initFresco();
|
||||
HaloApp.getInstance().isAlreadyUpAndRunning = true;
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
@ -297,19 +297,7 @@ class SplashScreenActivity : BaseActivity() {
|
||||
private fun doFlavorInit() {
|
||||
HaloApp.getInstance().flavorProvider.init(HaloApp.getInstance(), this, PkgHelper.getActivateRatio())
|
||||
|
||||
val whiteListChannel = arrayListOf(
|
||||
"GH_206",
|
||||
"KS-GHZS-KY1",
|
||||
"KS-GHZS-MC1",
|
||||
"GDT_GHZS_MC1",
|
||||
"T11-GH-APPDY-ZC01",
|
||||
"T7-GH-APPDY-KY03",
|
||||
"T8-GH-APPUX-KY04",
|
||||
"T1-GHZS-MC01",
|
||||
"T4-GHZS-MC03"
|
||||
)
|
||||
|
||||
if (whiteListChannel.contains(HaloApp.getInstance().channel) || PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
if (HaloApp.getInstance().channel == "GH_206" || PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,10 +12,6 @@ import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.gh.common.chain.AutoSwitchAssistantInstallHandler;
|
||||
import com.gh.common.chain.UnsupportedFeatureHandler;
|
||||
import com.gh.common.util.PackageLauncher;
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager;
|
||||
import com.gh.common.chain.BrowserInstallHandler;
|
||||
import com.gh.common.chain.CertificationHandler;
|
||||
import com.gh.common.chain.ChainBuilder;
|
||||
@ -26,15 +22,13 @@ 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.UnsupportedFeatureHandler;
|
||||
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.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
import com.gh.common.filter.RegionSetting;
|
||||
import com.gh.common.filter.RegionSettingHelper;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
@ -42,34 +36,38 @@ import com.gh.common.simulator.NewSimulatorGameManager;
|
||||
import com.gh.common.simulator.SimulatorDownloadManager;
|
||||
import com.gh.common.simulator.SimulatorGameManager;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.xapk.XapkInstaller;
|
||||
import com.gh.common.xapk.XapkUnzipStatus;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.utils.DataLogUtils;
|
||||
import com.gh.common.util.DetailDownloadUtils;
|
||||
import com.gh.gamecenter.common.utils.DialogHelper;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.gamecenter.core.utils.PageSwitchDataHelper;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageLauncher;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.gamecenter.feature.view.DownloadButton;
|
||||
import com.gh.common.xapk.XapkInstaller;
|
||||
import com.gh.common.xapk.XapkUnzipStatus;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.core.utils.StringUtils;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.entity.LinkEntity;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity;
|
||||
import com.gh.gamecenter.common.utils.DataLogUtils;
|
||||
import com.gh.gamecenter.common.utils.DialogHelper;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.core.utils.PageSwitchDataHelper;
|
||||
import com.gh.gamecenter.core.utils.StringUtils;
|
||||
import com.gh.gamecenter.eventbus.EBScroll;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
import com.gh.gamecenter.feature.view.DownloadButton;
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment;
|
||||
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment;
|
||||
import com.gh.gamecenter.teenagermode.TeenagerModeActivity;
|
||||
@ -227,7 +225,6 @@ public class DetailViewHolder {
|
||||
}
|
||||
case PLUGIN:
|
||||
ChainBuilder builder = new ChainBuilder();
|
||||
builder.addHandler(new AutoSwitchAssistantInstallHandler());
|
||||
builder.addHandler(new UnsupportedFeatureHandler());
|
||||
builder.addHandler(new UpdateNewSimulatorHandler());
|
||||
builder.addHandler(new GamePermissionHandler());
|
||||
|
||||
@ -138,8 +138,7 @@ public class GameDownloadFragment extends BaseFragment implements View.OnClickLi
|
||||
}
|
||||
}
|
||||
|
||||
adapter.getUrlMap().put(PackageUtils.getPackageNameByPath(HaloApp.getInstance().getApplication(),
|
||||
downloadEntity.getPath()), downloadEntity.getUrl());
|
||||
adapter.getUrlMap().put(downloadEntity.getPackageName(), downloadEntity.getUrl());
|
||||
|
||||
// 用户焦点在下载管理页面时有任务完成,直接把所有下载完成的任务标记为已读
|
||||
DownloadManager.getInstance().markDownloadedTaskAsRead();
|
||||
|
||||
@ -584,6 +584,7 @@ class UpdatableGameViewModel(
|
||||
downloadEntity.platform = update.platform
|
||||
downloadEntity.packageName = update.packageName
|
||||
downloadEntity.versionName = update.version
|
||||
downloadEntity.pluginDesc = update.pluginDesc
|
||||
downloadEntity.addMetaExtra(Constants.RAW_GAME_ICON, update.rawIcon)
|
||||
downloadEntity.addMetaExtra(Constants.GAME_ICON_SUBSCRIPT, update.iconSubscript)
|
||||
downloadEntity.addMetaExtra(Constants.DOWNLOAD_ID, downloadId)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
@ -29,7 +30,9 @@ class NewApiSettingsEntity(
|
||||
// VPN 配置
|
||||
class Install(
|
||||
@SerializedName("vpn_required")
|
||||
val vpnRequired: VpnSetting? = null
|
||||
val vpnRequired: VpnSetting? = null,
|
||||
@SerializedName("guides")
|
||||
val guides: List<Guide>? = null
|
||||
)
|
||||
|
||||
class VpnSetting(
|
||||
@ -38,4 +41,9 @@ class NewApiSettingsEntity(
|
||||
@SerializedName("packages")
|
||||
val vpnMatchedPackagesName: HashSet<String>
|
||||
)
|
||||
|
||||
class Guide(
|
||||
val type: String,
|
||||
val link: LinkEntity
|
||||
)
|
||||
}
|
||||
@ -773,7 +773,18 @@ class HomeSearchToolWrapperFragment : SearchToolWrapperFragment() {
|
||||
}
|
||||
|
||||
// 这里的 selectedPosition 指的是应该被高亮显示的 position
|
||||
val selectedPosition = (position + positionOffset).roundToInt()
|
||||
val selectedPosition = try {
|
||||
(position + positionOffset).roundToInt()
|
||||
} catch (e: IllegalArgumentException) {
|
||||
// roundToInt() 方法有时候会报 Cannot round NaN value. 错误
|
||||
// https://sentry.shanqu.cc/organizations/lightgame/issues/301377/?project=22
|
||||
SentryHelper.onEvent(
|
||||
"HOME_NAN_POSITION",
|
||||
"value",
|
||||
"$position+$positionOffset=(${position + positionOffset})"
|
||||
)
|
||||
position
|
||||
}
|
||||
val positionOffsetOnRealSelectedPosition = if (positionOffset >= 0.5) {
|
||||
positionOffset - 1
|
||||
} else {
|
||||
@ -797,8 +808,8 @@ class HomeSearchToolWrapperFragment : SearchToolWrapperFragment() {
|
||||
// positionOffset 小于零,表示 indicator 当前位置处于选中的 tab 的左边
|
||||
val indicatorOnLeft = positionOffset < 0F
|
||||
|
||||
val selectedTabBinding = mTabBindingList[selectedPosition]
|
||||
val selectedTabImageStyle = mTabImageStyleList[selectedPosition]
|
||||
val selectedTabBinding = mTabBindingList.safelyGetInRelease(selectedPosition) ?: return
|
||||
val selectedTabImageStyle = mTabImageStyleList.safelyGetInRelease(selectedPosition) ?: return
|
||||
|
||||
// 前一个 tab、当前选中的 tab、后一个 tab 的显示比例
|
||||
val preScaleRatio = 1 + abs(positionOffset) / 4
|
||||
|
||||
@ -84,6 +84,7 @@ class HomeSearchToolWrapperViewModel(application: Application) : AndroidViewMode
|
||||
if (pkgLinkEntity.type == tab.type
|
||||
&& (pkgLinkEntity.link == tab.link || tab.link == null)) {
|
||||
defaultTabPosition = index
|
||||
PkgHelper.markConfigUsed()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,6 @@ import com.gh.gamecenter.home.test_v2.HomeGameTestV2GameListRvAdapter
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2ViewModel
|
||||
import com.gh.gamecenter.home.test_v2.HomeItemGameTestV2ViewHolder
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
import com.gh.gamecenter.servers.GameServersActivity
|
||||
import com.gh.gamecenter.servers.gametest2.GameServerTestV2Activity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
@ -1270,38 +1269,51 @@ class GameFragmentAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGameCollectionExposureEventList(itemData: GameItemData): ArrayList<ExposureEvent> {
|
||||
private fun getHomeGameCollectionExposureEventList(
|
||||
itemData: GameItemData,
|
||||
refreshCurrentPosition: Int = -1
|
||||
): ArrayList<ExposureEvent> {
|
||||
val exposureList = arrayListOf<ExposureEvent>()
|
||||
runOnIoThread(true) {
|
||||
itemData.gameCollection?.gameCollectionItemDataList?.forEachIndexed { index, gameCollectionItemData ->
|
||||
val gameCollection = gameCollectionItemData.homeGameCollectionItem
|
||||
val gameCollectionSource =
|
||||
listOf(
|
||||
ExposureSource("游戏单合集", itemData.gameCollection?.id ?: ""),
|
||||
ExposureSource("游戏单", "${gameCollection?.title} + ${gameCollection?.id}")
|
||||
)
|
||||
val exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = GameEntity().apply {
|
||||
isAdData = gameCollection?.adIconActive ?: false
|
||||
outerSequence = gameCollectionItemData.outerSequence
|
||||
sequence = index
|
||||
},
|
||||
basicSource = mBasicExposureSource,
|
||||
source = gameCollectionSource
|
||||
)
|
||||
gameCollection?.games?.forEach {
|
||||
it.exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = it.apply {
|
||||
isAdData = gameCollection.adIconActive
|
||||
outerSequence = gameCollectionItemData.outerSequence
|
||||
sequence = index
|
||||
},
|
||||
basicSource = mBasicExposureSource,
|
||||
source = gameCollectionSource
|
||||
)
|
||||
itemData.gameCollection?.gameCollectionItemDataList?.run {
|
||||
val currentIndex = if (itemData.gameCollection?.style?.contains("refresh") == true) {
|
||||
refreshCurrentPosition % size
|
||||
} else -1
|
||||
forEachIndexed { index, gameCollectionItemData ->
|
||||
if (itemData.gameCollection?.style?.contains("refresh") == false || currentIndex == index) {
|
||||
gameCollectionItemData.homeGameCollectionItem?.let {
|
||||
val gameCollectionSource =
|
||||
listOf(
|
||||
ExposureSource("游戏单合集", itemData.gameCollection?.id ?: ""),
|
||||
ExposureSource("游戏单", "${it.title} + ${it.id}")
|
||||
)
|
||||
val gameExposureList = arrayListOf<ExposureEvent>()
|
||||
it.games?.forEach { game ->
|
||||
game.isAdData = it.adIconActive
|
||||
game.outerSequence = gameCollectionItemData.outerSequence
|
||||
game.sequence = index
|
||||
|
||||
val exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = game,
|
||||
basicSource = mBasicExposureSource,
|
||||
source = gameCollectionSource
|
||||
)
|
||||
game.exposureEvent = exposureEvent
|
||||
gameExposureList.add(exposureEvent)
|
||||
}
|
||||
exposureList.addAll(gameExposureList)
|
||||
gameCollectionItemData.exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = GameEntity().apply {
|
||||
adIconActive = it.adIconActive
|
||||
outerSequence = gameCollectionItemData.outerSequence
|
||||
sequence = index
|
||||
},
|
||||
basicSource = mBasicExposureSource,
|
||||
source = gameCollectionSource
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
gameCollectionItemData.exposureEvent = exposureEvent
|
||||
exposureList.add(exposureEvent)
|
||||
}
|
||||
}
|
||||
return exposureList
|
||||
@ -1309,7 +1321,7 @@ class GameFragmentAdapter(
|
||||
|
||||
private fun bindGameCollectionCarousel(holder: HomeGameCollectionCarouselViewHolder, position: Int) {
|
||||
val gameItemData = mItemDataList[position]
|
||||
gameItemData.exposureEventList = getGameCollectionExposureEventList(gameItemData)
|
||||
gameItemData.exposureEventList = getHomeGameCollectionExposureEventList(gameItemData)
|
||||
gameItemData.gameCollection?.let {
|
||||
holder.bindGameCollectionList(
|
||||
it,
|
||||
@ -1322,7 +1334,7 @@ class GameFragmentAdapter(
|
||||
|
||||
private fun bindGameCollectionSlide(holder: HomeGameCollectionSlideViewHolder, position: Int) {
|
||||
val gameItemData = mItemDataList[position]
|
||||
gameItemData.exposureEventList = getGameCollectionExposureEventList(gameItemData)
|
||||
gameItemData.exposureEventList = getHomeGameCollectionExposureEventList(gameItemData)
|
||||
gameItemData.gameCollection?.let {
|
||||
holder.bindGameCollectionSlide(
|
||||
it,
|
||||
@ -1335,7 +1347,7 @@ class GameFragmentAdapter(
|
||||
|
||||
private fun bindGameCollectionRefresh(holder: HomeGameCollectionRefreshViewHolder, position: Int) {
|
||||
val gameItemData = mItemDataList[position]
|
||||
gameItemData.exposureEventList = getGameCollectionExposureEventList(gameItemData)
|
||||
gameItemData.exposureEventList = getHomeGameCollectionExposureEventList(gameItemData, holder.currentPosition)
|
||||
gameItemData.gameCollection?.let {
|
||||
holder.bindGameCollectionRefresh(
|
||||
it,
|
||||
@ -1343,7 +1355,7 @@ class GameFragmentAdapter(
|
||||
mViewModel.blockData?.link ?: "",
|
||||
mViewModel.blockData?.name ?: ""
|
||||
) {
|
||||
mViewModel.changeGameCollectionRefresh(it.id)
|
||||
mViewModel.changeGameCollectionRefresh(it.id, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,17 +598,17 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
}
|
||||
}
|
||||
|
||||
fun changeGameCollectionRefresh(collectionId: String): Boolean {
|
||||
fun changeGameCollectionRefresh(collectionId: String, isRefreshClick: Boolean): Boolean {
|
||||
val page = (mRefreshGameCollectionPageMap[collectionId] ?: 1) + 1
|
||||
return if (page != 0) {
|
||||
getGameCollectionRefresh(collectionId, page)
|
||||
getGameCollectionRefresh(collectionId, page, isRefreshClick)
|
||||
true // 表示需要从接口获取数据
|
||||
} else {
|
||||
false // 表示已加载完毕
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGameCollectionRefresh(collectionId: String, page: Int) {
|
||||
private fun getGameCollectionRefresh(collectionId: String, page: Int, isRefreshClick: Boolean) {
|
||||
mSensitiveApi.getGameCollectionRefresh(collectionId, "block", page, 1)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -622,6 +622,15 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
addAll(response)
|
||||
}
|
||||
}
|
||||
|
||||
// 手动点击刷新获取时,若游戏单内游戏被全部屏蔽会自动获取下一个游戏单
|
||||
if (isRefreshClick) {
|
||||
val filterGameList = RegionSettingHelper.filterGame(response[0].games)
|
||||
if (filterGameList.isEmpty()) {
|
||||
changeGameCollectionRefresh(collectionId, true)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// -1 表示加载完毕
|
||||
mRefreshGameCollectionPageMap[collectionId] = -1
|
||||
@ -707,6 +716,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
if (!(!isTopItemShown && index == 0)
|
||||
&& !shouldShowDivider
|
||||
&& !hideSubjectName
|
||||
&& !(subjectEntity.type == "game_list_collection" && subjectEntity.style == LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_VERTICAL_REFRESH_STYLE)
|
||||
) {
|
||||
mItemDataListCache.add(getBlankSpacingItem())
|
||||
}
|
||||
@ -1006,7 +1016,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
}
|
||||
for (item in subjectEntity.gameListCollection!!) {
|
||||
item.games = RegionSettingHelper.filterGame(item.games)
|
||||
if (!item.games.isNullOrEmpty() || subjectEntity.style?.contains("carousel") == true) {
|
||||
if (!item.games.isNullOrEmpty() || subjectEntity.style == LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_CAROUSEL_STYLE || subjectEntity.style == LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_SMALL_SLIDE_STYLE) {
|
||||
add(
|
||||
GameCollectionListItemData(
|
||||
homeGameCollectionItem = item,
|
||||
@ -1017,6 +1027,13 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
}
|
||||
}
|
||||
}
|
||||
if (itemDataList.isEmpty()) {
|
||||
if (subjectEntity.style?.contains("refresh") == true) {
|
||||
subjectEntity.id?.let { changeGameCollectionRefresh(it, false) }
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
// 轮播图样式需要至少3个游戏单
|
||||
if ((subjectEntity.style == LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_CAROUSEL_STYLE && itemDataList.size >= 3) || subjectEntity.style != LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_CAROUSEL_STYLE) {
|
||||
if (subjectEntity.style?.contains("refresh") == false) {
|
||||
|
||||
@ -15,10 +15,19 @@ import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
class CommonCollectionAdapter(
|
||||
context: Context,
|
||||
private var mSubjectEntity: SubjectEntity,
|
||||
private var mClickClosure: (position: Int, contentEntity: CommonCollectionContentEntity) -> Unit,
|
||||
private var mExposureClosure: (position: Int, entity: ExposureLinkEntity) -> Unit
|
||||
) : BaseRecyclerAdapter<CommonCollectionItemViewHolder>(context) {
|
||||
|
||||
private var mExposureClosure: ((position: Int, entity: ExposureLinkEntity) -> Unit)? = null
|
||||
private var mClickClosure: ((position: Int, contentEntity: CommonCollectionContentEntity) -> Unit)? = null
|
||||
|
||||
fun setCallback(
|
||||
clickClosure: ((position: Int, contentEntity: CommonCollectionContentEntity) -> Unit),
|
||||
exposureClosure: ((position: Int, entity: ExposureLinkEntity) -> Unit)
|
||||
) {
|
||||
mClickClosure = clickClosure
|
||||
mExposureClosure = exposureClosure
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CommonCollectionItemViewHolder {
|
||||
return CommonCollectionItemViewHolder(parent.toBinding())
|
||||
}
|
||||
@ -45,7 +54,7 @@ class CommonCollectionAdapter(
|
||||
}
|
||||
|
||||
if (linkEntity.type == "game") {
|
||||
mExposureClosure.invoke(position, linkEntity)
|
||||
mExposureClosure?.invoke(position, linkEntity)
|
||||
}
|
||||
|
||||
holder.binding.apply {
|
||||
@ -81,7 +90,7 @@ class CommonCollectionAdapter(
|
||||
rootParams.rightMargin = if (position == itemCount - 1) 16F.dip2px() else 0
|
||||
root.layoutParams = rootParams
|
||||
|
||||
root.setOnClickListener { mClickClosure.invoke(position, contentEntity) }
|
||||
root.setOnClickListener { mClickClosure?.invoke(position, contentEntity) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -55,15 +55,20 @@ class CommonCollectionViewHolder(val binding: CommonCollectionListBinding) : Bas
|
||||
}
|
||||
}
|
||||
})
|
||||
adapter = CommonCollectionAdapter(context, mCollection!!, clickClosure, exposureClosure)
|
||||
adapter = CommonCollectionAdapter(context, mCollection!!).also {
|
||||
it.setCallback(clickClosure, exposureClosure)
|
||||
}
|
||||
} else {
|
||||
mLayoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
if (itemDecorationCount > 0) {
|
||||
removeItemDecorationAt(0)
|
||||
}
|
||||
addItemDecoration(SpacingItemDecoration(notDecorateTheFirstItem = true, left = 8f.dip2px()))
|
||||
addItemDecoration(SpacingItemDecoration(notDecorateTheFirstItem = true, left = 8F.dip2px()))
|
||||
layoutManager = mLayoutManager
|
||||
(adapter as CommonCollectionAdapter).checkResetData(mCollection!!)
|
||||
(adapter as CommonCollectionAdapter).apply {
|
||||
setCallback(clickClosure, exposureClosure)
|
||||
checkResetData(mCollection!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ class GameCollectionHotListAdapter(
|
||||
private val mPath: String,
|
||||
private val mBasicExposureSource: List<ExposureSource>
|
||||
) : ListAdapter<GameCollectionListItemData>(context), IExposable {
|
||||
private val mCoverWidth = (DisplayUtils.getScreenWidth() - 40F.dip2px()) / 2
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == itemCount - 1) ItemViewType.ITEM_FOOTER else ItemViewType.ITEM_BODY
|
||||
}
|
||||
@ -94,7 +95,7 @@ class GameCollectionHotListAdapter(
|
||||
stampIv.setBackgroundResource(if (entity?.stamp == "official") R.drawable.label_game_collection_official else R.drawable.label_game_collection_special_choice)
|
||||
titleTv.text = entity?.title
|
||||
userTv.text = entity?.user?.name
|
||||
coverImage.setTag(ImageUtils.TAG_TARGET_WIDTH, DisplayUtils.getScreenWidth() - 40F.dip2px())
|
||||
coverImage.setTag(ImageUtils.TAG_TARGET_WIDTH, mCoverWidth)
|
||||
ImageUtils.display(coverImage, entity?.cover)
|
||||
ImageUtils.display(userIv, entity?.user?.icon)
|
||||
|
||||
|
||||
@ -55,6 +55,7 @@ class GameCollectionSquareAdapter(
|
||||
private val mRefreshCallback: () -> Unit
|
||||
) :
|
||||
ListAdapter<GameCollectionListItemData>(context), IExposable {
|
||||
private val mPosterWidth = DisplayUtils.getScreenWidth() - 32F.dip2px()
|
||||
|
||||
override fun setListData(updateData: MutableList<GameCollectionListItemData>?) {
|
||||
if (updateData == null) {
|
||||
@ -409,7 +410,7 @@ class GameCollectionSquareAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
class GameCollectionSquareItemViewHolder(val binding: GameCollectionSquareItemBinding) :
|
||||
inner class GameCollectionSquareItemViewHolder(val binding: GameCollectionSquareItemBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun bindGameCollection(
|
||||
@ -421,6 +422,7 @@ class GameCollectionSquareAdapter(
|
||||
) {
|
||||
binding.run {
|
||||
val context = root.context
|
||||
poster.setTag(ImageUtils.TAG_TARGET_WIDTH, mPosterWidth)
|
||||
display(poster, gamesCollectionEntity.cover)
|
||||
display(userIv, gamesCollectionEntity.user?.icon)
|
||||
titleTv.text = gamesCollectionEntity.title
|
||||
|
||||
@ -324,17 +324,18 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
||||
}
|
||||
}
|
||||
|
||||
fun changeGameCollectionRefresh(collectionId: String): Boolean {
|
||||
fun changeGameCollectionRefresh(collectionId: String, isRefreshClick: Boolean): Boolean {
|
||||
val page = (mRefreshGameCollectionPageMap[collectionId] ?: 1) + 1
|
||||
return if (page != 0) {
|
||||
getGameCollectionRefresh(collectionId, page)
|
||||
getGameCollectionRefresh(collectionId, page, isRefreshClick)
|
||||
true // 表示需要从接口获取数据
|
||||
} else {
|
||||
false // 表示已加载完毕
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGameCollectionRefresh(collectionId: String, page: Int) {
|
||||
private fun getGameCollectionRefresh(collectionId: String, page: Int, isRefreshClick: Boolean) {
|
||||
// 每次获取一个游戏单
|
||||
mApi.getGameCollectionRefresh(collectionId, "home_content", page, 1)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -348,6 +349,15 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
||||
addAll(response)
|
||||
}
|
||||
}
|
||||
|
||||
// 手动点击刷新获取时,若游戏单内游戏被全部屏蔽会自动获取下一个游戏单
|
||||
if (isRefreshClick) {
|
||||
val filterGameList = RegionSettingHelper.filterGame(response[0].games)
|
||||
if (filterGameList.isEmpty()) {
|
||||
changeGameCollectionRefresh(collectionId, true)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// -1 表示加载完毕
|
||||
mRefreshGameCollectionPageMap[collectionId] = -1
|
||||
@ -882,12 +892,19 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
||||
}
|
||||
for (item in homeContent.linkGameCollection!!) {
|
||||
item.games = RegionSettingHelper.filterGame(item.games)
|
||||
if (!item.games.isNullOrEmpty() || homeContent.style.contains("carousel")) {
|
||||
if (!item.games.isNullOrEmpty() || homeContent.style == LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_CAROUSEL_STYLE || homeContent.style == LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_SMALL_SLIDE_STYLE) {
|
||||
add(GameCollectionListItemData(homeGameCollectionItem = item))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (itemDataList.isEmpty()) {
|
||||
if (homeContent.style.contains("refresh")) {
|
||||
changeGameCollectionRefresh(homeContent.linkId, false)
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
// 轮播图样式需要至少3个游戏单
|
||||
if ((homeContent.style == LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_CAROUSEL_STYLE && itemDataList.size >= 3) || homeContent.style != LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_CAROUSEL_STYLE) {
|
||||
if (!homeContent.style.contains("refresh")) {
|
||||
|
||||
@ -1045,59 +1045,72 @@ class LegacyHomeFragmentAdapterAssistant(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getGameCollectionExposureEventList(itemData: LegacyHomeItemData): ArrayList<ExposureEvent> {
|
||||
private fun getHomeGameCollectionExposureEventList(
|
||||
itemData: LegacyHomeItemData,
|
||||
refreshCurrentPosition: Int = -1
|
||||
): ArrayList<ExposureEvent> {
|
||||
val exposureList = arrayListOf<ExposureEvent>()
|
||||
runOnIoThread(true) {
|
||||
itemData.gameCollection?.gameCollectionItemDataList?.forEachIndexed { index, gameCollectionItemData ->
|
||||
val gameCollection = gameCollectionItemData.homeGameCollectionItem
|
||||
val gameCollectionSource =
|
||||
listOf(
|
||||
ExposureSource("游戏单合集", itemData.gameCollection?.id ?: ""),
|
||||
ExposureSource("游戏单", "${gameCollection?.title} + ${gameCollection?.id}")
|
||||
)
|
||||
val exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = GameEntity().apply {
|
||||
isAdData = gameCollection?.adIconActive ?: false
|
||||
outerSequence = itemData.blockPosition
|
||||
sequence = index
|
||||
},
|
||||
basicSource = mBasicExposureSources,
|
||||
source = gameCollectionSource
|
||||
)
|
||||
gameCollection?.games?.forEach {
|
||||
it.exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = it.apply {
|
||||
isAdData = gameCollection.adIconActive
|
||||
outerSequence = itemData.blockPosition
|
||||
sequence = index
|
||||
},
|
||||
basicSource = mBasicExposureSources,
|
||||
source = gameCollectionSource
|
||||
)
|
||||
itemData.gameCollection?.gameCollectionItemDataList?.run {
|
||||
val currentIndex = if (itemData.gameCollection?.style?.contains("refresh") == true) {
|
||||
refreshCurrentPosition % size
|
||||
} else -1
|
||||
forEachIndexed { index, gameCollectionItemData ->
|
||||
if (itemData.gameCollection?.style?.contains("refresh") == false || currentIndex == index) {
|
||||
gameCollectionItemData.homeGameCollectionItem?.let {
|
||||
val gameCollectionSource =
|
||||
listOf(
|
||||
ExposureSource("游戏单合集", itemData.gameCollection?.id ?: ""),
|
||||
ExposureSource("游戏单", "${it.title} + ${it.id}")
|
||||
)
|
||||
val gameExposureList = arrayListOf<ExposureEvent>()
|
||||
it.games?.forEach { game ->
|
||||
game.isAdData = it.adIconActive
|
||||
game.outerSequence = itemData.blockPosition
|
||||
game.sequence = index
|
||||
|
||||
val exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = game,
|
||||
basicSource = mBasicExposureSources,
|
||||
source = gameCollectionSource
|
||||
)
|
||||
game.exposureEvent = exposureEvent
|
||||
gameExposureList.add(exposureEvent)
|
||||
}
|
||||
exposureList.addAll(gameExposureList)
|
||||
gameCollectionItemData.exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity = GameEntity().apply {
|
||||
adIconActive = it.adIconActive
|
||||
outerSequence = itemData.blockPosition
|
||||
sequence = index
|
||||
},
|
||||
basicSource = mBasicExposureSources,
|
||||
source = gameCollectionSource
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
gameCollectionItemData.exposureEvent = exposureEvent
|
||||
exposureList.add(exposureEvent)
|
||||
}
|
||||
}
|
||||
return exposureList
|
||||
}
|
||||
|
||||
private fun bindGameCollectionCarousel(holder: HomeGameCollectionCarouselViewHolder, item: LegacyHomeItemData) {
|
||||
item.exposureEventList = getGameCollectionExposureEventList(item)
|
||||
item.exposureEventList = getHomeGameCollectionExposureEventList(item)
|
||||
item.gameCollection?.let { holder.bindGameCollectionList(it, "首页内容列表") }
|
||||
}
|
||||
|
||||
private fun bindGameCollectionSlide(holder: HomeGameCollectionSlideViewHolder, item: LegacyHomeItemData) {
|
||||
item.exposureEventList = getGameCollectionExposureEventList(item)
|
||||
item.exposureEventList = getHomeGameCollectionExposureEventList(item)
|
||||
item.gameCollection?.let { holder.bindGameCollectionSlide(it, "首页内容列表") }
|
||||
}
|
||||
|
||||
private fun bindGameCollectionRefresh(holder: HomeGameCollectionRefreshViewHolder, item: LegacyHomeItemData) {
|
||||
item.exposureEventList = getGameCollectionExposureEventList(item)
|
||||
item.exposureEventList = getHomeGameCollectionExposureEventList(item, holder.currentPosition)
|
||||
item.gameCollection?.let {
|
||||
holder.bindGameCollectionRefresh(it, "首页内容列表") {
|
||||
if (mAdapter is HomeFragmentAdapter) {
|
||||
(mAdapter as HomeFragmentAdapter).viewModel.changeGameCollectionRefresh(it.id)
|
||||
(mAdapter as HomeFragmentAdapter).viewModel.changeGameCollectionRefresh(it.id, true)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ class HomeGameCollectionCarouselAdapter(
|
||||
private val mBlockName: String = ""
|
||||
) :
|
||||
BaseRecyclerAdapter<HomeGameCollectionCarouselAdapter.HomeGameCollectionCardViewHolder>(context) {
|
||||
private val mPosterWidth = DisplayUtils.getScreenWidth() - 50F.dip2px()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||
HomeGameCollectionCardViewHolder(HomeGameCollectionCarouselItemCell(mContext).apply { inflate() })
|
||||
@ -69,7 +70,7 @@ class HomeGameCollectionCarouselAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
class HomeGameCollectionCardViewHolder(cell: HomeGameCollectionCarouselItemCell) :
|
||||
inner class HomeGameCollectionCardViewHolder(val cell: HomeGameCollectionCarouselItemCell) :
|
||||
BaseRecyclerViewHolder<Any>(cell) {
|
||||
fun bindGameCollectionCard(
|
||||
binding: HomeGameCollectionCardItemBinding,
|
||||
@ -83,9 +84,9 @@ class HomeGameCollectionCarouselAdapter(
|
||||
binding.run {
|
||||
val context = root.context
|
||||
val gamesCollectionEntity = itemData.homeGameCollectionItem
|
||||
root.layoutParams.width = DisplayUtils.getScreenWidth() - 50F.dip2px()
|
||||
root.layoutParams.width = mPosterWidth
|
||||
if (gamesCollectionEntity != null) {
|
||||
poster.setTag(ImageUtils.TAG_TARGET_WIDTH, DisplayUtils.getScreenWidth() - 50F.dip2px())
|
||||
poster.setTag(ImageUtils.TAG_TARGET_WIDTH, mPosterWidth)
|
||||
ImageUtils.display(poster, gamesCollectionEntity.cover)
|
||||
ImageUtils.display(userIv, gamesCollectionEntity.user?.icon)
|
||||
titleTv.text = gamesCollectionEntity.title
|
||||
|
||||
@ -26,7 +26,7 @@ class HomeGameCollectionRefreshViewHolder(val binding: HomeGameCollectionRefresh
|
||||
BaseRecyclerViewHolder<ViewHolder>(binding.root) {
|
||||
private var mIsHorizontal = false
|
||||
private var mSpanCount = 0
|
||||
private var mCurrentPosition = 0
|
||||
var currentPosition = 0
|
||||
private var mSnapHelper: SpanCountPagerSnapHelper? = null
|
||||
private var mGameCollectionList: List<GameCollectionListItemData>? = null
|
||||
private var mGameCollectionItemData: GameCollectionListItemData? = null
|
||||
@ -145,7 +145,7 @@ class HomeGameCollectionRefreshViewHolder(val binding: HomeGameCollectionRefresh
|
||||
binding.refreshLottie.setOnClickListener {
|
||||
if (!binding.refreshLottie.isAnimating) {
|
||||
binding.refreshLottie.playAnimation()
|
||||
mCurrentPosition++
|
||||
currentPosition++
|
||||
if (!refreshAction()) {
|
||||
refreshGameCollection()
|
||||
if (!mIsHorizontal) changeSpanCountIfNeeded()
|
||||
@ -170,7 +170,7 @@ class HomeGameCollectionRefreshViewHolder(val binding: HomeGameCollectionRefresh
|
||||
|
||||
private fun refreshGameCollection() {
|
||||
mGameCollectionList?.let {
|
||||
mGameCollectionItemData = it.safelyGetInRelease(mCurrentPosition % it.size)
|
||||
mGameCollectionItemData = it.safelyGetInRelease(currentPosition % it.size)
|
||||
mGameCollection = mGameCollectionItemData?.homeGameCollectionItem
|
||||
mGameList = mGameCollection?.games ?: listOf()
|
||||
mSpanCount = if (mGameList.size < 3) mGameList.size else 3
|
||||
|
||||
@ -85,7 +85,7 @@ class HomeGameCollectionSlideAdapter(
|
||||
listOf(gameItem1, gameItem2, gameItem3).forEachIndexed { index, binding ->
|
||||
binding.root.goneIf(games.size < index + 1) {
|
||||
val gameEntity = games[index]
|
||||
holder.updateGameItem(binding, gameEntity, gameCollectionItemData)
|
||||
holder.updateGameItem(binding, gameEntity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ class HomeGameCollectionSlideAdapter(
|
||||
mContext,
|
||||
gameEntity.id,
|
||||
BaseActivity.mergeEntranceAndPath(mEntrance, "游戏单合集"),
|
||||
gameCollectionItemData?.exposureEvent
|
||||
gameEntity.exposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -289,9 +289,9 @@ class HomeGameCollectionSlideAdapter(
|
||||
(itemView as HomeGameCollectionBigSlideCardCell).binding?.run {
|
||||
|
||||
when (position) {
|
||||
0 -> updateGameItem(gameItem1, dataList[position], mGameCollectionListItemData)
|
||||
1 -> updateGameItem(gameItem2, dataList[position], mGameCollectionListItemData)
|
||||
2 -> updateGameItem(gameItem3, dataList[position], mGameCollectionListItemData)
|
||||
0 -> updateGameItem(gameItem1, dataList[position])
|
||||
1 -> updateGameItem(gameItem2, dataList[position])
|
||||
2 -> updateGameItem(gameItem3, dataList[position])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -312,7 +312,7 @@ class HomeGameCollectionSlideAdapter(
|
||||
listOf(gameItem1, gameItem2, gameItem3).forEachIndexed { index, binding ->
|
||||
binding.root.goneIf(games.size < index + 1) {
|
||||
val gameEntity = games[index]
|
||||
updateGameItem(binding, gameEntity, mGameCollectionListItemData)
|
||||
updateGameItem(binding, gameEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -323,8 +323,7 @@ class HomeGameCollectionSlideAdapter(
|
||||
|
||||
fun updateGameItem(
|
||||
binding: ItemHomeGameCollectionBigSlideCardGameBinding,
|
||||
gameEntity: GameEntity,
|
||||
itemData: GameCollectionListItemData? = null
|
||||
gameEntity: GameEntity
|
||||
) {
|
||||
binding.root.visibility = View.VISIBLE
|
||||
|
||||
@ -340,7 +339,7 @@ class HomeGameCollectionSlideAdapter(
|
||||
null,
|
||||
mEntrance,
|
||||
"游戏单合集",
|
||||
itemData?.exposureEvent,
|
||||
gameEntity.exposureEvent,
|
||||
clickCallback = null,
|
||||
refreshCallback = {
|
||||
DownloadItemUtils.updateItem(
|
||||
@ -381,7 +380,7 @@ class HomeGameCollectionSlideAdapter(
|
||||
mContext,
|
||||
gameEntity.id,
|
||||
BaseActivity.mergeEntranceAndPath(mEntrance, "游戏单合集"),
|
||||
itemData?.exposureEvent
|
||||
gameEntity.exposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
package com.gh.gamecenter.pkg
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.utils.toJsonIgnoredNull
|
||||
import com.gh.gamecenter.core.provider.IPkgConfigProvider
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Route(path = RouteConsts.provider.pkgConfig, name = "PkgConfig暴露服务")
|
||||
class PkgConfigProviderImpl: IPkgConfigProvider {
|
||||
|
||||
override fun getPkgConfig(): ArrayList<String> {
|
||||
val configList = arrayListOf<String>()
|
||||
|
||||
val sdk = when (BuildConfig.FLAVOR) {
|
||||
"tea" -> "头条"
|
||||
"kuaishou" -> "快手"
|
||||
"gdt" -> "广点通"
|
||||
else -> "普通包"
|
||||
} + " " + BuildConfig.SDK_VERSION + " (仅头条有效)"
|
||||
|
||||
val coreEvent = if (PkgHelper.getCoreEventGameCategory() == "online") {
|
||||
"网游"
|
||||
} else {
|
||||
"普通"
|
||||
}
|
||||
|
||||
configList.add(sdk)
|
||||
if (BuildConfig.FLAVOR == "kuaishou") {
|
||||
configList.add("appid: ${BuildConfig.SDK_APP_ID.ifEmpty { "81537" }}")
|
||||
configList.add("appname: ${BuildConfig.SDK_APP_NAME.ifEmpty { "guanghuanzhushou_1"}}")
|
||||
}
|
||||
|
||||
configList.add(HaloApp.getInstance().channel)
|
||||
configList.add("${PkgHelper.getActivateRatio()}%")
|
||||
configList.add(coreEvent)
|
||||
configList.add(PkgHelper.getPkgConfigLink()?.toJsonIgnoredNull() ?: "")
|
||||
|
||||
return configList
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
}
|
||||
@ -11,6 +11,7 @@ import com.gh.gamecenter.core.utils.SPUtils
|
||||
import java.nio.charset.Charset
|
||||
|
||||
object PkgHelper {
|
||||
private var mTempPkgConfigEntity : PkgConfigEntity.PkgLinkEntity? = null
|
||||
|
||||
private var mPkgConfigLink: PkgConfigEntity.PkgLinkEntity? = null
|
||||
private const val SP_PKG_CONFIG_IS_USED = "pkg_config_is_used"
|
||||
@ -25,7 +26,7 @@ object PkgHelper {
|
||||
/**
|
||||
* 获取激活比例
|
||||
*/
|
||||
fun getActivateRatio() : Int {
|
||||
fun getActivateRatio(): Int {
|
||||
return if (mActivateRatioFromInternet > 0) {
|
||||
mActivateRatioFromInternet
|
||||
} else {
|
||||
@ -41,17 +42,18 @@ object PkgHelper {
|
||||
}
|
||||
|
||||
fun getPkgConfig(isFromHomeTopTab: Boolean): PkgConfigEntity.PkgLinkEntity? {
|
||||
if (mPkgConfigLink == null
|
||||
&& !SPUtils.getBoolean(SP_PKG_CONFIG_IS_USED, false)
|
||||
if (!SPUtils.getBoolean(SP_PKG_CONFIG_IS_USED, false)
|
||||
&& BuildConfig.FIRST_LAUNCH.isNotEmpty()
|
||||
) {
|
||||
if (mPkgConfigLink == null) {
|
||||
mPkgConfigLink =
|
||||
String(Base64.decode(BuildConfig.FIRST_LAUNCH, Base64.DEFAULT), Charset.defaultCharset()).toObject()
|
||||
}
|
||||
|
||||
mPkgConfigLink =
|
||||
String(Base64.decode(BuildConfig.FIRST_LAUNCH, Base64.DEFAULT), Charset.defaultCharset()).toObject()
|
||||
mTempPkgConfigEntity = mPkgConfigLink
|
||||
|
||||
return if (isFromHomeTopTab) {
|
||||
if (mPkgConfigLink?.shouldStayAtHomePage != true && mPkgConfigLink?.homeBottomTab == "home") {
|
||||
markConfigUsed()
|
||||
if (mPkgConfigLink?.shouldStayAtHomePage == true && mPkgConfigLink?.homeBottomTab == "home") {
|
||||
mPkgConfigLink
|
||||
} else {
|
||||
null
|
||||
@ -61,6 +63,10 @@ object PkgHelper {
|
||||
}
|
||||
}
|
||||
|
||||
if (mPkgConfigLink != null) {
|
||||
mTempPkgConfigEntity = mPkgConfigLink
|
||||
}
|
||||
|
||||
return mPkgConfigLink
|
||||
}
|
||||
|
||||
@ -70,7 +76,7 @@ object PkgHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取特殊包配置
|
||||
* 从接口获取特殊包配置
|
||||
*/
|
||||
fun requestPkgConfig(configId: String) {
|
||||
if (SPUtils.getBoolean(SP_PKG_CONFIG_IS_USED, false)) return
|
||||
@ -80,7 +86,10 @@ object PkgHelper {
|
||||
mActivateRatioFromInternet = it.data?.activateRatio ?: 0
|
||||
mCoreEventGameCategory = it.data?.coreEventGameCategory
|
||||
}
|
||||
}
|
||||
|
||||
fun getPkgConfigLink(): PkgConfigEntity.PkgLinkEntity? {
|
||||
return mTempPkgConfigEntity
|
||||
}
|
||||
|
||||
}
|
||||
@ -534,8 +534,7 @@ class SearchGameIndexAdapter(
|
||||
if (key.contains(download.packageName) && key.contains(download.gameId)) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size && mEntityList[position].game != null) {
|
||||
mEntityList[position].game!!.getEntryMap()[download.platform] = download
|
||||
notifyItemChanged(position)
|
||||
DownloadItemUtils.processDate(mEntityList[position].game!!, download, this, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,8 @@ import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
|
||||
|
||||
class GameBigImageViewHolder(val binding: ItemGameServerTestBigImageBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
private val mGameImageWidth = DisplayUtils.getScreenWidth() - 32F.dip2px()
|
||||
|
||||
fun bindAttachGame(
|
||||
holder: GameBigImageViewHolder,
|
||||
gameEntity: GameEntity,
|
||||
@ -32,7 +34,7 @@ class GameBigImageViewHolder(val binding: ItemGameServerTestBigImageBinding) :
|
||||
) {
|
||||
holder.bindGameInfo(gameEntity, adapter, exposureEvent, entrance)
|
||||
holder.binding.gameImage.goneIf(gameEntity.topVideo != null || gameEntity.homeSetting.image.isEmpty()) {
|
||||
binding.gameImage.setTag(ImageUtils.TAG_TARGET_WIDTH, DisplayUtils.getScreenWidth() - 32F.dip2px())
|
||||
binding.gameImage.setTag(ImageUtils.TAG_TARGET_WIDTH, mGameImageWidth)
|
||||
ImageUtils.display(binding.gameImage, gameEntity.homeSetting.image)
|
||||
val hierarchy = binding.gameImage.hierarchy
|
||||
try {
|
||||
|
||||
@ -102,6 +102,7 @@ class GameServerTestV2ListFragment :
|
||||
}
|
||||
|
||||
override fun initSkeletonScreen() {
|
||||
if (mBinding?.skeleton == null) return
|
||||
mSkeletonScreen = Skeleton.bind(mBinding?.skeleton)
|
||||
.shimmer(true)
|
||||
.angle(Constants.SHIMMER_ANGLE)
|
||||
|
||||
@ -3,6 +3,7 @@ package com.gh.ndownload
|
||||
import android.text.TextUtils
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.gh.download.DownloadDataHelper
|
||||
import com.gh.download.DownloadDataSimpleHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils
|
||||
import com.gh.gamecenter.common.utils.addMetaExtra
|
||||
@ -142,9 +143,7 @@ object NDownloadBridge : InnerDownloadListener, IErrorRetryHandler {
|
||||
override fun onProgressWithoutThrottle(id: String?, progress: Float) {
|
||||
if (id != null && (mStartUpTimeMap[id] ?: 0) > 0) {
|
||||
val startupTime: Long = System.currentTimeMillis() - (mStartUpTimeMap[id] ?: 0)
|
||||
getDownloadEntityFromSnapshot(id)?.let { downloadEntity ->
|
||||
downloadEntity.meta.put(DownloadEntity.DOWNLOAD_STARTUP_TIME_KEY, startupTime.toString())
|
||||
}
|
||||
DownloadDataSimpleHelper.updateDownloadDataSimpleEntity(id, downloadStartUpTime = startupTime)
|
||||
mStartUpTimeMap[id] = 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ object VArchiveHelper {
|
||||
if (isSuccess) {
|
||||
val vGameEntity = VHelper.getVGameSnapshot(packageName = packageName)
|
||||
runOnIoThread {
|
||||
val fileMd5 = MD5Utils.calculateMD5(mLatestArchiveFile)
|
||||
val fileMd5 = MD5Utils.calculateMD5(mLatestArchiveFile) ?: return@runOnIoThread
|
||||
val vArchiveEntity = VArchiveEntity(
|
||||
id = fileMd5,
|
||||
gameId = vGameEntity?.downloadEntity?.gameId ?: "",
|
||||
|
||||
@ -157,6 +157,9 @@ object VHelper {
|
||||
|
||||
if (it.type == EBPackage.TYPE_INSTALLED) {
|
||||
SensorsBridge.trackEvent("HaloFunInstallDone", "space_schema_type", if (isVSpace32) "32位" else "64位")
|
||||
if (isVSpace32) {
|
||||
SensorsBridge.trackEvent("HaloFunExpandInstallDone")
|
||||
}
|
||||
|
||||
if (skip64VSpaceInstalled) return@PackageChangeListener
|
||||
|
||||
@ -956,11 +959,21 @@ object VHelper {
|
||||
location: String? = null) {
|
||||
Utils.log(LOG_TAG, "检测是需要安装还是启动 ${downloadEntity.gameId}")
|
||||
|
||||
if (downloadEntity.name.isNullOrEmpty()) {
|
||||
SentryHelper.onEvent(
|
||||
"V_GAME_DOWNLOAD_ENTITY_NAME_EMPTY",
|
||||
"game_id",
|
||||
downloadEntity.gameId,
|
||||
"location",
|
||||
location
|
||||
)
|
||||
}
|
||||
|
||||
installOrLaunch(
|
||||
context,
|
||||
downloadEntity.packageName,
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.name,
|
||||
downloadEntity.name ?: "",
|
||||
downloadEntity.getGameCategory(),
|
||||
downloadEntity.getMetaExtra(KEY_BIT),
|
||||
location
|
||||
@ -1340,7 +1353,6 @@ object VHelper {
|
||||
VSpace32DialogFragment.showDownloadDialog(
|
||||
context,
|
||||
getVSpaceDownloadEntity(false),
|
||||
autoDownload = true,
|
||||
gameId = gameId,
|
||||
gameName = gameName
|
||||
)
|
||||
|
||||
@ -46,6 +46,7 @@ class VSpace32DialogFragment : BaseDraggableDialogFragment() {
|
||||
private val mBinding by lazy { DialogVspace32Binding.inflate(layoutInflater) }
|
||||
private var mIsLogInstallShow = false
|
||||
private var mIsLogAutoInstallClick = false
|
||||
private var mIsClickDownloadThisTime = false // 是否本次弹出Dialog点击的下载按钮
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
if (downloadEntity.url == mDownloadUrl && isAdded) {
|
||||
@ -146,6 +147,8 @@ class VSpace32DialogFragment : BaseDraggableDialogFragment() {
|
||||
downloadType
|
||||
).toJson()
|
||||
|
||||
mIsClickDownloadThisTime = true
|
||||
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
DownloadManager.getInstance().cancel(mDownloadUrl)
|
||||
DownloadManager.getInstance().add(downloadEntity)
|
||||
@ -165,7 +168,7 @@ class VSpace32DialogFragment : BaseDraggableDialogFragment() {
|
||||
|
||||
// 上面监听安装包名变化的 LiveData 监听有可能被冲掉了
|
||||
// 手动再检查一下安装状态,避免出现已安装但是没有 dismiss 弹窗的问题
|
||||
if (PackageUtils.isInstalled(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) {
|
||||
if (PackageUtils.isInstalledFromAllPackage(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
@ -221,7 +224,7 @@ class VSpace32DialogFragment : BaseDraggableDialogFragment() {
|
||||
val isVSpace32DownloadOnly =
|
||||
downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.VSPACE_32_DOWNLOAD_ONLY
|
||||
val isAutoInstall = SPUtils.getBoolean(Constants.SP_AUTO_INSTALL, true)
|
||||
if (!isVSpace32DownloadOnly && isAutoInstall && !mIsLogAutoInstallClick) {
|
||||
if (!isVSpace32DownloadOnly && isAutoInstall && !mIsLogAutoInstallClick && mIsClickDownloadThisTime) {
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_click")
|
||||
SensorsBridge.trackEvent("HaloFunExpandInstallButtonClick")
|
||||
mIsLogAutoInstallClick = true
|
||||
@ -260,15 +263,11 @@ class VSpace32DialogFragment : BaseDraggableDialogFragment() {
|
||||
|
||||
companion object {
|
||||
const val KEY_APP_ENTITY_32 = "app_entity_32"
|
||||
const val KEY_AUTO_DOWNLOAD = "auto_download"
|
||||
const val KEY_IS_UPDATE = "is_update"
|
||||
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(
|
||||
context: Context?,
|
||||
appEntity32: AppEntity,
|
||||
autoDownload: Boolean = false,
|
||||
isUpdate: Boolean = false,
|
||||
gameId: String = "",
|
||||
gameName: String = ""
|
||||
) {
|
||||
@ -291,8 +290,6 @@ class VSpace32DialogFragment : BaseDraggableDialogFragment() {
|
||||
putParcelable(KEY_APP_ENTITY_32, appEntity32)
|
||||
putString(EntranceConsts.KEY_GAME_ID, gameId)
|
||||
putString(EntranceConsts.KEY_GAME_NAME, gameName)
|
||||
putBoolean(KEY_AUTO_DOWNLOAD, autoDownload)
|
||||
putBoolean(KEY_IS_UPDATE, isUpdate)
|
||||
}
|
||||
}
|
||||
downloadDialog.show(
|
||||
@ -301,24 +298,6 @@ class VSpace32DialogFragment : BaseDraggableDialogFragment() {
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(
|
||||
context: Context?,
|
||||
appEntity32: AppEntity,
|
||||
gameEntity: GameEntity?,
|
||||
autoDownload: Boolean = false,
|
||||
isUpdate: Boolean = false
|
||||
) {
|
||||
showDownloadDialog(
|
||||
context,
|
||||
appEntity32,
|
||||
autoDownload,
|
||||
isUpdate,
|
||||
gameEntity?.id ?: "",
|
||||
gameEntity?.name ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
private fun hasDialogDisplayedInCurrentActivity(fragmentActivity: FragmentActivity): Boolean {
|
||||
val fragments: List<Fragment> = fragmentActivity.supportFragmentManager.fragments
|
||||
fragments.forEach { fragment ->
|
||||
|
||||
@ -39,6 +39,13 @@ import com.lightgame.download.DownloadStatus.*
|
||||
import com.lightgame.utils.AppManager
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* 1. 单独的 64 位组件的下载和更新使用本 VSpaceDialogFragment
|
||||
* 2. 已经安装了 64 位组件,后续操作所调起的 32 位组件的首次下载使用亦 VSpace32DialogFragment
|
||||
* 3. 64 位组件已安装且 64 位组件无需更新时,32 位组件需要更新时,使用本 VSpaceDialogFragment
|
||||
* 4. 64 位组件已安装且 64,32 位都需要更新时,64 位更新使用本 VSpaceDialogFragment
|
||||
* (同时下载64位组件和32位组件,但是32位在64位安装完成之前不触发安装), 32 位安装使用跳转 VSpaceUpdate32DialogFragment 进行
|
||||
*/
|
||||
class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
|
||||
private var mAppEntity64: AppEntity? = null
|
||||
@ -52,6 +59,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
private val mBinding by lazy { DialogVspaceBinding.inflate(layoutInflater) }
|
||||
private var mIsLogInstallShow = false
|
||||
private var mIsLogAutoInstallClick = false
|
||||
private var mIsClickDownloadThisTime = false // 是否本次弹出Dialog点击的下载按钮
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
if (((mAppEntity64 != null && downloadEntity.url == mDownloadUrl64) || (mAppEntity64 == null && downloadEntity.url == mDownloadUrl32)) && isAdded) {
|
||||
@ -92,13 +100,8 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
|
||||
val mViewModel = viewModelProvider<VSpaceDialogViewModel>()
|
||||
mViewModel.packageLiveData.observe(this) {
|
||||
if (it.packageName == VHelper.DEFAULT_VSPACE_PACKAGENAME) {
|
||||
if (mIsUpdate) showVSpace32UpdateDialogIfNeeded() else showVSpace32DownloadDialogIfNeeded()
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
if (it.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
show32BitRelatedDialogIfNeeded()
|
||||
dismissDialogIfInstalled()
|
||||
}
|
||||
|
||||
mBinding.downloadBtn.text = "下载畅玩助手服务组件"
|
||||
@ -157,6 +160,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity32, "开始")
|
||||
}
|
||||
|
||||
mIsClickDownloadThisTime = true
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
if (downloadEntity64 != null) {
|
||||
DownloadManager.getInstance().cancel(mDownloadUrl64)
|
||||
@ -204,13 +208,42 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
super.onStart()
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
|
||||
// 上面监听安装包名变化的 LiveData 监听有可能被冲掉了
|
||||
// 手动再检查一下安装状态,避免出现已安装但是没有 dismiss 弹窗的问题
|
||||
if (PackageUtils.isInstalled(requireContext(), VHelper.DEFAULT_VSPACE_PACKAGENAME)) {
|
||||
if (mIsUpdate) showVSpace32UpdateDialogIfNeeded() else showVSpace32DownloadDialogIfNeeded()
|
||||
dismissAllowingStateLoss()
|
||||
show32BitRelatedDialogIfNeeded()
|
||||
|
||||
// 检查安装状态,避免出现已安装但是没有 dismiss 弹窗的问题
|
||||
dismissDialogIfInstalled()
|
||||
}
|
||||
|
||||
// 弹下载/更新 32 位组件,前提是 64 位组件已经安装并安装了指定的版本
|
||||
private fun show32BitRelatedDialogIfNeeded() {
|
||||
if (PackageUtils.isInstalledFromAllPackage(requireContext(), VHelper.DEFAULT_VSPACE_PACKAGENAME)
|
||||
&& mAppEntity64?.version == PackageUtils.getVersionNameByPackageName(VHelper.DEFAULT_VSPACE_PACKAGENAME)) {
|
||||
// 该游戏需要 32 位组件,且后台配置的 32 位组件不为空
|
||||
if (mBit == "32" && mAppEntity32 != null && !mAppEntity32?.url.isNullOrEmpty()) {
|
||||
if (mIsUpdate) {
|
||||
showVSpace32UpdateDialog()
|
||||
} else {
|
||||
showVSpace32DownloadDialogIfNeeded()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PackageUtils.isInstalled(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) {
|
||||
}
|
||||
|
||||
/**
|
||||
* dismiss 当前 VSpaceDialogFragment (如果满足入参条件的话)
|
||||
*/
|
||||
private fun dismissDialogIfInstalled() {
|
||||
// 需要下载的 64 位组件是否与已安装的 64 位组件版本一致
|
||||
val is64BitVersionMatched =
|
||||
mAppEntity64 == null
|
||||
|| mAppEntity64?.version == PackageUtils.getVersionNameByPackageName(VHelper.DEFAULT_VSPACE_PACKAGENAME)
|
||||
|
||||
// 需要下载的 32 位组件是否与已安装的 32 位组件版本一致
|
||||
val is32BitVersionMatched =
|
||||
(mAppEntity32 == null || mBit != "32")
|
||||
|| mAppEntity32?.version == PackageUtils.getVersionNameByPackageName(VHelper.VSPACE_32BIT_PACKAGENAME)
|
||||
|
||||
if (is64BitVersionMatched && is32BitVersionMatched) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
@ -218,7 +251,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
private fun showVSpace32DownloadDialogIfNeeded() {
|
||||
val is32VSpaceInstalled =
|
||||
PackageUtils.isInstalledFromAllPackage(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)
|
||||
if (!is32VSpaceInstalled && mBit == "32" && mAppEntity32 != null && !mAppEntity32?.url.isNullOrEmpty()) {
|
||||
if (!is32VSpaceInstalled) {
|
||||
VSpace32DialogFragment.showDownloadDialog(
|
||||
requireContext(),
|
||||
mAppEntity32!!,
|
||||
@ -228,15 +261,13 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showVSpace32UpdateDialogIfNeeded() {
|
||||
if (mBit == "32" && mAppEntity32 != null && !mAppEntity32?.url.isNullOrEmpty()) {
|
||||
VSpaceUpdate32DialogFragment.showDownloadDialog(
|
||||
requireContext(),
|
||||
mAppEntity32!!,
|
||||
gameId = mGameId,
|
||||
gameName = mGameName
|
||||
)
|
||||
}
|
||||
private fun showVSpace32UpdateDialog() {
|
||||
VSpaceUpdate32DialogFragment.showDownloadDialog(
|
||||
requireContext(),
|
||||
mAppEntity32!!,
|
||||
gameId = mGameId,
|
||||
gameName = mGameName
|
||||
)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
@ -277,6 +308,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
DownloadManager.getInstance().resume(downloadEntity, false)
|
||||
}
|
||||
}
|
||||
|
||||
done -> {
|
||||
downloadBtn.setText(R.string.install)
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
@ -288,8 +320,14 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
mIsLogInstallShow = true
|
||||
}
|
||||
|
||||
if (SPUtils.getBoolean(Constants.SP_AUTO_INSTALL, true) && !mIsLogAutoInstallClick) {
|
||||
SensorsBridge.trackEvent("HaloFunInstallButtonClick", "space_schema_type", vSpaceType)
|
||||
if (SPUtils.getBoolean(
|
||||
Constants.SP_AUTO_INSTALL,
|
||||
true
|
||||
) && !mIsLogAutoInstallClick && mIsClickDownloadThisTime
|
||||
) {
|
||||
downloadBtn.postDelayed({
|
||||
SensorsBridge.trackEvent("HaloFunInstallButtonClick", "space_schema_type", vSpaceType)
|
||||
}, SENSORS_LOG_DELAY)
|
||||
mIsLogAutoInstallClick = true
|
||||
}
|
||||
|
||||
@ -316,6 +354,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
DownloadManager.getInstance().resume(downloadEntity, true)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
@ -328,6 +367,8 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
const val KEY_AUTO_DOWNLOAD = "auto_download"
|
||||
const val KEY_IS_UPDATE = "is_update"
|
||||
|
||||
const val SENSORS_LOG_DELAY = 1000L
|
||||
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(
|
||||
context: Context?,
|
||||
@ -370,7 +411,6 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
val downloadDialog = VSpaceDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
if (appEntity64 != null) putParcelable(KEY_APP_ENTITY_64, appEntity64)
|
||||
@ -388,6 +428,14 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示下载弹窗
|
||||
* @param appEntity64 需要下载的 64 位组件实体,不为空即代表需要下载
|
||||
* @param appEntity32 需要下载的 32 位组件实体,不为空即代表需要下载
|
||||
* @param gameEntity 游戏相关的实体
|
||||
* @param autoDownload 是否需要显示弹窗即进行下载
|
||||
* @param isUpdate 是否为更新
|
||||
*/
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(
|
||||
context: Context?,
|
||||
|
||||
@ -141,7 +141,8 @@ class VSpaceUpdate32DialogFragment : BaseDialogFragment() {
|
||||
|
||||
// 上面监听安装包名变化的 LiveData 监听有可能被冲掉了
|
||||
// 手动再检查一下安装状态,避免出现已安装但是没有 dismiss 弹窗的问题
|
||||
if (PackageUtils.isInstalled(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) {
|
||||
if (PackageUtils.isInstalledFromAllPackage(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)
|
||||
&& mAppEntity?.version == PackageUtils.getVersionNameByPackageName(VHelper.VSPACE_32BIT_PACKAGENAME)) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Matrix
|
||||
import android.view.WindowManager
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
@ -15,6 +16,7 @@ import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
@ -38,7 +40,11 @@ class ShortcutManager private constructor() {
|
||||
object : ShortcutAction() {
|
||||
override fun showPermissionDialog(context: Context, check: Int, executor: Executor) {
|
||||
runOnUiThread {
|
||||
mResult?.showPermissionDialog(executor)
|
||||
try {
|
||||
mResult?.showPermissionDialog(executor)
|
||||
} catch (e: WindowManager.BadTokenException) {
|
||||
ToastUtils.toast("创建快捷方式失败,请稍后再试")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,7 +58,11 @@ class ShortcutManager private constructor() {
|
||||
} else {
|
||||
//创建失败估计还是权限问题,直接弹出跳转权限设置
|
||||
runOnUiThread {
|
||||
mResult?.showPermissionDialog(executor)
|
||||
try {
|
||||
mResult?.showPermissionDialog(executor)
|
||||
} catch (e: WindowManager.BadTokenException) {
|
||||
ToastUtils.toast("创建快捷方式失败,请稍后再试")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,12 +227,12 @@ public class HaloApp extends MultiDexApplication {
|
||||
PlayerFactory.setPlayManager(Exo2PlayerManager.class);
|
||||
CacheFactory.setCacheManager(ExoPlayerCacheManager.class);
|
||||
|
||||
initFresco();
|
||||
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
initDataHelper();
|
||||
ExtensionsKt.doOnMainProcessOnly(this, () -> Tracker.init(this));
|
||||
|
||||
initFresco();
|
||||
|
||||
deviceRamSize = DeviceUtils.getTotalRamSizeOfDevice(this);
|
||||
mChannel = mFlavorProvider.getChannelStr(this);
|
||||
|
||||
|
||||
@ -474,4 +474,8 @@
|
||||
<string name="article_detail_top_category_dialog_title">请选择置顶类型</string>
|
||||
<string name="article_detail_top_success_toast">置顶成功</string>
|
||||
<string name="unsupported_browser_install_hint">此游戏不支持浏览器安装,已切换为助手安装</string>
|
||||
<string name="update_all_has_land_page_address_dialog_title">提示</string>
|
||||
<string name="update_all_has_land_page_address_dialog_content">部分游戏下载资源由第三方提供,此类游戏无法自动更新,请手动点击游戏【更新】按钮前往第三方网址更新游戏</string>
|
||||
<string name="update_all_has_land_page_address_dialog_confirm">我知道了</string>
|
||||
<string name="miui_open_adb_hint">请查看关闭教程,先开启开发者模式</string>
|
||||
</resources>
|
||||
|
||||
@ -7,9 +7,11 @@ import android.text.TextUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.bytedance.hume.readapk.HumeSDK
|
||||
import com.gh.gamecenter.TeaHelper
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import java.io.File
|
||||
@ -58,6 +60,11 @@ class FlavorProviderImp : IFlavorProvider {
|
||||
|
||||
override fun logCoreEvent() {
|
||||
logEvent("game_addiction")
|
||||
if (BuildConfig.ACTIVATE_REPORTING_RATIO == 1) {
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast("关键行为 game_addiction")
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
|
||||
private fun amILucky(percentage: Int = 100): Boolean {
|
||||
|
||||
@ -84,6 +84,10 @@ class AppProviderImpl : IAppProvider {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFlavor(): String {
|
||||
return "internal"
|
||||
}
|
||||
|
||||
override fun getIsBrandNewInstall(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -80,6 +80,10 @@ class AppProviderImpl : IAppProvider {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFlavor(): String {
|
||||
return "internal"
|
||||
}
|
||||
|
||||
override fun isUserAcceptPrivacyPolicy(context: Context): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -80,6 +80,10 @@ class AppProviderImpl : IAppProvider {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFlavor(): String {
|
||||
return "internal"
|
||||
}
|
||||
|
||||
override fun isUserAcceptPrivacyPolicy(context: Context): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.gamecenter.xapk.io
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.content.pm.PackageInstaller.Session
|
||||
import android.content.pm.PackageInstaller.SessionParams
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
@ -35,9 +36,6 @@ class SplitApksOutput(
|
||||
.packageInstaller
|
||||
// 创建安装会话并获取返回会话ID
|
||||
val sessionId = installer.createSession(it)
|
||||
.also { sessionId ->
|
||||
SessionPool.put(installer, sessionId)
|
||||
}
|
||||
// 开启安装会话
|
||||
val session = installer.openSession(sessionId)
|
||||
try {
|
||||
@ -59,24 +57,4 @@ class SplitApksOutput(
|
||||
} else {
|
||||
throw ApkOutputUnsupportedSplitApksException()
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private object SessionPool {
|
||||
private val sessionIdList = mutableListOf<Int>()
|
||||
|
||||
|
||||
fun put(installer: PackageInstaller, sessionId: Int) {
|
||||
sessionIdList.removeAll {
|
||||
installer.getSessionInfo(it) == null
|
||||
}
|
||||
|
||||
sessionIdList.add(sessionId)
|
||||
|
||||
installer.mySessions.forEach {
|
||||
if (!sessionIdList.contains(it.sessionId)) {
|
||||
installer.abandonSession(it.sessionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
init.internal.gradle
Normal file
65
init.internal.gradle
Normal file
@ -0,0 +1,65 @@
|
||||
allprojects { project ->
|
||||
buildscript {
|
||||
ext.booster_version = '4.9.0'
|
||||
ext.plugin_version = "0.3.0"
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven { url 'https://oss.sonatype.org/content/repositories/public' }
|
||||
maven { url "https://artifact.bytedance.com/repository/byteX/" }
|
||||
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// byteX
|
||||
classpath "com.bytedance.android.byteX:base-plugin:${plugin_version}"
|
||||
classpath "com.bytedance.android.byteX:const-inline-plugin:${plugin_version}"
|
||||
classpath "com.bytedance.android.byteX:method-call-opt-plugin:${plugin_version}"
|
||||
classpath "com.bytedance.android.byteX:field-assign-opt-plugin:${plugin_version}"
|
||||
|
||||
// booster
|
||||
classpath "com.didiglobal.booster:booster-gradle-plugin:$booster_version"
|
||||
classpath "com.didiglobal.booster:booster-transform-shared-preferences:$booster_version"
|
||||
classpath "com.didiglobal.booster:booster-transform-r-inline:$booster_version"
|
||||
classpath "com.didiglobal.booster:booster-transform-finalizer-watchdog-daemon:$booster_version"
|
||||
classpath "com.didiglobal.booster:booster-transform-res-check:$booster_version"
|
||||
classpath "com.didiglobal.booster:booster-transform-activity-thread:$booster_version"
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
mavenLocal()
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven { url 'https://oss.sonatype.org/content/repositories/public' }
|
||||
maven { url "https://artifact.bytedance.com/repository/byteX/" }
|
||||
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||
}
|
||||
|
||||
project.afterEvaluate {
|
||||
// apply plugin only with this init script
|
||||
if (project.name == "app") {
|
||||
project.apply plugin: 'com.didiglobal.booster'
|
||||
|
||||
project.apply plugin: "com.gh.gamecenter.plugin"
|
||||
|
||||
project.apply plugin: 'bytex'
|
||||
project.apply plugin: 'bytex.field_assign_opt' //去除重复的赋值 https://github.com/bytedance/ByteX/blob/master/field-assign-opt-plugin/README-zh.md
|
||||
|
||||
project.field_assign_opt {
|
||||
enable false
|
||||
enableInDebug false
|
||||
logLevel "INFO"
|
||||
removeLineNumber true // 同时移除赋值对应的行号信息(如果有的话),默认true。
|
||||
whiteList = [
|
||||
//白名单,ClassName.FieldName 。不支持模式匹配
|
||||
//"android.support.constraint.solver.ArrayRow.isSimpleDefinition"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -75,6 +75,7 @@ object RouteConsts {
|
||||
const val vpn = "/vpn/vpn"
|
||||
|
||||
const val pkg = "/pkg/pkg"
|
||||
const val pkgConfig = "/pkgConfig/pkgConfig"
|
||||
const val floatingwindow = "/floatingwindow/floatingwindow"
|
||||
|
||||
const val exposureManager = "/exposure/exposureManager"
|
||||
|
||||
@ -4,15 +4,24 @@ import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Build
|
||||
import android.text.Html
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.StyleSpan
|
||||
import android.view.*
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.gamecenter.common.R
|
||||
import com.gh.gamecenter.common.base.TrackableDialog
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.constant.Config
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.databinding.DialogAlertDefaultBinding
|
||||
import com.gh.gamecenter.common.databinding.DialogGuideBinding
|
||||
@ -45,7 +54,7 @@ object DialogHelper {
|
||||
confirmClickCallback: (() -> Unit)? = null,
|
||||
cancelClickCallback: (() -> Unit)? = null,
|
||||
extraConfig: Config? = null,
|
||||
uiModificationCallback: ((binding: DialogAlertDefaultBinding) -> Unit)? = null,
|
||||
uiModificationCallback: ((binding: DefaultDialogAlertDefaultBindingWrapper) -> Unit)? = null,
|
||||
trackMtaEvent: Boolean = false,
|
||||
mtaEvent: String = "",
|
||||
mtaKey: String = ""
|
||||
@ -112,7 +121,7 @@ object DialogHelper {
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
uiModificationCallback?.invoke(binding)
|
||||
uiModificationCallback?.invoke(DefaultDialogAlertDefaultBindingWrapper(dialog, binding))
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog.setContentView(contentView)
|
||||
@ -622,18 +631,6 @@ object DialogHelper {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context may be is application context
|
||||
* @return activity context
|
||||
*/
|
||||
fun checkDialogContext(context: Context?): Context? {
|
||||
if (context == null) {
|
||||
throw NullPointerException("dialog context is null")
|
||||
}
|
||||
return context as? Activity ?: AppManager.getInstance().currentActivity()
|
||||
|
||||
// currentActivity 是否存在 isDestroyed 的情况?
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showUnsupportedFeatureDialog(context: Context) {
|
||||
@ -655,6 +652,51 @@ object DialogHelper {
|
||||
)
|
||||
}
|
||||
|
||||
fun showMiuiOptimizationWarning(
|
||||
context: Context,
|
||||
onHintClick: () -> Unit,
|
||||
onConfirmClick: (DefaultDialogAlertDefaultBindingWrapper) -> Unit,
|
||||
) {
|
||||
showDialog(
|
||||
context = context,
|
||||
title = context.getString(R.string.miui_optimization_warning_dialog_title),
|
||||
content = SpannableStringBuilder(
|
||||
context.getString(R.string.miui_optimization_warning_dialog_content)
|
||||
).apply {
|
||||
setSpan(StyleSpan(Typeface.BOLD), 10, 15, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
|
||||
},
|
||||
confirmText = context.getString(R.string.miui_optimizaition_warning_dialog_confirm),
|
||||
cancelText = context.getString(R.string.miui_optimizaition_warning_dialog_cancel),
|
||||
extraConfig = Config(),
|
||||
uiModificationCallback = { binding ->
|
||||
binding.hintTv.text = context.getString(R.string.miui_optimizaition_warning_dialog_hint)
|
||||
binding.hintTv.visibility = View.VISIBLE
|
||||
binding.hintTv.paint.flags = Paint.UNDERLINE_TEXT_FLAG
|
||||
binding.hintTv.paint.isAntiAlias = true
|
||||
binding.hintTv.setTextColor(ContextCompat.getColor(context, R.color.theme_font))
|
||||
binding.hintTv.setOnClickListener {
|
||||
onHintClick.invoke()
|
||||
}
|
||||
binding.confirmTv.setOnClickListener {
|
||||
onConfirmClick.invoke(binding)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context may be is application context
|
||||
* @return activity context
|
||||
*/
|
||||
fun checkDialogContext(context: Context?): Context? {
|
||||
if (context == null) {
|
||||
throw NullPointerException("dialog context is null")
|
||||
}
|
||||
return context as? Activity ?: AppManager.getInstance().currentActivity()
|
||||
|
||||
// currentActivity 是否存在 isDestroyed 的情况?
|
||||
}
|
||||
|
||||
class Config(
|
||||
val hint: String = "",
|
||||
val showCloseIcon: Boolean = false,
|
||||
@ -665,4 +707,23 @@ object DialogHelper {
|
||||
val titleIcon: Int = -1
|
||||
)
|
||||
|
||||
/**
|
||||
* 通用Alert弹窗包装类,可通过该类代理一些Dialog相关的方法
|
||||
*/
|
||||
class DefaultDialogAlertDefaultBindingWrapper(
|
||||
private val dialog: Dialog,
|
||||
private val binding: DialogAlertDefaultBinding
|
||||
) {
|
||||
val root: View = binding.root
|
||||
val titleTv: TextView get() = binding.titleTv
|
||||
val contentTv: TextView get() = binding.contentTv
|
||||
val hintTv: TextView get() = binding.hintTv
|
||||
val centerDivider: View get() = binding.centerDivider
|
||||
val closeContainer: RelativeLayout get() = binding.closeContainer
|
||||
val cancelTv: TextView get() = binding.cancelTv
|
||||
val confirmTv: TextView get() = binding.confirmTv
|
||||
val lineView: View get() = binding.lineView
|
||||
fun dismiss() = dialog.dismiss()
|
||||
}
|
||||
|
||||
}
|
||||
@ -402,6 +402,10 @@ inline fun <reified T : Any> T.toJson(): String {
|
||||
return GsonUtils.toJson(this)
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> T.toJsonIgnoredNull(): String {
|
||||
return GsonUtils.toJsonIgnoreNull(this)
|
||||
}
|
||||
|
||||
fun String.insert(index: Int, string: String): String {
|
||||
return this.substring(0, index) + string + this.substring(index, this.length)
|
||||
}
|
||||
|
||||
@ -0,0 +1,92 @@
|
||||
package com.gh.gamecenter.common.utils;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MiuiUtils {
|
||||
|
||||
public static boolean isMiui() {
|
||||
return !TextUtils.isEmpty(SystemUtils.getSystemProperty("ro.miui.ui.version.name"));
|
||||
}
|
||||
|
||||
public static String getMiuiVersionName() {
|
||||
String versionName = SystemUtils.getSystemProperty("ro.miui.ui.version.name");
|
||||
return !TextUtils.isEmpty(versionName) ? versionName : "???";
|
||||
}
|
||||
|
||||
public static int getMiuiVersionCode() {
|
||||
try {
|
||||
return Integer.parseInt(Objects.requireNonNull(SystemUtils.getSystemProperty("ro.miui.ui.version.code")));
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getActualMiuiVersion() {
|
||||
return Build.VERSION.INCREMENTAL;
|
||||
}
|
||||
|
||||
private static int[] parseVersionIntoParts(String version) {
|
||||
try {
|
||||
String[] versionParts = version.split("\\.");
|
||||
int[] intVersionParts = new int[versionParts.length];
|
||||
|
||||
for (int i = 0; i < versionParts.length; i++)
|
||||
intVersionParts[i] = Integer.parseInt(versionParts[i]);
|
||||
|
||||
return intVersionParts;
|
||||
} catch (Exception e) {
|
||||
return new int[]{-1};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 0 if versions are equal, values less than 0 if ver1 is lower than ver2, value more than 0 if ver1 is higher than ver2
|
||||
*/
|
||||
private static int compareVersions(String version1, String version2) {
|
||||
if (version1.equals(version2))
|
||||
return 0;
|
||||
|
||||
int[] version1Parts = parseVersionIntoParts(version1);
|
||||
int[] version2Parts = parseVersionIntoParts(version2);
|
||||
|
||||
for (int i = 0; i < version2Parts.length; i++) {
|
||||
if (i >= version1Parts.length)
|
||||
return -1;
|
||||
|
||||
if (version1Parts[i] < version2Parts[i])
|
||||
return -1;
|
||||
|
||||
if (version1Parts[i] > version2Parts[i])
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static boolean isActualMiuiVersionAtLeast(String targetVer) {
|
||||
return compareVersions(getActualMiuiVersion(), targetVer) >= 0;
|
||||
}
|
||||
|
||||
@SuppressLint("PrivateApi")
|
||||
public static boolean isMiuiOptimizationDisabled() {
|
||||
final String miuiOptimization = SystemUtils.getSystemProperty("persist.sys.miui_optimization");
|
||||
if ("0".equals(miuiOptimization) || "false".equals(miuiOptimization))
|
||||
return true;
|
||||
|
||||
try {
|
||||
return (boolean) Class.forName("android.miui.AppOpsUtils")
|
||||
.getDeclaredMethod("isXOptMode")
|
||||
.invoke(null);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isFixedMiui() {
|
||||
return isActualMiuiVersionAtLeast("20.2.20") || isMiuiOptimizationDisabled();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.gh.gamecenter.common.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
|
||||
|
||||
object SystemUtils {
|
||||
@SuppressLint("PrivateApi")
|
||||
@JvmStatic
|
||||
fun getSystemProperty(key: String?): String? {
|
||||
return try {
|
||||
Class.forName("android.os.SystemProperties")
|
||||
.getDeclaredMethod("get", String::class.java)
|
||||
.invoke(null, key) as String
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否开启开发者选项
|
||||
* @param context 上下文
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isDevelopmentSettingsEnabled(context: Context): Boolean = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
Settings.Global.getInt(context.contentResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED) > 0
|
||||
} else {
|
||||
Settings.Secure.getInt(context.contentResolver, Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED) > 0
|
||||
}
|
||||
|
||||
}
|
||||
@ -74,4 +74,9 @@
|
||||
<string name="unsupported_feature_dialog_hint">当前版本不支持该功能,\n建议您升级到最新版本体验哦</string>
|
||||
<string name="unsupported_feature_dialog_confirm_text">体验升级</string>
|
||||
<string name="unspported_feature_dialog_cancel_text">取消</string>
|
||||
<string name="miui_optimization_warning_dialog_title">温馨提示</string>
|
||||
<string name="miui_optimization_warning_dialog_content">安装该游戏需要关闭MIUI优化,否则将无法解压安装\n注意:MIUI优化关闭后可能会导致手机系统不稳定,以及无法使用MIUI提供的服务。你可以在游戏安装完成后重新开启</string>
|
||||
<string name="miui_optimizaition_warning_dialog_confirm">立即关闭</string>
|
||||
<string name="miui_optimizaition_warning_dialog_cancel">以后再说</string>
|
||||
<string name="miui_optimizaition_warning_dialog_hint"><![CDATA[查看MIUI优化关闭教程>]]></string>
|
||||
</resources>
|
||||
@ -32,5 +32,7 @@ interface IAppProvider : IProvider {
|
||||
|
||||
fun getFlavorProvider(): IFlavorProvider
|
||||
|
||||
fun getFlavor(): String
|
||||
|
||||
fun getIsBrandNewInstall(): Boolean
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.gh.gamecenter.core.provider
|
||||
|
||||
import com.alibaba.android.arouter.facade.template.IProvider
|
||||
|
||||
interface IPkgConfigProvider : IProvider {
|
||||
|
||||
fun getPkgConfig(): ArrayList<String>
|
||||
|
||||
}
|
||||
@ -127,4 +127,14 @@ object SPUtils {
|
||||
editor.remove(key)
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用传入的 SP 来移除 KV
|
||||
*/
|
||||
@JvmStatic
|
||||
fun remove(sharedPreferences: SharedPreferences, key: String) {
|
||||
val editor = sharedPreferences.edit()
|
||||
editor.remove(key)
|
||||
editor.apply()
|
||||
}
|
||||
}
|
||||
@ -84,6 +84,10 @@ class AppProviderImpl : IAppProvider {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFlavor(): String {
|
||||
return "internal"
|
||||
}
|
||||
|
||||
override fun getIsBrandNewInstall(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -15,7 +15,6 @@ import androidx.core.content.ContextCompat
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.provider.*
|
||||
@ -84,8 +83,26 @@ class AboutFragment : ToolbarFragment() {
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
val appProvider = ARouter.getInstance().build(RouteConsts.provider.app).navigation() as? IAppProvider
|
||||
if (appProvider?.getFlavor() != "publish") {
|
||||
val pkgConfigProvider = ARouter.getInstance().build(RouteConsts.provider.pkgConfig).navigation() as? IPkgConfigProvider
|
||||
var clickCount = 0
|
||||
mBinding.appNameTv.setOnClickListener {
|
||||
clickCount = clickCount + 1
|
||||
if (clickCount % 5 == 0) {
|
||||
val configList = pkgConfigProvider?.getPkgConfig()
|
||||
var configString = ""
|
||||
configList?.forEach {
|
||||
if (it.isNotEmpty()) {
|
||||
configString = "$configString$it\n"
|
||||
}
|
||||
}
|
||||
toastLong(configString)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun initView() {
|
||||
|
||||
@ -72,6 +72,9 @@ class AppProviderImpl : IAppProvider {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFlavor(): String {
|
||||
return "internal"
|
||||
}
|
||||
|
||||
override fun isUserAcceptPrivacyPolicy(context: Context): Boolean {
|
||||
return true
|
||||
|
||||
Submodule ndownload updated: 47c4714e2b...e0a991aa7b
@ -7,7 +7,7 @@ versionCode=$(awk -v FS="versionCode = " 'NF>1{print $2}' dependencies.gradle |
|
||||
build_time=$(TZ=Asia/Shanghai date +'%Y-%m%d-%H%M')
|
||||
build_time_without_divider=$(TZ=Asia/Shanghai date +'%Y%m%d%H%M')L
|
||||
|
||||
post_init_script=init.gradle
|
||||
post_init_script=init.internal.gradle
|
||||
|
||||
git checkout module_common/build.gradle
|
||||
git checkout gradle.properties
|
||||
@ -26,7 +26,6 @@ git log --pretty=format:'%s' --max-count=20 --no-merges > app/src/main/assets/gi
|
||||
while getopts "c" arg
|
||||
do
|
||||
sed -i '260 a implementation(project(\x27:module_setting_compose\x27)) { exclude group: \x27androidx.swiperefreshlayout\x27 }' app/build.gradle
|
||||
post_init_script=init.gradle
|
||||
done
|
||||
|
||||
./gradlew rIR -I ${post_init_script}
|
||||
|
||||
@ -78,12 +78,12 @@ fi
|
||||
|
||||
# 保存快手 app_id
|
||||
if [ "${app_id}" != "" ]; then
|
||||
sed -i "s/String KUAI_SHOU_APP_ID = \"\"/String KUAI_SHOU_APP_ID = \"${app_id}\"/g" app/build.gradle
|
||||
sed -i "s/String SDK_APP_ID = \"\"/String SDK_APP_ID = \"${app_id}\"/g" app/build.gradle
|
||||
fi
|
||||
|
||||
# 保存快手 app_name
|
||||
if [ "${app_name}" != "" ]; then
|
||||
sed -i "s/String KUAI_SHOU_APP_NAME = \"\"/String KUAI_SHOU_APP_NAME = \"${app_name}\"/g" app/build.gradle
|
||||
sed -i "s/String SDK_APP_NAME = \"\"/String SDK_APP_NAME = \"${app_name}\"/g" app/build.gradle
|
||||
fi
|
||||
|
||||
# 保存推广时上报关键行为事件的游戏类型
|
||||
@ -93,14 +93,16 @@ fi
|
||||
|
||||
# 是否选择了 sdk 类型
|
||||
if [ "${sdk_platform}" != "" ]; then
|
||||
if [ "${activate_reporting_ratio}" == "" ]; then
|
||||
activate_reporting_ratio="100"
|
||||
fi
|
||||
# 调整上报比例
|
||||
sed -i "s/int ACTIVATE_REPORTING_RATIO = 100/int ACTIVATE_REPORTING_RATIO = ${activate_reporting_ratio}/g" app/build.gradle
|
||||
|
||||
sed -i "s/String SDK_VERSION = \"\"/String SDK_VERSION = \"${sdk_version}\"/g" app/build.gradle
|
||||
|
||||
# 头条包
|
||||
if [ "${sdk_platform}" == "toutiao" ]; then
|
||||
if [ "${activate_reporting_ratio}" == "" ]; then
|
||||
activate_reporting_ratio="100"
|
||||
fi
|
||||
# 调整上报比例
|
||||
sed -i "s/int ACTIVATE_REPORTING_RATIO = 100/int ACTIVATE_REPORTING_RATIO = ${activate_reporting_ratio}/g" app/build.gradle
|
||||
|
||||
if [ "${sdk_version}" == "5.3.0" ]; then
|
||||
sed -i "s/bytedanceApplog = \"6.14.3\"/bytedanceApplog = \"${sdk_version}\"/g" dependencies.gradle
|
||||
rm app/src/tea/java/com/gh/gamecenter/TeaHelper.kt
|
||||
|
||||
Reference in New Issue
Block a user