Compare commits
5 Commits
v5.36.3-10
...
pack/test-
| Author | SHA1 | Date | |
|---|---|---|---|
| 1023e0492b | |||
| 0fda3ecfcd | |||
| 166abd5c9b | |||
| af3102f6be | |||
| 93363f23b4 |
@ -71,8 +71,7 @@ android_build:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feature-GHZS-5816
|
||||
- feat/GHZSCY-5250
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
@ -153,5 +152,4 @@ oss-upload&send-email:
|
||||
- /usr/local/bin/python /ci-android-mail-jira-comment.py
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feature-GHZS-5816
|
||||
- feat/GHZSCY-5250
|
||||
@ -126,10 +126,6 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude 'META-INF/gradle/incremental.annotation.processors'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
debuggable true
|
||||
@ -352,7 +348,7 @@ dependencies {
|
||||
implementation "com.llew.huawei:verifier:${verifier}"
|
||||
|
||||
teaImplementation "com.bytedance.applog:RangersAppLog-Lite-cn:${bytedanceApplog}"
|
||||
teaImplementation "com.bytedance.ads:AppConvert:${bytedanceAppConvert}"
|
||||
teaImplementation "com.bytedance.applog:RangersAppLog-All-convert:${bytedanceApplog}"
|
||||
|
||||
implementation "net.lingala.zip4j:zip4j:${zip4j}"
|
||||
|
||||
@ -361,9 +357,7 @@ dependencies {
|
||||
|
||||
implementation "com.lg:easyfloat:${easyFloat}"
|
||||
|
||||
implementation ("com.lg:apksig:${apksig}") {
|
||||
exclude group: 'com.google.protobuf'
|
||||
}
|
||||
implementation "com.lg:apksig:${apksig}"
|
||||
|
||||
implementation "com.lg:gid:${gid}"
|
||||
|
||||
@ -403,6 +397,7 @@ dependencies {
|
||||
implementation(project(':module_message')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
// implementation(project(':feature:vpn'))
|
||||
implementation(project(':feature:pkg'))
|
||||
implementation(project(':feature:oaid'))
|
||||
implementation(project(':feature:floating-window'))
|
||||
@ -414,9 +409,8 @@ dependencies {
|
||||
}
|
||||
internalImplementation(project(':module_internal_test'))
|
||||
|
||||
def pushProperty = findProperty('BUILD_PUSH_TYPE')
|
||||
// 根据BUILD_PUSH_TYPE决定使用哪个推送SDK,目前默认使用极光推送
|
||||
def pushProject = (pushProperty == null || pushProperty == 'jg')
|
||||
// 根据BUILD_PUSH_TYPE决定使用哪个推送SDK,目前默认使用阿里云推送
|
||||
def pushProject = findProperty('BUILD_PUSH_TYPE') == 'jg'
|
||||
? project(':feature:jg_push') : project(':feature:acloud_push')
|
||||
implementation(pushProject) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
@ -574,16 +568,7 @@ andResGuard {
|
||||
"R.id.cardMask",
|
||||
"R.id.cardGradientMask",
|
||||
"R.id.gameIconIv",
|
||||
"R.id.titleContainer",
|
||||
"R.id.v_login_background",
|
||||
"R.id.tv_login_tips",
|
||||
"R.id.tv_login",
|
||||
"R.id.v_code_background",
|
||||
"R.id.tv_code_tips",
|
||||
"R.id.tv_code",
|
||||
"R.id.tv_copy",
|
||||
"R.id.v_indicator_background",
|
||||
"R.id.v_indicator"
|
||||
"R.id.titleContainer"
|
||||
]
|
||||
compressFilePattern = [
|
||||
"*.png",
|
||||
|
||||
@ -28,9 +28,6 @@ object GdtHelper {
|
||||
} else {
|
||||
GDTAction.init(application, USER_ACTION_SET_ID, APP_SECRET_ID, channel)
|
||||
}
|
||||
|
||||
GDTAction.start()
|
||||
|
||||
Utils.log("init GdtHelper")
|
||||
}
|
||||
|
||||
|
||||
BIN
app/src/gdt/libs/GDTActionSDK.min.1.8.8.aar
Normal file
BIN
app/src/gdt/libs/GDTActionSDK.min.1.8.8.aar
Normal file
Binary file not shown.
Binary file not shown.
BIN
app/src/kuaishou/libs/channelsdk-0.2.2.aar
Normal file
BIN
app/src/kuaishou/libs/channelsdk-0.2.2.aar
Normal file
Binary file not shown.
Binary file not shown.
@ -111,14 +111,6 @@
|
||||
android:name="android.permission.ACCESS_COARSE_LOCATION"
|
||||
tools:node="remove" />
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
|
||||
tools:node="remove" />
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.ACCESS_FINE_LOCATION"
|
||||
tools:node="remove" />
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity="true"
|
||||
android:largeScreens="true"
|
||||
@ -755,11 +747,11 @@
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.minigame.qq.QGameHomeWrapperActivity"
|
||||
android:name="com.gh.gamecenter.qgame.QGameHomeWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.minigame.MiniGameSearchActivity"
|
||||
android:name="com.gh.gamecenter.qgame.QGameSearchActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
@ -778,19 +770,8 @@
|
||||
android:name="com.gh.gamecenter.wrapper.ToolbarWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".forum.home.CommunityActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".forum.home.follow.FollowDynamicActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.Transparent" />
|
||||
|
||||
<activity
|
||||
android:name=".forum.home.follow.AllFollowedActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppCompatTheme.APP" />
|
||||
<activity android:name=".forum.home.CommunityActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<!-- <activity-->
|
||||
<!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"-->
|
||||
|
||||
@ -191,11 +191,10 @@ object AdDelegateHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 热启动是否需要显示开屏广告(目前只展示第三方广告)
|
||||
* 热启动是否需要显示开屏广告
|
||||
*/
|
||||
private fun shouldShowStartUpAdWhenHotLaunch() = (mCsjAdImpl != null || mBeiziAdImpl != null)
|
||||
&& mSplashAd?.displayRule?.hotStartSplashAd?.type == AD_TYPE_SDK
|
||||
&& mSplashAd?.hotStartThirdPartyAd != null
|
||||
private fun shouldShowStartUpAdWhenHotLaunch() =
|
||||
mSplashAd?.displayRule?.hotStartSplashAd?.type == AD_TYPE_SDK && mSplashAd?.hotStartThirdPartyAd != null
|
||||
|
||||
/**
|
||||
* 是否需要显示下载管理广告
|
||||
|
||||
@ -45,14 +45,6 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
}
|
||||
isFromBackgroundToForeground = false
|
||||
}
|
||||
|
||||
if (activityCount == 1) {
|
||||
// 清除桌面角标
|
||||
if (activity !is SplashScreenActivity && activity !is AuthorizationActivity) {
|
||||
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
|
||||
pushProvider?.cleanBadgeNumber(activity.applicationContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResumed(activity: Activity) {
|
||||
@ -92,6 +84,10 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
}
|
||||
|
||||
XapkInstaller.updateCurrentInstallStatus()
|
||||
|
||||
// 清除桌面角标
|
||||
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
|
||||
pushProvider?.cleanBadgeNumber(activity.applicationContext)
|
||||
}
|
||||
|
||||
override fun onActivityPaused(activity: Activity) {
|
||||
|
||||
@ -32,13 +32,9 @@ import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.provider.IPushProvider
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.entity.SensorsEvent
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
@ -73,7 +69,7 @@ class DefaultJsApi(
|
||||
private var mFragment: Fragment? = null,
|
||||
private var mBbsId: String? = "",
|
||||
private var mOriginUrl: String? = "",
|
||||
private val mForumName: String? = "",
|
||||
private val mForumName: String? = ""
|
||||
) {
|
||||
|
||||
companion object {
|
||||
@ -93,11 +89,6 @@ class DefaultJsApi(
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun isEnableForceDark(msg: Any): Boolean {
|
||||
return DarkModeUtils.isWebViewForceDarkEnabled
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun isGhzs(msg: Any): String {
|
||||
return "true"
|
||||
@ -342,12 +333,6 @@ class DefaultJsApi(
|
||||
return HaloApp.getInstance().oaid
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getPushId(): String {
|
||||
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
|
||||
return pushProvider?.getRegistrationId(HaloApp.getInstance()) ?: "unknown"
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun showIncompatibleVersionDialog(msg: Any) {
|
||||
DialogHelper.showUpgradeDialog(context)
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package com.gh.common.constant;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
@ -15,7 +14,6 @@ import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.constant.CommonConsts;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.common.utils.DarkModeUtils;
|
||||
@ -30,7 +28,6 @@ import com.gh.gamecenter.entity.VSetting;
|
||||
import com.gh.gamecenter.feature.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity;
|
||||
import com.gh.gamecenter.feature.utils.ContentBlockedHelper;
|
||||
import com.gh.gamecenter.receiver.PackageChangeBroadcastReceiver;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.vspace.VHelper;
|
||||
import com.halo.assistant.HaloApp;
|
||||
@ -80,11 +77,24 @@ public class Config {
|
||||
return !SPUtils.getBoolean(Constants.SP_TEENAGER_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* VPN 开关选项是否开启
|
||||
*/
|
||||
public static boolean isVpnOptionEnabled() {
|
||||
if (mNewApiSettingsEntity == null
|
||||
|| mNewApiSettingsEntity.getInstall() == null
|
||||
|| mNewApiSettingsEntity.getInstall().getVpnRequired() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mNewApiSettingsEntity.getInstall().getVpnRequired().getShouldShowVpnOption();
|
||||
}
|
||||
|
||||
public static void setSettings(SettingsEntity settingsEntity) {
|
||||
getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply();
|
||||
mSettingsEntity = settingsEntity;
|
||||
|
||||
PackageHelper.refreshPackageNameList();
|
||||
PackageHelper.refreshList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -299,9 +309,7 @@ public class Config {
|
||||
String filterString = UrlFilterUtils.getFilterQuery(
|
||||
"manufacturer", Build.MANUFACTURER,
|
||||
"model", Build.MODEL,
|
||||
"android_sdk_version", String.valueOf(Build.VERSION.SDK_INT),
|
||||
"rom", MetaUtil.INSTANCE.getRom().name() + " " + MetaUtil.INSTANCE.getRom().getVersionName()
|
||||
);
|
||||
"android_sdk_version", String.valueOf(Build.VERSION.SDK_INT));
|
||||
|
||||
RetrofitManager.getInstance()
|
||||
.getNewApi().getNewSettings(PackageUtils.getGhVersionName(), channel, filterString)
|
||||
@ -323,31 +331,8 @@ public class Config {
|
||||
if (mNewApiSettingsEntity.getGameShieldContents() != null) {
|
||||
ContentBlockedHelper.INSTANCE.init(mNewApiSettingsEntity.getGameShieldContents());
|
||||
}
|
||||
|
||||
// 更新安装列表是否开启的配置
|
||||
if (mNewApiSettingsEntity.getInstalledComplianceSwitch() != null) {
|
||||
PackageHelper.INSTANCE.updateIsGetInstalledPackagesApiAgreedRequired(mNewApiSettingsEntity.getInstalledComplianceSwitch());
|
||||
} else {
|
||||
PackageHelper.INSTANCE.updateIsGetInstalledPackagesApiAgreedRequired(false);
|
||||
}
|
||||
|
||||
// 更新包名监听是否开启
|
||||
if (mNewApiSettingsEntity.isPackageObserveEnable()) {
|
||||
observePackageChange(mNewApiSettingsEntity.getPackageObserveActions());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void observePackageChange(NewApiSettingsEntity.PackageObserveActions packageObserveActions) {
|
||||
PackageChangeBroadcastReceiver receiver = new PackageChangeBroadcastReceiver(packageObserveActions);
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(packageObserveActions.getAdd());
|
||||
intentFilter.addAction(packageObserveActions.getRem());
|
||||
intentFilter.addAction(packageObserveActions.getRep());
|
||||
intentFilter.addDataScheme("package");
|
||||
HaloApp.getInstance().registerReceiver(receiver, intentFilter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import com.aliyun.sls.android.producer.Log
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.common.loghub.TLogHubHelper
|
||||
import com.gh.gamecenter.common.loghub.LoghubHelper
|
||||
import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.lightgame.utils.Utils
|
||||
import com.volcengine.model.tls.LogItem
|
||||
|
||||
/**
|
||||
* A handful tool for committing logs to aliyun loghub.
|
||||
@ -78,20 +78,19 @@ object ExposureManager {
|
||||
|
||||
private fun uploadExposures(eventSet: HashSet<ExposureEvent>, forced: Boolean) {
|
||||
eventSet.forEach {
|
||||
TLogHubHelper.sendLog(buildLog(it), LOG_STORE)
|
||||
// LoghubHelper.uploadLog(buildLog(it), LOG_STORE, forced)
|
||||
LoghubHelper.uploadLog(buildLog(it), LOG_STORE, forced)
|
||||
// it.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildLog(event: ExposureEvent) = LogItem(System.currentTimeMillis()).apply {
|
||||
addContent("__id", event.id)
|
||||
addContent("payload", event.payload.toJson())
|
||||
addContent("event", event.event.toString())
|
||||
addContent("source", eliminateMultipleBrackets(event.source.toJson()))
|
||||
addContent("meta", event.meta.toJson())
|
||||
addContent("real_millisecond", event.timeInMillisecond.toString())
|
||||
addContent(
|
||||
private fun buildLog(event: ExposureEvent) = Log().apply {
|
||||
putContent("id", event.id)
|
||||
putContent("payload", event.payload.toJson())
|
||||
putContent("event", event.event.toString())
|
||||
putContent("source", eliminateMultipleBrackets(event.source.toJson()))
|
||||
putContent("meta", event.meta.toJson())
|
||||
putContent("real_millisecond", event.timeInMillisecond.toString())
|
||||
putContent(
|
||||
"e-traces", if (event.eTrace != null) {
|
||||
eliminateMultipleBrackets(event.eTrace?.toJson() ?: "")
|
||||
} else ""
|
||||
|
||||
@ -9,12 +9,10 @@ import androidx.fragment.app.FragmentActivity
|
||||
import com.gh.common.iinterface.ISuperiorChain
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.gamecenter.SplashAdActivity
|
||||
import com.gh.gamecenter.SplashScreenActivity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.entity.DialogEntity
|
||||
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
|
||||
@ -44,13 +42,12 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
return activity is FragmentActivity
|
||||
&& !activity.isFinishing
|
||||
&& activity !is SplashScreenActivity
|
||||
&& activity !is SplashAdActivity
|
||||
}
|
||||
|
||||
/**
|
||||
* 预启动所有的优先级弹窗管理链
|
||||
*/
|
||||
fun preStart(withSpecialDelay: Boolean) {
|
||||
fun preStart() {
|
||||
val launchRedirectHandler = LaunchRedirectHandler(-101)
|
||||
val updateDialogHandler = UpdateDialogHandler(-100)
|
||||
val privacyPolicyDialogHandler = PrivacyPolicyDialogHandler(-99)
|
||||
@ -67,13 +64,8 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
|
||||
launchRedirectHandler.doPreProcess()
|
||||
updateDialogHandler.doPreProcess()
|
||||
|
||||
// 首次启动延迟 300ms,保证请求首次启动时已经获取到了 GID 、 OAID 等标记
|
||||
val requestDelay = if (withSpecialDelay) 300L else 0L
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
requestOpeningDialogData(welcomeDialogHandler, privacyPolicyDialogHandler)
|
||||
requestReserveDialogData(reserveDialogHandler)
|
||||
}, requestDelay)
|
||||
requestOpeningDialogData(welcomeDialogHandler, privacyPolicyDialogHandler)
|
||||
requestReserveDialogData(reserveDialogHandler)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,17 +123,6 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
mainChain.resume()
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加新的 handler 到优先级弹窗管理链 (插队!)
|
||||
*/
|
||||
fun queueNewHandler(handler: PriorityChainHandler) {
|
||||
if (mainChain.isHandlerQueueEmpty()) {
|
||||
observeLifecycle()
|
||||
}
|
||||
|
||||
mainChain.addHandler(handler)
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求首页启动弹窗相关的数据并执行相关 handler 的 preProcess
|
||||
*/
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
package com.gh.common.prioritychain
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
|
||||
class RequestInstalledListPermissionHandler : PriorityChainHandler(-1000) {
|
||||
|
||||
init {
|
||||
updateStatus(STATUS_VALID)
|
||||
}
|
||||
|
||||
override fun onProcess(): Boolean {
|
||||
val currentActivity = GlobalActivityManager.currentActivity ?: return false
|
||||
|
||||
if (currentActivity !is FragmentActivity) return false
|
||||
|
||||
PackageHelper.showGetInstallAppsListDialogAndRequestPermissionIfNeeded(
|
||||
activity = currentActivity,
|
||||
ignorePermanentlyDenied = true
|
||||
) {
|
||||
processNext()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@ -32,6 +32,5 @@ class BuildConfigImpl : IBuildConfigProvider {
|
||||
override fun getVApiHost(): String = BuildConfig.VAPI_HOST
|
||||
|
||||
override fun getVDevApiHost(): String = BuildConfig.DEV_VAPI_HOST
|
||||
|
||||
override fun getLogProducerProject(): String = BuildConfig.LOG_HUB_PROJECT
|
||||
}
|
||||
@ -1,103 +0,0 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.util.ConcernContentUtils
|
||||
import com.gh.common.view.ImageContainerView
|
||||
import com.gh.gamecenter.ImageViewerActivity.Companion.getIntent
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.utils.toArrayList
|
||||
import com.gh.gamecenter.core.provider.IConcernArticleUtilsProvider
|
||||
import com.gh.gamecenter.databinding.RecyclerGameArticleBinding
|
||||
import com.gh.gamecenter.message.R
|
||||
|
||||
@Route(path = RouteConsts.provider.concernContentUtils, name = "ConcernContentUtils暴露服务")
|
||||
class ConcernArticleUtilsProviderImpl : IConcernArticleUtilsProvider {
|
||||
override fun addContentPic(
|
||||
context: Context,
|
||||
linearLayout: LinearLayout,
|
||||
list: List<String>,
|
||||
entrance: String,
|
||||
width: Int
|
||||
) {
|
||||
ConcernContentUtils.addContentPic(context, linearLayout, list, entrance, width)
|
||||
}
|
||||
|
||||
override fun createArticleBinding(parent: ViewGroup): ViewBinding {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return RecyclerGameArticleBinding.inflate(inflater, parent, false)
|
||||
}
|
||||
|
||||
override fun initArticleStyle(binding: ViewBinding) {
|
||||
if (binding is RecyclerGameArticleBinding) {
|
||||
val context = binding.root.context
|
||||
binding.root
|
||||
.setBackground(ContextCompat.getDrawable(context, R.drawable.reuse_listview_item_style))
|
||||
binding.tvGameName.setTextColor(ContextCompat.getColor(context, R.color.text_primary))
|
||||
binding.tvTime.setTextColor(ContextCompat.getColor(context, R.color.text_tertiary))
|
||||
binding.tvTitle.setTextColor(ContextCompat.getColor(context, R.color.text_primary))
|
||||
binding.tvDescription.setTextColor(ContextCompat.getColor(context, R.color.text_secondary))
|
||||
binding.tvComment.setTextColor(ContextCompat.getColor(context, R.color.text_tertiary))
|
||||
binding.tvShare.setTextColor(ContextCompat.getColor(context, R.color.text_tertiary))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIvIcon(binding: ViewBinding): View =
|
||||
(binding as RecyclerGameArticleBinding).ivIcon
|
||||
|
||||
override fun getTvGameName(binding: ViewBinding): TextView =
|
||||
(binding as RecyclerGameArticleBinding).tvGameName
|
||||
|
||||
override fun getTvTime(binding: ViewBinding): TextView = (binding as RecyclerGameArticleBinding).tvTime
|
||||
|
||||
override fun getTvTitle(binding: ViewBinding): TextView = (binding as RecyclerGameArticleBinding).tvTitle
|
||||
|
||||
override fun getTvDescription(binding: ViewBinding): TextView =
|
||||
(binding as RecyclerGameArticleBinding).tvDescription
|
||||
|
||||
override fun bindImgs(binding: ViewBinding, img: List<String>) {
|
||||
if (binding is RecyclerGameArticleBinding) {
|
||||
val images = img.map {
|
||||
ImageContainerView.ImageContainerData.ImageInfo(it, 3, 2)
|
||||
}
|
||||
val imageContainerData =
|
||||
ImageContainerView.ImageContainerData("", false, images, show = images.isNotEmpty())
|
||||
binding.ivImagesContainer.bindData(imageContainerData,
|
||||
object : ImageContainerView.OnImageContainerEventListener {
|
||||
override fun onImageClick(
|
||||
images: List<String>,
|
||||
position: Int,
|
||||
imageViewList: ArrayList<SimpleDraweeView>
|
||||
) {
|
||||
val checkIntent = getIntent(
|
||||
binding.root.context,
|
||||
images.toArrayList(),
|
||||
position,
|
||||
imageViewList,
|
||||
""
|
||||
)
|
||||
binding.root.context.startActivity(checkIntent)
|
||||
}
|
||||
|
||||
override fun onVideoCLick(videoId: String) = Unit
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTvComment(binding: ViewBinding): TextView = (binding as RecyclerGameArticleBinding).tvComment
|
||||
|
||||
override fun getTvShare(binding: ViewBinding): TextView = (binding as RecyclerGameArticleBinding).tvShare
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.LinearLayout
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.util.ConcernContentUtils
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IConcernContentUtilsProvider
|
||||
|
||||
@Route(path = RouteConsts.provider.concernContentUtils, name = "ConcernContentUtils暴露服务")
|
||||
class ConcernContentUtilsProviderImpl : IConcernContentUtilsProvider {
|
||||
override fun addContentPic(
|
||||
context: Context,
|
||||
linearLayout: LinearLayout,
|
||||
list: List<String>,
|
||||
entrance: String,
|
||||
width: Int
|
||||
) {
|
||||
ConcernContentUtils.addContentPic(context, linearLayout, list, entrance, width)
|
||||
}
|
||||
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.core.provider.IConcernGiftPackUtilsProvider
|
||||
import com.gh.gamecenter.databinding.RecyclerGiftPackBinding
|
||||
|
||||
@Route(path = RouteConsts.provider.concernGiftPackUtils, name = "ConcernGiftPackUtils暴露服务")
|
||||
class ConcernGiftPackUtilsProviderImpl : IConcernGiftPackUtilsProvider {
|
||||
override fun createBinding(parent: ViewGroup): ViewBinding {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return RecyclerGiftPackBinding.inflate(inflater, parent, false)
|
||||
.also {
|
||||
it.gCode.goneIf(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun initStyle(viewBinding: ViewBinding) {
|
||||
with(viewBinding as RecyclerGiftPackBinding) {
|
||||
val context = root.context
|
||||
tvGameName.setTextColor(R.color.text_primary.toColor(context))
|
||||
tvTime.setTextColor(R.color.text_tertiary.toColor(context))
|
||||
tvGiftPackName.setTextColor(R.color.text_primary.toColor(context))
|
||||
tvGiftPackContent.setTextColor(R.color.text_secondary.toColor(context))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIvGameIcon(viewBinding: ViewBinding) =
|
||||
(viewBinding as RecyclerGiftPackBinding).ivIcon
|
||||
|
||||
override fun getTvGameName(viewBinding: ViewBinding) =
|
||||
(viewBinding as RecyclerGiftPackBinding).tvGameName
|
||||
|
||||
override fun getTvTime(viewBinding: ViewBinding) =
|
||||
(viewBinding as RecyclerGiftPackBinding).tvTime
|
||||
|
||||
override fun getTvGiftPackName(viewBinding: ViewBinding) =
|
||||
(viewBinding as RecyclerGiftPackBinding).tvGiftPackName
|
||||
|
||||
override fun getTvGiftPackContent(viewBinding: ViewBinding) =
|
||||
(viewBinding as RecyclerGiftPackBinding).tvGiftPackContent
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// Do Nothing
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IConcernShareNewsProvider
|
||||
import com.gh.gamecenter.newsdetail.NewsShareDialog
|
||||
|
||||
@Route(path = RouteConsts.provider.concernShareNews, name = "ConcernShareNews暴露服务")
|
||||
class ConcernShareNewsProviderImpl : IConcernShareNewsProvider {
|
||||
override fun share(activity: AppCompatActivity, shortId: String?, id: String?, gameIcon: String?, title: String?) {
|
||||
NewsShareDialog.show(activity, shortId, id, gameIcon, title)
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// Do Nothing
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
@ -70,18 +69,10 @@ class DirectProviderImpl : IDirectProvider {
|
||||
DirectUtils.directToAmway(context, fixedTopAmwayCommentId, entrance, path)
|
||||
}
|
||||
|
||||
override fun directToQQGameHome(context: Context) {
|
||||
override fun directToQGame(context: Context) {
|
||||
return DirectUtils.directToQGameHome(context)
|
||||
}
|
||||
|
||||
override fun directToQQGameById(activity: Activity, qqAppId: String) {
|
||||
DirectUtils.directToQQGameById(activity, qqAppId)
|
||||
}
|
||||
|
||||
override fun directToWechatGameById(activity: Activity, qqAppId: String) {
|
||||
DirectUtils.directToWechatGameById(activity, qqAppId)
|
||||
}
|
||||
|
||||
override fun directToExternalBrowser(context: Context, url: String) {
|
||||
DirectUtils.directToExternalBrowser(context, url)
|
||||
}
|
||||
|
||||
@ -7,8 +7,8 @@ import android.widget.LinearLayout;
|
||||
import com.facebook.drawee.drawable.ScalingUtils;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.gamecenter.ImageViewerActivity;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -121,4 +121,5 @@ public class ConcernContentUtils {
|
||||
}
|
||||
return imageView;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.NewsDetailEntity;
|
||||
import com.gh.gamecenter.feature.utils.PlatformUtils;
|
||||
import com.gh.gamecenter.manager.DataCollectionManager;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -29,7 +32,7 @@ public class DataCollectionUtils {
|
||||
map.put("type", android.os.Build.MODEL);
|
||||
map.put("system", android.os.Build.VERSION.SDK_INT + "=" + android.os.Build.VERSION.RELEASE);
|
||||
// WIFI实时
|
||||
DataCollectionManager.onEvent(context, "error", map, true);
|
||||
DataCollectionManager.onEvent(context, "error", map, NetworkUtils.isWifiConnected(context));
|
||||
}
|
||||
|
||||
// 上传下载数据(开始、完成)
|
||||
|
||||
@ -14,10 +14,12 @@ import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager;
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.gh.gamecenter.core.utils.SentryHelper;
|
||||
import com.gh.gamecenter.login.entity.IdCardEntity;
|
||||
@ -30,6 +32,8 @@ import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.sentry.Sentry;
|
||||
import io.sentry.android.core.SentryAndroid;
|
||||
@ -104,51 +108,45 @@ public class DataUtils {
|
||||
}
|
||||
|
||||
public static void getGid() {
|
||||
// 默认用 APP 级已存储的 GID 来使用,不使用外部 GID
|
||||
String savedGid = SPUtils.getString(Constants.GID);
|
||||
if (!TextUtils.isEmpty(savedGid)) {
|
||||
HaloApp.getInstance().setGid(savedGid);
|
||||
onGidReceived(savedGid);
|
||||
} else {
|
||||
GidHelper.getInstance().registerDevice(HaloApp.getInstance().getApplication(), new GidCallback() {
|
||||
@Override
|
||||
public void onSuccess(String gid) {
|
||||
Utils.log("Gid", gid);
|
||||
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit().putString(Constants.DEVICE_KEY, gid).apply();
|
||||
GidHelper.getInstance().registerDevice(HaloApp.getInstance().getApplication(), new GidCallback() {
|
||||
@Override
|
||||
public void onSuccess(String gid) {
|
||||
Utils.log("Gid", gid);
|
||||
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit().putString(Constants.DEVICE_KEY, gid).apply();
|
||||
|
||||
// 默认用 APP 级已存储的 GID 来使用,不使用外部 GID
|
||||
String savedGid = SPUtils.getString(Constants.GID);
|
||||
if (!TextUtils.isEmpty(savedGid)) {
|
||||
gid = savedGid;
|
||||
} else {
|
||||
SPUtils.setString(Constants.GID, gid);
|
||||
|
||||
onGidReceived(gid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String s) {
|
||||
// 更新广告配置
|
||||
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
|
||||
HaloApp.getInstance().setGid(gid);
|
||||
|
||||
// 更新广告配置
|
||||
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
|
||||
|
||||
getDeviceCertification(gid);
|
||||
|
||||
// 避免初始化顺序问题导致 MetaUtil 一直持有空的 gid
|
||||
MetaUtil.INSTANCE.refreshMeta();
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(GhContentProvider.KEY_GID, gid);
|
||||
values.put(GhContentProvider.KEY_ANDROID_ID, MetaUtil.getBase64EncodedAndroidId());
|
||||
try {
|
||||
HaloApp.getInstance().getContentResolver().insert(Uri.parse("content://com.gh.gamecenter.provider/device"), values);
|
||||
} catch (Exception exception) {
|
||||
SentryHelper.INSTANCE.onEvent("DEVICE_INSERT_ERROR", "exception_digest", exception.getLocalizedMessage());
|
||||
exception.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void onGidReceived(String gid) {
|
||||
HaloApp.getInstance().setGid(gid);
|
||||
// 更新广告配置
|
||||
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
|
||||
|
||||
getDeviceCertification(gid);
|
||||
|
||||
// 避免初始化顺序问题导致 MetaUtil 一直持有空的 gid
|
||||
MetaUtil.INSTANCE.refreshMeta();
|
||||
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(GhContentProvider.KEY_GID, gid);
|
||||
values.put(GhContentProvider.KEY_ANDROID_ID, MetaUtil.getBase64EncodedAndroidId());
|
||||
try {
|
||||
HaloApp.getInstance().getContentResolver().insert(Uri.parse("content://com.gh.gamecenter.provider/device"), values);
|
||||
} catch (Exception exception) {
|
||||
SentryHelper.INSTANCE.onEvent("DEVICE_INSERT_ERROR", "exception_digest", exception.getLocalizedMessage());
|
||||
exception.printStackTrace();
|
||||
@Override
|
||||
public void onFailure(String s) {
|
||||
// 更新广告配置
|
||||
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -633,19 +633,7 @@ public class DialogUtils {
|
||||
|
||||
binding.gameIcon.displayGameIcon(gameEntity);
|
||||
binding.gameNameTv.setText(context.getString(R.string.dialog_land_page_address_hint, gameEntity.getName()));
|
||||
|
||||
AtomicBoolean dismissByButton = new AtomicBoolean(false);
|
||||
|
||||
binding.closeIv.setOnClickListener(v -> {
|
||||
dismissByButton.set(true);
|
||||
SensorsBridge.INSTANCE.trackJumpLandPageAddressDialogClick(
|
||||
"取消",
|
||||
gameEntity.getId(),
|
||||
gameEntity.getName() != null ? gameEntity.getName() : "",
|
||||
gameEntity.getCategoryChinese()
|
||||
);
|
||||
dialog.dismiss();
|
||||
});
|
||||
binding.closeIv.setOnClickListener(v -> dialog.dismiss());
|
||||
|
||||
binding.urlTv.setText(gameEntity.getLandPageAddressDialog().getLink());
|
||||
|
||||
@ -655,28 +643,10 @@ public class DialogUtils {
|
||||
|
||||
binding.downloadBtn.setText(downloadText);
|
||||
binding.downloadBtn.setOnClickListener(v -> {
|
||||
dismissByButton.set(true);
|
||||
SensorsBridge.INSTANCE.trackJumpLandPageAddressDialogClick(
|
||||
"前往第三方网站下载游戏",
|
||||
gameEntity.getId(),
|
||||
gameEntity.getName() != null ? gameEntity.getName() : "",
|
||||
gameEntity.getCategoryChinese()
|
||||
);
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.setOnDismissListener(dialog1 -> {
|
||||
if (!dismissByButton.get()) {
|
||||
SensorsBridge.INSTANCE.trackJumpLandPageAddressDialogClick(
|
||||
"关闭弹窗",
|
||||
gameEntity.getId(),
|
||||
gameEntity.getName() != null ? gameEntity.getName() : "",
|
||||
gameEntity.getCategoryChinese()
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
@ -685,12 +655,6 @@ public class DialogUtils {
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
|
||||
SensorsBridge.INSTANCE.trackJumpLandPageAddressDialogShow(
|
||||
gameEntity.getId(),
|
||||
gameEntity.getName() != null ? gameEntity.getName() : "",
|
||||
gameEntity.getCategoryChinese()
|
||||
);
|
||||
}
|
||||
|
||||
public static void showGameH5DownloadDialog(Context context, GameEntity gameEntity, RegionSetting.GameH5Download gameH5Download) {
|
||||
|
||||
@ -43,13 +43,11 @@ import com.gh.gamecenter.feature.entity.MeEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent.Companion.createEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureType
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.feature.provider.IConcernInfoProvider
|
||||
import com.gh.gamecenter.forum.detail.ForumDetailActivity
|
||||
import com.gh.gamecenter.forum.home.CommunityActivity
|
||||
import com.gh.gamecenter.forum.search.ForumOrUserSearchActivity
|
||||
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
|
||||
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailFragment
|
||||
import com.gh.gamecenter.game.commoncollection.detail.CustomCommonCollectionDetailActivity
|
||||
import com.gh.gamecenter.game.upload.GameSubmissionActivity
|
||||
import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
|
||||
@ -65,9 +63,6 @@ import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
|
||||
import com.gh.gamecenter.help.HelpAndFeedbackBridge
|
||||
import com.gh.gamecenter.libao.LibaoDetailActivity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayUseCase
|
||||
import com.gh.gamecenter.minigame.MiniGameSearchActivity
|
||||
import com.gh.gamecenter.minigame.qq.QGameHomeWrapperActivity
|
||||
import com.gh.gamecenter.newsdetail.NewsDetailActivity
|
||||
import com.gh.gamecenter.personalhome.UserHomeActivity
|
||||
import com.gh.gamecenter.personalhome.background.PersonalityBackgroundActivity
|
||||
@ -78,6 +73,9 @@ import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.questions.newdetail.NewQuestionDetailActivity
|
||||
import com.gh.gamecenter.qa.subject.CommunitySubjectActivity
|
||||
import com.gh.gamecenter.qa.video.detail.ForumVideoDetailActivity
|
||||
import com.gh.gamecenter.qgame.QGameHomeWrapperActivity
|
||||
import com.gh.gamecenter.qgame.QGameSearchActivity
|
||||
import com.gh.gamecenter.qgame.QGameViewModel
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.servers.GameServerTestActivity
|
||||
import com.gh.gamecenter.servers.GameServersActivity
|
||||
@ -97,8 +95,6 @@ import com.gh.vspace.VDownloadManagerActivity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.halo.assistant.fragment.WebFragment
|
||||
import com.lightgame.utils.Utils
|
||||
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import retrofit2.HttpException
|
||||
@ -112,14 +108,8 @@ import kotlin.math.roundToInt
|
||||
object DirectUtils {
|
||||
|
||||
@JvmStatic
|
||||
fun directToLinkPage(
|
||||
context: Context,
|
||||
linkEntity: LinkEntity,
|
||||
entrance: String,
|
||||
path: String,
|
||||
sourceEntrance: String = ""
|
||||
) {
|
||||
directToLinkPage(context, linkEntity, entrance, path, null, sourceEntrance)
|
||||
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String, sourceEntrance: String = "") {
|
||||
directToLinkPage(context, linkEntity, entrance, path, null, sourceEntrance)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -253,7 +243,7 @@ object DirectUtils {
|
||||
path
|
||||
)
|
||||
|
||||
HOST_WEB, HOST_WEB_INURL, HOST_WEB_AL, HOST_QA_CONTENT -> {
|
||||
HOST_WEB, HOST_WEB_INURL, HOST_WEB_AL -> {
|
||||
when {
|
||||
linkEntity.link!!.contains("v.douyin") && PackageHelper.localPackageNameSet.contains("com.ss.android.ugc.aweme") -> {
|
||||
directDouyin(context, "1402577827140941")
|
||||
@ -353,7 +343,7 @@ object DirectUtils {
|
||||
|
||||
"feedback" -> directToFeedback(context, linkEntity.name, false, "", false, false, entrance)
|
||||
|
||||
"qa", "Q&A" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "")
|
||||
"qa", "qa_content", "Q&A" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "")
|
||||
|
||||
"qa_list" -> directToHelpAndFeedback(context)
|
||||
|
||||
@ -485,22 +475,17 @@ object DirectUtils {
|
||||
)
|
||||
)
|
||||
|
||||
ColumnCollectionDetailFragment.TYPE_QQ_MINI_GAME_COLUMN -> directToQGameHome(context)
|
||||
"qq_mini_game_column" -> directToQGameHome(context)
|
||||
|
||||
// QQ游戏专题详情页
|
||||
ViewPagerFragmentHelper.TYPE_QQ_MINI_GAME_COLUMN, ViewPagerFragmentHelper.TYPE_WECHAT_GAME_COLUMN -> {
|
||||
val subjectType = if (linkEntity.type == ViewPagerFragmentHelper.TYPE_QQ_MINI_GAME_COLUMN) {
|
||||
SubjectData.SubjectType.QQ_GAME
|
||||
} else {
|
||||
SubjectData.SubjectType.WECHAT_GAME
|
||||
}
|
||||
"qq_mini_game_column_detail" -> {
|
||||
directToSubject(
|
||||
context = context,
|
||||
id = linkEntity.link ?: "",
|
||||
subjectName = linkEntity.text,
|
||||
entrance = BaseActivity.mergeEntranceAndPath(entrance, path),
|
||||
exposureEvent = exposureEvent,
|
||||
subjectType = subjectType
|
||||
isQQMiniGame = true
|
||||
)
|
||||
}
|
||||
|
||||
@ -551,10 +536,6 @@ object DirectUtils {
|
||||
}
|
||||
}
|
||||
|
||||
"wechat_game" -> linkEntity.link?.let {
|
||||
MiniGameItemHelper.launchMiniGame(it, Constants.WECHAT_MINI_GAME)
|
||||
}
|
||||
|
||||
"" -> {
|
||||
// do nothing
|
||||
}
|
||||
@ -793,12 +774,7 @@ object DirectUtils {
|
||||
}
|
||||
}
|
||||
if (traceEvent != null) {
|
||||
val clickEvent = createEvent(
|
||||
GameEntity(id = id, name = name),
|
||||
traceEvent.source,
|
||||
appendTrace(traceEvent),
|
||||
ExposureType.CLICK
|
||||
)
|
||||
val clickEvent = createEvent(GameEntity(id = id, name = name), traceEvent.source, appendTrace(traceEvent), ExposureType.CLICK)
|
||||
log(clickEvent)
|
||||
bundle.putParcelable(KEY_TRACE_EVENT, clickEvent)
|
||||
}
|
||||
@ -861,12 +837,12 @@ object DirectUtils {
|
||||
subjectName: String? = "",
|
||||
entrance: String? = null,
|
||||
exposureEvent: ExposureEvent? = null,
|
||||
subjectType: SubjectData.SubjectType = SubjectData.SubjectType.NORMAL
|
||||
isQQMiniGame: Boolean = false,
|
||||
) {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
val subjectData =
|
||||
SubjectData(subjectId = id, subjectName = subjectName, isOrder = false, subjectType = subjectType)
|
||||
SubjectData(subjectId = id, subjectName = subjectName, isOrder = false, isQQMiniGame = isQQMiniGame)
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, SubjectActivity::class.java.name)
|
||||
bundle.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, subjectData)
|
||||
@ -1015,13 +991,7 @@ object DirectUtils {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToQuestionDetail(
|
||||
context: Context,
|
||||
id: String,
|
||||
entrance: String? = null,
|
||||
path: String? = null,
|
||||
sourceEntrance: String = ""
|
||||
) {
|
||||
fun directToQuestionDetail(context: Context, id: String, entrance: String? = null, path: String? = null, sourceEntrance: String = "") {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
@ -1965,7 +1935,7 @@ object DirectUtils {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToMiniGameSearch(
|
||||
fun directToQGameSearch(
|
||||
context: Context,
|
||||
hint: String,
|
||||
sourceEntrance: String,
|
||||
@ -1977,7 +1947,7 @@ object DirectUtils {
|
||||
searchBoxPattern: String = ""
|
||||
) {
|
||||
context.startActivity(
|
||||
MiniGameSearchActivity.getIntent(
|
||||
QGameSearchActivity.getIntent(
|
||||
context,
|
||||
hint,
|
||||
sourceEntrance,
|
||||
@ -1993,10 +1963,11 @@ object DirectUtils {
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun directToQQGameById(
|
||||
fun directToQGameById(
|
||||
activity: Activity,
|
||||
qqAppId: String
|
||||
qqGameId: String
|
||||
) {
|
||||
|
||||
if (activity !is AppCompatActivity || activity.supportFragmentManager.isDestroyed) {
|
||||
ToastUtils.toast("启动QQ小游戏失败,请稍后再试")
|
||||
return
|
||||
@ -2017,40 +1988,25 @@ object DirectUtils {
|
||||
val qGameProvider = ARouter
|
||||
.getInstance()
|
||||
.build(RouteConsts.provider.qGame)
|
||||
.navigation() as IQGameProvider
|
||||
.navigation() as IQGameProvider<*>
|
||||
qGameProvider.setLoginInfo(activity, userId, userName, userToken)
|
||||
qGameProvider.launchGame(activity, qqAppId) { _, _ ->
|
||||
MiniGameRecentlyPlayUseCase.submitRecentPlayedQGame(qqAppId, userId)
|
||||
qGameProvider.launchGame(activity, qqGameId) { _, _ ->
|
||||
RetrofitManager
|
||||
.getInstance()
|
||||
.newApi
|
||||
.postQGamePlay(qqGameId, userId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
QGameViewModel.notifyQGameSubjectUpdate() // 通知QQ小游戏首页列表刷新
|
||||
},
|
||||
{}
|
||||
) // 秒玩记录上报
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun directToWechatGameById(
|
||||
activity: Activity,
|
||||
wechatAppId: String,
|
||||
) {
|
||||
|
||||
val wxApiProxy = WXAPIFactory.createWXAPI(
|
||||
activity,
|
||||
Config.WECHAT_APPID
|
||||
)
|
||||
if (!wxApiProxy.isWXAppInstalled) {
|
||||
ToastUtils.toast("请安装微信客户端")
|
||||
return
|
||||
}
|
||||
|
||||
wxApiProxy.sendReq(
|
||||
WXLaunchMiniProgram.Req().apply {
|
||||
userName = wechatAppId
|
||||
path = Constants.WECHAT_MINI_GAME_PCS
|
||||
miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE;
|
||||
}
|
||||
)
|
||||
|
||||
MiniGameRecentlyPlayUseCase.submitRecentPlayedWGame(wechatAppId, HaloApp.getInstance().gid)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToMessageCenter(defaultTabIndex: Int) {
|
||||
ARouter.getInstance().build(RouteConsts.activity.messageWrapperActivity)
|
||||
@ -2126,7 +2082,7 @@ object DirectUtils {
|
||||
)
|
||||
)
|
||||
|
||||
BottomTab.SearchStyle.TYPE_MINI_GAME -> directToMiniGameSearch(
|
||||
BottomTab.SearchStyle.TYPE_QQ_MINI_GAME -> directToQGameSearch(
|
||||
context,
|
||||
"请输入小游戏关键词",
|
||||
sourceEntrance,
|
||||
|
||||
@ -27,6 +27,7 @@ import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.callback.CancelListener
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
@ -40,7 +41,6 @@ import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.teenagermode.TeenagerModeActivity
|
||||
import com.gh.vspace.VHelper
|
||||
import com.lightgame.download.DownloadConfig
|
||||
@ -247,8 +247,9 @@ object DownloadItemUtils {
|
||||
}
|
||||
return
|
||||
}
|
||||
if (gameEntity.isMiniGame()) {
|
||||
if (gameEntity.isMiniGameOffShelve()) {
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
val isQQMiniGameOffShelve = gameEntity.qqMiniGameAppStatus == 1 // QQ小游戏是否下架
|
||||
if (isQQMiniGameOffShelve) {
|
||||
downloadBtn.apply {
|
||||
isClickable = false
|
||||
text = context.getString(R.string.off_shelve)
|
||||
@ -843,11 +844,12 @@ object DownloadItemUtils {
|
||||
}
|
||||
return
|
||||
}
|
||||
if (gameEntity.isMiniGame()) {
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
downloadBtn.setOnClickListener {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
clickCallback?.onCallback()
|
||||
allStateClickCallback?.onCallback()
|
||||
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
|
||||
GlobalActivityManager.currentActivity?.let { activity ->
|
||||
DirectUtils.directToQGameById(activity, gameEntity.qqMiniGameAppId)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -2007,6 +2007,29 @@ object NewFlatLogUtils {
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
// vpn 弹窗显示
|
||||
fun logVpnHintDialogShow(gameId: String, gameName: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "vpn_pre_access_dialog_show"
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
// vpn 弹窗点击
|
||||
fun logVpnHintDialogClick(gameId: String, gameName: String, button: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "vpn_pre_access_dialog_click"
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
"button" to button
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
// 谷歌框架弹窗显示
|
||||
fun logGAppsDialogShowed(gameId: String, gameName: String) {
|
||||
val json = json {
|
||||
@ -2577,6 +2600,17 @@ object NewFlatLogUtils {
|
||||
log(json)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logQGameClick(qqGameId: String, qqGameName: String?) {
|
||||
val json = json {
|
||||
KEY_EVENT to "qq_game_click"
|
||||
"qq_game_id" to qqGameId
|
||||
"qq_game_name" to qqGameName ?: ""
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 点击个人主页的认证文案事件
|
||||
@JvmStatic
|
||||
fun logClickAuthText(linkType: String, linkId: String, linkText: String, userId: String, text: String) {
|
||||
|
||||
@ -1,186 +0,0 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.download.PackageObserver
|
||||
import com.gh.gamecenter.common.utils.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.lightgame.utils.Utils
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
|
||||
private const val TAG = "PackageChangeHelper"
|
||||
|
||||
private const val INSTALL_PENDING = 1
|
||||
private const val UNINSTALL_PENDING = 2
|
||||
private const val UPDATE_PENDING = 3
|
||||
|
||||
// <包名,pending 类型,应用版本> Triple
|
||||
private var pendingPackagePair: Triple<String, Int, String>? = null
|
||||
private var pendingGhId: String ? = null
|
||||
|
||||
/**
|
||||
* 添加一个等待中,待确定是否已成功安装的应用
|
||||
*/
|
||||
fun addInstallPendingPackage(packageName: String) {
|
||||
val installData = PackagesManager.getInstalledData(packageName)
|
||||
|
||||
if (installData == null) {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待安装成功")
|
||||
pendingPackagePair = Triple(packageName, INSTALL_PENDING, "")
|
||||
} else {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待安装更新成功")
|
||||
|
||||
val ghId = PackageUtils.getGhId(packageName)
|
||||
|
||||
// 记录光环插件相关信息,用于安装成功后的处理
|
||||
if (ghId != null) {
|
||||
pendingGhId = ghId.toString()
|
||||
}
|
||||
|
||||
pendingPackagePair = Triple(packageName, UPDATE_PENDING, installData.version)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个等待中,待确定是否已成功卸载的应用
|
||||
*/
|
||||
fun addUninstallPendingPackage(packageName: String) {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待卸载成功")
|
||||
pendingPackagePair = Triple(packageName, UNINSTALL_PENDING, "")
|
||||
}
|
||||
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
super.onResume(owner)
|
||||
|
||||
if (pendingPackagePair != null) {
|
||||
val packageName = pendingPackagePair?.first ?: return
|
||||
val isInstallPending = pendingPackagePair?.second == INSTALL_PENDING
|
||||
val isUninstallPending = pendingPackagePair?.second == UNINSTALL_PENDING
|
||||
val isUpdatePending = pendingPackagePair?.second == UPDATE_PENDING
|
||||
|
||||
val pendingVersion = pendingPackagePair?.third ?: ""
|
||||
|
||||
val installedVersionName = PackageUtils.getVersionNameByPackageName(packageName)
|
||||
val isInstalled = installedVersionName != null
|
||||
|
||||
if (isInstallPending && isInstalled) {
|
||||
pendingPackagePair = null
|
||||
pendingGhId = null
|
||||
|
||||
PackageRepository.addInstalledGame(packageName)
|
||||
|
||||
// 添加到额外的包名白名单,下次启动同时查询此包的安装情况
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = true)
|
||||
|
||||
performInstallSuccessAction(packageName)
|
||||
} else if (isUninstallPending && !isInstalled) {
|
||||
pendingPackagePair = null
|
||||
pendingGhId = null
|
||||
|
||||
// 从额外的包名白名单移除,下次启动时不再查询此包的安装情况
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = false)
|
||||
|
||||
performUninstallSuccessAction(packageName)
|
||||
} else if (isUpdatePending) {
|
||||
val isUpdateValid = if (installedVersionName != pendingVersion) {
|
||||
true
|
||||
} else {
|
||||
!pendingGhId.isNullOrEmpty() && pendingGhId != PackageUtils.getGhId(packageName).toString()
|
||||
}
|
||||
|
||||
pendingPackagePair = null
|
||||
pendingGhId = null
|
||||
|
||||
if (isUpdateValid) {
|
||||
performUninstallSuccessAction(packageName)
|
||||
performInstallSuccessAction(packageName)
|
||||
}
|
||||
|
||||
// 添加到额外的包名白名单,下次启动同时查询此包的安装情况
|
||||
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对外暴露的方法,用于添加一个安装成功的应用
|
||||
* @param packageName 包名
|
||||
* @param cachedGameEntity 缓存的 GameEntity,用于快速更新状态
|
||||
*/
|
||||
fun addInstall(packageName: String, cachedGameEntity: GameEntity? = null) {
|
||||
performInstallSuccessAction(packageName, cachedGameEntity)
|
||||
}
|
||||
|
||||
/**
|
||||
* 对外暴露的方法,用于添加一个卸载成功的应用
|
||||
* @param packageName 包名
|
||||
* @param cachedGameEntity 缓存的 GameEntity,用于快速更新状态
|
||||
*/
|
||||
fun addUpdate(packageName: String, cachedGameEntity: GameEntity? = null) {
|
||||
performUninstallSuccessAction(packageName)
|
||||
performInstallSuccessAction(packageName, cachedGameEntity)
|
||||
}
|
||||
|
||||
/**
|
||||
* 对应包名安装成功后的操作,继承至 PackageChangeBroadcastObserver
|
||||
* @param packageName 包名
|
||||
* @param cachedGameEntity 缓存的 GameEntity,用于快速更新状态
|
||||
* @param withLog 是否需要记录日志
|
||||
*/
|
||||
private fun performInstallSuccessAction(packageName: String,
|
||||
cachedGameEntity: GameEntity? = null,
|
||||
withLog: Boolean = true) {
|
||||
Utils.log(TAG, "安装了: $packageName 包名的程序")
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName)
|
||||
val gameId = if (downloadEntity != null && downloadEntity.gameId != null) downloadEntity.gameId else ""
|
||||
val gameName = if (downloadEntity != null && downloadEntity.name != null) downloadEntity.name else ""
|
||||
|
||||
if (withLog) {
|
||||
NewFlatLogUtils.logGameInstallComplete(gameId, gameName)
|
||||
SensorsBridge.trackInstallGameFinish(gameId, gameName)
|
||||
}
|
||||
|
||||
InstallUtils.getInstance().removeInstall(packageName)
|
||||
PackageHelper.refreshLocalPackageList()
|
||||
|
||||
val versionName = PackageUtils.getVersionNameByPackageName(packageName)
|
||||
val installEb = EBPackage(EBPackage.TYPE_INSTALLED, packageName, versionName)
|
||||
|
||||
PackageObserver.onPackageChanged(installEb, cachedGameEntity)
|
||||
EventBus.getDefault().post(installEb)
|
||||
}
|
||||
|
||||
fun addUninstall(packageName: String) {
|
||||
performUninstallSuccessAction(packageName)
|
||||
}
|
||||
|
||||
/**
|
||||
* 对应包名卸载成功后的操作,继承至 PackageChangeBroadcastObserver
|
||||
*/
|
||||
private fun performUninstallSuccessAction(packageName: String, withLog: Boolean = true) {
|
||||
Utils.log(TAG, "卸载了: $packageName 包名的程序")
|
||||
val install = PackagesManager.getInstalledData(packageName)
|
||||
val gameId = if (install?.id != null) install.id else ""
|
||||
val gameName = if (install?.name != null) install.name else ""
|
||||
|
||||
if (withLog) {
|
||||
NewFlatLogUtils.logGameUninstallComplete(gameId!!, gameName!!)
|
||||
SensorsBridge.trackUnloadGameFinish(gameId, gameName)
|
||||
}
|
||||
|
||||
InstallUtils.getInstance().removeUninstall(packageName)
|
||||
PackageHelper.refreshLocalPackageList()
|
||||
|
||||
val uninstallEb = EBPackage(EBPackage.TYPE_UNINSTALLED, packageName, "")
|
||||
PackageObserver.onPackageChanged(uninstallEb)
|
||||
EventBus.getDefault().post(uninstallEb)
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
@ -8,31 +7,15 @@ import android.content.pm.PackageManager
|
||||
import android.content.pm.PermissionInfo
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.DialogHelper
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.common.utils.toObject
|
||||
import com.gh.gamecenter.core.GHThreadFactory
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper.isGetInstalledListPermissionDisabled
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.entity.WhitePackageListEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.SettingsEntity
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.HashMap
|
||||
import java.util.concurrent.Executors
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
@ -40,34 +23,16 @@ object PackageHelper {
|
||||
|
||||
private const val TAG = "PackageHelper"
|
||||
|
||||
private const val SP_GET_INSTALLED_PACKAGES_AGREED = "get_installed_packages_agreed" // 用户是否同意使用已安装应用列表 API
|
||||
|
||||
private const val SP_GET_INSTALLED_PACKAGES_BY_ALTERNATIVE_API = "get_installed_packages_by_alternative_api" // 是否使用另类方式获取已安装应用列表
|
||||
|
||||
private const val SP_USER_USED_GET_INSTALLED_API_SWITCH_PACKAGE = "user_used_get_installed_api_switch_package" // 用户是否使用过含有已安装应用列表获取开关的包
|
||||
|
||||
private const val SP_ADDITIONAL_WHITELIST_PACKAGE_NAME_LIST = "additional_whitelist_package_name_list" // 额外的白名单包名列表 (曾经更正为已安装的包名列表)
|
||||
private const val SP_GET_INSTALLED_API_AGREED = "get_installed_api_agreed"
|
||||
|
||||
private const val UNKNOWN = -1
|
||||
private const val UNSUPPORTED = 0
|
||||
private const val SUPPORTED = 1
|
||||
|
||||
private const val ENABLED = 2
|
||||
private const val DISABLED = 3
|
||||
|
||||
private var lastSuccessfullyGetInstalledPackagesTimeMills = 0L
|
||||
private var cachedInstalledPackagesList: List<PackageInfo> = arrayListOf()
|
||||
private var additionalWhiteListPackageNameSet: HashSet<String> = hashSetOf()
|
||||
|
||||
private var isGetInstalledPackagesAgreed = false // 用户是否已经同意使用已安装应用列表
|
||||
private var isGetInstalledPackagesAgreedRequired = UNKNOWN // 需要用户手动授权才获取已安装应用列表的功能的开关
|
||||
private var isGetInstalledPackagesPermissionSupported = UNKNOWN // 设备是否支持禁用获取已安装应用列表
|
||||
|
||||
private var useAlternativeWayToGetInstalledPackages = false
|
||||
|
||||
private var cachedPkgNameAndGameEntityMap = HashMap<String, GameEntity>() // 缓存的状态异常包名和游戏实体的映射 (用于免接口请求更新状态)
|
||||
|
||||
private val packageExecutor by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_PACKAGE_THREAD")) }
|
||||
private var lastInstalledPackageListTime = 0L
|
||||
private var installedPackageList: List<PackageInfo> = arrayListOf()
|
||||
private var isGetInstalledPackagesApiAgreed = false
|
||||
private var isGetInstalledListPermissionSupported = UNKNOWN // 设备是否支持禁用获取已安装应用列表。-1 代表支持情况未知,0 代表不支持, 1 代表支持
|
||||
|
||||
// 评论黑名单包名列表,避免用户安装了 Xposed Installer 这样的工具,也能在包含该安装包的游戏详情页评论
|
||||
private var _commentPackageNameBlackList = arrayListOf<String>()
|
||||
@ -85,10 +50,6 @@ object PackageHelper {
|
||||
private var _relatedPackageList = arrayListOf<SettingsEntity.GameWithPackages>()
|
||||
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages> = _relatedPackageList
|
||||
|
||||
// 接口控制的已安装应用列表获取开关状态 (UI 显示)
|
||||
private var _installedPackageApiSwitchStatusLiveData = MutableLiveData<Boolean>()
|
||||
val installedPackageApiSwitchStatusLiveData: LiveData<Boolean> = _installedPackageApiSwitchStatusLiveData
|
||||
|
||||
// 本地已安装包的列表
|
||||
var localPackageNameSet = hashSetOf<String>()
|
||||
get() {
|
||||
@ -100,62 +61,6 @@ object PackageHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否需要忽略接口控制的已安装应用列表获取开关
|
||||
* 用于覆盖安装首次启动时的检查 https://jira.shanqu.cc/browse/GHZSCY-5694
|
||||
*/
|
||||
fun checkIfGetInstalledApiSwitchShouldBeIgnored(context: Context) {
|
||||
val userHasUsedGetInstalledApiSwitchPackage = SPUtils.getBoolean(SP_USER_USED_GET_INSTALLED_API_SWITCH_PACKAGE, false)
|
||||
if (!userHasUsedGetInstalledApiSwitchPackage) {
|
||||
val isSupportGetInstalledAppsPermission = isSupportGetInstalledAppsPermission(context)
|
||||
|
||||
if (!isSupportGetInstalledAppsPermission) {
|
||||
// 设备不支持动态管理获取已安装应用列表,忽略接口控制,使用另类方式获取已安装应用列表
|
||||
updateUseAlternativeWayToGetInstalledPackages()
|
||||
onGetInstalledPackagesAgreed()
|
||||
} else if (!PermissionHelper.isGetInstalledListPermissionDisabled(context)) {
|
||||
// 设备支持动态管理获取已安装应用列表但已经授权,忽略接口控制,使用另类方式获取已安装应用列表
|
||||
updateUseAlternativeWayToGetInstalledPackages()
|
||||
onGetInstalledPackagesAgreed()
|
||||
}
|
||||
|
||||
SPUtils.getBoolean(SP_USER_USED_GET_INSTALLED_API_SWITCH_PACKAGE, true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取包名白名单列表(为了在没有已安装应用列表获取能力的时候也能正常判断更新、插件化)
|
||||
* @param additionalWhiteList 额外的已安装白名单
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun getPackagesWhiteList(additionalWhiteList: HashSet<String>) {
|
||||
RetrofitManager.getInstance().newApi.installWhitelist
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<WhitePackageListEntity>() {
|
||||
override fun onSuccess(data: WhitePackageListEntity) {
|
||||
val installedWhiteList = hashSetOf<String>()
|
||||
|
||||
if (additionalWhiteList.isNotEmpty()) {
|
||||
installedWhiteList.addAll(additionalWhiteList)
|
||||
}
|
||||
|
||||
data.data?.let {
|
||||
installedWhiteList.addAll(it)
|
||||
}
|
||||
|
||||
addInstalledButMissingPackages(installedWhiteList)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
super.onFailure(exception)
|
||||
|
||||
if (additionalWhiteList.isNotEmpty()) {
|
||||
addInstalledButMissingPackages(additionalWhiteList)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun refreshLocalPackageList() {
|
||||
localPackageNameSet = getAllPackageName(HaloApp.getInstance().application)
|
||||
@ -163,7 +68,7 @@ object PackageHelper {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun refreshPackageNameList() {
|
||||
fun refreshList() {
|
||||
Config.getSettings()?.gameCommentBlackList?.let { _commentPackageNameBlackList = ArrayList(it) }
|
||||
Config.getSettings()?.gameDownloadBlackList?.let { _downloadPackageNameBlackList = ArrayList(it) }
|
||||
Config.getSettings()?.gamePackageMatch?.let { _relatedPackageList = ArrayList(it) }
|
||||
@ -201,90 +106,24 @@ object PackageHelper {
|
||||
* 弃用已安装列表缓存
|
||||
*/
|
||||
fun dumpInstalledListCache() {
|
||||
lastSuccessfullyGetInstalledPackagesTimeMills = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 在超时后,若后台没有开启获取已安装应用列表的功能,回落到以接口不控制的方式获取已安装应用列表
|
||||
*/
|
||||
fun ignoreInstalledPackageApiSwitchAfterTimeout(timeout: Long) {
|
||||
CoroutineScope(SupervisorJob()).launch {
|
||||
delay(timeout)
|
||||
if (isGetInstalledPackagesAgreedRequired == UNKNOWN && !isGetInstalledPackagesAgreed()) {
|
||||
Utils.log(TAG, "后台没有开启获取已安装应用列表的功能,超时后回落到以接口不控制的方式获取已安装应用列表")
|
||||
updateIsGetInstalledPackagesApiAgreedRequired(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新已安装应用列表获取开关状态
|
||||
*/
|
||||
fun updateIsGetInstalledPackagesApiAgreedRequired(isEnabled: Boolean) {
|
||||
Utils.log(TAG, "updateIsGetInstalledPackagesApiAgreedRequired 入参为 $isEnabled")
|
||||
|
||||
// 状态不变,无需更新
|
||||
if ((isEnabled == true && isGetInstalledPackagesAgreedRequired == ENABLED)
|
||||
|| (isEnabled == false && isGetInstalledPackagesAgreedRequired == DISABLED)
|
||||
) {
|
||||
Utils.log(TAG, "isGetInstalledPackagesApiAgreedRequired 状态不变,无需更新")
|
||||
return
|
||||
}
|
||||
|
||||
// 若用户已经同意使用了,无需更新
|
||||
if (isGetInstalledPackagesAgreed()) {
|
||||
Utils.log(TAG, "用户已经同意使用了,无需再更新已安装应用列表获取开关状态")
|
||||
return
|
||||
}
|
||||
|
||||
if (isEnabled) {
|
||||
Utils.log(TAG, "开启获取已安装应用列表限制")
|
||||
|
||||
additionalWhiteListPackageNameSet = SPUtils.getString(SP_ADDITIONAL_WHITELIST_PACKAGE_NAME_LIST).toObject() ?: hashSetOf()
|
||||
|
||||
Utils.log(TAG, "额外的白名单为 $additionalWhiteListPackageNameSet")
|
||||
|
||||
getPackagesWhiteList(additionalWhiteListPackageNameSet)
|
||||
_installedPackageApiSwitchStatusLiveData.postValue(true)
|
||||
isGetInstalledPackagesAgreedRequired = ENABLED
|
||||
} else {
|
||||
Utils.log(TAG, "不开启获取已安装应用列表限制")
|
||||
|
||||
isGetInstalledPackagesAgreedRequired = DISABLED
|
||||
|
||||
// 启用另类获取已安装应用列表的 API
|
||||
updateUseAlternativeWayToGetInstalledPackages()
|
||||
|
||||
onGetInstalledPackagesAgreed()
|
||||
}
|
||||
lastInstalledPackageListTime = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户是否已经允许了调用获取已安装应用列表接口
|
||||
* 优先用内存的值,没有再从 SP 中获取并更新
|
||||
*/
|
||||
fun isGetInstalledPackagesAgreed(): Boolean {
|
||||
return isGetInstalledPackagesAgreed
|
||||
|| (SPUtils.getBoolean(SP_GET_INSTALLED_PACKAGES_AGREED).also { isGetInstalledPackagesAgreed = it })
|
||||
fun isGetInstalledPackagesApiAgreed(): Boolean {
|
||||
return isGetInstalledPackagesApiAgreed
|
||||
|| (SPUtils.getBoolean(SP_GET_INSTALLED_API_AGREED).also { isGetInstalledPackagesApiAgreed = it })
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户是否已经允许了调用获取已安装应用列表接口
|
||||
* 优先用内存的值,没有再从 SP 中获取并更新
|
||||
* 同意使用已安装应用列表 API
|
||||
*/
|
||||
private fun isUseAlternativeWayToGetInstalledPackages(): Boolean {
|
||||
return useAlternativeWayToGetInstalledPackages
|
||||
|| (SPUtils.getBoolean(SP_GET_INSTALLED_PACKAGES_BY_ALTERNATIVE_API).also { useAlternativeWayToGetInstalledPackages = it })
|
||||
}
|
||||
|
||||
private fun updateUseAlternativeWayToGetInstalledPackages() {
|
||||
// 启用另类获取已安装应用列表的 API
|
||||
useAlternativeWayToGetInstalledPackages = true
|
||||
SPUtils.setBoolean(SP_GET_INSTALLED_PACKAGES_BY_ALTERNATIVE_API, true)
|
||||
}
|
||||
|
||||
fun isGetInstalledPackagesAgreedRequired(): Boolean {
|
||||
return isGetInstalledPackagesAgreedRequired == ENABLED
|
||||
fun agreeOnGetInstalledPackagesApi() {
|
||||
isGetInstalledPackagesApiAgreed = true
|
||||
SPUtils.setBoolean(SP_GET_INSTALLED_API_AGREED, true)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -293,158 +132,52 @@ object PackageHelper {
|
||||
fun getInstalledPackages(context: Context?, flags: Int): List<PackageInfo> {
|
||||
Utils.log(TAG, "即将获取已安装应用列表")
|
||||
|
||||
// Utils.log(TAG, "即将获取已安装应用列表" + Thread.currentThread().getStackTrace().contentToString().replace( ',', '\n' ))
|
||||
|
||||
// 用户未同意使用已安装应用列表 API,返回空列表
|
||||
if (!isGetInstalledPackagesAgreed()) {
|
||||
if (!isGetInstalledPackagesApiAgreed()) {
|
||||
Utils.log(TAG, "用户未同意使用已安装应用列表 API,返回空列表")
|
||||
return cachedInstalledPackagesList
|
||||
return installedPackageList
|
||||
}
|
||||
|
||||
// 简单 debounce 过于频繁的获取已安装应用列表调用
|
||||
if (System.currentTimeMillis() - lastSuccessfullyGetInstalledPackagesTimeMills < 20 * 1000
|
||||
&& cachedInstalledPackagesList.isNotEmpty()) {
|
||||
if (System.currentTimeMillis() - lastInstalledPackageListTime < 3000 && installedPackageList.isNotEmpty()) {
|
||||
Utils.log(TAG, "使用了缓存的已安装应用列表")
|
||||
return cachedInstalledPackagesList
|
||||
return installedPackageList
|
||||
}
|
||||
|
||||
var shouldGetNewInstalledPackagedList = false
|
||||
|
||||
// 当前设备是否支持限制获取已安装应用列表的功能
|
||||
if (isSupportGetInstalledAppsPermission(context!!)) {
|
||||
Utils.log(TAG, "当前设备支持动态管理获取已安装应用列表的功能")
|
||||
Utils.log(TAG, "当前设备支持限制获取已安装应用列表的功能")
|
||||
// 当前设备是否支持禁用了获取已安装应用列表
|
||||
if (!PermissionHelper.isGetInstalledListPermissionDisabled(context)) {
|
||||
Utils.log(TAG, "当前设备支持动态管理但没有限制获取已安装应用列表的功能")
|
||||
if (!isGetInstalledListPermissionDisabled(context)) {
|
||||
Utils.log(TAG, "当前设备没有限制获取已安装应用列表的功能")
|
||||
shouldGetNewInstalledPackagedList = true
|
||||
} else {
|
||||
Utils.log(TAG, "当前设备支持动态管理且已限制获取已安装应用列表的功能")
|
||||
Utils.log(TAG, "当前设备已限制获取已安装应用列表的功能")
|
||||
}
|
||||
} else {
|
||||
Utils.log(TAG, "当前设备不支持动态管理获取已安装应用列表的功能")
|
||||
Utils.log(TAG, "当前设备不支持限制获取已安装应用列表的功能")
|
||||
shouldGetNewInstalledPackagedList = true
|
||||
}
|
||||
|
||||
if (shouldGetNewInstalledPackagedList) {
|
||||
lastSuccessfullyGetInstalledPackagesTimeMills = System.currentTimeMillis()
|
||||
cachedInstalledPackagesList = getInstalledPackagesInternal(context, flags)
|
||||
|
||||
Utils.log(TAG, "获取已安装应用列表成功,数量为 ${cachedInstalledPackagesList.size}")
|
||||
lastInstalledPackageListTime = System.currentTimeMillis()
|
||||
installedPackageList = getInstalledPackagesInternal(context, flags)
|
||||
}
|
||||
|
||||
return cachedInstalledPackagesList
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示获取已安装应用列表的对话框并请求权限
|
||||
*/
|
||||
fun showGetInstallAppsListDialogAndRequestPermissionIfNeeded(
|
||||
activity: FragmentActivity,
|
||||
ignorePermanentlyDenied: Boolean = false,
|
||||
resultClosure: (Boolean) -> Unit
|
||||
) {
|
||||
|
||||
if (isSupportGetInstalledAppsPermission(activity)) {
|
||||
// 若系统已经授予了获取应用列表的权限,直接执行授权成功回调
|
||||
if (!PermissionHelper.isGetInstalledListPermissionDisabled(activity)) {
|
||||
onGetInstalledPackagesAgreed()
|
||||
resultClosure.invoke(true)
|
||||
return
|
||||
}
|
||||
|
||||
PermissionHelper.showGetInstalledAppsListPermissionDialog(
|
||||
activity = activity,
|
||||
requestPermission = true,
|
||||
ignorePermanentlyDenied = ignorePermanentlyDenied
|
||||
) { isGranted ->
|
||||
if (isGranted) {
|
||||
SensorsBridge.trackInstalledListPermissionsResult("成功")
|
||||
onGetInstalledPackagesAgreed()
|
||||
resultClosure.invoke(true)
|
||||
|
||||
trackInstalledListAfterDelay()
|
||||
} else {
|
||||
resultClosure.invoke(false)
|
||||
SensorsBridge.trackInstalledListPermissionsResult("拒绝")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val hintDialog = PermissionHelper.showGetInstalledAppsListPermissionDialog(
|
||||
activity = activity,
|
||||
requestPermission = false,
|
||||
) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
SensorsBridge.trackInstalledListPermissionsCustomDialogShow()
|
||||
|
||||
val noticeDialog = DialogHelper.showGuideDialog(
|
||||
context = activity,
|
||||
title = "权限申请",
|
||||
content = "是否允许“光环助手”获取已安装的应用信息",
|
||||
confirmText = "开启",
|
||||
cancelText = "拒绝",
|
||||
confirmClickCallback = {
|
||||
SensorsBridge.trackInstalledListPermissionsCustomClick("开启")
|
||||
onGetInstalledPackagesAgreed()
|
||||
resultClosure.invoke(true)
|
||||
|
||||
trackInstalledListAfterDelay()
|
||||
},
|
||||
cancelClickCallback = {
|
||||
resultClosure.invoke(false)
|
||||
SensorsBridge.trackInstalledListPermissionsCustomClick("拒绝")
|
||||
}
|
||||
)
|
||||
|
||||
noticeDialog?.setOnDismissListener {
|
||||
hintDialog?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行用户授权获取已安装应用列表的操作
|
||||
*/
|
||||
private fun onGetInstalledPackagesAgreed() {
|
||||
isGetInstalledPackagesAgreed = true
|
||||
SPUtils.setBoolean(SP_GET_INSTALLED_PACKAGES_AGREED, true)
|
||||
|
||||
_installedPackageApiSwitchStatusLiveData.postValue(false)
|
||||
|
||||
// 进行包名初始化相关的操作
|
||||
initPackageRelatedData()
|
||||
}
|
||||
|
||||
/**
|
||||
* 进行包名初始化相关的操作
|
||||
*/
|
||||
fun initPackageRelatedData() {
|
||||
PackageRepository.initData()
|
||||
refreshLocalPackageList()
|
||||
refreshPackageNameList()
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟5秒后上报已安装应用列表
|
||||
*/
|
||||
private fun trackInstalledListAfterDelay() {
|
||||
CoroutineScope(SupervisorJob()).launch {
|
||||
delay(5000)
|
||||
SensorsBridge.trackNumberOfInstalledList(localPackageNameSet.size, localPackageNameSet)
|
||||
}
|
||||
return installedPackageList
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持动态获取已安装应用列表权限
|
||||
*/
|
||||
fun isSupportGetInstalledAppsPermission(context: Context): Boolean {
|
||||
if (isUseAlternativeWayToGetInstalledPackages()) {
|
||||
// 已经使用另类获取已安装应用列表形式,强制判定为不支持动态获取已安装应用列表权限
|
||||
return false
|
||||
}
|
||||
|
||||
// 若存在缓存,直接返回缓存结果。
|
||||
if (isGetInstalledPackagesPermissionSupported != UNKNOWN) {
|
||||
return isGetInstalledPackagesPermissionSupported != UNSUPPORTED
|
||||
if (isGetInstalledListPermissionSupported != UNKNOWN) {
|
||||
return isGetInstalledListPermissionSupported != UNSUPPORTED
|
||||
}
|
||||
|
||||
try {
|
||||
@ -452,7 +185,7 @@ object PackageHelper {
|
||||
val flag =
|
||||
Settings.Secure.getInt(context.contentResolver, "oem_installed_apps_runtime_permission_enable", 0)
|
||||
if (flag == 1) {
|
||||
isGetInstalledPackagesPermissionSupported = SUPPORTED
|
||||
isGetInstalledListPermissionSupported = SUPPORTED
|
||||
return true
|
||||
}
|
||||
|
||||
@ -461,239 +194,62 @@ object PackageHelper {
|
||||
val permissionInfo = packageManager.getPermissionInfo("com.android.permission.GET_INSTALLED_APPS", 0)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
if (permissionInfo.protection == PermissionInfo.PROTECTION_DANGEROUS) {
|
||||
isGetInstalledPackagesPermissionSupported = SUPPORTED
|
||||
isGetInstalledListPermissionSupported = SUPPORTED
|
||||
return true
|
||||
} else {
|
||||
isGetInstalledPackagesPermissionSupported = UNSUPPORTED
|
||||
isGetInstalledListPermissionSupported = UNSUPPORTED
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
isGetInstalledPackagesPermissionSupported = UNSUPPORTED
|
||||
isGetInstalledListPermissionSupported = UNSUPPORTED
|
||||
return false
|
||||
}
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
isGetInstalledPackagesPermissionSupported = UNSUPPORTED
|
||||
isGetInstalledListPermissionSupported = UNSUPPORTED
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保指定包名的应用在已安装了的情况下能正常收录
|
||||
* 在5.1系统手机使用PackageManager获取已安装应用容易发生Package manager has died异常
|
||||
* https://stackoverflow.com/questions/13235793/transactiontoolargeeception-when-trying-tÏo-get-a-list-of-applications-installed/30062632#30062632
|
||||
*/
|
||||
fun addInstalledButMissingPackages(packageNameSet: HashSet<String>) {
|
||||
Utils.log(TAG, "addInstalledButMissingPackages 检查已安装但未收录的应用")
|
||||
private fun getInstalledPackagesInternal(context: Context, flags: Int): List<PackageInfo> {
|
||||
Utils.log(TAG, "调用系统 API 获取已安装应用列表")
|
||||
|
||||
val installedPackageNameSet: HashSet<String> = hashSetOf()
|
||||
|
||||
for (packageName in packageNameSet) {
|
||||
val installedPkgNameExistInMemory = PackagesManager.isInstalled(packageName)
|
||||
val packageNameInstalledOnDevice = PackageUtils.getVersionNameByPackageName(packageName) != null
|
||||
|
||||
if (!installedPkgNameExistInMemory && packageNameInstalledOnDevice) {
|
||||
installedPackageNameSet.add(packageName)
|
||||
}
|
||||
|
||||
if (!packageNameInstalledOnDevice) {
|
||||
additionalWhiteListPackageNameSet.remove(packageName)
|
||||
}
|
||||
}
|
||||
|
||||
SPUtils.setString(SP_ADDITIONAL_WHITELIST_PACKAGE_NAME_LIST, additionalWhiteListPackageNameSet.toJson())
|
||||
|
||||
Utils.log(TAG, "addInstalledButMissingPackages 需要请求接口获取的包数量为 ${installedPackageNameSet.size}")
|
||||
|
||||
PackageRepository.addInstalledGames(
|
||||
pkgNameList = ArrayList(installedPackageNameSet),
|
||||
updateInstallStatus = true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新额外的白名单包名列表
|
||||
* @param packageName 包名
|
||||
* @param isAdd 是否添加
|
||||
*/
|
||||
fun updateAdditionalWhiteListPackageName(packageName: String, isAdd: Boolean) {
|
||||
val isUpdated = if (isAdd) {
|
||||
additionalWhiteListPackageNameSet.add(packageName)
|
||||
} else {
|
||||
additionalWhiteListPackageNameSet.remove(packageName)
|
||||
}
|
||||
|
||||
Utils.log(TAG, "updateAdditionalWhiteListPackageName 更新额外的白名单包名列表 $isAdd $packageName ,结果是 $isUpdated")
|
||||
|
||||
if (isUpdated) {
|
||||
SPUtils.setString(SP_ADDITIONAL_WHITELIST_PACKAGE_NAME_LIST, additionalWhiteListPackageNameSet.toJson())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新安装状态异常 (适用于仅存在包名信息的列表)
|
||||
*/
|
||||
fun refreshWrongInstallStatus(packageNameSet: MutableSet<String>) {
|
||||
packageExecutor.execute {
|
||||
Utils.log(TAG, "refreshWrongInstallStatus 检查安装状态异常的应用")
|
||||
|
||||
val uninstalledButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
|
||||
val updatedButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
|
||||
|
||||
for (packageName in packageNameSet) {
|
||||
val installedVersionName = PackageUtils.getVersionNameByPackageName(packageName)
|
||||
|
||||
if (PackagesManager.isInstalled(packageName)
|
||||
&& installedVersionName == null) {
|
||||
uninstalledButKeepingWrongStatusPackageNameSet.add(packageName)
|
||||
} else if (PackagesManager.isInstalled(packageName)
|
||||
&& installedVersionName != null
|
||||
&& !PackagesManager.isInstalledWithSpecificVersion(packageName, installedVersionName)) {
|
||||
updatedButKeepingWrongStatusPackageNameSet.add(packageName)
|
||||
}
|
||||
}
|
||||
|
||||
Utils.log(TAG, "refreshWrongInstallStatus 需要更新已更新状态的包数量为 ${updatedButKeepingWrongStatusPackageNameSet.size}")
|
||||
Utils.log(TAG, "refreshWrongInstallStatus 需要移除已安装的包数量为 ${uninstalledButKeepingWrongStatusPackageNameSet.size}")
|
||||
|
||||
runOnUiThread {
|
||||
if (uninstalledButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
|
||||
for (packageName in uninstalledButKeepingWrongStatusPackageNameSet) {
|
||||
PackageChangeHelper.addUninstall(packageName)
|
||||
additionalWhiteListPackageNameSet.remove(packageName)
|
||||
}
|
||||
|
||||
SPUtils.setString(SP_ADDITIONAL_WHITELIST_PACKAGE_NAME_LIST, additionalWhiteListPackageNameSet.toString())
|
||||
}
|
||||
|
||||
if (updatedButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
|
||||
for (packageName in updatedButKeepingWrongStatusPackageNameSet) {
|
||||
PackageChangeHelper.addUpdate(packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新安装状态异常 (适用于存在游戏信息的列表)
|
||||
*/
|
||||
fun refreshWrongInstallStatus(gameEntityList: ArrayList<GameEntity>) {
|
||||
packageExecutor.execute {
|
||||
Utils.log(TAG, "refreshWrongInstallStatus 检查安装状态异常的应用")
|
||||
|
||||
val installedButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
|
||||
val uninstalledButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
|
||||
val updatedButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
|
||||
|
||||
for (game in gameEntityList) {
|
||||
for (apk in game.getApk()) {
|
||||
val packageName = apk.packageName
|
||||
val installedVersionName = PackageUtils.getVersionNameByPackageName(packageName)
|
||||
|
||||
if (!PackagesManager.isInstalled(packageName)
|
||||
&& installedVersionName != null
|
||||
) {
|
||||
cachedPkgNameAndGameEntityMap.put(packageName, game)
|
||||
installedButKeepingWrongStatusPackageNameSet.add(packageName)
|
||||
} else if (PackagesManager.isInstalled(packageName)
|
||||
&& installedVersionName == null
|
||||
) {
|
||||
uninstalledButKeepingWrongStatusPackageNameSet.add(packageName)
|
||||
} else if (PackagesManager.isInstalled(packageName)
|
||||
&& installedVersionName != null
|
||||
&& !PackagesManager.isInstalledWithSpecificVersion(packageName, installedVersionName)
|
||||
&& !PackagesManager.isCanUpdate(game.id, packageName, false)
|
||||
) {
|
||||
cachedPkgNameAndGameEntityMap.put(packageName, game)
|
||||
updatedButKeepingWrongStatusPackageNameSet.add(packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Utils.log(TAG, "refreshWrongInstallStatus 需要更新已安装状态的包数量为 ${installedButKeepingWrongStatusPackageNameSet.size}")
|
||||
Utils.log(TAG, "refreshWrongInstallStatus 需要更新已更新状态的包数量为 ${updatedButKeepingWrongStatusPackageNameSet.size}")
|
||||
Utils.log(TAG, "refreshWrongInstallStatus 需要移除已安装的包数量为 ${uninstalledButKeepingWrongStatusPackageNameSet.size}")
|
||||
|
||||
runOnUiThread {
|
||||
if (installedButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
|
||||
for (packageName in installedButKeepingWrongStatusPackageNameSet) {
|
||||
PackageChangeHelper.addInstall(packageName, cachedPkgNameAndGameEntityMap.remove(packageName))
|
||||
additionalWhiteListPackageNameSet.add(packageName)
|
||||
}
|
||||
|
||||
SPUtils.setString(SP_ADDITIONAL_WHITELIST_PACKAGE_NAME_LIST, additionalWhiteListPackageNameSet.toString())
|
||||
}
|
||||
|
||||
if (uninstalledButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
|
||||
for (packageName in uninstalledButKeepingWrongStatusPackageNameSet) {
|
||||
PackageChangeHelper.addUninstall(packageName)
|
||||
additionalWhiteListPackageNameSet.remove(packageName)
|
||||
}
|
||||
|
||||
SPUtils.setString(SP_ADDITIONAL_WHITELIST_PACKAGE_NAME_LIST, additionalWhiteListPackageNameSet.toString())
|
||||
}
|
||||
|
||||
if (updatedButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
|
||||
for (packageName in updatedButKeepingWrongStatusPackageNameSet) {
|
||||
PackageChangeHelper.addUpdate(packageName, cachedPkgNameAndGameEntityMap.remove(packageName))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInstalledPackagesInternal(
|
||||
context: Context,
|
||||
flags: Int
|
||||
): List<PackageInfo> {
|
||||
return if (isUseAlternativeWayToGetInstalledPackages()) {
|
||||
Utils.log(TAG, "调用另类系统 API 获取已安装应用列表")
|
||||
getInstalledPackageByAlternative(context)
|
||||
} else {
|
||||
Utils.log(TAG, "调用默认系统 API 获取已安装应用列表")
|
||||
getInstalledPackageByDefault(context, flags)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInstalledPackageByDefault(context: Context, flags: Int): List<PackageInfo> {
|
||||
val pm = context.packageManager
|
||||
try {
|
||||
return pm.getInstalledPackages(flags)
|
||||
} catch (ignored: java.lang.Exception) {
|
||||
//we don't care why it didn't succeed. We'll do it using an alternative way instead
|
||||
}
|
||||
// use fallback:
|
||||
val process: Process
|
||||
val result: MutableList<PackageInfo> = java.util.ArrayList()
|
||||
var bufferedReader: BufferedReader? = null
|
||||
try {
|
||||
process = Runtime.getRuntime().exec("pm list packages")
|
||||
bufferedReader = BufferedReader(InputStreamReader(process.inputStream))
|
||||
var line: String
|
||||
while ((bufferedReader.readLine().also { line = it }) != null) {
|
||||
val packageName = line.substring(line.indexOf(':') + 1)
|
||||
val packageInfo = pm.getPackageInfo(packageName, flags)
|
||||
result.add(packageInfo)
|
||||
}
|
||||
process.waitFor()
|
||||
} catch (e: java.lang.Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
return arrayListOf()
|
||||
}
|
||||
|
||||
private fun getInstalledPackageByAlternative(context: Context): ArrayList<PackageInfo> {
|
||||
val packageManager = context.getPackageManager()
|
||||
val packageList = arrayListOf<PackageInfo>()
|
||||
var packagesArray: Array<String>? = null
|
||||
var uid = android.os.Process.FIRST_APPLICATION_UID
|
||||
|
||||
while (uid <= android.os.Process.LAST_APPLICATION_UID) {
|
||||
try {
|
||||
packagesArray = packageManager.getPackagesForUid(uid)
|
||||
if (packagesArray != null && packagesArray.isNotEmpty()) {
|
||||
for (packageName in packagesArray) {
|
||||
try {
|
||||
val packageInfo = packageManager.getPackageInfo(packageName, 0)
|
||||
if (packageInfo == null) {
|
||||
break
|
||||
}
|
||||
|
||||
packageList.add(packageInfo)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (securityException: SecurityException) {
|
||||
securityException.printStackTrace()
|
||||
if (e is InterruptedException) {
|
||||
Thread.currentThread().interrupt()
|
||||
}
|
||||
} finally {
|
||||
if (bufferedReader != null) try {
|
||||
bufferedReader.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
uid++
|
||||
}
|
||||
|
||||
return packageList
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,6 +6,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.FileProvider
|
||||
import com.gh.common.dialog.InstallPermissionDialogFragment
|
||||
@ -19,13 +20,13 @@ import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.install.InstallService
|
||||
import com.gh.gamecenter.vpn.VpnHelper
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
import java.io.File
|
||||
|
||||
// TODO 将弹窗改成以责任链模式来处理
|
||||
object PackageInstaller {
|
||||
|
||||
/**
|
||||
@ -107,12 +108,6 @@ object PackageInstaller {
|
||||
return
|
||||
}
|
||||
|
||||
val packageName = downloadEntity?.packageName ?: PackageUtils.getPackageNameByPath(context, pkgPath)
|
||||
|
||||
packageName?.let {
|
||||
PackageChangeHelper.addInstallPendingPackage(packageName)
|
||||
}
|
||||
|
||||
try {
|
||||
// 判断是否需要使用浏览器来进行安装
|
||||
if (BrowserInstallHelper.isUseBrowserToInstallEnabled()
|
||||
@ -123,13 +118,13 @@ object PackageInstaller {
|
||||
}
|
||||
|
||||
if (PackageUtils.isCanLaunchSetup(context, pkgPath)) {
|
||||
installWithPureModeHandled(
|
||||
context,
|
||||
pkgPath,
|
||||
downloadEntity?.gameId ?: "unknown",
|
||||
downloadEntity?.name ?: "unknown",
|
||||
downloadEntity?.categoryChinese ?: "unknown"
|
||||
)
|
||||
val currentActivity = CurrentActivityHolder.getCurrentActivity()
|
||||
|
||||
if (VpnHelper.shouldUseVpn() && currentActivity is AppCompatActivity) {
|
||||
turnOnVpnThenInstall(currentActivity, pkgPath, downloadEntity)
|
||||
} else {
|
||||
install(context, pkgPath)
|
||||
}
|
||||
} else {
|
||||
if (isPluggin) {
|
||||
DialogHelper.showPluginDialog(
|
||||
@ -159,21 +154,6 @@ object PackageInstaller {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理纯净模式后的安装
|
||||
*/
|
||||
private fun installWithPureModeHandled(
|
||||
context: Context,
|
||||
pkgPath: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
gameType: String,
|
||||
) {
|
||||
PureModeHelper.handlePureModeIfNeeded(context, gameId, gameName, gameType) {
|
||||
install(context, pkgPath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 最终执行安装的方法
|
||||
*/
|
||||
@ -270,8 +250,6 @@ object PackageInstaller {
|
||||
fun uninstallForPackageName(context: Context, pkn: String?) {
|
||||
if (pkn.isNullOrEmpty()) return
|
||||
|
||||
PackageChangeHelper.addUninstallPendingPackage(pkn)
|
||||
|
||||
val uninstallIntent = Intent()
|
||||
uninstallIntent.action = Intent.ACTION_DELETE
|
||||
uninstallIntent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
@ -305,4 +283,82 @@ object PackageInstaller {
|
||||
return MD5Utils.getContentMD5(gameName + "_" + System.currentTimeMillis())
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动 VPN 然后安装应用 (若没有授权会先提醒授权 VPN ,若拒绝授权会回落到直接执行安装)
|
||||
*/
|
||||
private fun turnOnVpnThenInstall(currentActivity: AppCompatActivity,
|
||||
pkgPath: String,
|
||||
downloadEntity: DownloadEntity?) {
|
||||
if (VpnHelper.isVpnPermissionGranted(currentActivity) == true) {
|
||||
VpnHelper.startVpn(currentActivity) { shouldShowVpnError ->
|
||||
if (shouldShowVpnError) {
|
||||
ToastUtils.toast("安装防护功能启动失败")
|
||||
}
|
||||
install(currentActivity, pkgPath)
|
||||
}
|
||||
} else {
|
||||
val isTheFirstTimeToShowVpnHintDialog = VpnHelper.isTheFistTimeToShowVpnHintDialog()
|
||||
|
||||
downloadEntity?.let {
|
||||
NewFlatLogUtils.logVpnHintDialogShow(it.gameId, it.name)
|
||||
}
|
||||
|
||||
// 将 VPN 提示弹窗标记为已读(已读后的下一次显示"不再提醒"按钮)
|
||||
VpnHelper.setVpnHintDialogShowed()
|
||||
if (!VpnHelper.shouldShowVpnHintDialog()) {
|
||||
VpnHelper.startVpn(currentActivity) { shouldShowVpnError ->
|
||||
if (shouldShowVpnError) {
|
||||
ToastUtils.toast("安装防护功能启动失败")
|
||||
}
|
||||
install(currentActivity, pkgPath)
|
||||
}
|
||||
} else {
|
||||
DialogHelper.showGuideDialog(
|
||||
context = currentActivity,
|
||||
title = "开启安装防护",
|
||||
content = "建议您开启安装防护功能,该功能有助于帮助您更快的完成安装,避免因提示和置换导致的重复下载等问题,安装防护功能需要获取您的VPN权限",
|
||||
confirmText = "立即授权开启防护",
|
||||
cancelText = "不再提醒",
|
||||
confirmClickCallback = {
|
||||
VpnHelper.ignoreVpnHintDialog()
|
||||
VpnHelper.startVpn(currentActivity) { shouldShowVpnError ->
|
||||
if (shouldShowVpnError) {
|
||||
ToastUtils.toast("安装防护功能启动失败")
|
||||
}
|
||||
install(currentActivity, pkgPath)
|
||||
}
|
||||
|
||||
downloadEntity?.let {
|
||||
NewFlatLogUtils.logVpnHintDialogClick(it.gameId, it.name, "立即授权")
|
||||
}
|
||||
},
|
||||
cancelClickCallback = {
|
||||
VpnHelper.ignoreVpnFunction()
|
||||
install(currentActivity, pkgPath)
|
||||
downloadEntity?.let {
|
||||
NewFlatLogUtils.logVpnHintDialogClick(it.gameId, it.name, "不再提醒")
|
||||
}
|
||||
},
|
||||
extraConfig = DialogHelper.Config(
|
||||
showCloseIcon = true,
|
||||
showAlternativeCancelStyle = !isTheFirstTimeToShowVpnHintDialog
|
||||
),
|
||||
uiModificationCallback = { binding ->
|
||||
binding.cancelTv.visibility = View.GONE
|
||||
binding.closeContainer.setOnClickListener {
|
||||
binding.markDismissByTouchInside()
|
||||
|
||||
install(currentActivity, pkgPath)
|
||||
binding.dismiss()
|
||||
|
||||
downloadEntity?.let {
|
||||
NewFlatLogUtils.logVpnHintDialogClick(it.gameId, it.name, "关闭按钮")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -7,12 +7,14 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.PermissionInfo;
|
||||
import android.content.pm.Signature;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@ -27,6 +29,7 @@ import com.gh.common.xapk.XapkInstaller;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper;
|
||||
import com.gh.gamecenter.core.utils.MD5Utils;
|
||||
import com.gh.gamecenter.core.utils.SentryHelper;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
@ -45,10 +48,12 @@ import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
@ -69,7 +74,7 @@ public class PackageUtils {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).applicationInfo.sourceDir;
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -307,7 +312,7 @@ public class PackageUtils {
|
||||
return new String[]{null, null};
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new String[]{null, null};
|
||||
}
|
||||
@ -587,7 +592,7 @@ public class PackageUtils {
|
||||
.getPackageInfo(packageName, 0);
|
||||
return packageInfo.firstInstallTime;
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -614,7 +619,7 @@ public class PackageUtils {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager()
|
||||
.getPackageInfo(BuildConfig.APPLICATION_ID, 0).lastUpdateTime;
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -628,7 +633,7 @@ public class PackageUtils {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -641,7 +646,7 @@ public class PackageUtils {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionCode;
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -655,7 +660,7 @@ public class PackageUtils {
|
||||
PackageManager packageManager = context.getApplicationContext().getPackageManager();
|
||||
return packageManager.getApplicationIcon(packageName);
|
||||
} catch (NameNotFoundException e) {
|
||||
// do nothing
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -5,12 +5,12 @@ import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.retrofit.JSONObjectResponse;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.feature.entity.CommentEntity;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.walkud.rom.checker.RomIdentifier;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
@ -37,7 +37,7 @@ public class PostCommentUtils {
|
||||
device.put("model", Build.MODEL);
|
||||
device.put("manufacturer", Build.MANUFACTURER);
|
||||
device.put("android_version", android.os.Build.VERSION.RELEASE);
|
||||
device.put("rom", MetaUtil.INSTANCE.getRom().name() + " " + MetaUtil.INSTANCE.getRom().getVersionName());
|
||||
device.put("rom", RomIdentifier.getRom().name() + " " + RomIdentifier.getRom().getVersionName());
|
||||
content.put("device", device);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@ -1,342 +0,0 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.common.utils.DialogHelper
|
||||
import com.gh.gamecenter.entity.NewApiSettingsEntity
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.common.utils.enlargeTouchArea
|
||||
import com.gh.gamecenter.common.utils.setDrawableEnd
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
|
||||
/**
|
||||
* 处理厂商纯净/安全模式的辅助类
|
||||
*/
|
||||
object PureModeHelper {
|
||||
|
||||
private const val TAG = "PureModeHelper"
|
||||
|
||||
private const val HW = "HUAWEI"
|
||||
|
||||
private const val HW_PURE_MODE_STATE = "pure_mode_state"
|
||||
private const val HW_PURE_ENHANCED_MODE_STATE = "pure_enhanced_mode_state"
|
||||
|
||||
private const val HW_PURE_MODE = "harmony_os_pure_mode"
|
||||
private const val HW_PURE_ENHANCED_MODE = "harmony_os_pure_enhanced_mode"
|
||||
|
||||
private const val SP_USER_IGNORE_GUIDE = "user_ignore_guide"
|
||||
|
||||
private const val SWITCH_EXIST = 1
|
||||
private const val SWITCH_ON = 0
|
||||
private const val SWITCH_OFF = -1
|
||||
|
||||
private var isThisDeviceUsingEnhancedMode = false // 当前设备是否是增强纯净模式
|
||||
|
||||
fun handlePureModeIfNeeded(
|
||||
context: Context,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
gameType: String,
|
||||
callback: () -> Unit
|
||||
) {
|
||||
// 用户忽略提醒,不再走下面的逻辑
|
||||
if (SPUtils.getBoolean(SP_USER_IGNORE_GUIDE, false)) {
|
||||
callback()
|
||||
return
|
||||
}
|
||||
|
||||
// 仅适用于华为手机
|
||||
val manufacturer = android.os.Build.MANUFACTURER
|
||||
if (manufacturer != HW) {
|
||||
callback.invoke()
|
||||
return
|
||||
}
|
||||
|
||||
val solidContext = DialogHelper.checkDialogContext(context)
|
||||
|
||||
if (solidContext == null) {
|
||||
callback.invoke()
|
||||
return
|
||||
}
|
||||
|
||||
if (readState(solidContext, HW_PURE_ENHANCED_MODE_STATE) == SWITCH_ON) {
|
||||
Utils.log(TAG, "增强纯净模式开启!")
|
||||
isThisDeviceUsingEnhancedMode = true
|
||||
|
||||
val pureModeGuide =
|
||||
Config.getNewApiSettingsEntity()?.install?.guides?.firstOrNull { it.type == HW_PURE_ENHANCED_MODE }
|
||||
|
||||
if (pureModeGuide != null) {
|
||||
showHWHintDialog(solidContext, pureModeGuide, gameId, gameName, gameType, true, callback)
|
||||
} else {
|
||||
callback.invoke()
|
||||
}
|
||||
} else if (readState(solidContext, HW_PURE_ENHANCED_MODE_STATE) != SWITCH_EXIST
|
||||
&& readState(solidContext, HW_PURE_MODE_STATE) == SWITCH_ON
|
||||
) {
|
||||
Utils.log(TAG, "纯净模式开启!")
|
||||
isThisDeviceUsingEnhancedMode = false
|
||||
|
||||
val pureModeGuide =
|
||||
Config.getNewApiSettingsEntity()?.install?.guides?.firstOrNull { it.type == HW_PURE_MODE }
|
||||
|
||||
if (pureModeGuide != null) {
|
||||
showHWHintDialog(solidContext, pureModeGuide, gameId, gameName, gameType, false, callback)
|
||||
} else {
|
||||
callback.invoke()
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showHWHintDialog(
|
||||
context: Context,
|
||||
guide: NewApiSettingsEntity.Guide,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
gameType: String,
|
||||
isEnhancedMode: Boolean,
|
||||
callback: () -> Unit
|
||||
) {
|
||||
var isIgnored = false
|
||||
|
||||
if (context is Activity) {
|
||||
if (context.isFinishing) {
|
||||
callback.invoke()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
trackDialogShow(isEnhancedMode, gameId, gameName, gameType)
|
||||
|
||||
DialogHelper.showGuideDialog(
|
||||
context = context,
|
||||
title = guide.title,
|
||||
content = guide.content,
|
||||
confirmText = guide.buttonTextSettingJump,
|
||||
cancelText = guide.buttonTextClose,
|
||||
uiModificationCallback = { binding ->
|
||||
binding.hintTv.buildSpannableString {
|
||||
addText(guide.linkTextPrefix)
|
||||
addText(guide.linkText) {
|
||||
setColor(ColorResId(R.color.text_theme))
|
||||
onClick(false) {
|
||||
binding.extraHintIv.performClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.extraHintIv.setImageResource(R.drawable.ic_home_head_arrow)
|
||||
binding.extraHintIv.setOnClickListener {
|
||||
directToLink(
|
||||
context,
|
||||
guide,
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
isEnhancedMode,
|
||||
isIgnored
|
||||
)
|
||||
}
|
||||
binding.extraHintIv.enlargeTouchArea()
|
||||
binding.extraHintIv.visibility = View.VISIBLE
|
||||
binding.hintTv.visibility = View.VISIBLE
|
||||
binding.selectorContainer.visibility = if (guide.dialogFrequency == "once") View.VISIBLE else View.GONE
|
||||
binding.selectorContainer.setOnClickListener {
|
||||
binding.selectorContainer.isChecked = !binding.selectorContainer.isChecked
|
||||
isIgnored = binding.selectorContainer.isChecked
|
||||
}
|
||||
|
||||
binding.confirmTv.setOnClickListener {
|
||||
toHWPureModeSetting(context)
|
||||
trackDialogClicked(
|
||||
isEnhancedMode = isEnhancedMode,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameType,
|
||||
buttonName = guide.buttonTextSettingJump,
|
||||
isIgnored = isIgnored
|
||||
)
|
||||
}
|
||||
|
||||
// 监听是否已授权,授权后自动调起安装并 dismiss dialog
|
||||
if (context is AppCompatActivity) {
|
||||
val lifecycle = context.lifecycle
|
||||
lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
val granted = (isThisDeviceUsingEnhancedMode && readState(context, HW_PURE_ENHANCED_MODE_STATE) != SWITCH_ON)
|
||||
|| (!isThisDeviceUsingEnhancedMode && readState(context, HW_PURE_MODE_STATE) != SWITCH_ON)
|
||||
|
||||
if (granted) {
|
||||
binding.dialog.dismiss()
|
||||
callback.invoke()
|
||||
lifecycle.removeObserver(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
super.onDestroy(owner)
|
||||
|
||||
lifecycle.removeObserver(this)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
confirmClickCallback = {
|
||||
// do nothing, 上面 setOnClickListener 处理了
|
||||
},
|
||||
cancelClickCallback = {
|
||||
if (guide.dialogFrequency == "once" && isIgnored) {
|
||||
SPUtils.setBoolean(SP_USER_IGNORE_GUIDE, true)
|
||||
}
|
||||
trackDialogClicked(
|
||||
isEnhancedMode = isEnhancedMode,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameType,
|
||||
buttonName = guide.buttonTextClose,
|
||||
isIgnored = isIgnored
|
||||
)
|
||||
callback()
|
||||
},
|
||||
touchOutsideCallback = {
|
||||
if (guide.dialogFrequency == "once" && isIgnored) {
|
||||
SPUtils.setBoolean(SP_USER_IGNORE_GUIDE, true)
|
||||
}
|
||||
trackDialogClicked(
|
||||
isEnhancedMode = isEnhancedMode,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameType,
|
||||
buttonName = "关闭弹窗",
|
||||
isIgnored = isIgnored
|
||||
)
|
||||
callback()
|
||||
},
|
||||
extraConfig = DialogHelper.Config(centerTitle = true)
|
||||
)
|
||||
}
|
||||
|
||||
private fun directToLink(
|
||||
context: Context,
|
||||
guide: NewApiSettingsEntity.Guide,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
gameType: String,
|
||||
isEnhancedMode: Boolean,
|
||||
isIgnored: Boolean
|
||||
) {
|
||||
DirectUtils.directToLinkPage(context, guide.link, "纯净模式弹窗", "")
|
||||
trackDialogClicked(
|
||||
isEnhancedMode,
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
"跳转链接",
|
||||
isIgnored,
|
||||
guide.link.link ?: "",
|
||||
guide.link.type ?: "",
|
||||
guide.link.text ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
private fun trackDialogShow(
|
||||
isEnhancedMode: Boolean,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
gameType: String
|
||||
) {
|
||||
if (isEnhancedMode) {
|
||||
SensorsBridge.trackAddedProtectionDialogShow(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameType
|
||||
)
|
||||
} else {
|
||||
SensorsBridge.trackPureModeDialogShow(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameType
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun trackDialogClicked(
|
||||
isEnhancedMode: Boolean,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
gameType: String,
|
||||
buttonName: String,
|
||||
isIgnored: Boolean,
|
||||
linkId: String? = null,
|
||||
linkType: String? = null,
|
||||
linkText: String? = null
|
||||
) {
|
||||
if (isEnhancedMode) {
|
||||
SensorsBridge.trackAddedProtectionDialogClick(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameType,
|
||||
buttonName = buttonName,
|
||||
isIgnored = isIgnored,
|
||||
linkId = linkId ?: "",
|
||||
linkType = linkType ?: "",
|
||||
linkText = linkText ?: ""
|
||||
)
|
||||
} else {
|
||||
SensorsBridge.trackPureModeDialogClick(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameType,
|
||||
buttonName = buttonName,
|
||||
isIgnored = isIgnored,
|
||||
linkId = linkId ?: "",
|
||||
linkType = linkType ?: "",
|
||||
linkText = linkText ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toHWPureModeSetting(context: Context) {
|
||||
try {
|
||||
val intent = Intent()
|
||||
intent.setPackage("com.huawei.security.privacycenter")
|
||||
intent.setAction("com.huawei.securitycenter.PURE_MODE_ACTIVITY")
|
||||
intent.putExtra("intent_from_settings", true)
|
||||
context.startActivity(intent)
|
||||
} catch (_: Exception) {
|
||||
toSystemSettings(context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toSystemSettings(context: Context) {
|
||||
try {
|
||||
val intent = Intent(Settings.ACTION_SETTINGS)
|
||||
context.startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun readState(context: Context, key: String): Int {
|
||||
try {
|
||||
val result = Settings.Secure.getInt(context.getContentResolver(), key, SWITCH_OFF)
|
||||
Utils.log(TAG, "readState $key state >>> $result")
|
||||
return result
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return SWITCH_OFF
|
||||
}
|
||||
|
||||
}
|
||||
@ -27,8 +27,8 @@ import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
|
||||
|
||||
object SyncDataBetweenPageHelper {
|
||||
|
||||
const val REQUEST_CODE_TAG = "REQUEST_CODE_TAG"
|
||||
const val DATA_POSITION_TAG = "DATA_POSITION_TAG"
|
||||
private const val REQUEST_CODE_TAG = "REQUEST_CODE_TAG"
|
||||
private const val DATA_POSITION_TAG = "DATA_POSITION_TAG"
|
||||
private const val DEFAULT_NUMBER = -1111
|
||||
|
||||
fun startActivityForResult(context: Context, intent: Intent, requestCode: Int, dataPosition: Int) {
|
||||
|
||||
@ -62,8 +62,7 @@ object ViewPagerFragmentHelper {
|
||||
const val TYPE_GAME_LIST = "game_list" // 游戏单广场
|
||||
const val TYPE_FEEDBACK = "feedback" // 帮助与反馈
|
||||
const val TYPE_COLUMN = "column" // 游戏专题详情页
|
||||
const val TYPE_QQ_MINI_GAME_COLUMN = "qq_mini_game_column_detail" // QQ小游戏专题详情页
|
||||
const val TYPE_WECHAT_GAME_COLUMN = "wechat_game_column_detail" // 微信小游戏专题详情页
|
||||
const val TYPE_QQ_MINI_GAME_COLUMN = "qq_mini_game_column_detail" // QQ游戏专题详情页
|
||||
const val TYPE_COLUMN_COLLECTION = "column_collection" // 专题合集详情页
|
||||
const val TYPE_SERVER = "server" // 开服表
|
||||
const val TYPE_COLUMN_TEST = "column_test_v2" // 新游开测
|
||||
@ -152,16 +151,11 @@ object ViewPagerFragmentHelper {
|
||||
className = GameCollectionSquareFragment::class.java.name
|
||||
}
|
||||
// 游戏专题详情页/QQ游戏专题详情页
|
||||
TYPE_COLUMN, TYPE_QQ_MINI_GAME_COLUMN, TYPE_WECHAT_GAME_COLUMN -> {
|
||||
val subjectType = when(entity.type) {
|
||||
TYPE_QQ_MINI_GAME_COLUMN -> SubjectData.SubjectType.QQ_GAME
|
||||
TYPE_WECHAT_GAME_COLUMN -> SubjectData.SubjectType.WECHAT_GAME
|
||||
else -> SubjectData.SubjectType.NORMAL
|
||||
}
|
||||
TYPE_COLUMN, TYPE_QQ_MINI_GAME_COLUMN -> {
|
||||
className = SubjectFragment::class.java.name
|
||||
bundle.putParcelable(
|
||||
EntranceConsts.KEY_SUBJECT_DATA,
|
||||
SubjectData(entity.link, entity.text, false, subjectType = subjectType)
|
||||
SubjectData(entity.link, entity.text, false, isQQMiniGame = entity.type == "qq_mini_game_column_detail")
|
||||
)
|
||||
bundle.putBoolean(EntranceConsts.KEY_SHOW_DOWNLOAD_MENU, !isTabWrapper)
|
||||
}
|
||||
|
||||
@ -6,21 +6,25 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.get
|
||||
import com.facebook.drawee.drawable.ScalingUtils
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.debounceActionWithInterval
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toResString
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.TopCutProcess
|
||||
import com.gh.gamecenter.databinding.ItemCommunityImageBinding
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.feature.entity.ImageInfo
|
||||
import com.gh.gamecenter.feature.entity.CommunityVideoEntity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
|
||||
class ImageContainerView : LinearLayout {
|
||||
|
||||
private var data: ImageContainerData? = null
|
||||
private var mAnswerEntity: AnswerEntity? = null
|
||||
|
||||
//三图默认宽度
|
||||
private var mDefaultWidth = 0f
|
||||
@ -37,6 +41,9 @@ class ImageContainerView : LinearLayout {
|
||||
//长图比例
|
||||
private var mLongPictureRatio = 9 / 18f
|
||||
|
||||
private var mEntrance = ""
|
||||
private var mPath = ""
|
||||
|
||||
//图片之间的间距
|
||||
private val mItemSpace = 4f.dip2px()
|
||||
private var mOffset = 0
|
||||
@ -44,8 +51,6 @@ class ImageContainerView : LinearLayout {
|
||||
|
||||
private val imageViewList = arrayListOf<SimpleDraweeView>()
|
||||
|
||||
private var onImageContainerEventListener: OnImageContainerEventListener? = null
|
||||
|
||||
constructor(context: Context) : this(context, null)
|
||||
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
||||
@ -70,34 +75,40 @@ class ImageContainerView : LinearLayout {
|
||||
calculateWidth()
|
||||
}
|
||||
|
||||
fun bindData(
|
||||
data: ImageContainerData,
|
||||
listener: OnImageContainerEventListener? = null
|
||||
) {
|
||||
this.data = data
|
||||
onImageContainerEventListener = listener
|
||||
fun bindData(entity: AnswerEntity, entrance: String = "", path: String = "", imageClick: (() -> Unit)? = null) {
|
||||
imageViewList.clear()
|
||||
removeAllViews()
|
||||
if (entity.id != mAnswerEntity?.id) {
|
||||
removeAllViews()
|
||||
}
|
||||
mAnswerEntity = entity
|
||||
mEntrance = entrance
|
||||
mPath = path
|
||||
index = 0
|
||||
if (!data.show) {
|
||||
if ((entity.user.id == UserManager.getInstance().userId && entity.videos.isNotEmpty()) ||
|
||||
(entity.user.id != UserManager.getInstance().userId && entity.getPassVideos().isNotEmpty()) ||
|
||||
entity.images.isNullOrEmpty()
|
||||
) {
|
||||
visibility = View.GONE
|
||||
return
|
||||
}
|
||||
visibility = View.VISIBLE
|
||||
if (data.isPostCard) {
|
||||
if (mAnswerEntity?.type == "community_article") {
|
||||
//若文章内容含有图片及视频,则信息流卡片,仅展示图片,且标题后带有‘有视频’标签
|
||||
//若文章内容仅含有图片,则信息流卡片,仅展示图片,无标签
|
||||
//若文章内容仅含有视频,则信息流卡片,仅展示视频,无标签
|
||||
when {
|
||||
data.images.isNotEmpty() -> {
|
||||
data.images.take(3)
|
||||
.forEach {
|
||||
bindImage(it.url, it.width, it.height, data.images.size == 1)
|
||||
}
|
||||
entity.images.isNotEmpty() -> {
|
||||
val imagesInfo = entity.imagesInfo
|
||||
val images = entity.images.take(3)
|
||||
images.forEachIndexed { index, url ->
|
||||
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
|
||||
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
|
||||
bindImage(url, width, height, images.size == 1, imageClick)
|
||||
}
|
||||
}
|
||||
|
||||
data.video != null -> {
|
||||
val video = data.video
|
||||
entity.getPassVideos().isNotEmpty() -> {
|
||||
val video = entity.getPassVideos()[0]
|
||||
bindVideo(video, video.width, video.height, true)
|
||||
}
|
||||
|
||||
@ -109,22 +120,28 @@ class ImageContainerView : LinearLayout {
|
||||
//若问答内容含有图片及视频,则信息流卡片,同时展示图片及视频,且参考以往排序逻辑(视频优先放置第一位),无标签
|
||||
//若问答内容仅含有图片,则信息流卡片,仅展示图片,无标签
|
||||
//若问答内容仅含有视频,则信息流卡片,仅展示视频,无标签
|
||||
if (data.video != null) {
|
||||
val video = data.video
|
||||
bindVideo(video, video.width, video.height, data.images.isNullOrEmpty())
|
||||
data.images.take(2).forEach {
|
||||
bindImage(it.url, it.width, it.height, false)
|
||||
if (entity.getPassVideos().isNotEmpty()) {
|
||||
val video = entity.getPassVideos()[0]
|
||||
bindVideo(video, video.width, video.height, mAnswerEntity?.images.isNullOrEmpty())
|
||||
entity.images.take(2).forEachIndexed { index, url ->
|
||||
val imagesInfo = entity.imagesInfo
|
||||
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
|
||||
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
|
||||
bindImage(url, width, height, false, imageClick)
|
||||
}
|
||||
} else {
|
||||
data.images.take(3)
|
||||
.forEach {
|
||||
bindImage(it.url, it.width, it.height, data.images.size == 1)
|
||||
}
|
||||
val images = entity.images.take(3)
|
||||
images.forEachIndexed { index, url ->
|
||||
val imagesInfo = entity.imagesInfo
|
||||
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
|
||||
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
|
||||
bindImage(url, width, height, images.size == 1, imageClick)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindVideo(video: ImageContainerData.VideoInfo, width: Int, height: Int, isChangeRatio: Boolean) {
|
||||
private fun bindVideo(video: CommunityVideoEntity, width: Int, height: Int, isChangeRatio: Boolean) {
|
||||
val oldView = if (childCount == 0 || index >= childCount) null else getChildAt(index)
|
||||
val binding = if (oldView != null) {
|
||||
ItemCommunityImageBinding.bind(oldView)
|
||||
@ -141,7 +158,16 @@ class ImageContainerView : LinearLayout {
|
||||
displayImage(binding, video.poster, width.toFloat(), height.toFloat(), isChangeRatio, true)
|
||||
binding.root.setOnClickListener {
|
||||
debounceActionWithInterval(it.id, 1000) {
|
||||
onImageContainerEventListener?.onVideoCLick(video.id)
|
||||
if (mAnswerEntity == null) return@debounceActionWithInterval
|
||||
val videoEntity = mAnswerEntity!!.getPassVideos().firstOrNull()
|
||||
DirectUtils.directToVideoDetail(
|
||||
context,
|
||||
videoEntity?.id ?: "",
|
||||
VideoDetailContainerViewModel.Location.VIDEO_HOT.value,
|
||||
showComment = false,
|
||||
entrance = mEntrance,
|
||||
path = mPath
|
||||
)
|
||||
}
|
||||
}
|
||||
index++
|
||||
@ -151,7 +177,8 @@ class ImageContainerView : LinearLayout {
|
||||
url: String,
|
||||
width: Int,
|
||||
height: Int,
|
||||
isChangeRatio: Boolean
|
||||
isChangeRatio: Boolean,
|
||||
imageClick: (() -> Unit)?
|
||||
) {
|
||||
val oldView = if (childCount == 0 || index >= childCount) null else getChildAt(index)
|
||||
val binding = if (oldView != null) {
|
||||
@ -168,21 +195,25 @@ class ImageContainerView : LinearLayout {
|
||||
binding.videoPlay.visibility = View.GONE
|
||||
displayImage(binding, url, width.toFloat(), height.toFloat(), isChangeRatio)
|
||||
binding.root.setOnClickListener {
|
||||
if (data?.status == "pending" || data?.status == "fail") return@setOnClickListener
|
||||
if (mAnswerEntity?.status == "pending" || mAnswerEntity?.status == "fail") return@setOnClickListener
|
||||
imageClick?.invoke()
|
||||
debounceActionWithInterval(it.id, 1000) {
|
||||
data?.run {
|
||||
val position = if (isPostCard) {
|
||||
binding.root.tag as Int
|
||||
} else {
|
||||
if (video == null) binding.root.tag as Int else (binding.root.tag as Int) - 1
|
||||
}
|
||||
onImageContainerEventListener?.onImageClick(
|
||||
images.map(ImageContainerData.ImageInfo::url),
|
||||
position,
|
||||
imageViewList
|
||||
)
|
||||
if (mAnswerEntity == null) return@debounceActionWithInterval
|
||||
val position = if (mAnswerEntity?.type == "community_article") {
|
||||
binding.root.tag as Int
|
||||
} else {
|
||||
if (mAnswerEntity!!.getPassVideos()
|
||||
.isNullOrEmpty()
|
||||
) binding.root.tag as Int else (binding.root.tag as Int) - 1
|
||||
}
|
||||
|
||||
if (mAnswerEntity?.communityId.isNullOrEmpty()) {
|
||||
mAnswerEntity?.communityId = mAnswerEntity?.bbs?.id
|
||||
}
|
||||
val intent = ImageViewerActivity.getIntent(
|
||||
context, mAnswerEntity!!.images as ArrayList<String>, position, imageViewList,
|
||||
if (mAnswerEntity?.type == "community_article") mAnswerEntity else null, mEntrance, true
|
||||
)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
index++
|
||||
@ -248,7 +279,7 @@ class ImageContainerView : LinearLayout {
|
||||
}
|
||||
|
||||
binding.pendingView.run {
|
||||
when (data?.status) {
|
||||
when (mAnswerEntity?.status) {
|
||||
"pending" -> {
|
||||
visibility = View.VISIBLE
|
||||
text = R.string.pending_status.toResString()
|
||||
@ -266,7 +297,7 @@ class ImageContainerView : LinearLayout {
|
||||
}
|
||||
|
||||
|
||||
val imageCount = data?.images?.size ?: 0
|
||||
val imageCount = mAnswerEntity?.images?.size ?: 0
|
||||
if (!isVideo && index == 2 && imageCount > 3) {
|
||||
binding.labelIcon.visibility = View.GONE
|
||||
binding.durationOrNumTv.visibility = View.VISIBLE
|
||||
@ -277,80 +308,4 @@ class ImageContainerView : LinearLayout {
|
||||
if (index != 0) params.leftMargin = mItemSpace
|
||||
binding.root.layoutParams = params
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val COMMUNITY_ARTICLE = "community_article"
|
||||
|
||||
fun AnswerEntity.toImageContainerData(): ImageContainerData {
|
||||
val imageInfoList = arrayListOf<ImageContainerData.ImageInfo>()
|
||||
images.forEachIndexed { index, url ->
|
||||
if (index < 3) {
|
||||
imageInfoList.add(ImageContainerData.ImageInfo(url))
|
||||
}
|
||||
}
|
||||
imageInfoList.forEachIndexed { index, imageInfo ->
|
||||
val item = imagesInfo.getOrNull(index)
|
||||
if (item != null) {
|
||||
imageInfo.width = item.width
|
||||
imageInfo.height = item.height
|
||||
}
|
||||
}
|
||||
val video =
|
||||
getPassVideos().firstOrNull()?.let {
|
||||
ImageContainerData.VideoInfo(
|
||||
it.id,
|
||||
it.duration,
|
||||
it.poster,
|
||||
it.width,
|
||||
it.height
|
||||
)
|
||||
}
|
||||
val show = !((user.id == UserManager.getInstance().userId && videos.isNotEmpty())
|
||||
|| (user.id != UserManager.getInstance().userId && getPassVideos().isNotEmpty())
|
||||
|| images.isNullOrEmpty())
|
||||
return ImageContainerData(
|
||||
status = status,
|
||||
isPostCard = type == COMMUNITY_ARTICLE,
|
||||
images = imageInfoList,
|
||||
video = video,
|
||||
show
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class ImageContainerData(
|
||||
val status: String,
|
||||
val isPostCard: Boolean, // 是否是帖子卡片
|
||||
val images: List<ImageInfo>,
|
||||
val video: VideoInfo? = null,
|
||||
val show: Boolean
|
||||
) {
|
||||
|
||||
data class ImageInfo(
|
||||
val url: String,
|
||||
var width: Int = 0,
|
||||
var height: Int = 0
|
||||
)
|
||||
|
||||
data class VideoInfo(
|
||||
val id: String,
|
||||
val duration: String,
|
||||
val poster: String,
|
||||
var width: Int = 0,
|
||||
var height: Int = 0,
|
||||
)
|
||||
}
|
||||
|
||||
interface OnImageContainerEventListener {
|
||||
|
||||
fun onImageClick(
|
||||
images: List<String>,
|
||||
position: Int,
|
||||
imageViewList: ArrayList<SimpleDraweeView>
|
||||
)
|
||||
|
||||
fun onVideoCLick(videoId: String)
|
||||
}
|
||||
}
|
||||
@ -6,12 +6,8 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.text.underline
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.activityresult.ActResultRequest
|
||||
@ -41,14 +37,6 @@ object XapkDialogHelper {
|
||||
|
||||
val previousShowedDialog = mUnzipFailureDialogRef?.get()
|
||||
|
||||
val useRebootStyle = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
|
||||
|
||||
val content = if (useRebootStyle) {
|
||||
"未授权允许未知来源安装、数据包格式、设备兼容性…等均可能导致解压失败。"
|
||||
} else {
|
||||
"未授权允许未知来源安装、数据包格式、设备兼容性…等均可能导致解压失败。\n如果开启权限后仍未能解决,请提交反馈帮助我们改进。"
|
||||
}
|
||||
|
||||
if (previousShowedDialog != null
|
||||
&& previousShowedDialog.isShowing
|
||||
&& context == previousShowedDialog.ownerActivity
|
||||
@ -60,9 +48,9 @@ object XapkDialogHelper {
|
||||
val dialog = DialogHelper.showGuideDialog(
|
||||
context = context,
|
||||
title = "",
|
||||
content = content,
|
||||
content = "未授权允许未知来源安装、数据包格式、设备兼容性…等均可能导致解压失败。\n如果开启权限后仍未能解决,请提交反馈帮助我们改进。",
|
||||
confirmText = "开启权限",
|
||||
cancelText = if (useRebootStyle) "重启助手" else "提交反馈",
|
||||
cancelText = "提交反馈",
|
||||
confirmClickCallback = {
|
||||
if (context is AppCompatActivity) {
|
||||
val intent = PermissionHelper.getToInstallPermissionSettingIntent(context)
|
||||
@ -95,7 +83,11 @@ object XapkDialogHelper {
|
||||
)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
restart(context)
|
||||
val pm = context.packageManager
|
||||
val restartIntent = pm.getLaunchIntentForPackage(context.packageName)
|
||||
val mainIntent = Intent.makeRestartActivityTask(restartIntent!!.component)
|
||||
context.startActivity(mainIntent)
|
||||
Runtime.getRuntime().exit(0)
|
||||
} else {
|
||||
XapkInstaller.install(context, downloadEntity, true)
|
||||
}
|
||||
@ -108,22 +100,27 @@ object XapkDialogHelper {
|
||||
}
|
||||
},
|
||||
cancelClickCallback = {
|
||||
if (useRebootStyle) {
|
||||
// 记录应用重启前需要重解压的信息
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, context.javaClass.name)
|
||||
SPUtils.setString(Constants.SP_XAPK_URL, downloadEntity.url)
|
||||
val hint = "游戏安装包解压失败,问题反馈:"
|
||||
HelpAndFeedbackBridge.startSuggestionActivity(
|
||||
context,
|
||||
SuggestType.GAME,
|
||||
null,
|
||||
hint,
|
||||
SimpleGameEntity(downloadEntity.gameId, downloadEntity.name, downloadEntity.icon)
|
||||
)
|
||||
NewFlatLogUtils.logXApkUnzipFailedDialogClick(
|
||||
"提交反馈",
|
||||
false,
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.name
|
||||
)
|
||||
|
||||
SensorsBridge.trackGameDecompressionFailedDialogClick(
|
||||
buttonName = "重启助手",
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.name,
|
||||
downloadEntity.categoryChinese
|
||||
)
|
||||
|
||||
restart(context)
|
||||
} else {
|
||||
doFeedback(context, downloadEntity)
|
||||
}
|
||||
SensorsBridge.trackGameDecompressionFailedDialogClick(
|
||||
buttonName = "提交反馈",
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.name,
|
||||
downloadEntity.categoryChinese
|
||||
)
|
||||
},
|
||||
uiModificationCallback = { binding ->
|
||||
binding.headIv.setBackgroundResource(R.drawable.dialog_unzip_failure_head_background)
|
||||
@ -149,30 +146,6 @@ object XapkDialogHelper {
|
||||
)
|
||||
binding.dismiss()
|
||||
}
|
||||
if (useRebootStyle) {
|
||||
val spannableString = SpannableStringBuilder()
|
||||
.append("未能解决问题?点击 ")
|
||||
.underline { append("提交反馈") }
|
||||
.append(" ")
|
||||
binding.alternativeCancelTv.visibility = View.VISIBLE
|
||||
binding.alternativeCancelTv.text = spannableString
|
||||
binding.alternativeCancelTv.setTextColor(R.color.text_secondary.toColor(context))
|
||||
binding.alternativeCancelTv.setDrawableEnd(R.drawable.ic_right_arrow_xapk)
|
||||
binding.alternativeCancelTv.setOnClickListener {
|
||||
doFeedback(context, downloadEntity)
|
||||
}
|
||||
|
||||
binding.hintTv.text = "开启权限后请务必重启光环助手,再进行安装"
|
||||
binding.hintTv.setTextColor(R.color.text_theme.toColor(context))
|
||||
binding.hintTv.setTextAppearance(R.style.TextCaption1)
|
||||
binding.hintTv.visibility = View.VISIBLE
|
||||
binding.hintTv.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
topMargin = 8F.dip2px()
|
||||
}
|
||||
binding.confirmTv.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
topMargin = 16F.dip2px()
|
||||
}
|
||||
}
|
||||
},
|
||||
touchOutsideCallback = {
|
||||
SensorsBridge.trackGameDecompressionFailedDialogClick(
|
||||
@ -191,37 +164,4 @@ object XapkDialogHelper {
|
||||
mUnzipFailureDialogRef = WeakReference(dialog)
|
||||
}
|
||||
|
||||
private fun restart(context: Context) {
|
||||
val pm = context.packageManager
|
||||
val restartIntent = pm.getLaunchIntentForPackage(context.packageName)
|
||||
val mainIntent = Intent.makeRestartActivityTask(restartIntent!!.component)
|
||||
context.startActivity(mainIntent)
|
||||
Runtime.getRuntime().exit(0)
|
||||
}
|
||||
|
||||
private fun doFeedback(context: Context, downloadEntity: DownloadEntity) {
|
||||
val hint = "游戏安装包解压失败,问题反馈:"
|
||||
|
||||
HelpAndFeedbackBridge.startSuggestionActivity(
|
||||
context,
|
||||
SuggestType.GAME,
|
||||
null,
|
||||
hint,
|
||||
SimpleGameEntity(downloadEntity.gameId, downloadEntity.name, downloadEntity.icon)
|
||||
)
|
||||
NewFlatLogUtils.logXApkUnzipFailedDialogClick(
|
||||
"提交反馈",
|
||||
false,
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.name
|
||||
)
|
||||
|
||||
SensorsBridge.trackGameDecompressionFailedDialogClick(
|
||||
buttonName = "提交反馈",
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.name,
|
||||
downloadEntity.categoryChinese
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@ -10,8 +10,8 @@ import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil.getMeta
|
||||
import com.gh.gamecenter.common.loghub.LoghubUtils
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.SentryHelper
|
||||
import com.gh.ndownload.NDataChanger
|
||||
import com.gh.ndownload.NDownloadBridge
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadConfig
|
||||
import com.lightgame.download.DownloadEntity
|
||||
@ -124,7 +124,6 @@ object DownloadDataHelper {
|
||||
val payloadObject = JSONObject()
|
||||
payloadObject.put("host", downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown")
|
||||
payloadObject.put("path", downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] ?: "unknown")
|
||||
payloadObject.put("redirected_host_list", downloadEntity.meta[NDownloadBridge.REDIRECTED_HOST_LIST] ?: "unknown")
|
||||
payloadObject.put("game_id", downloadEntity.gameId)
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
@ -213,7 +212,6 @@ object DownloadDataHelper {
|
||||
|
||||
payloadObject.put("host", downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown")
|
||||
payloadObject.put("path", downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] ?: "unknown")
|
||||
payloadObject.put("redirected_host_list", downloadEntity.meta[NDownloadBridge.REDIRECTED_HOST_LIST] ?: "unknown")
|
||||
payloadObject.put("game_id", downloadEntity.gameId)
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
@ -253,7 +251,6 @@ object DownloadDataHelper {
|
||||
|
||||
payloadObject.put("host", downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown")
|
||||
payloadObject.put("path", downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] ?: "unknown")
|
||||
payloadObject.put("redirected_host_list", downloadEntity.meta[NDownloadBridge.REDIRECTED_HOST_LIST] ?: "unknown")
|
||||
payloadObject.put("game_id", downloadEntity.gameId)
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
@ -318,7 +315,6 @@ object DownloadDataHelper {
|
||||
|
||||
payloadObject.put("host", downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown")
|
||||
payloadObject.put("path", downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] ?: "unknown")
|
||||
payloadObject.put("redirected_host_list", downloadEntity.meta[NDownloadBridge.REDIRECTED_HOST_LIST] ?: "unknown")
|
||||
payloadObject.put("game_id", downloadEntity.gameId)
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
@ -361,7 +357,6 @@ object DownloadDataHelper {
|
||||
sheet = JSONObject()
|
||||
sheet.put("host", downloadEntity.meta[DownloadEntity.DOWNLOAD_HOST_KEY] ?: "unknown")
|
||||
sheet.put("path", downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] ?: "unknown")
|
||||
sheet.put("redirected_host_list", downloadEntity.meta[NDownloadBridge.REDIRECTED_HOST_LIST] ?: "unknown")
|
||||
sheet.put("game_id", downloadEntity.gameId)
|
||||
sheet.put("platform", downloadEntity.platform)
|
||||
sheet.put("package", downloadEntity.packageName)
|
||||
@ -381,7 +376,6 @@ object DownloadDataHelper {
|
||||
"path",
|
||||
downloadEntity.meta[DownloadEntity.DOWNLOAD_PATH_KEY] ?: "unknown"
|
||||
) // 初始化记录的 path 为空
|
||||
sheet.put("redirected_host_list", downloadEntity.meta[NDownloadBridge.REDIRECTED_HOST_LIST] ?: "unknown")
|
||||
sheet.put("total_size", downloadEntity.size / 1024 / 1024) // 初始化记录的 total_size 有可能为0
|
||||
sheet.put("progress_size", downloadEntity.progress / 1024 - progressSize)
|
||||
sheet.put("current_progress_size", downloadEntity.progress / 1024)
|
||||
|
||||
@ -22,6 +22,7 @@ import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity;
|
||||
import com.gh.gamecenter.feature.entity.CustomPageTrackData;
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
@ -33,10 +34,16 @@ import com.gh.common.util.LunchType;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.utils.DeviceUtils;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.FileUtils;
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.core.utils.AppDebugConfig;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.PageSwitchDataHelper;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
@ -48,6 +55,7 @@ import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation;
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent;
|
||||
import com.gh.gamecenter.login.user.UserManager;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository;
|
||||
@ -56,6 +64,7 @@ import com.gh.ndownload.NDownloadBridge;
|
||||
import com.gh.ndownload.NDownloadService;
|
||||
import com.gh.vspace.VHelper;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.ConnectionUtils;
|
||||
import com.lightgame.download.DataWatcher;
|
||||
import com.lightgame.download.DownloadConfig;
|
||||
import com.lightgame.download.DownloadDao;
|
||||
@ -170,6 +179,9 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
mUpdateMarks = SPUtils.getStringSet(UPDATE_IS_READ_MARK);
|
||||
|
||||
// 只有下载模块需要这坨东西,因此移动到这里初始化
|
||||
ConnectionUtils.initHttpsUrlConnection(mContext);
|
||||
|
||||
updateDownloadMetaMap();
|
||||
|
||||
lastTimeMap = new ArrayMap<>();
|
||||
|
||||
@ -14,13 +14,12 @@ import com.gh.gamecenter.common.retrofit.EmptyResponse
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.NewFlatLogUtils
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.ThirdPartyPackageHelper
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.gamecenter.entity.GameDigestEntity
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.utils.ConcernUtils
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
@ -56,7 +55,7 @@ object PackageObserver {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onPackageChanged(busFour: EBPackage, cachedGameEntity: GameEntity? = null) {
|
||||
fun onPackageChanged(busFour: EBPackage) {
|
||||
val application = HaloApp.getInstance().application
|
||||
val packageName = busFour.packageName
|
||||
val versionName = busFour.versionName
|
||||
@ -100,7 +99,7 @@ object PackageObserver {
|
||||
if (EBPackage.TYPE_INSTALLED == busFour.type) {
|
||||
if (!busFour.isVGame) {
|
||||
// 非畅玩游戏才执行下面的代码
|
||||
mPackageViewModel.addInstalledGame(packageName, cachedGameEntity)
|
||||
mPackageViewModel.addInstalledGame(packageName)
|
||||
BrowserInstallHelper.onApkInstalled(mDownloadEntity?.path)
|
||||
}
|
||||
|
||||
@ -154,7 +153,7 @@ object PackageObserver {
|
||||
}
|
||||
}
|
||||
|
||||
AppExecutor.logExecutor.execute { postNewlyInstalledApp(gameId, packageName) }
|
||||
runOnIoThread { postNewlyInstalledApp(gameId, packageName) }
|
||||
}
|
||||
|
||||
if (EBPackage.TYPE_UNINSTALLED == busFour.type) {
|
||||
|
||||
@ -24,7 +24,6 @@ import com.gh.gamecenter.common.base.fragment.BaseDraggableDialogFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.observeNonNull
|
||||
import com.gh.gamecenter.common.utils.safelyGetInRelease
|
||||
import com.gh.gamecenter.common.utils.throwExceptionInDebug
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.TimeElapsedHelper
|
||||
@ -182,7 +181,7 @@ class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
recyclerView.adapter?.let {
|
||||
for (i in 0 until it.itemCount) {
|
||||
val apkEntity = itemList.safelyGetInRelease(i)?.normal ?: continue
|
||||
val apkEntity = itemList[i].normal ?: continue
|
||||
val apkCollection = apkEntity.apkCollection
|
||||
val platformName = platformList[0].name
|
||||
val packageName = platformList[0].packageName
|
||||
|
||||
@ -10,9 +10,6 @@ import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.game.GameFragment
|
||||
|
||||
/**
|
||||
* 板块
|
||||
*/
|
||||
class BlockActivity : DownloadToolbarActivity() {
|
||||
|
||||
companion object {
|
||||
|
||||
@ -14,7 +14,6 @@ import com.halo.assistant.fragment.ApkCleanerFragment;
|
||||
|
||||
/**
|
||||
* Created by khy on 2017/1/24.
|
||||
* 清理安装包
|
||||
*/
|
||||
@Route(path = RouteConsts.activity.cleanApkActivity)
|
||||
public class CleanApkActivity extends ToolBarActivity {
|
||||
|
||||
@ -16,7 +16,6 @@ import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by khy on 18/07/17.
|
||||
* 我的收藏
|
||||
*/
|
||||
public class CollectionActivity extends ToolBarActivity {
|
||||
@Override
|
||||
|
||||
@ -23,9 +23,6 @@ import java.lang.ref.SoftReference;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* 裁剪图片
|
||||
*/
|
||||
public class CropImageActivity extends ToolBarActivity {
|
||||
|
||||
protected CropImageCustom mCropImageCustom;
|
||||
|
||||
@ -24,7 +24,7 @@ import com.halo.assistant.HaloApp
|
||||
|
||||
/**
|
||||
* Created by khy on 2017/3/24.
|
||||
* 游戏详情页
|
||||
* 游戏详情适配器
|
||||
*/
|
||||
class GameDetailActivity : DownloadToolbarActivity() {
|
||||
|
||||
|
||||
@ -16,7 +16,6 @@ import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by khy on 2016/12/12.
|
||||
* 礼包中心
|
||||
*/
|
||||
@Deprecated
|
||||
public class LibaoActivity extends ToolBarActivity {
|
||||
|
||||
@ -285,6 +285,9 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
// 耗时操作
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
// 上传数据
|
||||
DataCollectionManager.getInstance().upload();
|
||||
|
||||
// 初始化PlatformUtils
|
||||
PlatformUtils.getInstance(getApplicationContext());
|
||||
|
||||
@ -553,10 +556,7 @@ public class MainActivity extends BaseActivity {
|
||||
} else {
|
||||
TextView jumpBtn = findViewById(R.id.jumpBtn);
|
||||
jumpBtn.setText(String.format(Locale.CHINA, "跳过 %d", COUNTDOWN_MAX_COUNT - mCountdownCount));
|
||||
Message newMsg = Message.obtain();
|
||||
newMsg.what = COUNTDOWN_AD;
|
||||
newMsg.obj = msg.obj;
|
||||
mBaseHandler.sendMessageDelayed(newMsg, 1000);
|
||||
mBaseHandler.sendEmptyMessageDelayed(COUNTDOWN_AD, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -877,6 +877,13 @@ public class MainActivity extends BaseActivity {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
// 上传数据
|
||||
DataCollectionManager.getInstance().statClickData();
|
||||
super.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NotNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
@ -922,7 +929,7 @@ public class MainActivity extends BaseActivity {
|
||||
Config.refreshVSettingEntity();
|
||||
}
|
||||
|
||||
// mPackageViewModel.checkData();
|
||||
mPackageViewModel.checkData();
|
||||
deleteSimulatorGame();
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@ import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.db.ISearchHistoryDao
|
||||
import com.gh.gamecenter.db.SearchHistoryDao
|
||||
import com.gh.gamecenter.eventbus.EBSearch
|
||||
import com.gh.gamecenter.search.SearchDefaultFragment
|
||||
@ -30,9 +29,6 @@ import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* 游戏搜索页
|
||||
*/
|
||||
open class SearchActivity : BaseActivity() {
|
||||
|
||||
lateinit var searchEt: EditText
|
||||
@ -40,7 +36,7 @@ open class SearchActivity : BaseActivity() {
|
||||
lateinit var backBtn: RelativeLayout
|
||||
private lateinit var deleteIv: ImageView
|
||||
|
||||
protected val mDao: ISearchHistoryDao by lazy { provideDao() }
|
||||
private var mDao: SearchHistoryDao? = null
|
||||
|
||||
protected var mSearchKey: String? = null
|
||||
protected var mIsAutoSearchDisabled: Boolean = false
|
||||
@ -79,6 +75,7 @@ open class SearchActivity : BaseActivity() {
|
||||
val searchImmediately = intent.getBooleanExtra(KEY_SEARCH_IMMEDIATELY, false)
|
||||
var ignoreTextChanges = savedInstanceState != null
|
||||
|
||||
mDao = SearchHistoryDao(this)
|
||||
mPublishSubject = PublishSubject.create()
|
||||
|
||||
mPublishSubject!!
|
||||
@ -102,7 +99,7 @@ open class SearchActivity : BaseActivity() {
|
||||
searchEt.hint = hint
|
||||
if (searchImmediately) {
|
||||
mDisplayType = GAME_DETAIL
|
||||
mDao.add(hint)
|
||||
mDao?.add(hint)
|
||||
search(SearchType.DEFAULT, hint)
|
||||
}
|
||||
} else {
|
||||
@ -190,12 +187,12 @@ open class SearchActivity : BaseActivity() {
|
||||
mIsAutoSearchDisabled = false
|
||||
}
|
||||
|
||||
protected open fun handleAutoSearch(key: String?) {
|
||||
private fun handleAutoSearch(key: String?) {
|
||||
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
|
||||
if (newSearchKey.isEmpty()) {
|
||||
val hint = searchEt.hint.toString()
|
||||
if (!TextUtils.isEmpty(hint) && HINT_TEXT != hint) {
|
||||
mDao.add(hint)
|
||||
mDao?.add(hint)
|
||||
search(SearchType.DEFAULT, hint)
|
||||
}
|
||||
} else {
|
||||
@ -213,7 +210,7 @@ open class SearchActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun handleDefaultSearch(key: String?) {
|
||||
private fun handleDefaultSearch(key: String?) {
|
||||
mSearchKey = key
|
||||
searchEt.setText(key)
|
||||
searchEt.setSelection(searchEt.text.length)
|
||||
@ -230,14 +227,14 @@ open class SearchActivity : BaseActivity() {
|
||||
// MtaHelper.onEvent("游戏搜索", "默认搜索", key)
|
||||
}
|
||||
|
||||
protected open fun handleHotSearch(key: String?) {
|
||||
private fun handleHotSearch(key: String?) {
|
||||
mSearchKey = key
|
||||
searchEt.setText(key)
|
||||
searchEt.setSelection(searchEt.text.length)
|
||||
updateDisplayType(GAME_DETAIL)
|
||||
}
|
||||
|
||||
protected open fun handleHistorySearch(key: String?) {
|
||||
private fun handleHistorySearch(key: String?) {
|
||||
mSearchKey = key
|
||||
searchEt.setText(key)
|
||||
searchEt.setSelection(searchEt.text.length)
|
||||
@ -254,12 +251,12 @@ open class SearchActivity : BaseActivity() {
|
||||
// MtaHelper.onEvent("游戏搜索", "历史搜索", key)
|
||||
}
|
||||
|
||||
protected open fun handleManualSearch() {
|
||||
private fun handleManualSearch() {
|
||||
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
|
||||
if (newSearchKey.isEmpty()) {
|
||||
val hint = searchEt.hint.toString()
|
||||
if (!TextUtils.isEmpty(hint) && HINT_TEXT != hint) {
|
||||
mDao.add(hint)
|
||||
mDao?.add(hint)
|
||||
search(SearchType.DEFAULT, hint)
|
||||
}
|
||||
} else if (newSearchKey != mSearchKey || mDisplayType != GAME_DETAIL) {
|
||||
@ -273,7 +270,7 @@ open class SearchActivity : BaseActivity() {
|
||||
mSourceEntrance
|
||||
)
|
||||
|
||||
mDao.add(mSearchKey)
|
||||
mDao?.add(mSearchKey)
|
||||
updateDisplayType(GAME_DETAIL)
|
||||
} else {
|
||||
toast("请输入搜索内容")
|
||||
@ -283,8 +280,6 @@ open class SearchActivity : BaseActivity() {
|
||||
// MtaHelper.onEvent("游戏搜索", "主动搜索", newSearchKey)
|
||||
}
|
||||
|
||||
protected open fun provideDao(): ISearchHistoryDao = SearchHistoryDao(this)
|
||||
|
||||
open fun updateDisplayType(type: DisplayType) {
|
||||
val transaction = supportFragmentManager.beginTransaction()
|
||||
when (type) {
|
||||
|
||||
@ -48,7 +48,6 @@ import io.reactivex.functions.Consumer;
|
||||
|
||||
/**
|
||||
* Created by khy on 2016/11/7.
|
||||
* 分享卡片
|
||||
*/
|
||||
public class ShareCardPicActivity extends ToolBarActivity {
|
||||
|
||||
|
||||
@ -21,7 +21,6 @@ import com.tencent.tauth.Tencent;
|
||||
|
||||
/**
|
||||
* Created by khy on 2017/2/6.
|
||||
* 分享光环
|
||||
*/
|
||||
public class ShareGhActivity extends ToolBarActivity {
|
||||
|
||||
|
||||
@ -55,18 +55,15 @@ import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity;
|
||||
import com.gh.gamecenter.common.entity.LinkEntity;
|
||||
import com.gh.gamecenter.common.entity.SimpleGameEntity;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.ToastUtils;
|
||||
import com.gh.gamecenter.entity.SubjectData;
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity;
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity;
|
||||
import com.gh.gamecenter.feature.utils.PlatformUtils;
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper;
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel;
|
||||
import com.gh.gamecenter.video.videomanager.VideoManagerActivity;
|
||||
import com.gh.vspace.shortcut.OnCreateShortcutResult;
|
||||
@ -155,7 +152,7 @@ public class SkipActivity extends BaseActivity {
|
||||
DirectUtils.directToGameDetail(this, path, "", entrance, "true".equals(uri.getQueryParameter("auto_download")), to, null);
|
||||
break;
|
||||
case HOST_COLUMN:
|
||||
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), entrance, null, SubjectData.SubjectType.NORMAL);
|
||||
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), entrance, null, false);
|
||||
break;
|
||||
case HOST_SUGGESTION:
|
||||
if (!TextUtils.isEmpty(qaId)) {
|
||||
@ -404,7 +401,7 @@ public class SkipActivity extends BaseActivity {
|
||||
try {
|
||||
JSONObject extJsonObject = new JSONObject(extJson);
|
||||
String qqGameId = extJsonObject.optString("aid");
|
||||
MiniGameItemHelper.INSTANCE.launchMiniGame(qqGameId, Constants.QQ_MINI_GAME);
|
||||
DirectUtils.directToQGameById(this, qqGameId);
|
||||
} catch (JSONException ignored) {
|
||||
}
|
||||
break;
|
||||
|
||||
@ -115,7 +115,6 @@ class SplashScreenActivity : BaseActivity() {
|
||||
)
|
||||
}
|
||||
} else {
|
||||
PackageHelper.checkIfGetInstalledApiSwitchShouldBeIgnored(this)
|
||||
cancelPreviousUpdateTask()
|
||||
launchMainActivity()
|
||||
}
|
||||
@ -168,12 +167,10 @@ class SplashScreenActivity : BaseActivity() {
|
||||
if (isMalfunctioningHonorDevice) {
|
||||
showHonorNotification()
|
||||
mBaseHandler.postDelayed({
|
||||
launchMainActivity()
|
||||
// requestGetInstallListPermissionAndLaunchMainActivity()
|
||||
requestGetInstallListPermissionAndLaunchMainActivity()
|
||||
}, 100L)
|
||||
} else {
|
||||
launchMainActivity()
|
||||
// requestGetInstallListPermissionAndLaunchMainActivity()
|
||||
requestGetInstallListPermissionAndLaunchMainActivity()
|
||||
}
|
||||
} else {
|
||||
DialogUtils.showPrivacyPolicyDisallowDialog(this) {
|
||||
@ -199,17 +196,9 @@ class SplashScreenActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
// 尝试获取安装应用列表权限并启动首页(不在乎结果)
|
||||
// private fun requestGetInstallListPermissionAndLaunchMainActivity() {
|
||||
// if (PackageHelper.isSupportGetInstalledAppsPermission(this)
|
||||
// && PermissionHelper.isGetInstalledListPermissionDisabled(this)
|
||||
// ) {
|
||||
// PermissionHelper.requestGetInstalledAppsListPermission(this, true) {
|
||||
// launchMainActivity()
|
||||
// }
|
||||
// } else {
|
||||
// launchMainActivity()
|
||||
// }
|
||||
// }
|
||||
private fun requestGetInstallListPermissionAndLaunchMainActivity() {
|
||||
launchMainActivity()
|
||||
}
|
||||
|
||||
// 删除更新后的光环助手包
|
||||
private fun cancelPreviousUpdateTask() {
|
||||
|
||||
@ -7,9 +7,6 @@ import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
import com.halo.assistant.fragment.user.UserInfoFragment
|
||||
|
||||
/**
|
||||
* 编辑资料
|
||||
*/
|
||||
class UserInfoActivity : ToolBarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
@ -8,9 +8,6 @@ import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.login.user.UserViewModel
|
||||
import com.halo.assistant.fragment.user.UserInfoEditFragment
|
||||
|
||||
/**
|
||||
* 修改个人信息
|
||||
*/
|
||||
class UserInfoEditActivity : ToolBarActivity() {
|
||||
companion object {
|
||||
fun getIntent(context: Context, editType: String): Intent {
|
||||
|
||||
@ -8,7 +8,6 @@ import com.halo.assistant.fragment.user.SelectRegionFragment;
|
||||
|
||||
/**
|
||||
* Created by khy on 25/09/17.
|
||||
* 选择地区
|
||||
*/
|
||||
public class UserRegionActivity extends ToolBarActivity {
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ import kotlin.math.abs
|
||||
|
||||
class AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {
|
||||
|
||||
private val mViewModel: AmwayViewModel by lazy { viewModelProvider() }
|
||||
private lateinit var mViewModel: AmwayViewModel
|
||||
private val mElapsedHelper by lazy { TimeElapsedHelper() }
|
||||
private lateinit var mExposureListener: ExposureListener
|
||||
|
||||
@ -131,13 +131,14 @@ class AmwayFragment : LazyListFragment<AmwayListItemData, AmwayViewModel>() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemDecoration() = VerticalItemDecoration(context, 12F, false)
|
||||
.apply { mItemDecoration = this }
|
||||
|
||||
override fun provideListViewModel(): AmwayViewModel? {
|
||||
override fun provideListViewModel(): AmwayViewModel {
|
||||
mViewModel = viewModelProvider()
|
||||
return mViewModel
|
||||
}
|
||||
|
||||
override fun getItemDecoration() = VerticalItemDecoration(context, 12F, false)
|
||||
.apply { mItemDecoration = this }
|
||||
|
||||
override fun provideListAdapter(): ListAdapter<*> {
|
||||
if (mAdapter == null) {
|
||||
val basicExposureSource = arrayListOf<ExposureSource>().apply {
|
||||
|
||||
@ -9,12 +9,12 @@ import com.gh.gamecenter.DisplayType
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.SearchActivity
|
||||
import com.gh.gamecenter.SearchType
|
||||
import com.gh.gamecenter.db.ISearchHistoryDao
|
||||
import com.gh.gamecenter.search.SearchDefaultFragment
|
||||
|
||||
class AmwaySearchActivity : SearchActivity() {
|
||||
|
||||
private lateinit var mViewModel: AmwaySearchViewModel
|
||||
private val mSearchHistoryDao by lazy { AmwaySearchDao() }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -22,43 +22,38 @@ class AmwaySearchActivity : SearchActivity() {
|
||||
mViewModel = viewModelProvider()
|
||||
}
|
||||
|
||||
override fun provideDao(): ISearchHistoryDao = AmwaySearchDao()
|
||||
|
||||
override fun handleAutoSearch(key: String?) {
|
||||
mSearchKey = key
|
||||
updateDisplayType(DisplayType.GAME_DIGEST)
|
||||
mViewModel.getSearchResult(mSearchKey!!)
|
||||
}
|
||||
|
||||
override fun handleHistorySearch(key: String?) {
|
||||
mSearchKey = key
|
||||
searchEt.setText(key)
|
||||
searchEt.setSelection(searchEt.text.length)
|
||||
mViewModel.getSearchResult(mSearchKey!!)
|
||||
updateDisplayType(DisplayType.GAME_DETAIL)
|
||||
}
|
||||
|
||||
private fun handleOtherSearch() {
|
||||
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
|
||||
if (newSearchKey != mSearchKey || mDisplayType != DisplayType.GAME_DETAIL) {
|
||||
mSearchKey = newSearchKey
|
||||
if (!TextUtils.isEmpty(mSearchKey)) {
|
||||
mViewModel.getSearchResult(mSearchKey!!)
|
||||
mDao.add(mSearchKey!!)
|
||||
updateDisplayType(DisplayType.GAME_DETAIL)
|
||||
} else {
|
||||
toast("请先输入游戏名再搜索~")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun search(type: SearchType, key: String?) {
|
||||
mSearchType = type
|
||||
mIsAutoSearchDisabled = true
|
||||
|
||||
when (type) {
|
||||
SearchType.AUTO -> handleAutoSearch(key)
|
||||
SearchType.HISTORY -> handleHistorySearch(key)
|
||||
else -> handleOtherSearch()
|
||||
SearchType.AUTO -> {
|
||||
mSearchKey = key
|
||||
updateDisplayType(DisplayType.GAME_DIGEST)
|
||||
mViewModel.getSearchResult(mSearchKey!!)
|
||||
}
|
||||
|
||||
SearchType.HISTORY -> {
|
||||
mSearchKey = key
|
||||
searchEt.setText(key)
|
||||
searchEt.setSelection(searchEt.text.length)
|
||||
mViewModel.getSearchResult(mSearchKey!!)
|
||||
updateDisplayType(DisplayType.GAME_DETAIL)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
|
||||
if (newSearchKey != mSearchKey || mDisplayType != DisplayType.GAME_DETAIL) {
|
||||
mSearchKey = newSearchKey
|
||||
if (!TextUtils.isEmpty(mSearchKey)) {
|
||||
mViewModel.getSearchResult(mSearchKey!!)
|
||||
mSearchHistoryDao.add(mSearchKey!!)
|
||||
updateDisplayType(DisplayType.GAME_DETAIL)
|
||||
} else {
|
||||
toast("请先输入游戏名再搜索~")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mIsAutoSearchDisabled = false
|
||||
}
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
package com.gh.gamecenter.amway.search
|
||||
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.db.ISearchHistoryDao
|
||||
|
||||
class AmwaySearchDao : ISearchHistoryDao {
|
||||
|
||||
override fun add(keyword: String) {
|
||||
class AmwaySearchDao {
|
||||
fun add(keyword: String) {
|
||||
val originString = SPUtils.getString(SP_KEY)
|
||||
|
||||
if (originString.isEmpty()) {
|
||||
@ -30,18 +28,16 @@ class AmwaySearchDao : ISearchHistoryDao {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAll(): ArrayList<String>? {
|
||||
fun getAll(): ArrayList<String>? {
|
||||
val list = SPUtils.getString(SP_KEY).split(SEARCH_KEY_DIVIDER)
|
||||
|
||||
return if (list.size == 1 && list[0].isEmpty()) null else ArrayList(list)
|
||||
}
|
||||
|
||||
override fun deleteAll() {
|
||||
fun deleteAll() {
|
||||
SPUtils.setString(SP_KEY, "")
|
||||
}
|
||||
|
||||
override fun delete(item: String) {}
|
||||
|
||||
companion object {
|
||||
const val SP_KEY = "amway_key"
|
||||
const val SEARCH_KEY_DIVIDER = "<-||->"
|
||||
|
||||
@ -7,7 +7,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentAmwaySearchDefaultBinding
|
||||
import com.gh.gamecenter.db.ISearchHistoryDao
|
||||
import com.gh.gamecenter.eventbus.EBSearch
|
||||
import com.gh.gamecenter.search.SearchDefaultFragment
|
||||
import com.lightgame.utils.Util_System_Keyboard
|
||||
@ -15,6 +14,7 @@ import org.greenrobot.eventbus.EventBus
|
||||
|
||||
class AmwaySearchDefaultFragment : SearchDefaultFragment() {
|
||||
|
||||
private lateinit var mSearchDao: AmwaySearchDao
|
||||
private lateinit var mViewModel: AmwaySearchViewModel
|
||||
|
||||
private val mAmwayBinding by lazy { FragmentAmwaySearchDefaultBinding.inflate(layoutInflater) }
|
||||
@ -22,15 +22,11 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
|
||||
override fun getLayoutId() = 0
|
||||
override fun getInflatedLayout() = mAmwayBinding.root
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
mViewModel = viewModelProviderFromParent()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mViewModel.playedGames.observeNonNull(viewLifecycleOwner) {
|
||||
mViewModel = viewModelProviderFromParent()
|
||||
mViewModel.playedGames.observeNonNull(this) {
|
||||
defaultViewModel?.isExistHotSearch = it.isNotEmpty()
|
||||
updateView()
|
||||
mBinding.hotList.run {
|
||||
@ -42,21 +38,28 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun provideDao(): ISearchHistoryDao = AmwaySearchDao()
|
||||
override fun initView() {
|
||||
mBinding = mAmwayBinding.searchContent
|
||||
mBinding.hotHeadContainer.headTitle.text = "最近玩过"
|
||||
mBinding.historyFlexContainer.setLimitHeight(mFlexMaxHeight)
|
||||
|
||||
updateHistorySearchView(null)
|
||||
defaultViewModel?.historySearchLiveData?.observe(this) {
|
||||
updateHistorySearchView(it)
|
||||
}
|
||||
|
||||
initHeadView()
|
||||
override fun initDao() {
|
||||
mSearchDao = AmwaySearchDao()
|
||||
mHistoryList = mSearchDao.getAll()
|
||||
}
|
||||
|
||||
override fun initHeadView() {
|
||||
override fun initView() {
|
||||
mBinding = mAmwayBinding.searchContent
|
||||
defaultViewModel?.isExistHistory = mHistoryList?.isNotEmpty() == true
|
||||
updateView()
|
||||
mBinding.hotHeadContainer.headTitle.text = "最近玩过"
|
||||
mBinding.historyFlexContainer.setLimitHeight(mFlexMaxHeight)
|
||||
createFlexContent(mBinding.historyFlex, mHistoryList, clickListener = {
|
||||
val key = mHistoryList!![it]
|
||||
mSearchDao.add(key)
|
||||
EventBus.getDefault().post(EBSearch("history", key))
|
||||
Util_System_Keyboard.hideSoftKeyboardByIBinder(context, mBinding.historyFlex.windowToken)
|
||||
})
|
||||
|
||||
initHistoryHeadView()
|
||||
}
|
||||
|
||||
private fun initHistoryHeadView() {
|
||||
mBinding.historyHeadContainer.run {
|
||||
headTitle.text = getString(R.string.search_history)
|
||||
headTitle.textSize = 16F
|
||||
@ -70,15 +73,17 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
|
||||
)
|
||||
headActionTv.setOnClickListener {
|
||||
DialogHelper.showCenterWarningDialog(requireContext(), "清空记录", "确定清空历史搜索记录?", confirmClickCallback = {
|
||||
defaultViewModel?.deleteAll()
|
||||
mSearchDao.deleteAll()
|
||||
defaultViewModel?.isExistHistory = false
|
||||
updateView()
|
||||
updateNoPlayedGameHint()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateNoPlayedGameHint() {
|
||||
val historyList = defaultViewModel?.historySearchLiveData?.value
|
||||
if (!historyList.isNullOrEmpty()) {
|
||||
if (mSearchDao.getAll() != null && mSearchDao.getAll()?.size != 0) {
|
||||
mAmwayBinding.noDataContainer.visibility = View.GONE
|
||||
return
|
||||
}
|
||||
@ -90,21 +95,4 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateHistorySearchView(historyList: List<String>?) {
|
||||
defaultViewModel?.isExistHistory = historyList?.isNotEmpty() == true
|
||||
updateView()
|
||||
updateNoPlayedGameHint()
|
||||
historyList?.let {
|
||||
createFlexContent(mBinding.historyFlex, historyList, clickListener = { id ->
|
||||
val key = it[id]
|
||||
defaultViewModel?.add(key)
|
||||
EventBus.getDefault().post(EBSearch("history", key))
|
||||
Util_System_Keyboard.hideSoftKeyboardByIBinder(
|
||||
context,
|
||||
mBinding.historyFlex.windowToken
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,9 +15,7 @@ import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.ActivityAuthorizationBinding
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.login.view.LoginActivity
|
||||
import com.gh.vspace.VHelper
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
/**
|
||||
* @author : liujiarui
|
||||
@ -164,12 +162,9 @@ class AuthorizationActivity : ToolBarActivity() {
|
||||
|
||||
private fun checkLogin(block: () -> Unit) {
|
||||
//判断光环是否登陆
|
||||
if (CheckLoginUtils.isLogin()) {
|
||||
CheckLoginUtils.checkLogin(this, "光环助手授权登陆") {
|
||||
initData()
|
||||
block()
|
||||
} else {
|
||||
Utils.toast(this, "需要登录")
|
||||
startActivity(LoginActivity.getIntent(this, "光环助手授权登陆"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,9 +8,6 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
|
||||
/**
|
||||
* 新分类2.0
|
||||
*/
|
||||
class CategoryV2Activity : DownloadToolbarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
@ -5,7 +5,6 @@ import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.utils.formatTime
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.databinding.ItemArchiveLimitBinding
|
||||
import com.gh.gamecenter.entity.ArchiveEntity
|
||||
@ -30,7 +29,10 @@ class ArchiveLimitAdapter(context: Context) : ListAdapter<ArchiveLimitAdapter.Ar
|
||||
if (holder is ArchiveLimitViewHolder) {
|
||||
val item = mEntityList[position]
|
||||
holder.binding.tvTitle.text = item.data.name
|
||||
holder.binding.tvTime.text = item.data.time.create.formatTime("yyyy-MM-dd HH:mm")
|
||||
val timeLong = item.data.time.create
|
||||
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA)
|
||||
val date = Date(timeLong)
|
||||
holder.binding.tvTime.text = sdf.format(date)
|
||||
|
||||
val resId = if (item.isChecked) R.drawable.ic_selector_selected else R.drawable.ic_selector_default
|
||||
holder.binding.ivSelector.setImageResource(resId)
|
||||
@ -51,10 +53,10 @@ class ArchiveLimitAdapter(context: Context) : ListAdapter<ArchiveLimitAdapter.Ar
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: MutableList<Any?>) {
|
||||
if (holder is ArchiveLimitViewHolder) {
|
||||
if (payloads.isEmpty()) {
|
||||
if(holder is ArchiveLimitViewHolder){
|
||||
if(payloads.isEmpty()){
|
||||
onBindViewHolder(holder, position)
|
||||
} else {
|
||||
}else{
|
||||
val item = mEntityList[position]
|
||||
val resId = if (item.isChecked) R.drawable.ic_selector_selected else R.drawable.ic_selector_default
|
||||
holder.binding.ivSelector.setImageResource(resId)
|
||||
|
||||
@ -41,9 +41,6 @@ import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* 云存档管理
|
||||
*/
|
||||
class CloudArchiveManagerActivity : BaseActivity_TabLayout(), ArchiveLimitSelectedListener {
|
||||
|
||||
private lateinit var mBinding: ActivityCloudArchiveManagerBinding
|
||||
|
||||
120
app/src/main/java/com/gh/gamecenter/db/DataCollectionDao.java
Normal file
120
app/src/main/java/com/gh/gamecenter/db/DataCollectionDao.java
Normal file
@ -0,0 +1,120 @@
|
||||
package com.gh.gamecenter.db;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.gh.gamecenter.db.info.DataCollectionInfo;
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
// TODO 这个数据库其实没有用了,上传到 loghub 已经有相关的逻辑处理,有空删掉它
|
||||
public class DataCollectionDao {
|
||||
|
||||
private DatabaseHelper helper;
|
||||
private Dao<DataCollectionInfo, String> dao;
|
||||
|
||||
public DataCollectionDao(Context context) {
|
||||
try {
|
||||
helper = DatabaseHelper.getHelper(context);
|
||||
dao = helper.getDao(DataCollectionInfo.class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找一个数据
|
||||
*/
|
||||
public List<DataCollectionInfo> findByType(String type) {
|
||||
try {
|
||||
return dao.queryForEq("type", type);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个数据
|
||||
*/
|
||||
public void add(DataCollectionInfo entity) {
|
||||
try {
|
||||
dao.create(entity);
|
||||
} catch (Exception e) {
|
||||
// java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个数据
|
||||
*/
|
||||
public void delete(String id) {
|
||||
try {
|
||||
dao.deleteById(id);
|
||||
} catch (Exception e) {
|
||||
// java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一组数据
|
||||
*/
|
||||
public void delete(List<String> ids) {
|
||||
try {
|
||||
dao.deleteIds(ids);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id获取某一个数据
|
||||
*/
|
||||
public DataCollectionInfo find(String id) {
|
||||
try {
|
||||
return dao.queryForId(id);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有的数据
|
||||
*/
|
||||
public List<DataCollectionInfo> getAll() {
|
||||
try {
|
||||
return dao.queryForAll();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取点击数据
|
||||
*/
|
||||
public List<DataCollectionInfo> getClickData() {
|
||||
try {
|
||||
return dao.queryForEq("type", "click-item");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新数据
|
||||
*/
|
||||
public void update(DataCollectionInfo entity) {
|
||||
try {
|
||||
dao.update(entity);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,7 +5,9 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import androidx.collection.ArrayMap;
|
||||
|
||||
import com.gh.gamecenter.db.info.DataCollectionInfo;
|
||||
import com.gh.gamecenter.db.info.GameTrendsInfo;
|
||||
import com.gh.gamecenter.db.info.PackageInfo;
|
||||
import com.gh.gamecenter.db.info.SearchHistoryInfo;
|
||||
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
@ -50,6 +52,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||
try {
|
||||
Utils.log("DatabaseHelper onCreate");
|
||||
TableUtils.createTable(connectionSource, SearchHistoryInfo.class);
|
||||
TableUtils.createTable(connectionSource, DataCollectionInfo.class);
|
||||
TableUtils.createTable(connectionSource, PackageInfo.class);
|
||||
TableUtils.createTable(connectionSource, GameTrendsInfo.class);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
@ -61,6 +65,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||
try {
|
||||
Utils.log("DatabaseHelper onUpgrade");
|
||||
TableUtils.dropTable(connectionSource, SearchHistoryInfo.class, true);
|
||||
TableUtils.dropTable(connectionSource, DataCollectionInfo.class, true);
|
||||
TableUtils.dropTable(connectionSource, PackageInfo.class, true);
|
||||
TableUtils.dropTable(connectionSource, GameTrendsInfo.class, true);
|
||||
onCreate(database, connectionSource);
|
||||
} catch (SQLException e) {
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
package com.gh.gamecenter.db;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ISearchHistoryDao {
|
||||
|
||||
void deleteAll();
|
||||
|
||||
void add(String item);
|
||||
|
||||
void delete(String item);
|
||||
|
||||
List<String> getAll();
|
||||
}
|
||||
@ -11,7 +11,7 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class SearchHistoryDao implements ISearchHistoryDao {
|
||||
public class SearchHistoryDao {
|
||||
|
||||
private DatabaseHelper helper;
|
||||
private Dao<SearchHistoryInfo, String> dao;
|
||||
@ -25,7 +25,6 @@ public class SearchHistoryDao implements ISearchHistoryDao {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(String item) {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
try {
|
||||
@ -36,7 +35,6 @@ public class SearchHistoryDao implements ISearchHistoryDao {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String item) {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
try {
|
||||
@ -47,7 +45,6 @@ public class SearchHistoryDao implements ISearchHistoryDao {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
CloseableIterator<SearchHistoryInfo> iterator = dao.iterator();
|
||||
@ -62,7 +59,6 @@ public class SearchHistoryDao implements ISearchHistoryDao {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAll() {
|
||||
List<String> history = new ArrayList<String>();
|
||||
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
package com.gh.gamecenter.db.info;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@DatabaseTable(tableName = "tb_datacollection")
|
||||
public class DataCollectionInfo implements Serializable {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 3196892351397147390L;
|
||||
|
||||
@DatabaseField(id = true, columnName = "id")
|
||||
private String id;
|
||||
|
||||
@DatabaseField(columnName = "type")
|
||||
private String type;
|
||||
|
||||
@DatabaseField(columnName = "data")
|
||||
private String data;
|
||||
|
||||
public DataCollectionInfo() {
|
||||
|
||||
}
|
||||
|
||||
public DataCollectionInfo(String id, String type, String data) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DataCollectionEntity [id=" + id + ", type=" + type + ", data="
|
||||
+ data + "]";
|
||||
}
|
||||
|
||||
}
|
||||
42
app/src/main/java/com/gh/gamecenter/db/info/PackageInfo.java
Normal file
42
app/src/main/java/com/gh/gamecenter/db/info/PackageInfo.java
Normal file
@ -0,0 +1,42 @@
|
||||
package com.gh.gamecenter.db.info;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@DatabaseTable(tableName = "tb_package")
|
||||
public class PackageInfo implements Serializable {
|
||||
|
||||
@DatabaseField(id = true, columnName = "packageName")
|
||||
private String packageName;
|
||||
|
||||
@DatabaseField(columnName = "time")
|
||||
private long time;
|
||||
|
||||
public PackageInfo() {
|
||||
|
||||
}
|
||||
|
||||
public PackageInfo(String packageName, long time) {
|
||||
this.packageName = packageName;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,10 +6,12 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.PagerSnapHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.utils.safelyGetInRelease
|
||||
@ -19,7 +21,6 @@ import com.gh.gamecenter.entity.AdConfig
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.game.GameItemViewHolder
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.lightgame.download.DownloadEntity
|
||||
|
||||
@ -92,8 +93,11 @@ class AdGameBannerAdapter(
|
||||
it.id,
|
||||
it.name ?: ""
|
||||
)
|
||||
if (it.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(it.miniGameAppId, it.miniGameType)
|
||||
if (it.isQQMiniGame()) {
|
||||
GlobalActivityManager.currentActivity?.let { activity ->
|
||||
NewFlatLogUtils.logQGameClick(it.qqMiniGameAppId, it.name)
|
||||
DirectUtils.directToQGameById(activity, it.qqMiniGameAppId)
|
||||
}
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
|
||||
@ -21,7 +21,6 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.ad.AdDelegateHelper
|
||||
import com.gh.common.util.HomePluggableHelper
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.common.util.PackageInstaller
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.DownloadManagerActivity
|
||||
@ -277,12 +276,6 @@ class DownloadFragment : BaseFragment_TabLayout() {
|
||||
if (mBinding.adGameItemContainer.isVisible) {
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
refreshInstallStatus()
|
||||
}
|
||||
|
||||
private fun refreshInstallStatus() {
|
||||
PackageHelper.refreshWrongInstallStatus(PackagesManager.getInstalledSet())
|
||||
}
|
||||
|
||||
override fun onParentActivityFinish() {
|
||||
|
||||
@ -10,8 +10,8 @@ import com.ethanhua.skeleton.ViewSkeletonScreen
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
@ -27,7 +27,9 @@ import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.GameInstall
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel
|
||||
import com.gh.gamecenter.wrapper.MainWrapperFragment
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
@ -108,11 +110,6 @@ class NewInstalledGameFragment : ToolbarFragment() {
|
||||
|
||||
mPackageViewModel =
|
||||
ViewModelProvider(this, PackageViewModel.Factory()).get(PackageViewModel::class.java)
|
||||
|
||||
if (mPackageViewModel?.getGameInstalledLiveData()?.value.isNullOrEmpty() == true) {
|
||||
mInstallGameViewModel.initData(arrayListOf())
|
||||
}
|
||||
|
||||
mPackageViewModel?.getGameInstalledLiveData()?.observe(
|
||||
this
|
||||
) { gameInstalls ->
|
||||
@ -150,20 +147,15 @@ class NewInstalledGameFragment : ToolbarFragment() {
|
||||
}
|
||||
|
||||
mBinding.run {
|
||||
val isGetInstalledListDisagreed = PackageHelper.isGetInstalledPackagesAgreedRequired()
|
||||
&& !PackageHelper.isGetInstalledPackagesAgreed()
|
||||
val isGetInstalledListPermissionDisabled = PermissionHelper.isGetInstalledListPermissionDisabled(requireContext())
|
||||
|
||||
if (isGetInstalledListDisagreed || isGetInstalledListPermissionDisabled) {
|
||||
if (PermissionHelper.isGetInstalledListPermissionDisabled(requireContext())) {
|
||||
reuseNoneData.reuseNoneDataIv.visibility = View.GONE
|
||||
reuseNoneData.reuseNoneDataTv.text = "开启应用列表权限"
|
||||
reuseNoneData.reuseNoneDataDescTv.text = " 及时获悉游戏最新的更新消息"
|
||||
reuseNoneData.reuseResetLoadTv.text = "去开启"
|
||||
reuseNoneData.reuseResetLoadTv.setOnClickListener {
|
||||
PackageHelper.showGetInstallAppsListDialogAndRequestPermissionIfNeeded(requireActivity()) { isGranted ->
|
||||
if (isGranted) {
|
||||
updateNoDataView()
|
||||
}
|
||||
PermissionHelper.showGetInstalledAppsListPermissionDialogAndRequestPermission(requireActivity()) {
|
||||
updateNoDataView()
|
||||
PackageRepository.initData()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -3,7 +3,6 @@ package com.gh.gamecenter.download
|
||||
import android.view.View
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.LazyFragment
|
||||
@ -14,6 +13,7 @@ import com.gh.gamecenter.common.view.FixLinearLayoutManager
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.FragmentGameUpdatableBinding
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
@ -51,16 +51,10 @@ class UpdatableGameFragment : LazyFragment() {
|
||||
super.onFragmentFirstVisible()
|
||||
|
||||
mPackageViewModel = viewModelProvider(PackageViewModel.Factory())
|
||||
|
||||
if (mPackageViewModel?.getGameUpdateIncludeCurrentVersion()?.value.isNullOrEmpty() == true) {
|
||||
mViewModel?.setUpdatableList(arrayListOf())
|
||||
}
|
||||
|
||||
mPackageViewModel?.getGameUpdateIncludeCurrentVersion()
|
||||
?.observeNonNull(viewLifecycleOwner) { updatableList ->
|
||||
mViewModel?.setUpdatableList(updatableList)
|
||||
}
|
||||
|
||||
mViewModel?.updatableData?.observe(viewLifecycleOwner) {
|
||||
mAdapter?.submitList(it)
|
||||
mBinding?.noDataContainer?.root?.goneIf(!it.isNullOrEmpty())
|
||||
@ -100,19 +94,18 @@ class UpdatableGameFragment : LazyFragment() {
|
||||
noDataContainer.reuseResetLoadTv.layoutParams = layoutParam
|
||||
noDataContainer.reuseResetLoadTv.visibility = View.VISIBLE
|
||||
noDataContainer.reuseNoneDataDescTv.visibility = View.VISIBLE
|
||||
|
||||
val isGetInstalledListDisagreed = !PackageHelper.isGetInstalledPackagesAgreed()
|
||||
val isGetInstalledListPermissionDisabled = PermissionHelper.isGetInstalledListPermissionDisabled(requireContext())
|
||||
|
||||
if (isGetInstalledListDisagreed || isGetInstalledListPermissionDisabled) {
|
||||
if (PermissionHelper.isGetInstalledListPermissionDisabled(requireContext())) {
|
||||
noDataContainer.reuseNoneDataIv.visibility = View.GONE
|
||||
noDataContainer.reuseNoneDataTv.text = "开启应用列表权限"
|
||||
noDataContainer.reuseNoneDataDescTv.text = "及时获悉游戏最新的更新消息"
|
||||
noDataContainer.reuseResetLoadTv.text = "去开启"
|
||||
noDataContainer.reuseResetLoadTv.setOnClickListener {
|
||||
PackageHelper.showGetInstallAppsListDialogAndRequestPermissionIfNeeded(requireActivity()) { isGranted ->
|
||||
PermissionHelper.showGetInstalledAppsListPermissionDialogAndRequestPermission(
|
||||
requireActivity()
|
||||
) { isGranted ->
|
||||
if (isGranted) {
|
||||
updateNoDataView()
|
||||
PackageRepository.initData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,19 +26,19 @@ data class BottomTab(
|
||||
@SerializedName("is_default_page")
|
||||
var default: Boolean = false, // 是否为默认显示页
|
||||
var isTransparentStyle: Boolean = false // 本地字段,透明底部Tab
|
||||
) : Parcelable {
|
||||
): Parcelable {
|
||||
@Parcelize
|
||||
data class SearchStyle(
|
||||
@SerializedName("style_type")
|
||||
var styleType: String = STYLE_TWO_LINES, // 样式类型(two_lines:搜索栏与顶部tab分为两行、apposition:搜索栏与顶部tab同一行)
|
||||
@SerializedName("search_type")
|
||||
var searchType: String = TYPE_HALO_GAME, // 搜索类型(halo_game:光环游戏、bbs:论坛、mini_game:小游戏搜索(低于v5.36版本返回qq_mini_game))
|
||||
) : Parcelable {
|
||||
var searchType: String = TYPE_HALO_GAME, // 搜索类型(halo_game:光环游戏、qq_mini_game:QQ小游戏、bbs:论坛)
|
||||
): Parcelable {
|
||||
companion object {
|
||||
const val STYLE_TWO_LINES = "two_lines"
|
||||
const val STYLE_APPOSITION = "apposition"
|
||||
const val TYPE_HALO_GAME = "halo_game"
|
||||
const val TYPE_MINI_GAME = "mini_game"
|
||||
const val TYPE_QQ_MINI_GAME = "qq_mini_game"
|
||||
const val TYPE_BBS = "bbs"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageData
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class FollowCommonContentCollection(
|
||||
@SerializedName("title")
|
||||
private val _title: String? = null,
|
||||
@SerializedName("link")
|
||||
private val _link: LinkEntity? = null,
|
||||
@SerializedName("link_common_collection")
|
||||
private val _linkCommonCollection: CustomPageData.CommonContentCollection? = null
|
||||
) {
|
||||
val title: String
|
||||
get() = _title ?: ""
|
||||
|
||||
val link: LinkEntity
|
||||
get() = _link ?: LinkEntity()
|
||||
|
||||
val linkCommonCollection: CustomPageData.CommonContentCollection
|
||||
get() = _linkCommonCollection ?: CustomPageData.CommonContentCollection()
|
||||
}
|
||||
@ -1,137 +0,0 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.gh.gamecenter.feature.entity.*
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class FollowDynamicEntity(
|
||||
@SerializedName("type")
|
||||
private val _type: String? = null,
|
||||
@SerializedName("libao")
|
||||
val libao: LibaoEntity? = null,
|
||||
@SerializedName("libao_exchange")
|
||||
val libaoExchange: LibaoEntity? = null,
|
||||
@SerializedName("game")
|
||||
private val _game: GameEntity? = null,
|
||||
@SerializedName("me")
|
||||
private val _me: MeEntity? = null,
|
||||
@SerializedName("time")
|
||||
private val _time: Long? = null,
|
||||
@SerializedName("article")
|
||||
val article: Article? = null,
|
||||
@SerializedName("user_post")
|
||||
val userPost: ArticleEntity? = null
|
||||
) : Parcelable {
|
||||
|
||||
val type: String
|
||||
get() = _type ?: ""
|
||||
|
||||
val game: GameEntity
|
||||
get() = _game ?: GameEntity()
|
||||
|
||||
val me: MeEntity
|
||||
get() = _me ?: MeEntity()
|
||||
|
||||
val time: Long
|
||||
get() = _time ?: 0L
|
||||
|
||||
companion object {
|
||||
|
||||
const val FOLLOW_UPDATE_TYPE_LIBAO = "libao"
|
||||
const val FOLLOW_UPDATE_TYPE_LIBAO_EXCHANGE = "libao_exchange"
|
||||
const val FOLLOW_UPDATE_TYPE_ARTICLE = "article"
|
||||
const val FOLLOW_UPDATE_TYPE_USER_POST = "user_post"
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class Article(
|
||||
@SerializedName("_id")
|
||||
private val _id: String? = null,
|
||||
@SerializedName("title")
|
||||
private val _title: String? = null,
|
||||
@SerializedName("content")
|
||||
private val _content: String? = null,
|
||||
@SerializedName("img")
|
||||
private val _img: List<String>? = null,
|
||||
@SerializedName("count")
|
||||
private val _count: Count? = null,
|
||||
@SerializedName("game")
|
||||
private val _game: GameEntity? = null,
|
||||
@SerializedName("time")
|
||||
private val _time: Long? = null,
|
||||
@SerializedName("_seq")
|
||||
private val _shortId: String? = null
|
||||
) : Parcelable {
|
||||
|
||||
val id: String
|
||||
get() = _id ?: ""
|
||||
|
||||
val title: String
|
||||
get() = _title ?: ""
|
||||
|
||||
val content: String
|
||||
get() = _content ?: ""
|
||||
|
||||
val img: List<String>
|
||||
get() = _img ?: listOf()
|
||||
|
||||
val count: Count
|
||||
get() = _count ?: Count()
|
||||
|
||||
val game: GameEntity
|
||||
get() = _game ?: GameEntity()
|
||||
|
||||
val time: Long
|
||||
get() = _time ?: 0L
|
||||
|
||||
val shortId: String
|
||||
get() = _shortId ?: ""
|
||||
|
||||
@Parcelize
|
||||
data class Count(
|
||||
@SerializedName("comment")
|
||||
private val _comment: Int? = null
|
||||
) : Parcelable {
|
||||
|
||||
val comment: Int
|
||||
get() = _comment ?: 0
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class LibaoExchange(
|
||||
@SerializedName("_id")
|
||||
private val _id: String? = null,
|
||||
@SerializedName("libao_id")
|
||||
private val _libaoId: String? = null,
|
||||
@SerializedName("libao_code")
|
||||
private val _libaoCode: String? = null,
|
||||
@SerializedName("name")
|
||||
private val _name: String? = null,
|
||||
@SerializedName("content")
|
||||
private val _content: String? = null,
|
||||
@SerializedName("active")
|
||||
private val _active: Boolean? = null
|
||||
) : Parcelable {
|
||||
|
||||
val id: String
|
||||
get() = _id ?: ""
|
||||
|
||||
val libaoId: String
|
||||
get() = _libaoId ?: ""
|
||||
|
||||
val libaoCode: String
|
||||
get() = _libaoCode ?: ""
|
||||
|
||||
val name: String
|
||||
get() = _name ?: ""
|
||||
|
||||
val content: String
|
||||
get() = _content ?: ""
|
||||
|
||||
val active: Boolean
|
||||
get() = _active ?: false
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
data class FollowOperateTopRequest(
|
||||
val _id: String,
|
||||
val order: Int
|
||||
) {
|
||||
}
|
||||
@ -1,159 +0,0 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.User
|
||||
import com.gh.gamecenter.feature.entity.UserEntity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.util.Objects
|
||||
|
||||
@Parcelize
|
||||
data class FollowUserEntity(
|
||||
@SerializedName("_id")
|
||||
private val _id: String? = null,
|
||||
@SerializedName("type")
|
||||
private val _type: String? = null, // user:用户、bbs:论坛
|
||||
@SerializedName("user")
|
||||
private val _user: UserEntity? = null,
|
||||
@SerializedName("bbs")
|
||||
private var _bbs: Bbs? = null,
|
||||
@SerializedName("is_top")
|
||||
private val _isTop: Int? = null,
|
||||
@SerializedName("is_show_tip")
|
||||
private val _isShowTip: Int? = null,
|
||||
) : Parcelable {
|
||||
|
||||
val id: String
|
||||
get() = _id ?: ""
|
||||
|
||||
val type: String
|
||||
get() = _type ?: ""
|
||||
|
||||
val user: UserEntity
|
||||
get() = _user ?: UserEntity()
|
||||
|
||||
val isTop: Boolean
|
||||
get() = _isTop == 1
|
||||
|
||||
val isShowTip: Boolean
|
||||
get() = _isShowTip == 1
|
||||
|
||||
val bbs: Bbs
|
||||
get() = _bbs ?: Bbs()
|
||||
|
||||
val isUser: Boolean
|
||||
get() = type == TYPE_USER
|
||||
|
||||
val name: String
|
||||
get() = if (isUser) {
|
||||
user.name ?: ""
|
||||
} else {
|
||||
bbs.name
|
||||
}
|
||||
|
||||
val icon: String
|
||||
get() = when {
|
||||
type == TYPE_USER -> user.icon ?: ""
|
||||
bbs.type == BBS_TYPE_GAME -> bbs.game.icon ?: ""
|
||||
else -> bbs.icon
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is FollowUserEntity
|
||||
&& id == other.id
|
||||
&& type == other.type
|
||||
&& user.id == other.user.id
|
||||
&& user.name == other.user.name
|
||||
&& bbs.id == other.bbs.id
|
||||
&& bbs.name == other.bbs.name
|
||||
&& bbs.type == other.bbs.type
|
||||
&& bbs.icon == other.bbs.icon
|
||||
&& bbs.game.icon == other.bbs.game.icon
|
||||
&& isTop == other.isTop
|
||||
&& isShowTip == other.isShowTip
|
||||
&& icon == other.icon
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return Objects.hash(
|
||||
_id,
|
||||
type,
|
||||
user.id,
|
||||
user.name,
|
||||
bbs.id,
|
||||
bbs.name,
|
||||
bbs.type,
|
||||
bbs.icon,
|
||||
bbs.game.icon,
|
||||
isTop,
|
||||
isShowTip,
|
||||
icon
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TYPE_USER = "user"
|
||||
private const val BBS_TYPE_GAME = "game_bbs"
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class Bbs(
|
||||
@SerializedName("_id")
|
||||
private val _id: String? = null,
|
||||
@SerializedName("name")
|
||||
private val _name: String? = null,
|
||||
@SerializedName("type")
|
||||
private val _type: String? = null,
|
||||
@SerializedName("icon")
|
||||
private val _icon: String? = null,
|
||||
@SerializedName("game")
|
||||
private val _game: GameEntity? = null
|
||||
) : Parcelable {
|
||||
|
||||
val id: String
|
||||
get() = _id ?: ""
|
||||
|
||||
val name: String
|
||||
get() = _name ?: ""
|
||||
|
||||
val type: String
|
||||
get() = _type ?: ""
|
||||
|
||||
val icon: String
|
||||
get() = _icon ?: ""
|
||||
|
||||
val game: GameEntity
|
||||
get() = _game ?: GameEntity()
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class Game(
|
||||
@SerializedName("_id")
|
||||
private val _id: String? = null,
|
||||
@SerializedName("name")
|
||||
private val _name: String? = null,
|
||||
@SerializedName("icon")
|
||||
private val _icon: String? = null,
|
||||
@SerializedName("ori_icon")
|
||||
private val _oriIcon: String? = null,
|
||||
@SerializedName("active")
|
||||
private val _active: Boolean? = null
|
||||
) : Parcelable {
|
||||
|
||||
val id: String
|
||||
get() = _id ?: ""
|
||||
|
||||
val name: String
|
||||
get() = _name ?: ""
|
||||
|
||||
val icon: String
|
||||
get() = _icon ?: ""
|
||||
|
||||
val oriIcon: String
|
||||
get() = _oriIcon ?: ""
|
||||
|
||||
val active: Boolean
|
||||
get() = _active ?: false
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.feature.entity.SettingsEntity
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
@ -12,16 +11,9 @@ class NewApiSettingsEntity(
|
||||
var startup: StartupAdEntity? = null,//启动文案广告
|
||||
@SerializedName("user_interested_game")
|
||||
var userInterestedGame: Boolean = false, //偏好设置状态开关
|
||||
@SerializedName("installed_compliance_switch")
|
||||
var installedComplianceSwitch: Boolean? = false, //安装合规开关
|
||||
@SerializedName("listen_switch")
|
||||
var isPackageObserveEnable: Boolean = false, // 安装包监听开关
|
||||
@SerializedName("listen_str")
|
||||
var packageObserveActions: PackageObserveActions? = null, // 安装包监听的三个 action
|
||||
var install: Install, // 安装相关的
|
||||
@SerializedName("game_shield_contents")
|
||||
var gameShieldContents: List<String>? = listOf(),//游戏屏蔽内容
|
||||
var search: SettingsEntity.Search? = null// 游戏搜索配置
|
||||
) {
|
||||
/**
|
||||
*
|
||||
@ -35,51 +27,23 @@ class NewApiSettingsEntity(
|
||||
val install: Boolean
|
||||
)
|
||||
|
||||
// VPN 配置
|
||||
class Install(
|
||||
@SerializedName("vpn_required")
|
||||
val vpnRequired: VpnSetting? = null,
|
||||
@SerializedName("guides")
|
||||
val guides: List<Guide>? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* 当为鸿蒙纯净模式相关时
|
||||
* {
|
||||
* "type': "harmony_os_pure_mode", // 华为鸿蒙系统纯净模式相关 harmony_os_pure_mode/harmony_os_pure_enhanced_mode
|
||||
* "link": {
|
||||
* "type": "qa_content",
|
||||
* "link": "61026d03802abe4d7260fdc3",
|
||||
* "text": "点击查看教程" // 链接文案,有设置时替换该字段,无设置时读取对应通用链接原本的文案
|
||||
* },
|
||||
* "title": "",
|
||||
* "content": "",
|
||||
* "link_text_prefix": "关闭场景模式:", // 链接引导文案
|
||||
* "button_text_close": "", // 关闭按钮
|
||||
* "button_text_setting_jump": "", // 前往设置按钮
|
||||
* "dialog_frequency": "once" // once/every_time
|
||||
* }
|
||||
*/
|
||||
class Guide(
|
||||
val type: String,
|
||||
val link: LinkEntity,
|
||||
val title: String = "",
|
||||
val content: String = "",
|
||||
@SerializedName("link_text_prefix")
|
||||
val linkTextPrefix: String = "",
|
||||
@SerializedName("link_text")
|
||||
val linkText: String = "",
|
||||
@SerializedName("button_text_close")
|
||||
val buttonTextClose: String = "",
|
||||
@SerializedName("button_text_setting_jump")
|
||||
val buttonTextSettingJump: String = "",
|
||||
@SerializedName("dialog_frequency")
|
||||
val dialogFrequency: String = "",
|
||||
class VpnSetting(
|
||||
@SerializedName("current_device")
|
||||
val shouldShowVpnOption: Boolean,
|
||||
@SerializedName("packages")
|
||||
val vpnMatchedPackagesName: HashSet<String>
|
||||
)
|
||||
|
||||
class PackageObserveActions(
|
||||
@SerializedName("ADD")
|
||||
val add: String,
|
||||
@SerializedName("REM")
|
||||
val rem: String,
|
||||
@SerializedName("REP")
|
||||
val rep: String
|
||||
class Guide(
|
||||
val type: String,
|
||||
val link: LinkEntity
|
||||
)
|
||||
}
|
||||
@ -163,14 +163,6 @@ data class PersonalHistoryEntity(
|
||||
get() = community.name
|
||||
set(_) {}
|
||||
|
||||
override fun vote(isVote: Boolean) {
|
||||
_count.vote = if (isVote) {
|
||||
_count.vote + 1
|
||||
} else {
|
||||
_count.vote - 1
|
||||
}
|
||||
}
|
||||
|
||||
fun getPassVideos(): List<CommunityVideoEntity> {
|
||||
val passVideos = arrayListOf<CommunityVideoEntity>()
|
||||
for (video in videos) {
|
||||
|
||||
@ -17,7 +17,7 @@ class SubjectData(
|
||||
var filter: String = "", // Filter: 类型(分类)
|
||||
var tagType: String? = "", // 游戏Item 标签类型
|
||||
var briefStyle: String = "",
|
||||
var subjectType: SubjectType = SubjectType.NORMAL,
|
||||
var isQQMiniGame: Boolean = false,
|
||||
var subjectStyle: String = "",
|
||||
|
||||
var requireUpdateSetting: Boolean = false, // 多专题页面需要专题页面自行获取专题配置
|
||||
@ -43,24 +43,4 @@ class SubjectData(
|
||||
tag = tagType
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 专题类型
|
||||
*/
|
||||
enum class SubjectType {
|
||||
/**
|
||||
* 普通专题
|
||||
*/
|
||||
NORMAL,
|
||||
|
||||
/**
|
||||
* QQ小游戏专题
|
||||
*/
|
||||
QQ_GAME,
|
||||
|
||||
/**
|
||||
* 微信小游戏专题
|
||||
*/
|
||||
WECHAT_GAME
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import android.text.TextUtils
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
@ -100,9 +102,6 @@ data class SubjectEntity(
|
||||
@SerializedName("is_qq_column")
|
||||
var isQQColumn: Boolean = false,
|
||||
|
||||
@SerializedName("is_wechat_column")
|
||||
var isWechatColumn: Boolean = false,
|
||||
|
||||
var explain: String = "", // 游戏单合集说明
|
||||
|
||||
@SerializedName("show_star")
|
||||
@ -111,22 +110,11 @@ data class SubjectEntity(
|
||||
|
||||
@IgnoredOnParcel
|
||||
var data: MutableList<GameEntity>?
|
||||
get() = filteredData ?: RegionSettingHelper.filterGame(mData).also { filteredData = it }
|
||||
get() = RegionSettingHelper.filterGame(mData)
|
||||
set(value) {
|
||||
mData = RegionSettingHelper.filterGame(value).also { filteredData = it }
|
||||
mData = value
|
||||
}
|
||||
|
||||
@IgnoredOnParcel
|
||||
private var filteredData: MutableList<GameEntity>? = null
|
||||
|
||||
val subjectType: SubjectData.SubjectType get() = when {
|
||||
isQQColumn -> SubjectData.SubjectType.QQ_GAME
|
||||
isWechatColumn -> SubjectData.SubjectType.WECHAT_GAME
|
||||
else -> SubjectData.SubjectType.NORMAL
|
||||
}
|
||||
|
||||
val isMiniGame: Boolean get() = isQQColumn || isWechatColumn
|
||||
|
||||
val showStar: Boolean
|
||||
get() = _showStar ?: false
|
||||
|
||||
|
||||
@ -4,7 +4,10 @@ import android.os.Parcelable
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IConfigProvider
|
||||
import com.gh.gamecenter.feature.entity.*
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.MeEntity
|
||||
import com.gh.gamecenter.feature.entity.SourceEntity
|
||||
import com.gh.gamecenter.feature.entity.UserEntity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
@ -59,16 +62,6 @@ open class VideoEntity(
|
||||
@SerializedName("_source")
|
||||
val ipSource: SourceEntity? = null,
|
||||
|
||||
// 关注首页新增字段
|
||||
@SerializedName("choiceness")
|
||||
private val _choiceness: Boolean? = null,
|
||||
@SerializedName("video_info")
|
||||
private val _videoInfo: VideoInfo? = null,
|
||||
@SerializedName("show_me_only")
|
||||
private val _showMeOnly: Boolean? = null,
|
||||
@SerializedName("count")
|
||||
private val _count: Count? = null,
|
||||
|
||||
//本地数据
|
||||
@IgnoredOnParcel
|
||||
var videoIsMuted: Boolean = false,//是否静音标记
|
||||
@ -80,18 +73,6 @@ open class VideoEntity(
|
||||
val gameName: String
|
||||
get() = mGameName.removeSuffix(".")
|
||||
|
||||
val choiceness: Boolean
|
||||
get() = _choiceness ?: false
|
||||
|
||||
val videoInfo: VideoInfo
|
||||
get() = _videoInfo ?: VideoInfo()
|
||||
|
||||
val showMeOnly: Boolean
|
||||
get() = _showMeOnly ?: false
|
||||
|
||||
val count: Count
|
||||
get() = _count ?: Count()
|
||||
|
||||
fun getThumb(): String {
|
||||
val configProvider = ARouter.getInstance().build(RouteConsts.provider.config).navigation() as? IConfigProvider
|
||||
return if (!configProvider?.getVideoSnapshotSuffix().isNullOrEmpty()) {
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
class WhitePackageListEntity {
|
||||
var data: HashSet<String>? = null
|
||||
}
|
||||
@ -42,10 +42,6 @@ class ForumArticleAskListAdapter(
|
||||
private var mVideoOrderList = listOf("推荐", "发布")
|
||||
private var mFilterPosition = if (path == "视频") 1 else 0
|
||||
|
||||
override fun setListData(updateData: MutableList<AnswerEntity>?) {
|
||||
super.setListData(updateData)
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItem: AnswerEntity?, newItem: AnswerEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
}
|
||||
|
||||
@ -10,9 +10,6 @@ import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
|
||||
/**
|
||||
* 论坛详情
|
||||
*/
|
||||
class ForumDetailActivity : BaseActivity() {
|
||||
|
||||
private var mContainerFragment: Fragment? = null
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
package com.gh.gamecenter.forum.home
|
||||
|
||||
import android.app.Activity
|
||||
import com.gh.gamecenter.common.entity.AdditionalParamsEntity
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.common.utils.ShareUtils
|
||||
import com.gh.gamecenter.common.utils.isPublishEnv
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.shuyu.gsyvideoplayer.utils.OrientationUtils
|
||||
|
||||
class AnswerArticleVideoViewEventHelper(
|
||||
private val entity: ForumVideoEntity,
|
||||
private val orientationUtils: OrientationUtils
|
||||
) : ArticleItemVideoView.OnArticleItemVideoViewEventListener {
|
||||
override fun onTrackVideoStartPlaying() {
|
||||
SensorsBridge.trackVideoStartPlaying(
|
||||
articleId = entity.id,
|
||||
bbsId = entity.bbs?.id ?: "",
|
||||
bbsType = entity.bbs?.typeChinese ?: "综合论坛",
|
||||
customerType = entity.user.auth?.text ?: "",
|
||||
videoId = entity.id,
|
||||
playType = "视频贴",
|
||||
gameForumType = entity.bbs?.game?.categoryChinese ?: "",
|
||||
activityTag = entity.tagActivityName,
|
||||
articleType = entity.typeChinese
|
||||
)
|
||||
}
|
||||
|
||||
override fun onTrackVideoEndPlaying(maxPlayedProgress: Int) {
|
||||
SensorsBridge.trackVideoEndPlaying(
|
||||
articleId = entity.id,
|
||||
bbsId = entity.bbs?.id ?: "",
|
||||
bbsType = entity.bbs?.typeChinese ?: "综合论坛",
|
||||
customerType = entity.user.auth?.text ?: "",
|
||||
videoId = entity.id,
|
||||
playType = "视频贴",
|
||||
gameForumType = entity.bbs?.game?.categoryChinese ?: "",
|
||||
activityTag = entity.tagActivityName,
|
||||
articleType = entity.typeChinese,
|
||||
result = if (maxPlayedProgress >= 95) "是" else "否"
|
||||
)
|
||||
}
|
||||
|
||||
override fun onShare(videoView: ArticleItemVideoView) {
|
||||
val shareIcon = entity.poster
|
||||
val shareUrl = if (isPublishEnv()) {
|
||||
"https://m.ghzs666.com/video/${entity.id}"
|
||||
} else {
|
||||
"https://resource.ghzs.com/page/video_play/video/video.html?video=${entity.id}"
|
||||
}
|
||||
val additionalParams = AdditionalParamsEntity().apply {
|
||||
contentType = "视频帖"
|
||||
contentId = entity.id ?: ""
|
||||
bbsId = entity.bbs?.id ?: ""
|
||||
bbsType = entity.bbs?.typeChinese ?: "综合论坛"
|
||||
customerType = entity.user.auth?.text ?: ""
|
||||
activityTagName = entity.tagActivityName ?: ""
|
||||
gameForumType = entity.bbs?.game?.categoryChinese ?: ""
|
||||
refUserId = UserManager.getInstance().userId
|
||||
}
|
||||
val activity = (videoView.context as? Activity) ?: return
|
||||
ShareUtils.getInstance(videoView.context).showShareWindowsCallback(activity,
|
||||
videoView,
|
||||
shareUrl,
|
||||
shareIcon,
|
||||
entity.title,
|
||||
entity.des,
|
||||
ShareUtils.ShareEntrance.video,
|
||||
entity.id,
|
||||
additionalParams,
|
||||
object : ShareUtils.ShareCallBack {
|
||||
override fun onSuccess(label: String) = Unit
|
||||
|
||||
override fun onCancel() = Unit
|
||||
})
|
||||
}
|
||||
|
||||
override fun onMutedChanged(isMuted: Boolean) {
|
||||
entity.videoIsMuted = isMuted
|
||||
}
|
||||
|
||||
override fun onStartWindowFullscreen() {
|
||||
orientationUtils.resolveByClick()
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,7 @@
|
||||
package com.gh.gamecenter.forum.home
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.Surface
|
||||
@ -13,9 +12,11 @@ import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.entity.AdditionalParamsEntity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.video.detail.CustomManager
|
||||
import com.lightgame.utils.Utils
|
||||
import com.shuyu.gsyvideoplayer.utils.CommonUtil
|
||||
@ -24,12 +25,13 @@ import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
|
||||
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge
|
||||
import io.reactivex.disposables.Disposable
|
||||
import java.util.*
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
|
||||
class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
StandardGSYVideoPlayer(context, attrs) {
|
||||
|
||||
var data: ArticleVideoData? = null
|
||||
|
||||
private var mVideoEntity: ForumVideoEntity? = null
|
||||
private var mMuteDisposable: Disposable? = null
|
||||
private var mIsAutoPlay = false
|
||||
var uuid = UUID.randomUUID().toString()
|
||||
@ -51,8 +53,6 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
|
||||
private val mTrackHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
private var onEventListener: OnArticleItemVideoViewEventListener? = null
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.layout_article_item_video
|
||||
}
|
||||
@ -81,7 +81,7 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
fun startPlayLogic(isAutoPlay: Boolean) {
|
||||
mIsAutoPlay = isAutoPlay
|
||||
if (mIsAutoPlay) {
|
||||
val seekTime = ForumScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(data?.url))
|
||||
val seekTime = ForumScrollCalculatorHelper.getPlaySchedule(MD5Utils.getContentMD5(mVideoEntity?.url))
|
||||
seekOnStart = seekTime
|
||||
}
|
||||
startPlayLogic()
|
||||
@ -137,7 +137,7 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
}
|
||||
|
||||
override fun onClickUiToggle(e: MotionEvent?) {
|
||||
if (data?.status != "pending" && data?.status != "fail") {
|
||||
if (mVideoEntity?.status != "pending" && mVideoEntity?.status != "fail") {
|
||||
if (mCurrentState == CURRENT_STATE_PLAYING) {
|
||||
if (mStartButton.visibility == View.VISIBLE) {
|
||||
changeUiToPlayingClear()
|
||||
@ -156,6 +156,7 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
super.onSurfaceUpdated(surface)
|
||||
if (mThumbImageViewLayout != null && mThumbImageViewLayout.visibility == View.VISIBLE) {
|
||||
mThumbImageViewLayout.visibility = View.INVISIBLE
|
||||
uploadVideoStreamingPlaying("开始播放")
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,9 +169,14 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
// }
|
||||
|
||||
override fun releaseVideos() {
|
||||
uploadVideoStreamingPlaying("结束播放")
|
||||
CustomManager.releaseAllVideos(getKey())
|
||||
}
|
||||
|
||||
override fun onVideoPause() {
|
||||
super.onVideoPause()
|
||||
uploadVideoStreamingPlaying("暂停播放")
|
||||
}
|
||||
|
||||
// 重载以减少横竖屏切换的时间
|
||||
override fun checkoutState() {
|
||||
@ -200,7 +206,9 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
private fun showBackBtn() {
|
||||
mTopContainer.background = ContextCompat.getDrawable(context, R.drawable.video_title_bg)
|
||||
back.visibility = View.VISIBLE
|
||||
data?.title?.let(titleTv::setText)
|
||||
mVideoEntity?.run {
|
||||
titleTv.text = title
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideBackBtn() {
|
||||
@ -209,32 +217,19 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
titleTv.text = ""
|
||||
}
|
||||
|
||||
fun updateVideoData(video: ArticleVideoData, listener: OnArticleItemVideoViewEventListener) {
|
||||
this.onEventListener = listener
|
||||
fun updateThumb(url: String) {
|
||||
ImageUtils.display(thumbImage, url)
|
||||
}
|
||||
|
||||
fun updateDurationTv(duration: String) {
|
||||
durationTv.text = duration
|
||||
}
|
||||
|
||||
fun updateVideoData(video: ForumVideoEntity) {
|
||||
this.mStopTrackRunnable = null
|
||||
|
||||
data = video
|
||||
mVideoEntity = video
|
||||
titleTv.text = if (mIfCurrentIsFullscreen) video.title else ""
|
||||
|
||||
ImageUtils.display(thumbImage, video.poster)
|
||||
|
||||
if (!mIfCurrentIsFullscreen) {
|
||||
durationTv.text = video.duration
|
||||
setVideoStatus(video.status)
|
||||
fullscreenButton.setOnClickListener {
|
||||
val horizontalVideoView =
|
||||
startWindowFullscreen(context, true, true) as? ArticleItemVideoView
|
||||
if (horizontalVideoView == null) {
|
||||
toastInInternalRelease("全屏失败,请向技术人员提供具体的操作步骤")
|
||||
return@setOnClickListener
|
||||
}
|
||||
onEventListener?.onStartWindowFullscreen()
|
||||
horizontalVideoView.uuid = uuid
|
||||
horizontalVideoView.updateVideoData(video, listener)
|
||||
horizontalVideoView.violenceUpdateMuteStatus()
|
||||
horizontalVideoView.setFullViewStatus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setViewShowState(view: View?, visibility: Int) {
|
||||
@ -271,16 +266,25 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
override fun setStateAndUi(state: Int) {
|
||||
if (state != currentState
|
||||
&& state == CURRENT_STATE_PLAYING
|
||||
&& currentState != CURRENT_STATE_PLAYING_BUFFERING_START
|
||||
) {// 上报开始视频播放埋点
|
||||
&& currentState != CURRENT_STATE_PLAYING_BUFFERING_START) {// 上报开始视频播放埋点
|
||||
// 视频停止播放后再恢复播放的间隔时间未超过3秒,则取消上报结束视频播放埋点
|
||||
mStopTrackRunnable?.let { runnable ->
|
||||
mTrackHandler.removeCallbacks(runnable)
|
||||
}
|
||||
|
||||
data?.let {
|
||||
mVideoEntity?.let {
|
||||
val startTrackRunnable = Runnable {
|
||||
onEventListener?.onTrackVideoStartPlaying()
|
||||
SensorsBridge.trackVideoStartPlaying(
|
||||
articleId = it.id,
|
||||
bbsId = it.bbs?.id ?: "",
|
||||
bbsType = it.bbs?.typeChinese ?: "综合论坛",
|
||||
customerType = it.user.auth?.text ?: "",
|
||||
videoId = it.id,
|
||||
playType = "视频贴",
|
||||
gameForumType = it.bbs?.game?.categoryChinese ?: "",
|
||||
activityTag = it.tagActivityName,
|
||||
articleType = it.typeChinese
|
||||
)
|
||||
mStartTrackRunnable = null
|
||||
}.also {
|
||||
mStartTrackRunnable = it
|
||||
@ -299,9 +303,20 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
mTrackHandler.removeCallbacks(it)
|
||||
mStartTrackRunnable = null
|
||||
} ?: let {
|
||||
data?.let {
|
||||
mVideoEntity?.let {
|
||||
val stopTrackRunnable = Runnable {
|
||||
onEventListener?.onTrackVideoEndPlaying(mMaxPlayedProgress)
|
||||
SensorsBridge.trackVideoEndPlaying(
|
||||
articleId = it.id,
|
||||
bbsId = it.bbs?.id ?: "",
|
||||
bbsType = it.bbs?.typeChinese ?: "综合论坛",
|
||||
customerType = it.user.auth?.text ?: "",
|
||||
videoId = it.id,
|
||||
playType = "视频贴",
|
||||
gameForumType = it.bbs?.game?.categoryChinese ?: "",
|
||||
activityTag = it.tagActivityName,
|
||||
articleType = it.typeChinese,
|
||||
result = if (mMaxPlayedProgress >= 95) "是" else "否"
|
||||
)
|
||||
}.also {
|
||||
this.mStopTrackRunnable = it
|
||||
}
|
||||
@ -327,9 +342,10 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
replayTv.setOnClickListener {
|
||||
startButton.performClick()
|
||||
violenceUpdateMuteStatus()
|
||||
uploadVideoStreamingPlaying("重新播放")
|
||||
}
|
||||
shareTv.setOnClickListener {
|
||||
onEventListener?.onShare(this)
|
||||
share()
|
||||
}
|
||||
} else {
|
||||
setViewShowState(completeContainer, View.GONE)
|
||||
@ -347,33 +363,88 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
}
|
||||
|
||||
private fun toggleMute() {
|
||||
if (data?.videoIsMuted == true) {
|
||||
unMute()
|
||||
if (mVideoEntity?.videoIsMuted == true) {
|
||||
unMute(true)
|
||||
} else {
|
||||
mute()
|
||||
mute(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMuteStatus() {
|
||||
if (data?.videoIsMuted == true) {
|
||||
fun updateMuteStatus() {
|
||||
if (mVideoEntity?.videoIsMuted == true) {
|
||||
mute()
|
||||
} else {
|
||||
unMute()
|
||||
}
|
||||
}
|
||||
|
||||
private fun mute() {
|
||||
onEventListener?.onMutedChanged(true)
|
||||
data?.videoIsMuted = true
|
||||
fun mute(isManual: Boolean = false) {
|
||||
mVideoEntity?.videoIsMuted = true
|
||||
volume.setImageResource(R.drawable.ic_article_video_volume_off)
|
||||
CustomManager.getCustomManager(getKey()).isNeedMute = true
|
||||
if (isManual) {
|
||||
// Utils.toast(context, "当前处于静音状态")
|
||||
uploadVideoStreamingPlaying("点击静音")
|
||||
}
|
||||
}
|
||||
|
||||
private fun unMute() {
|
||||
onEventListener?.onMutedChanged(false)
|
||||
data?.videoIsMuted = false
|
||||
fun unMute(isManual: Boolean = false) {
|
||||
mVideoEntity?.videoIsMuted = false
|
||||
volume.setImageResource(R.drawable.ic_article_video_volume_on)
|
||||
CustomManager.getCustomManager(getKey()).isNeedMute = false
|
||||
if (isManual) {
|
||||
uploadVideoStreamingPlaying("取消静音")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAutoCompletion() {
|
||||
super.onAutoCompletion()
|
||||
uploadVideoStreamingPlaying("播放完毕")
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||
super.onStopTrackingTouch(seekBar)
|
||||
uploadVideoStreamingPlaying("拖动")
|
||||
}
|
||||
|
||||
private fun share() {
|
||||
mVideoEntity?.let {
|
||||
val shareIcon = it.poster
|
||||
val shareUrl = if (isPublishEnv()) {
|
||||
"https://m.ghzs666.com/video/${it.id}"
|
||||
} else {
|
||||
"https://dev-and-static.ghzs66.com/page/video_play/video/video.html?video=${it.id}"
|
||||
}
|
||||
val additionalParams = AdditionalParamsEntity().apply {
|
||||
contentType = "视频帖"
|
||||
contentId = mVideoEntity?.id ?: ""
|
||||
bbsId = mVideoEntity?.bbs?.id ?: ""
|
||||
bbsType = mVideoEntity?.bbs?.typeChinese ?: "综合论坛"
|
||||
customerType = mVideoEntity?.user?.auth?.text ?: ""
|
||||
activityTagName = mVideoEntity?.tagActivityName ?: ""
|
||||
gameForumType = mVideoEntity?.bbs?.game?.categoryChinese ?: ""
|
||||
refUserId = UserManager.getInstance().userId
|
||||
}
|
||||
ShareUtils.getInstance(context).showShareWindowsCallback(context as Activity,
|
||||
this,
|
||||
shareUrl,
|
||||
shareIcon,
|
||||
it.title,
|
||||
it.des,
|
||||
ShareUtils.ShareEntrance.video, it.id, additionalParams, object : ShareUtils.ShareCallBack {
|
||||
override fun onSuccess(label: String) {
|
||||
// if ("短信" == label || "复制链接" == label) viewModel?.shareVideoStatistics(it)
|
||||
}
|
||||
|
||||
override fun onCancel() {
|
||||
uploadVideoStreamingPlaying("取消分享")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun uploadVideoStreamingPlaying(action: String) {
|
||||
|
||||
}
|
||||
|
||||
fun setFullViewStatus() {
|
||||
@ -385,7 +456,7 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
durationTv.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun setVideoStatus(status: String) {
|
||||
fun setVideoStatus(status: String) {
|
||||
if (status == "pending" || status == "fail") {
|
||||
pendingView.text = if (status == "pending") "审核中...请耐心等待" else "审核不通过"
|
||||
pendingView.visibility = View.VISIBLE
|
||||
@ -423,32 +494,4 @@ class ArticleItemVideoView @JvmOverloads constructor(context: Context, attrs: At
|
||||
super.onDetachedFromWindow()
|
||||
mMuteDisposable?.dispose()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun ForumVideoEntity.toArticleVideoData() =
|
||||
ArticleVideoData(url, title, status, poster, duration, videoIsMuted)
|
||||
}
|
||||
|
||||
data class ArticleVideoData(
|
||||
val url: String,
|
||||
val title: String,
|
||||
val status: String,
|
||||
val poster: String,
|
||||
val duration: String,
|
||||
var videoIsMuted: Boolean
|
||||
)
|
||||
|
||||
interface OnArticleItemVideoViewEventListener {
|
||||
|
||||
fun onTrackVideoStartPlaying()
|
||||
|
||||
fun onTrackVideoEndPlaying(maxPlayedProgress: Int)
|
||||
|
||||
fun onShare(videoView: ArticleItemVideoView)
|
||||
|
||||
fun onMutedChanged(isMuted: Boolean)
|
||||
|
||||
fun onStartWindowFullscreen()
|
||||
}
|
||||
}
|
||||
@ -8,9 +8,6 @@ import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts.IS_DETAIL_PAGE
|
||||
import com.gh.gamecenter.video.detail.HomeVideoFragment
|
||||
|
||||
/**
|
||||
* 社区首页
|
||||
*/
|
||||
class CommunityActivity : BaseActivity() {
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.activity_community
|
||||
|
||||
@ -4,7 +4,6 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.ColorFilter
|
||||
import android.graphics.Typeface
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
@ -12,20 +11,17 @@ import android.view.*
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.airbnb.lottie.LottieProperty
|
||||
import com.airbnb.lottie.SimpleColorFilter
|
||||
import com.airbnb.lottie.model.KeyPath
|
||||
import com.airbnb.lottie.value.LottieValueCallback
|
||||
import com.gh.common.browse.BrowseTimer
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.browse.withLifecycle
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.common.util.ViewPagerFragmentHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.TrackableDialog
|
||||
import com.gh.gamecenter.common.base.adapter.FragmentAdapter
|
||||
@ -36,7 +32,6 @@ import com.gh.gamecenter.common.constant.EntranceConsts.IS_DETAIL_PAGE
|
||||
import com.gh.gamecenter.common.retrofit.ApiResponse
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.AvatarBorderView
|
||||
import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
@ -48,11 +43,8 @@ import com.gh.gamecenter.eventbus.EBSkip
|
||||
import com.gh.gamecenter.eventbus.EBTypeChange
|
||||
import com.gh.gamecenter.feature.entity.ArticleEntity
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.forum.home.follow.FollowHomeFilterPopWindow
|
||||
import com.gh.gamecenter.forum.home.follow.fragment.FollowHomeFragment
|
||||
import com.gh.gamecenter.forum.search.ForumOrUserSearchActivity
|
||||
import com.gh.gamecenter.login.entity.UserInfoEntity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.login.user.UserRepository
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailWebCacheManager
|
||||
import com.gh.gamecenter.qa.article.edit.ArticleEditActivity
|
||||
@ -62,7 +54,6 @@ import com.gh.gamecenter.qa.video.publish.VideoPublishActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.gh.gamecenter.wrapper.MainWrapperViewModel
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||
import com.halo.assistant.HaloApp
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
@ -75,7 +66,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
private var mViewModel: CommunityHomeViewModel? = null
|
||||
private var mMainWrapperViewModel: MainWrapperViewModel? = null
|
||||
private var mFragmentList = arrayListOf<Fragment>()
|
||||
private var mTitleList = arrayListOf("关注", "推荐", "论坛", "活动")
|
||||
private var mTitleList = arrayListOf("推荐", "论坛", "活动")
|
||||
private var mTabList = arrayListOf<Any>()
|
||||
private var mDefaultSelectedTab = -1
|
||||
private var mNavigationBitmap: Bitmap? = null
|
||||
@ -83,46 +74,11 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
private var mBottomTabId = ""
|
||||
|
||||
private val browseTimer = BrowseTimer()
|
||||
.withLifecycle(this)
|
||||
.withResult {
|
||||
SensorsBridge.trackCommunityBrowsingDuration(it / 1000.0)
|
||||
}
|
||||
|
||||
private val followFilterPopWindow by lazy {
|
||||
FollowHomeFilterPopWindow.create(requireContext()).apply {
|
||||
setOnDismissListener {
|
||||
resetFollowTab()
|
||||
}
|
||||
setFilterListener(object : FollowHomeFilterPopWindow.OnFilteredChangedListener {
|
||||
override fun filterFollowed(position: Int) {
|
||||
mViewModel?.filterFollowed(position)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private val obTabSelectedListener = object : OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
if (tab?.position == TAB_FOLLOW_INDEX) {
|
||||
mViewModel?.updateFilterResId(R.drawable.ic_follow_arrow_down)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) {
|
||||
if (tab?.position == TAB_FOLLOW_INDEX) {
|
||||
mViewModel?.updateFilterResId(null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) {
|
||||
if (mViewModel?.followFilterStatus?.value == R.drawable.ic_follow_arrow_down) {
|
||||
mViewModel?.updateFilterResId(R.drawable.ic_follow_arrow_up)
|
||||
mBinding?.tabLayout?.let(followFilterPopWindow::showAsDropDown)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun getRealLayoutId(): Int {
|
||||
return R.layout.fragment_community_home
|
||||
}
|
||||
@ -141,19 +97,6 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
super.onFragmentFirstVisible()
|
||||
|
||||
initViewPager()
|
||||
|
||||
mViewModel?.followFilterStatus?.observe(viewLifecycleOwner, Observer { resId ->
|
||||
val tabLayout = mBinding?.tabLayout ?: return@Observer
|
||||
val tab = tabLayout.getTabAt(TAB_FOLLOW_INDEX)
|
||||
val tvTitle = tab?.customView?.findViewById<TextView>(R.id.tab_title)
|
||||
if (resId != null) {
|
||||
tvTitle?.setDrawableEnd(resId, 8F.dip2px(), 8F.dip2px())
|
||||
} else {
|
||||
tvTitle?.setDrawableEnd(null, 8F.dip2px(), 8F.dip2px())
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
override fun initRealView() {
|
||||
@ -204,13 +147,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
topBg.visibleIf(!mIsDarkModeOn)
|
||||
|
||||
videoLottie.setOnClickListener {
|
||||
DirectUtils.directToLegacyVideoDetail(
|
||||
requireContext(),
|
||||
"",
|
||||
VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.value,
|
||||
referer = "视频流-社区右上角",
|
||||
isHomeVideo = true
|
||||
)
|
||||
DirectUtils.directToLegacyVideoDetail(requireContext(), "", VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.value, referer = "视频流-社区右上角", isHomeVideo = true)
|
||||
}
|
||||
searchIconIv.setOnClickListener {
|
||||
NewLogUtils.logCommunitySearchClick()
|
||||
@ -265,14 +202,13 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
mBottomTabId = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_ID, "") ?: ""
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
browseTimer.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
browseTimer.stop()
|
||||
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
||||
super.setUserVisibleHint(isVisibleToUser)
|
||||
if (isVisibleToUser) {
|
||||
browseTimer.start()
|
||||
} else {
|
||||
browseTimer.stop()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
@ -300,12 +236,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
mTabList.clear()
|
||||
mFragmentList.clear()
|
||||
val tag = "android:switcher:${viewPager.id}:"
|
||||
|
||||
val followFragment = childFragmentManager.findFragmentByTag("$tag$TAB_FOLLOW_INDEX")
|
||||
?: FollowHomeFragment()
|
||||
mFragmentList.add(followFragment)
|
||||
|
||||
val forumArticleListFragment = childFragmentManager.findFragmentByTag("$tag$TAB_RECOMMEND_INDEX")
|
||||
val forumArticleListFragment = childFragmentManager.findFragmentByTag("${tag}0")
|
||||
?: ForumArticleListFragment().with(
|
||||
bundleOf(
|
||||
EntranceConsts.KEY_ENTRANCE to "社区",
|
||||
@ -314,11 +245,11 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
)
|
||||
mFragmentList.add(forumArticleListFragment)
|
||||
|
||||
val forumFragment = childFragmentManager.findFragmentByTag("${tag}$TAB_FORUM_INDEX")
|
||||
val forumFragment = childFragmentManager.findFragmentByTag("${tag}1")
|
||||
?: ForumFragment().with(bundleOf(EntranceConsts.KEY_ENTRANCE to "社区"))
|
||||
mFragmentList.add(forumFragment)
|
||||
|
||||
val activityFragment = childFragmentManager.findFragmentByTag("${tag}$TAB_ACTIVITY_INDEX")
|
||||
val activityFragment = childFragmentManager.findFragmentByTag("${tag}2")
|
||||
?: ForumActivityFragment().with(bundleOf(EntranceConsts.KEY_ENTRANCE to "活动"))
|
||||
mFragmentList.add(activityFragment)
|
||||
|
||||
@ -332,16 +263,8 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
adapter = FragmentAdapter(childFragmentManager, mFragmentList, mTitleList)
|
||||
doOnScroll(
|
||||
onPageSelected = { position ->
|
||||
communityEditBtn.goneIf(position != TAB_RECOMMEND_INDEX && position != TAB_FOLLOW_INDEX)
|
||||
communityEditBtn.goneIf(position != 0)
|
||||
when (position) {
|
||||
TAB_FOLLOW_INDEX -> {
|
||||
root.setBackgroundColor(R.color.ui_background.toColor(requireContext()))
|
||||
topBg.translationY = 0F
|
||||
changeNavigationBg()
|
||||
NewLogUtils.logCommunityHomeEvent("click_for_you_tab")
|
||||
SensorsBridge.trackCommunityTopTabSelected("关注")
|
||||
}
|
||||
|
||||
TAB_RECOMMEND_INDEX -> {
|
||||
root.setBackgroundColor(R.color.ui_background.toColor(requireContext()))
|
||||
topBg.translationY = 0F
|
||||
@ -352,7 +275,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
|
||||
TAB_FORUM_INDEX -> {
|
||||
root.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
|
||||
(mFragmentList[2] as ForumFragment).translationY.run {
|
||||
(mFragmentList[1] as ForumFragment).translationY.run {
|
||||
topBg.translationY = -this.toFloat()
|
||||
changeNavigationBg(this)
|
||||
}
|
||||
@ -362,7 +285,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
|
||||
TAB_ACTIVITY_INDEX -> {
|
||||
root.setBackgroundColor(R.color.ui_background.toColor(requireContext()))
|
||||
(mFragmentList[3] as ForumActivityFragment).translationY.run {
|
||||
(mFragmentList[2] as ForumActivityFragment).translationY.run {
|
||||
topBg.translationY = -this.toFloat()
|
||||
changeNavigationBg(this)
|
||||
}
|
||||
@ -374,6 +297,8 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
onPageScrolled = { position, positionOffset, _ ->
|
||||
if (position + 1 != mTabList.size) {
|
||||
(mTabList[position] as TextView).run {
|
||||
layoutParams.width =
|
||||
(DEFAULT_TAB_TEXT_WIDTH + ((1 - positionOffset) * 4F.dip2px())).roundToInt()
|
||||
textSize = (DEFAULT_TAB_TEXT_SIZE + ((1 - positionOffset) * 4)).roundTo(1)
|
||||
setTextColor(
|
||||
ColorUtils.blendARGB(
|
||||
@ -385,6 +310,8 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
}
|
||||
if (mTabList[position + 1] is TextView) {
|
||||
(mTabList[position + 1] as TextView).run {
|
||||
layoutParams.width =
|
||||
(DEFAULT_TAB_TEXT_WIDTH + ((positionOffset) * 4F.dip2px())).roundToInt()
|
||||
textSize = (DEFAULT_TAB_TEXT_SIZE + ((positionOffset) * 4)).roundTo(1)
|
||||
setTextColor(
|
||||
ColorUtils.blendARGB(
|
||||
@ -396,12 +323,13 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
}
|
||||
} else {
|
||||
(mTabList[position + 1] as TabItemCommunityBinding).run {
|
||||
val layoutParams = tabImg.layoutParams
|
||||
layoutParams.width =
|
||||
(DEFAULT_TAB_IMG_WIDTH + 8F.dip2px() * positionOffset).roundToInt()
|
||||
layoutParams.height =
|
||||
((DEFAULT_TAB_IMG_HEIGHT) + 4F.dip2px() * positionOffset).roundToInt()
|
||||
tabImg.layoutParams = layoutParams
|
||||
tabTitle.layoutParams.width =
|
||||
(DEFAULT_TAB_TEXT_WIDTH + ((positionOffset) * 4F.dip2px())).roundToInt()
|
||||
tabTitle.textSize = (DEFAULT_TAB_TEXT_SIZE + ((positionOffset) * 4)).roundTo(1)
|
||||
tabImg.scaleX =
|
||||
(DEFAULT_TAB_IMG_WIDTH + ((positionOffset) * 8)).roundTo(1) / DEFAULT_TAB_IMG_WIDTH
|
||||
tabImg.scaleY =
|
||||
(DEFAULT_TAB_IMG_HEIGHT + ((positionOffset) * 4)).roundTo(1) / DEFAULT_TAB_IMG_HEIGHT
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
tabImg.imageTintList =
|
||||
ColorStateList.valueOf(
|
||||
@ -412,7 +340,6 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,26 +358,20 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
}
|
||||
)
|
||||
}
|
||||
tabLayout.addOnTabSelectedListener(obTabSelectedListener)
|
||||
|
||||
tabLayout.setupWithViewPager(viewPager)
|
||||
indicatorView.run {
|
||||
setupWithTabLayout(tabLayout)
|
||||
setupWithViewPager(viewPager)
|
||||
setIndicatorWidth(18)
|
||||
}
|
||||
|
||||
val selectedPosition = if (UserManager.getInstance().isLoggedIn) {
|
||||
TAB_FOLLOW_INDEX
|
||||
} else {
|
||||
TAB_RECOMMEND_INDEX
|
||||
}
|
||||
for (i in 0 until tabLayout.tabCount) {
|
||||
val tab = tabLayout.getTabAt(i) ?: continue
|
||||
val tabTitle = if (tab.text != null) tab.text.toString() else ""
|
||||
val tabViewBinding = generateTabView(tabTitle, i, selectedPosition)
|
||||
val tabViewBinding = generateTabView(tabTitle, i)
|
||||
tab.customView = tabViewBinding.root
|
||||
tab.view.setPadding(0, 0, 0, 0)
|
||||
}
|
||||
viewPager.setCurrentItem(selectedPosition, false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,6 +394,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
if (index == selectedPosition) {
|
||||
if (positionOffset == 0F) {
|
||||
titleView.setTextColor(TAB_SELECTED_COLOR.toColor(requireContext()))
|
||||
titleView.setTypeface(null, Typeface.NORMAL)
|
||||
titleView.setTypeface(titleView.typeface, Typeface.BOLD)
|
||||
} else if (positionOffset > 0F) {
|
||||
titleView.setTypeface(null, Typeface.NORMAL)
|
||||
@ -506,6 +428,9 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
} else {
|
||||
tabImg.setImageResource(R.drawable.ic_tab_activity_active)
|
||||
}
|
||||
tabTitle.layoutParams.width = 64F.dip2px()
|
||||
tabImg.scaleX = SCALE_TAB_IMG_WIDTH / DEFAULT_TAB_IMG_WIDTH
|
||||
tabImg.scaleY = SCALE_TAB_IMG_HEIGHT / DEFAULT_TAB_IMG_HEIGHT
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -519,22 +444,30 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
tabImg.imageTintList = ColorStateList.valueOf(TAB_DEFAULT_COLOR.toColor(requireContext()))
|
||||
}
|
||||
tabTitle.layoutParams.width = DEFAULT_TAB_TEXT_WIDTH
|
||||
tabImg.scaleX = 1F
|
||||
tabImg.scaleY = 1F
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateTabView(title: String, index: Int, selectedPosition: Int): TabItemCommunityBinding {
|
||||
private fun generateTabView(title: String, index: Int): TabItemCommunityBinding {
|
||||
val binding = TabItemCommunityBinding.inflate(LayoutInflater.from(requireContext()))
|
||||
binding.run {
|
||||
if (index == TAB_ACTIVITY_INDEX) {
|
||||
mTabList.add(binding)
|
||||
tabTitle.visibility = View.GONE
|
||||
tabTitle.visibility = View.INVISIBLE
|
||||
tabImg.visibility = View.VISIBLE
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
tabImg.setImageResource(R.drawable.ic_tab_activity_svg)
|
||||
} else {
|
||||
tabImg.setImageResource(R.drawable.ic_tab_activity_default)
|
||||
}
|
||||
tabTitle.run {
|
||||
text = title
|
||||
// textSize = DEFAULT_TAB_TEXT_SIZE
|
||||
// setTextColor(TAB_DEFAULT_COLOR.toColor(requireContext()))
|
||||
}
|
||||
} else {
|
||||
mTabList.add(tabTitle)
|
||||
tabTitle.visibility = View.VISIBLE
|
||||
@ -543,12 +476,13 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
text = title
|
||||
textSize = DEFAULT_TAB_TEXT_SIZE
|
||||
setTextColor(TAB_DEFAULT_COLOR.toColor(requireContext()))
|
||||
if (index == TAB_FOLLOW_INDEX && selectedPosition == TAB_FOLLOW_INDEX) {
|
||||
mViewModel?.updateFilterResId(R.drawable.ic_follow_arrow_down)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// binding.invisibleTabTitle.run {
|
||||
// text = title
|
||||
// textSize = DEFAULT_TAB_TEXT_SIZE
|
||||
// }
|
||||
return binding
|
||||
}
|
||||
|
||||
@ -636,18 +570,6 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetFollowTab() {
|
||||
mBinding?.tabLayout?.run {
|
||||
if (selectedTabPosition == TAB_FOLLOW_INDEX) {
|
||||
mViewModel?.updateFilterResId(R.drawable.ic_follow_arrow_down)
|
||||
} else {
|
||||
mViewModel?.updateFilterResId(null)
|
||||
}
|
||||
}
|
||||
mBinding?.tabLayout?.removeOnTabSelectedListener(obTabSelectedListener)
|
||||
mBinding?.tabLayout?.addOnTabSelectedListener(obTabSelectedListener)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
@ -674,13 +596,13 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
}
|
||||
|
||||
private fun insertDataToRecommendTab(entity: ArticleEntity) {
|
||||
(mFragmentList[TAB_RECOMMEND_INDEX] as? ForumArticleListFragment)?.insertDataToFirstIndex(entity)
|
||||
(mFragmentList[0] as? ForumArticleListFragment)?.insertDataToFirstIndex(entity)
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
mBinding?.viewPager?.run {
|
||||
if (currentItem == 1) {
|
||||
return (mFragmentList[1] as ForumArticleListFragment).onBackPressed()
|
||||
if (currentItem == 0) {
|
||||
return (mFragmentList[0] as ForumArticleListFragment).onBackPressed()
|
||||
}
|
||||
}
|
||||
return super.onBackPressed()
|
||||
@ -688,10 +610,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(status: EBTypeChange) {
|
||||
val currentPosition = mBinding?.viewPager?.currentItem ?: 0
|
||||
if (currentPosition != TAB_FOLLOW_INDEX && currentPosition != TAB_RECOMMEND_INDEX) {
|
||||
return
|
||||
}
|
||||
if (mBinding?.viewPager?.currentItem != 0) return
|
||||
|
||||
if (status.type == EB_SHOW_QUESTION_BUTTON) {
|
||||
setPutQuestionButtonStatus(View.VISIBLE)
|
||||
@ -717,14 +636,8 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
|
||||
private fun scrollToTop() {
|
||||
if (mFragmentList.isEmpty()) return
|
||||
val currentPosition = mBinding?.viewPager?.currentItem ?: 0
|
||||
val fragment = mFragmentList.getOrNull(currentPosition)
|
||||
if (fragment is IScrollable) {
|
||||
fragment.scrollToTop()
|
||||
}
|
||||
if (currentPosition == TAB_FOLLOW_INDEX || currentPosition == TAB_RECOMMEND_INDEX) {
|
||||
setPutQuestionButtonStatus(View.VISIBLE)
|
||||
}
|
||||
(mFragmentList[0] as ForumArticleListFragment).scrollToTop()
|
||||
setPutQuestionButtonStatus(View.VISIBLE)
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
@ -758,7 +671,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
} else if (!mIsDarkModeOn && navigationBg.drawable != null) {
|
||||
navigationBg.setBackgroundColor(R.color.transparent.toColor(requireContext()))
|
||||
navigationBg.setImageDrawable(null)
|
||||
} else if (viewPager.currentItem == TAB_RECOMMEND_INDEX || viewPager.currentItem == TAB_FOLLOW_INDEX) {
|
||||
} else if (viewPager.currentItem == TAB_RECOMMEND_INDEX) {
|
||||
navigationBg.setBackgroundColor(
|
||||
if (mIsDarkModeOn && y > 0) R.color.ui_surface.toColor(requireContext()) else if (mIsDarkModeOn && y == 0) R.color.ui_background.toColor(
|
||||
requireContext()
|
||||
@ -779,20 +692,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
for (i in 0 until tabCount) {
|
||||
val tab: TabLayout.Tab? = getTabAt(i)
|
||||
if (tab != null) {
|
||||
val tvTitle = tab.customView?.findViewById<TextView>(R.id.tab_title)
|
||||
if (tvTitle != null && tvTitle.visibility == View.VISIBLE) {
|
||||
tvTitle.post {
|
||||
if (i == TAB_FOLLOW_INDEX && tab.isSelected) {
|
||||
val resId = mViewModel?.followFilterStatus?.value
|
||||
if (resId != null) {
|
||||
mViewModel?.updateFilterResId(resId)
|
||||
}
|
||||
}
|
||||
tvTitle.setTextColor(
|
||||
ColorStateList.valueOf(R.color.text_primary.toColor(requireContext()))
|
||||
)
|
||||
}
|
||||
}
|
||||
updateTabStyle(mBinding?.viewPager?.currentItem ?: 0, 0f)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -817,21 +717,7 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
}
|
||||
}
|
||||
}
|
||||
searchIconIv.setImageResource(R.drawable.ic_column_search)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
searchIconIv.imageTintList = ColorStateList.valueOf(R.color.text_primary.toColor(requireContext()))
|
||||
}
|
||||
|
||||
val csl = AppCompatResources.getColorStateList(requireContext(), R.color.text_primary)
|
||||
val filter = SimpleColorFilter(csl.defaultColor)
|
||||
val keyPath = KeyPath("**")
|
||||
val callback = LottieValueCallback<ColorFilter>(filter)
|
||||
videoLottie.addValueCallback(keyPath, LottieProperty.COLOR_FILTER, callback)
|
||||
}
|
||||
|
||||
followFilterPopWindow.onDarkModeChanged()
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun getTopBgView() = mBinding?.topBg
|
||||
@ -839,14 +725,16 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
companion object {
|
||||
var TAB_SELECTED_COLOR: Int = R.color.text_primary
|
||||
var TAB_DEFAULT_COLOR: Int = R.color.community_forum_more
|
||||
var DEFAULT_TAB_TEXT_SIZE = 16F
|
||||
var DEFAULT_TAB_IMG_WIDTH = 34F.dip2px()
|
||||
var DEFAULT_TAB_IMG_HEIGHT = 16F.dip2px()
|
||||
var DEFAULT_TAB_TEXT_SIZE = 18F
|
||||
var DEFAULT_TAB_TEXT_WIDTH = 60F.dip2px()
|
||||
var DEFAULT_TAB_IMG_WIDTH = 34F
|
||||
var DEFAULT_TAB_IMG_HEIGHT = 18F
|
||||
var SCALE_TAB_IMG_WIDTH = 42F
|
||||
var SCALE_TAB_IMG_HEIGHT = 22F
|
||||
const val EB_TAB = "forum_tab"
|
||||
const val TAB_FOLLOW_INDEX = 0
|
||||
const val TAB_RECOMMEND_INDEX = 1
|
||||
const val TAB_FORUM_INDEX = 2
|
||||
const val TAB_ACTIVITY_INDEX = 3
|
||||
const val TAB_RECOMMEND_INDEX = 0
|
||||
const val TAB_FORUM_INDEX = 1
|
||||
const val TAB_ACTIVITY_INDEX = 2
|
||||
const val ARTICLE_REQUEST_CODE = 200
|
||||
const val QUESTION_REQUEST_CODE = 201
|
||||
const val VIDEO_REQUEST_CODE = 202
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
package com.gh.gamecenter.forum.home
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.*
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.feature.entity.ArticleEntity
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.feature.entity.TimeEntity
|
||||
import com.gh.gamecenter.feature.entity.UserEntity
|
||||
import com.gh.gamecenter.livedata.Event
|
||||
import com.gh.gamecenter.common.utils.clearHtmlFormatCompletely
|
||||
import com.gh.gamecenter.common.utils.observableToMain
|
||||
import com.gh.gamecenter.common.utils.removeInsertedContent
|
||||
import com.gh.gamecenter.common.utils.removeVideoContent
|
||||
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
|
||||
import com.gh.gamecenter.feature.entity.ArticleEntity
|
||||
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
|
||||
import com.gh.gamecenter.feature.entity.TimeEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.feature.entity.UserEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
|
||||
class CommunityHomeViewModel(application: Application) : AndroidViewModel(application) {
|
||||
@ -132,64 +131,4 @@ class CommunityHomeViewModel(application: Application) : AndroidViewModel(applic
|
||||
|
||||
return articleEntity
|
||||
}
|
||||
|
||||
private val _hasFollowedUsers = MutableLiveData<Boolean>()
|
||||
val hasFollowedUser: LiveData<Boolean> = _hasFollowedUsers
|
||||
fun updateHasFollowUser(show: Boolean) {
|
||||
_hasFollowedUsers.value = show
|
||||
}
|
||||
|
||||
private val filterDrawableResId = MutableLiveData<Int?>()
|
||||
fun updateFilterResId(resId: Int?) {
|
||||
filterDrawableResId.value = resId
|
||||
}
|
||||
|
||||
val followFilterStatus = MediatorLiveData<Int?>().apply {
|
||||
addSource(hasFollowedUser) {
|
||||
if (it) {
|
||||
value = filterDrawableResId.value
|
||||
} else {
|
||||
value = null
|
||||
}
|
||||
}
|
||||
|
||||
addSource(filterDrawableResId) { resId ->
|
||||
// 当 hasFollowedUser.value == null 时,不需要调用setValue
|
||||
if (hasFollowedUser.value == true) {
|
||||
value = resId
|
||||
} else if (hasFollowedUser.value == false) {
|
||||
value = null
|
||||
}
|
||||
when {
|
||||
resId == null ||
|
||||
hasFollowedUser.value == false -> {
|
||||
// 当resId == null 时,表示已切换到别的tab 直接setValue
|
||||
// 当 resId != null && hasFollowedUser,value 为false时,说明关注页数据已加载完毕,并且没有关注任何用户,直接setValue
|
||||
value = null
|
||||
}
|
||||
|
||||
hasFollowedUser.value == true -> {
|
||||
// 当 resId != null 且 有关注用户,显示当前 resId
|
||||
value = resId
|
||||
}
|
||||
|
||||
else -> {
|
||||
// do Nothing 当resId != null ,但是hasFollowedUser.value == null,说明关注页数据正在loading,等待,无需setValue
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val _filterFollowedAction = MutableLiveData<Event<Int>>()
|
||||
val filterFollowedAction: LiveData<Event<Int>> = _filterFollowedAction
|
||||
fun filterFollowed(position: Int) {
|
||||
val filterName = when (position) {
|
||||
0 -> "全部"
|
||||
1 -> "关注的人"
|
||||
else -> "关注的游戏"
|
||||
}
|
||||
SensorsBridge.trackFollowTabFilterOptionClick(filterName)
|
||||
_filterFollowedAction.value = Event(position)
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,6 @@ import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.SpacingItemDecoration
|
||||
import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.FragmentForumActivityBinding
|
||||
import com.gh.gamecenter.databinding.LayoutForumActivityCategoryItemBinding
|
||||
@ -21,7 +20,7 @@ import com.gh.gamecenter.entity.ForumActivityCategoryEntity
|
||||
import com.gh.gamecenter.entity.ForumActivityEntity
|
||||
import com.google.android.flexbox.FlexboxLayout
|
||||
|
||||
class ForumActivityFragment : LazyListFragment<ForumActivityEntity, ForumActivityViewModel>(), IScrollable {
|
||||
class ForumActivityFragment : LazyListFragment<ForumActivityEntity, ForumActivityViewModel>() {
|
||||
|
||||
private var mBinding: FragmentForumActivityBinding? = null
|
||||
private var mAdapter: ForumActivityAdapter? = null
|
||||
@ -201,12 +200,4 @@ class ForumActivityFragment : LazyListFragment<ForumActivityEntity, ForumActivit
|
||||
}
|
||||
changeCategoryBg()
|
||||
}
|
||||
|
||||
override fun scrollToTop() {
|
||||
mBinding?.listRv?.let {
|
||||
if (it.visibility == View.VISIBLE) {
|
||||
it.scrollToPosition(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,18 +6,13 @@ import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.view.View
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.common.view.ImageContainerView
|
||||
import com.gh.common.view.ImageContainerView.Companion.toImageContainerData
|
||||
import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.entity.AdditionalParamsEntity
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
@ -33,7 +28,6 @@ import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.feature.entity.ArticleEntity
|
||||
import com.gh.gamecenter.feature.entity.CommunityItemData
|
||||
import com.gh.gamecenter.forum.home.ArticleItemVideoView.Companion.toArticleVideoData
|
||||
import com.gh.gamecenter.forum.search.CommunitySearchEventListener
|
||||
import com.gh.gamecenter.forum.search.CommunitySearchEventListener.Companion.SEARCH_BUTTON_COMMENT
|
||||
import com.gh.gamecenter.forum.search.CommunitySearchEventListener.Companion.SEARCH_BUTTON_DISLIKE
|
||||
@ -48,7 +42,6 @@ import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
|
||||
import com.gh.gamecenter.qa.questions.invite.QuestionsInviteActivity
|
||||
import com.gh.gamecenter.qa.questions.newdetail.NewQuestionDetailActivity
|
||||
import com.gh.gamecenter.qa.video.detail.ForumVideoDetailActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
|
||||
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
|
||||
import com.shuyu.gsyvideoplayer.utils.OrientationUtils
|
||||
@ -155,46 +148,15 @@ class ForumArticleAskItemViewHolder(
|
||||
}
|
||||
}
|
||||
|
||||
binding.imageContainer.bindData(
|
||||
entity.toImageContainerData(),
|
||||
object : ImageContainerView.OnImageContainerEventListener {
|
||||
override fun onImageClick(
|
||||
images: List<String>,
|
||||
position: Int,
|
||||
imageViewList: ArrayList<SimpleDraweeView>,
|
||||
) {
|
||||
|
||||
clickListener?.onItemChildClick(
|
||||
entity.id,
|
||||
entity.type,
|
||||
htmlToString(entity.questions.title),
|
||||
position,
|
||||
SEARCH_BUTTON_VIEW_IMAGE,
|
||||
)
|
||||
|
||||
if (entity.communityId.isNullOrEmpty()) {
|
||||
entity.communityId = entity.bbs.id
|
||||
}
|
||||
val intent = ImageViewerActivity.getIntent(
|
||||
itemView.context, entity.images as ArrayList<String>, position, imageViewList,
|
||||
if (entity.type == "community_article") entity else null, entrance, true,
|
||||
)
|
||||
itemView.context.startActivity(intent)
|
||||
}
|
||||
|
||||
override fun onVideoCLick(videoId: String) {
|
||||
DirectUtils.directToVideoDetail(
|
||||
itemView.context,
|
||||
videoId,
|
||||
VideoDetailContainerViewModel.Location.VIDEO_HOT.value,
|
||||
showComment = false,
|
||||
entrance = entrance,
|
||||
path = path
|
||||
)
|
||||
}
|
||||
|
||||
},
|
||||
)
|
||||
binding.imageContainer.bindData(entity, entrance, path) {
|
||||
clickListener?.onItemChildClick(
|
||||
entity.id,
|
||||
entity.type,
|
||||
htmlToString(entity.questions.title),
|
||||
position,
|
||||
SEARCH_BUTTON_VIEW_IMAGE
|
||||
)
|
||||
}
|
||||
bindVideoData(entity.transformForumVideoEntity())
|
||||
|
||||
val user = entity.user
|
||||
@ -353,13 +315,34 @@ class ForumArticleAskItemViewHolder(
|
||||
.setVideoAllCallBack(object : GSYSampleCallBack() {
|
||||
override fun onQuitFullscreen(url: String?, vararg objects: Any) {
|
||||
orientationUtils.backToProtVideo()
|
||||
visibleView.uploadVideoStreamingPlaying("退出全屏")
|
||||
}
|
||||
})
|
||||
.build(visibleView)
|
||||
visibleView.updateVideoData(
|
||||
entity.toArticleVideoData(),
|
||||
AnswerArticleVideoViewEventHelper(entity, orientationUtils)
|
||||
)
|
||||
visibleView.run {
|
||||
updateVideoData(entity)
|
||||
updateThumb(entity.poster)
|
||||
updateDurationTv(entity.duration)
|
||||
|
||||
setVideoStatus(entity.status)
|
||||
|
||||
fullscreenButton.setOnClickListener {
|
||||
val horizontalVideoView =
|
||||
startWindowFullscreen(itemView.context, true, true) as? ArticleItemVideoView
|
||||
if (horizontalVideoView == null) {
|
||||
toastInInternalRelease("全屏失败,请向技术人员提供具体的操作步骤")
|
||||
return@setOnClickListener
|
||||
}
|
||||
orientationUtils.resolveByClick()
|
||||
horizontalVideoView.uuid = uuid
|
||||
horizontalVideoView.updateVideoData(entity)
|
||||
horizontalVideoView.updateThumb(entity.poster)
|
||||
horizontalVideoView.violenceUpdateMuteStatus()
|
||||
horizontalVideoView.setFullViewStatus()
|
||||
uploadVideoStreamingPlaying("开始播放")
|
||||
uploadVideoStreamingPlaying("点击全屏")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -399,13 +382,7 @@ class ForumArticleAskItemViewHolder(
|
||||
SEARCH_BUTTON_VIEW_FORUM_DETAIL
|
||||
)
|
||||
MtaHelper.onEvent(getEventId(entrance), getKey(entrance), entity.community.name)
|
||||
itemView.context.startActivity(
|
||||
ForumDetailActivity.getIntent(
|
||||
itemView.context,
|
||||
entity.community.id,
|
||||
entrance
|
||||
)
|
||||
)
|
||||
itemView.context.startActivity(ForumDetailActivity.getIntent(itemView.context, entity.community.id, entrance))
|
||||
LogUtils.uploadAccessToBbs(entity.community.id, "文章外所属论坛")
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,6 @@ import com.gh.gamecenter.common.base.fragment.LazyFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.GridSpacingItemColorDecoration
|
||||
import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
import com.gh.gamecenter.databinding.ForumBannerIndicatorItemBinding
|
||||
import com.gh.gamecenter.databinding.FragmentForumBinding
|
||||
import com.gh.gamecenter.entity.ForumBannerEntity
|
||||
@ -35,7 +34,7 @@ import com.halo.assistant.HaloApp
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class ForumFragment : LazyFragment(), SwipeRefreshLayout.OnRefreshListener, IScrollable {
|
||||
class ForumFragment : LazyFragment(), SwipeRefreshLayout.OnRefreshListener {
|
||||
|
||||
private var mBinding: FragmentForumBinding? = null
|
||||
private var mViewModel: ForumViewModel? = null
|
||||
@ -514,12 +513,4 @@ class ForumFragment : LazyFragment(), SwipeRefreshLayout.OnRefreshListener, IScr
|
||||
super.onDarkModeChanged()
|
||||
mBinding?.hotForumRv?.adapter?.let { it.notifyItemRangeChanged(0, it.itemCount) }
|
||||
}
|
||||
|
||||
override fun scrollToTop() {
|
||||
mBinding?.contentContainer?.let {
|
||||
if (it.visibility == View.VISIBLE) {
|
||||
it.scrollTo(0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package com.gh.gamecenter.forum.home.follow
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.forum.home.follow.fragment.AllFollowedFragment
|
||||
|
||||
class AllFollowedActivity : BaseActivity() {
|
||||
override fun getLayoutId(): Int = R.layout.activity_all_followed
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
DisplayUtils.setLightStatusBar(this, true)
|
||||
setStatusBarColor(Color.TRANSPARENT)
|
||||
val containerFragment = supportFragmentManager.findFragmentByTag(AllFollowedFragment::class.java.name)
|
||||
?: AllFollowedFragment().with(intent.extras)
|
||||
// 若 placeholder 外层为 RelativeLayout 的话,会出现莫名的偏移
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.layout_activity_content, containerFragment, AllFollowedFragment::class.java.name)
|
||||
.commitAllowingStateLoss()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun getIntent(context: Context): Intent = Intent(context, AllFollowedActivity::class.java)
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package com.gh.gamecenter.forum.home.follow
|
||||
|
||||
import com.gh.gamecenter.entity.FollowUserEntity
|
||||
|
||||
abstract class AllFollowedItem() {
|
||||
|
||||
abstract val itemType: Int
|
||||
|
||||
open fun areItemsTheSame(other: AllFollowedItem): Boolean {
|
||||
return other.itemType == itemType && doAreItemsTheSame(other)
|
||||
}
|
||||
|
||||
open fun areContentsTheSame(other: AllFollowedItem): Boolean {
|
||||
return other.itemType == itemType && doAreContentsTheSame(other)
|
||||
}
|
||||
|
||||
open fun doAreItemsTheSame(other: AllFollowedItem): Boolean = true
|
||||
|
||||
open fun doAreContentsTheSame(other: AllFollowedItem): Boolean = this == other
|
||||
|
||||
companion object {
|
||||
|
||||
const val ALL_FOLLOWED_ITEM_TYPE_NO_TOP = 0
|
||||
const val ALL_FOLLOWED_ITEM_TYPE_NORMAL = 1
|
||||
const val ALL_FOLLOWED_ITEM_TYPE_MY_FOLLOW_HEADER = 2
|
||||
}
|
||||
}
|
||||
|
||||
class AllFollowedNoTopItem : AllFollowedItem() {
|
||||
override val itemType: Int
|
||||
get() = ALL_FOLLOWED_ITEM_TYPE_NO_TOP
|
||||
|
||||
}
|
||||
|
||||
data class AllFollowedMyFollowedHeaderItem(val isTop: Boolean) : AllFollowedItem() {
|
||||
override val itemType: Int
|
||||
get() = ALL_FOLLOWED_ITEM_TYPE_MY_FOLLOW_HEADER
|
||||
}
|
||||
|
||||
data class AllFollowedNormalItem(
|
||||
val data: FollowUserEntity,
|
||||
var isTop: Boolean
|
||||
) : AllFollowedItem() {
|
||||
override val itemType: Int
|
||||
get() = ALL_FOLLOWED_ITEM_TYPE_NORMAL
|
||||
|
||||
override fun doAreItemsTheSame(other: AllFollowedItem): Boolean {
|
||||
return other is AllFollowedNormalItem && data.id == other.data.id
|
||||
}
|
||||
}
|
||||
@ -1,306 +0,0 @@
|
||||
package com.gh.gamecenter.forum.home.follow
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.ActivityResultRegistry
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
import androidx.activity.result.contract.ActivityResultContracts.GetContent
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.common.util.SyncDataBetweenPageHelper
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.PersonalHistoryEntity
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.feature.entity.ArticleEntity
|
||||
import com.gh.gamecenter.feature.entity.CommentEntity
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.personalhome.home.UserHistoryFragment
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
|
||||
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
|
||||
import com.gh.gamecenter.qa.questions.newdetail.NewQuestionDetailActivity
|
||||
import com.gh.gamecenter.qa.video.detail.ForumVideoDetailActivity
|
||||
|
||||
class FollowActivityResultLauncher(
|
||||
private val registry: ActivityResultRegistry,
|
||||
private val onResultListener: OnResultListener
|
||||
) : DefaultLifecycleObserver {
|
||||
|
||||
private lateinit var articleDetailLauncher: ActivityResultLauncher<LauncherDestination>
|
||||
|
||||
private lateinit var commentEntityLauncher: ActivityResultLauncher<LauncherDestination>
|
||||
|
||||
private lateinit var questionsDetailLauncher: ActivityResultLauncher<LauncherDestination>
|
||||
|
||||
private lateinit var forumVideoLauncher: ActivityResultLauncher<LauncherDestination>
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
super.onCreate(owner)
|
||||
articleDetailLauncher = registry.register(
|
||||
KEY_ARTICLE_DETAIL_LAUNCHER,
|
||||
owner,
|
||||
object : ActivityResultContract<LauncherDestination, ArticleDetailResult?>() {
|
||||
override fun createIntent(context: Context, input: LauncherDestination): Intent {
|
||||
val intent =
|
||||
if (input.historyEntity != null) {
|
||||
ArticleDetailActivity.getIntent(
|
||||
context,
|
||||
input.historyEntity.community,
|
||||
input.historyEntity.id,
|
||||
"",
|
||||
UserHistoryFragment.PATH_USER_QUESTION_ANSWER,
|
||||
sourceEntrance = "关注-用户动态"
|
||||
)
|
||||
} else {
|
||||
ArticleDetailActivity.getIntent(
|
||||
context,
|
||||
CommunityEntity(input.answerEntity?.bbs?.id ?: ""),
|
||||
input.answerEntity?.id ?: "",
|
||||
"",
|
||||
"",
|
||||
sourceEntrance = "关注-论坛动态",
|
||||
)
|
||||
}
|
||||
intent.putExtra(SyncDataBetweenPageHelper.DATA_POSITION_TAG, input.position)
|
||||
intent.putExtra(SyncDataBetweenPageHelper.REQUEST_CODE_TAG, 101)
|
||||
return intent
|
||||
}
|
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): ArticleDetailResult? {
|
||||
val position = intent?.getIntExtra(SyncDataBetweenPageHelper.DATA_POSITION_TAG, -1)
|
||||
val resultData =
|
||||
intent?.getParcelableExtra<ArticleDetailEntity>(ArticleDetailEntity::class.java.simpleName)
|
||||
if (position != null && resultData != null) {
|
||||
return ArticleDetailResult(position, resultData)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
})
|
||||
{
|
||||
it?.run {
|
||||
onResultListener.onArticleDetailResult(position, articleDetailEntity)
|
||||
}
|
||||
}
|
||||
|
||||
commentEntityLauncher = registry.register(
|
||||
KEY_COMMENT_LAUNCHER,
|
||||
owner,
|
||||
object : ActivityResultContract<LauncherDestination, CommentResult?>() {
|
||||
override fun createIntent(context: Context, input: LauncherDestination): Intent {
|
||||
val intent = NewQuestionDetailActivity.getSpecifiedCommentIntent(
|
||||
context,
|
||||
input.historyEntity?.question?.id ?: "",
|
||||
input.historyEntity?.id ?: "",
|
||||
"",
|
||||
UserHistoryFragment.PATH_USER_QUESTION_ANSWER,
|
||||
sourceEntrance = "关注-动态"
|
||||
)
|
||||
intent.putExtra(SyncDataBetweenPageHelper.DATA_POSITION_TAG, input.position)
|
||||
intent.putExtra(SyncDataBetweenPageHelper.REQUEST_CODE_TAG, 102)
|
||||
return intent
|
||||
}
|
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): CommentResult? {
|
||||
val position = intent?.getIntExtra(SyncDataBetweenPageHelper.DATA_POSITION_TAG, -1)
|
||||
val commentEntity = intent?.getParcelableExtra<CommentEntity>(CommentEntity::class.java.simpleName)
|
||||
if (position != null && commentEntity != null) {
|
||||
return CommentResult(position, commentEntity)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
})
|
||||
{
|
||||
it?.run {
|
||||
onResultListener.onCommentResult(position, commentEntity)
|
||||
}
|
||||
}
|
||||
|
||||
questionsDetailLauncher = registry.register(
|
||||
KEY_QUESTION_DETAIL_LAUNCHER,
|
||||
owner,
|
||||
object : ActivityResultContract<LauncherDestination, QuestionsDetailResult?>() {
|
||||
override fun createIntent(context: Context, input: LauncherDestination): Intent {
|
||||
val intent = if (input.historyEntity != null) {
|
||||
NewQuestionDetailActivity.getIntent(
|
||||
context,
|
||||
input.historyEntity.id,
|
||||
"",
|
||||
UserHistoryFragment.PATH_USER_QUESTION_ANSWER
|
||||
)
|
||||
} else {
|
||||
if (input.answerEntity?.type == "question") {
|
||||
NewQuestionDetailActivity.getIntent(
|
||||
context, input.answerEntity.id,
|
||||
"",
|
||||
"",
|
||||
sourceEntrance = "关注-论坛动态"
|
||||
)
|
||||
} else {
|
||||
NewQuestionDetailActivity.getCommentIntent(
|
||||
context,
|
||||
input.answerEntity?.questions?.id ?: "",
|
||||
input.answerEntity?.answerId ?: "",
|
||||
"",
|
||||
""
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
intent.putExtra(SyncDataBetweenPageHelper.DATA_POSITION_TAG, input.position)
|
||||
intent.putExtra(SyncDataBetweenPageHelper.REQUEST_CODE_TAG, 103)
|
||||
return intent
|
||||
}
|
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): QuestionsDetailResult? {
|
||||
val position = intent?.getIntExtra(SyncDataBetweenPageHelper.DATA_POSITION_TAG, -1)
|
||||
val questionsDetailEntity =
|
||||
intent?.getParcelableExtra<QuestionsDetailEntity>(QuestionsDetailEntity::class.java.simpleName)
|
||||
return if (position != null && questionsDetailEntity != null) {
|
||||
QuestionsDetailResult(position, questionsDetailEntity)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
) {
|
||||
it?.run {
|
||||
onResultListener.onQuestionsDetailResult(position, questionsDetailEntity)
|
||||
}
|
||||
}
|
||||
|
||||
forumVideoLauncher = registry.register(
|
||||
KEY_FORUM_VIDEO_LAUNCHER,
|
||||
owner,
|
||||
object : ActivityResultContract<LauncherDestination, ForumVideoResult?>() {
|
||||
override fun createIntent(context: Context, input: LauncherDestination): Intent {
|
||||
val intent = if (input.historyEntity != null) {
|
||||
ForumVideoDetailActivity.getIntent(
|
||||
context,
|
||||
input.historyEntity.id,
|
||||
input.historyEntity.community.id,
|
||||
sourceEntrance = "关注-个人动态"
|
||||
)
|
||||
} else {
|
||||
ForumVideoDetailActivity.getIntent(
|
||||
context,
|
||||
input.answerEntity?.id ?: "",
|
||||
input.answerEntity?.bbs?.id ?: "",
|
||||
"关注-论坛动态"
|
||||
)
|
||||
}
|
||||
|
||||
intent.putExtra(SyncDataBetweenPageHelper.DATA_POSITION_TAG, input.position)
|
||||
intent.putExtra(SyncDataBetweenPageHelper.REQUEST_CODE_TAG, 104)
|
||||
return intent
|
||||
}
|
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): ForumVideoResult? {
|
||||
val position = intent?.getIntExtra(SyncDataBetweenPageHelper.DATA_POSITION_TAG, -1)
|
||||
val forumVideoEntity =
|
||||
intent?.getParcelableExtra<ForumVideoEntity>(ForumVideoEntity::class.java.simpleName)
|
||||
return if (position != null && forumVideoEntity != null) {
|
||||
ForumVideoResult(position, forumVideoEntity)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
{
|
||||
it?.run {
|
||||
onResultListener.onForumVideoResult(position, forumVideoEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onPersonItemClick(position: Int, entity: PersonalHistoryEntity) {
|
||||
when {
|
||||
entity.type == "community_article"
|
||||
|| entity.type == "community_article_vote" -> {
|
||||
articleDetailLauncher.launch(LauncherDestination(position, historyEntity = entity))
|
||||
}
|
||||
|
||||
entity.type.contains("video") -> {
|
||||
forumVideoLauncher.launch(LauncherDestination(position, historyEntity = entity))
|
||||
}
|
||||
|
||||
entity.type.contains("question") -> {
|
||||
questionsDetailLauncher.launch(LauncherDestination(position, historyEntity = entity))
|
||||
}
|
||||
|
||||
else -> {
|
||||
commentEntityLauncher.launch(LauncherDestination(position, historyEntity = entity))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onBbsItemClick(position: Int, answerEntity: AnswerEntity) {
|
||||
when (answerEntity.type) {
|
||||
"community_article" -> {
|
||||
articleDetailLauncher.launch(LauncherDestination(position, answerEntity = answerEntity))
|
||||
}
|
||||
|
||||
"video" -> {
|
||||
forumVideoLauncher.launch(LauncherDestination(position, answerEntity = answerEntity))
|
||||
}
|
||||
|
||||
"question" -> {
|
||||
questionsDetailLauncher.launch(LauncherDestination(position, answerEntity = answerEntity))
|
||||
}
|
||||
|
||||
"answer" -> {
|
||||
questionsDetailLauncher.launch(LauncherDestination(position, answerEntity = answerEntity))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val KEY_ARTICLE_DETAIL_LAUNCHER = "key_article_detail_launcher"
|
||||
private const val KEY_COMMENT_LAUNCHER = "key_comment_launcher"
|
||||
private const val KEY_QUESTION_DETAIL_LAUNCHER = "key_question_detail_launcher"
|
||||
private const val KEY_FORUM_VIDEO_LAUNCHER = "KEY_forum_video_LAUNCHER"
|
||||
}
|
||||
|
||||
private data class LauncherDestination(
|
||||
val position: Int,
|
||||
val historyEntity: PersonalHistoryEntity? = null,
|
||||
val answerEntity: AnswerEntity? = null
|
||||
)
|
||||
|
||||
private data class ArticleDetailResult(
|
||||
val position: Int,
|
||||
val articleDetailEntity: ArticleDetailEntity
|
||||
)
|
||||
|
||||
private data class CommentResult(
|
||||
val position: Int,
|
||||
val commentEntity: CommentEntity
|
||||
)
|
||||
|
||||
private data class QuestionsDetailResult(
|
||||
val position: Int,
|
||||
val questionsDetailEntity: QuestionsDetailEntity
|
||||
)
|
||||
|
||||
private data class ForumVideoResult(
|
||||
val position: Int,
|
||||
val forumVideoEntity: ForumVideoEntity
|
||||
)
|
||||
|
||||
interface OnResultListener {
|
||||
|
||||
fun onArticleDetailResult(position: Int, articleDetailEntity: ArticleDetailEntity)
|
||||
|
||||
fun onCommentResult(position: Int, commentEntity: CommentEntity)
|
||||
|
||||
fun onQuestionsDetailResult(position: Int, questionsDetailEntity: QuestionsDetailEntity)
|
||||
|
||||
fun onForumVideoResult(position: Int, forumVideoEntity: ForumVideoEntity)
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
package com.gh.gamecenter.forum.home.follow
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Path
|
||||
import android.util.AttributeSet
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
|
||||
class FollowClippedView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : androidx.appcompat.widget.AppCompatImageView(context, attrs, defStyleAttr) {
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
val path = Path()
|
||||
path.addRect(
|
||||
0f,
|
||||
0f,
|
||||
width.toFloat(),
|
||||
(DisplayUtils.getStatusBarHeight(resources) + 52f.dip2px() + 56f.dip2px()).toFloat(),
|
||||
Path.Direction.CW
|
||||
)
|
||||
canvas.clipPath(path)
|
||||
|
||||
canvas.drawColor(ContextCompat.getColor(context, R.color.ui_background))
|
||||
super.onDraw(canvas)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user