Merge remote-tracking branch 'origin/dev' into dev-5.31.0
# Conflicts: # app/src/main/java/com/gh/gamecenter/fragment/MainWrapperFragment.java # app/src/main/java/com/gh/gamecenter/game/horizontal/GameHorizontalAdapter.kt
This commit is contained in:
@ -348,6 +348,9 @@ dependencies {
|
||||
implementation(project(':feature:csj_ad'))
|
||||
// implementation(project(':feature:beizi_startup_ad'))
|
||||
implementation(project(':feature:xapk-installer'))
|
||||
implementation(project(':feature:qq_game')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
}
|
||||
|
||||
File propFile = file('sign.properties')
|
||||
|
||||
@ -78,7 +78,11 @@
|
||||
androidx.constraintlayout.compose,
|
||||
androidx.compose.ui.test.manifest,
|
||||
com.bytedance.sdk.openadsdk,
|
||||
androidx.compose.ui.tooling.preview" />
|
||||
androidx.compose.ui.tooling.preview,
|
||||
com.tencent.qqmini,
|
||||
com.tencent.qqmini.minigame.external,
|
||||
com.tencent.qqmini.minigame.opensdk,
|
||||
com.tencent.qqmini.union.ad" />
|
||||
|
||||
<!-- 去掉 SDK 一些流氓权限 -->
|
||||
<uses-permission
|
||||
@ -741,6 +745,18 @@
|
||||
android:name="com.gh.gamecenter.gamecollection.hotlist.GameCollectionHotListActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qgame.QGameHomeWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qgame.QGameSearchActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qgame.QGameSubjectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
|
||||
<!-- <activity-->
|
||||
<!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"-->
|
||||
|
||||
@ -1,18 +1,20 @@
|
||||
package com.gh.base
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.DownloadManagerActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils.getBoolean
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
@ -58,6 +60,7 @@ abstract class DownloadToolbarActivity : ToolBarActivity() {
|
||||
}
|
||||
val downloadMenuView = mActionMenuView.menu.findItem(R.id.menu_download).actionView
|
||||
mDownloadCountHint = downloadMenuView?.findViewById(R.id.menu_download_count_hint)
|
||||
mDownloadCountHint?.typeface = Typeface.createFromAsset(assets, "fonts/d_din_bold_only_number.ttf")
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||
@ -74,19 +77,27 @@ abstract class DownloadToolbarActivity : ToolBarActivity() {
|
||||
if (mDownloadCountHint == null) return
|
||||
val count = DownloadManager.getInstance().getDownloadOrUpdateCount(updateList)
|
||||
if (count != null) {
|
||||
mDownloadCountHint!!.visibility = View.VISIBLE
|
||||
mDownloadCountHint!!.text = count
|
||||
val params = mDownloadCountHint!!.layoutParams
|
||||
if (TextUtils.isEmpty(count)) {
|
||||
params.width = DisplayUtils.dip2px(6f)
|
||||
params.height = DisplayUtils.dip2px(6f)
|
||||
} else {
|
||||
params.width = DisplayUtils.dip2px(12f)
|
||||
params.height = DisplayUtils.dip2px(12f)
|
||||
}
|
||||
mDownloadCountHint!!.layoutParams = params
|
||||
mDownloadCountHint?.visibility = View.VISIBLE
|
||||
mDownloadCountHint?.text = count
|
||||
val params = mDownloadCountHint?.layoutParams
|
||||
params?.width = if (count.isEmpty()) 6F.dip2px() else ConstraintLayout.LayoutParams.WRAP_CONTENT
|
||||
params?.height = if (count.isEmpty()) 6F.dip2px() else 14F.dip2px()
|
||||
(params as? ViewGroup.MarginLayoutParams)?.setMargins(
|
||||
0,
|
||||
if (count.isEmpty()) 0 else (-4F).dip2px(),
|
||||
if (count.isEmpty()) (-4F).dip2px() else (-8F).dip2px(),
|
||||
0
|
||||
)
|
||||
mDownloadCountHint?.setPadding(
|
||||
if (count.isEmpty()) 0 else 4F.dip2px(),
|
||||
0,
|
||||
if (count.isEmpty()) 0 else 4F.dip2px(),
|
||||
0
|
||||
)
|
||||
mDownloadCountHint?.minWidth = if (count.isEmpty()) 0 else 14F.dip2px()
|
||||
mDownloadCountHint?.layoutParams = params
|
||||
} else {
|
||||
mDownloadCountHint!!.visibility = View.GONE
|
||||
mDownloadCountHint?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,10 @@ class AppProviderImpl : IAppProvider {
|
||||
return HaloApp.getInstance().getString(R.string.app_name)
|
||||
}
|
||||
|
||||
override fun getAppVersion(): String {
|
||||
return BuildConfig.VERSION_NAME
|
||||
}
|
||||
|
||||
override fun getGid(): String {
|
||||
return HaloApp.getInstance().gid ?: ""
|
||||
}
|
||||
|
||||
@ -115,6 +115,10 @@ class DirectProviderImpl : IDirectProvider {
|
||||
DirectUtils.directToWinOrderDetail(context, orderId, activityId)
|
||||
}
|
||||
|
||||
override fun directToQGame(context: Context) {
|
||||
return DirectUtils.directToQGameHome(context)
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
@ -29,9 +30,9 @@ import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts.*
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.*
|
||||
import com.gh.gamecenter.common.entity.Display
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.provider.IQGameProvider
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.discovery.DiscoveryActivity
|
||||
@ -71,6 +72,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
|
||||
@ -94,7 +98,6 @@ import org.greenrobot.eventbus.EventBus
|
||||
import retrofit2.HttpException
|
||||
import java.net.URLEncoder
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
@ -422,6 +425,8 @@ object DirectUtils {
|
||||
)
|
||||
)
|
||||
|
||||
"qq_mini_game_column" -> directToQGameHome(context)
|
||||
|
||||
"" -> {
|
||||
// do nothing
|
||||
}
|
||||
@ -711,11 +716,12 @@ object DirectUtils {
|
||||
id: String,
|
||||
subjectName: String? = "",
|
||||
entrance: String? = null,
|
||||
exposureEvent: ExposureEvent? = null
|
||||
exposureEvent: ExposureEvent? = null,
|
||||
isQQMiniGame: Boolean = false,
|
||||
) {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
val subjectData = SubjectData(subjectId = id, subjectName = subjectName, isOrder = false)
|
||||
val subjectData = 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)
|
||||
@ -2024,6 +2030,61 @@ object DirectUtils {
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToQGameHome(context: Context) {
|
||||
context.startActivity(QGameHomeWrapperActivity.getIntent(context))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToQGameSearch(
|
||||
context: Context,
|
||||
hint: String,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
context.startActivity(QGameSearchActivity.getIntent(context, hint, sourceEntrance))
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun directToQGameById(
|
||||
activity: Activity,
|
||||
qqGameId: String
|
||||
) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
ToastUtils.toast("该游戏仅支持安卓5.0及以上设备")
|
||||
return
|
||||
}
|
||||
|
||||
CheckLoginUtils.checkLogin(
|
||||
activity, null, true, "QQ小游戏-秒开"
|
||||
) {
|
||||
val userToken = UserManager.getInstance().token
|
||||
val userId = UserManager.getInstance().userId
|
||||
val userName = UserManager.getInstance().userInfoEntity?.name ?: "unknown"
|
||||
|
||||
val qGameProvider = ARouter
|
||||
.getInstance()
|
||||
.build(RouteConsts.provider.qGame)
|
||||
.navigation() as IQGameProvider<*>
|
||||
qGameProvider.setLoginInfo(activity, userId, userName, userToken)
|
||||
qGameProvider.launchGame(activity, qqGameId) { _, _ ->
|
||||
RetrofitManager
|
||||
.getInstance()
|
||||
.newApi
|
||||
.postQGamePlay(qqGameId, userId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
QGameViewModel.notifyQGameSubjectUpdate() // 通知QQ小游戏首页列表刷新
|
||||
},
|
||||
{}
|
||||
) // 秒玩记录上报
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToMessageCenter(defaultTabIndex: Int) {
|
||||
ARouter.getInstance().build(RouteConsts.activity.messageWrapperActivity)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Message
|
||||
import android.text.TextUtils
|
||||
@ -7,6 +8,7 @@ import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.collection.ArrayMap
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.common.chain.*
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.dialog.DeviceRemindDialog
|
||||
@ -26,19 +28,24 @@ 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
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.provider.IQGameProvider
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
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.feature.view.DownloadButton
|
||||
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.teenagermode.TeenagerModeActivity
|
||||
import com.gh.vspace.VHelper
|
||||
import com.lightgame.download.DownloadConfig
|
||||
@ -237,6 +244,24 @@ object DownloadItemUtils {
|
||||
}
|
||||
return
|
||||
}
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
val isQQMiniGameOffShelve = gameEntity.qqMiniGameAppStatus == 1 // QQ小游戏是否下架
|
||||
if (isQQMiniGameOffShelve) {
|
||||
downloadBtn.apply {
|
||||
isClickable = false
|
||||
text = context.getString(R.string.off_shelve)
|
||||
buttonStyle = DownloadButton.ButtonStyle.NONE
|
||||
}
|
||||
} else {
|
||||
downloadBtn.apply {
|
||||
isClickable = true
|
||||
setBackgroundResource(R.drawable.download_button_normal_style)
|
||||
setTextColor(R.color.white.toColor(context))
|
||||
text = context.getString(R.string.quick_play)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
if (gameEntity.getApk().isEmpty() || gameEntity.downloadOffStatus != null) {
|
||||
val h5LinkEntity = gameEntity.h5Link
|
||||
val offStatus = gameEntity.downloadOffStatus
|
||||
@ -747,6 +772,15 @@ object DownloadItemUtils {
|
||||
}
|
||||
return
|
||||
}
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
downloadBtn.setOnClickListener {
|
||||
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
|
||||
GlobalActivityManager.currentActivity?.let { activity ->
|
||||
DirectUtils.directToQGameById(activity, gameEntity.qqMiniGameAppId)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
if (gameEntity.getApk().size == 0 && gameEntity.h5Link != null) {
|
||||
downloadBtn.setOnClickListener {
|
||||
allStateClickCallback?.onCallback()
|
||||
|
||||
@ -2400,4 +2400,15 @@ 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)
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
@ -29,6 +31,7 @@ import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.PackageFlavorHelper;
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper;
|
||||
import com.gh.gamecenter.core.utils.MD5Utils;
|
||||
import com.gh.gamecenter.core.utils.SentryHelper;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
@ -74,6 +77,9 @@ public class PackageUtils {
|
||||
|
||||
private static final String TAG = "PackageUtils";
|
||||
|
||||
// 设备是否支持禁用获取已安装应用列表。-1 代表支持情况未知,0 代表不支持, 1 代表支持
|
||||
private static int mIsSupportGetInstalledListPermission = -1;
|
||||
|
||||
public static String getInstallPackageInfoSourceDir(String packageName) {
|
||||
try {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
@ -966,18 +972,78 @@ public class PackageUtils {
|
||||
return new ArrayList<>(mInstalledPackageList);
|
||||
}
|
||||
|
||||
Utils.log(TAG, "调用系统 API 获取全新的已安装应用列表");
|
||||
// 是否需要调用系统 API 获取最新的已安装应用列表
|
||||
boolean shouldGetNewInstalledPackagedList = false;
|
||||
|
||||
// 当前设备是否支持限制获取已安装应用列表的功能
|
||||
if (isSupportGetInstalledAppsPermission(context)) {
|
||||
Utils.log(TAG, "当前设备支持限制获取已安装应用列表的功能");
|
||||
// 当前设备是否支持禁用了获取已安装应用列表
|
||||
if (!PermissionHelper.isGetInstalledListPermissionDisabled(context)) {
|
||||
Utils.log(TAG, "当前设备没有限制获取已安装应用列表的功能");
|
||||
shouldGetNewInstalledPackagedList = true;
|
||||
} else {
|
||||
Utils.log(TAG, "当前设备已限制获取已安装应用列表的功能");
|
||||
}
|
||||
} else {
|
||||
Utils.log(TAG, "当前设备不支持限制获取已安装应用列表的功能");
|
||||
shouldGetNewInstalledPackagedList = true;
|
||||
}
|
||||
|
||||
if (shouldGetNewInstalledPackagedList) {
|
||||
mLastInstalledPackageListTime = System.currentTimeMillis();
|
||||
mInstalledPackageList = getInstalledPackagesInternal(context, flags);
|
||||
}
|
||||
|
||||
if (mInstalledPackageList == null) {
|
||||
mInstalledPackageList = new ArrayList<>();
|
||||
}
|
||||
|
||||
mLastInstalledPackageListTime = System.currentTimeMillis();
|
||||
mInstalledPackageList = getInstalledPackagesInternal(context, flags);
|
||||
return mInstalledPackageList;
|
||||
}
|
||||
|
||||
public static boolean isSupportGetInstalledAppsPermission(Context context) {
|
||||
// 若存在缓存,直接返回缓存结果。为 0 代表不支持,为 1 代表支持
|
||||
if (mIsSupportGetInstalledListPermission != -1) {
|
||||
return mIsSupportGetInstalledListPermission != 0;
|
||||
}
|
||||
|
||||
try {
|
||||
// 根据官方提供的方法来判定是否支持限制获取已安装应用列表
|
||||
int flag = Settings.Secure.getInt(context.getContentResolver(), "oem_installed_apps_runtime_permission_enable", 0);
|
||||
if (flag == 1) {
|
||||
mIsSupportGetInstalledListPermission = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 部分未升级的手机没有上面配置项,有定义下面危险权限也认为是支持设备软件列表管控
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
PermissionInfo permissionInfo = packageManager.getPermissionInfo("com.android.permission.GET_INSTALLED_APPS", 0);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
if (permissionInfo.getProtection() == PermissionInfo.PROTECTION_DANGEROUS) {
|
||||
mIsSupportGetInstalledListPermission = 1;
|
||||
return true;
|
||||
} else {
|
||||
mIsSupportGetInstalledListPermission = 0;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
mIsSupportGetInstalledListPermission = 0;
|
||||
return false;
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
mIsSupportGetInstalledListPermission = 0;
|
||||
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
|
||||
*/
|
||||
private static List<PackageInfo> getInstalledPackagesInternal(Context context, int flags) {
|
||||
Utils.log(TAG, "调用系统 API 获取已安装应用列表");
|
||||
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
try {
|
||||
return pm.getInstalledPackages(flags);
|
||||
|
||||
@ -277,7 +277,11 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
|
||||
pendingSessionInfo.updateStatus(XapkPendingSessionInfo.STATUS_INSTALL_CANCELED)
|
||||
} else if (sessionInfo.progress <= 0.8F) {
|
||||
AppExecutor.ioExecutor.execute {
|
||||
installer.abandonSession(sessionInfo.sessionId)
|
||||
try {
|
||||
installer.abandonSession(sessionInfo.sessionId)
|
||||
} catch (_: Exception) {
|
||||
// 有概率抛SecurityException,这里只要直接catch不做处理即可
|
||||
}
|
||||
}
|
||||
pendingSessionInfo.updateStatus(XapkPendingSessionInfo.STATUS_INSTALL_CANCELED)
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_GAME_COLLECT
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_INVOKE_ONLY;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_LIBAO;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_QQ;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_QQ_GAME;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_QQ_GROUP;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_QQ_QUN;
|
||||
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_QUESTION;
|
||||
@ -49,19 +50,25 @@ import android.util.Base64;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.DownloadItemUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.constant.RouteConsts;
|
||||
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.provider.IQGameProvider;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.ToastUtils;
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity;
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity;
|
||||
import com.gh.gamecenter.feature.utils.PlatformUtils;
|
||||
import com.gh.gamecenter.login.entity.UserInfoEntity;
|
||||
import com.gh.gamecenter.login.user.UserManager;
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel;
|
||||
import com.gh.gamecenter.video.videomanager.VideoManagerActivity;
|
||||
import com.gh.vspace.shortcut.OnCreateShortcutResult;
|
||||
@ -72,6 +79,14 @@ import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.muugi.shortcut.core.Executor;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function2;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/11/16.
|
||||
* 链接跳转用
|
||||
@ -123,7 +138,7 @@ public class SkipActivity extends BaseActivity {
|
||||
DirectUtils.directToGameDetail(this, path, ENTRANCE_BROWSER, "true".equals(uri.getQueryParameter("auto_download")), to, null);
|
||||
break;
|
||||
case HOST_COLUMN:
|
||||
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), ENTRANCE_BROWSER, null);
|
||||
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), ENTRANCE_BROWSER, null, false);
|
||||
break;
|
||||
case HOST_SUGGESTION:
|
||||
String platform = uri.getQueryParameter(KEY_PLATFORM);
|
||||
@ -406,6 +421,14 @@ public class SkipActivity extends BaseActivity {
|
||||
case HOST_GAME_COLLECTION_SQUARE:
|
||||
DirectUtils.directToGameCollectionSquare(this, ENTRANCE_BROWSER, "", "", "", "", "", null);
|
||||
break;
|
||||
case HOST_QQ_GAME:
|
||||
String extJson = uri.getQueryParameter("ext");
|
||||
try {
|
||||
JSONObject extJsonObject = new JSONObject(extJson);
|
||||
String qqGameId = extJsonObject.optString("aid");
|
||||
DirectUtils.directToQGameById(this, qqGameId);
|
||||
} catch (JSONException ignored) {}
|
||||
break;
|
||||
default:
|
||||
EntranceUtils.jumpActivity(this, new Bundle()); // 跳转至首页
|
||||
return;
|
||||
|
||||
@ -16,6 +16,7 @@ class SubjectData(
|
||||
var tagType: String? = "", // 游戏Item 标签类型
|
||||
var briefStyle: String = "",
|
||||
var showSuffix: Boolean = true,
|
||||
var isQQMiniGame: Boolean = false,
|
||||
|
||||
var requireUpdateSetting: Boolean = false, // 多专题页面需要专题页面自行获取专题配置
|
||||
var isAdData: Boolean = false,
|
||||
|
||||
@ -96,7 +96,10 @@ data class SubjectEntity(
|
||||
var position: Int = -1,
|
||||
|
||||
// 本地字段,用来标记在外部页面中的序号,仅用于曝光记录,具体细节可见 https://git.ghzs.com/pm/halo-app-issues/-/issues/1087
|
||||
var outerSequence: Int = -1
|
||||
var outerSequence: Int = -1,
|
||||
|
||||
@SerializedName("is_qq_column")
|
||||
var isQQColumn: Boolean = false
|
||||
) : Parcelable {
|
||||
|
||||
@IgnoredOnParcel
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
package com.gh.gamecenter.fragment
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.gh.common.util.DataCollectionUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.LogUtils
|
||||
@ -15,8 +18,12 @@ import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.SentryHelper
|
||||
import com.gh.gamecenter.databinding.FragmentHomeGameWrapperBinding
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class HomeGameWrapperFragment : HomeTabWrapperFragment() {
|
||||
@ -80,6 +87,8 @@ class HomeGameWrapperFragment : HomeTabWrapperFragment() {
|
||||
DataCollectionUtils.uploadClick(activity, "下载图标", "主页")
|
||||
startActivity(DownloadManagerActivity.getDownloadMangerIntent(requireContext(), "游戏库"))
|
||||
}
|
||||
mBinding?.menuDownloadCountHint?.typeface =
|
||||
Typeface.createFromAsset(requireContext().assets, "fonts/d_din_bold_only_number.ttf")
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,16 +122,38 @@ class HomeGameWrapperFragment : HomeTabWrapperFragment() {
|
||||
}
|
||||
|
||||
mPackageViewModel?.filterSameUpdateLiveData?.observe(this) {
|
||||
val count = DownloadManager.getInstance().getDownloadOrUpdateCount(it)
|
||||
val params = mBinding?.menuDownloadCountHint?.layoutParams
|
||||
params?.width = if (count.isNullOrEmpty()) 6F.dip2px() else 12F.dip2px()
|
||||
params?.height = if (count.isNullOrEmpty()) 6F.dip2px() else 12F.dip2px()
|
||||
mBinding?.menuDownloadCountHint?.layoutParams = params
|
||||
mBinding?.menuDownloadCountHint?.goneIf(count == null)
|
||||
mBinding?.menuDownloadCountHint?.text = count.toString()
|
||||
setDownloadHint(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setDownloadHint(updateList: List<GameUpdateEntity>) {
|
||||
val count = DownloadManager.getInstance().getDownloadOrUpdateCount(updateList)
|
||||
val params = mBinding?.menuDownloadCountHint?.layoutParams
|
||||
params?.width = if (count.isNullOrEmpty()) 6F.dip2px() else ConstraintLayout.LayoutParams.WRAP_CONTENT
|
||||
params?.height = if (count.isNullOrEmpty()) 6F.dip2px() else 14F.dip2px()
|
||||
(params as ViewGroup.MarginLayoutParams).setMargins(
|
||||
0,
|
||||
if (count.isNullOrEmpty()) 0 else (-4F).dip2px(),
|
||||
if (count.isNullOrEmpty()) (-4F).dip2px() else (-8F).dip2px(),
|
||||
0
|
||||
)
|
||||
mBinding?.menuDownloadCountHint?.setPadding(
|
||||
if (count.isNullOrEmpty()) 0 else 4F.dip2px(),
|
||||
0,
|
||||
if (count.isNullOrEmpty()) 0 else 4F.dip2px(),
|
||||
0
|
||||
)
|
||||
mBinding?.menuDownloadCountHint?.minWidth = if (count.isNullOrEmpty()) 0 else 14F.dip2px()
|
||||
mBinding?.menuDownloadCountHint?.layoutParams = params
|
||||
mBinding?.menuDownloadCountHint?.goneIf(count == null)
|
||||
mBinding?.menuDownloadCountHint?.text = count.toString()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(status: EBDownloadStatus?) {
|
||||
mPackageViewModel?.filterSameUpdateLiveData?.value?.let { setDownloadHint(it) }
|
||||
}
|
||||
|
||||
override fun getLastTabRightMargin(): Int = 26F.dip2px()
|
||||
|
||||
override fun logTabSelected(tabEntity: SubjectRecommendEntity, position: Int) {
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.gamecenter.fragment;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Menu;
|
||||
@ -13,6 +14,7 @@ import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.ScaleAnimation;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@ -207,21 +209,40 @@ public class SearchToolbarFragment extends BaseLazyFragment implements View.OnCl
|
||||
mUnreadViewModel = ViewModelProviders.of(this,
|
||||
new MessageUnreadViewModel.Factory(HaloApp.getInstance().getApplication())).get(MessageUnreadViewModel.class);
|
||||
mUnreadViewModel.getMessageCenterUnreadCountLiveData().observe(this, this::setMessageUnread);
|
||||
|
||||
mDownloadHintTv.setTypeface(Typeface.createFromAsset(requireContext().getAssets(), "fonts/d_din_bold_only_number.ttf"));
|
||||
mMessageUnread.setTypeface(Typeface.createFromAsset(requireContext().getAssets(), "fonts/d_din_bold_only_number.ttf"));
|
||||
}
|
||||
|
||||
private void setMessageUnread(int unreadCount) {
|
||||
mMessageUnread.setVisibility(unreadCount == 0 ? View.GONE : View.VISIBLE);
|
||||
ViewGroup.LayoutParams params = mMessageUnread.getLayoutParams();
|
||||
if (unreadCount == -1) {
|
||||
mMessageUnread.setText("");
|
||||
params.width = DisplayUtils.dip2px(6);
|
||||
params.height = DisplayUtils.dip2px(6);
|
||||
setHintLayoutParams(mMessageUnread, true);
|
||||
} else {
|
||||
BindingAdapters.setMessageUnread(mMessageUnread, unreadCount);
|
||||
params.width = DisplayUtils.dip2px(12);
|
||||
params.height = DisplayUtils.dip2px(12);
|
||||
setHintLayoutParams(mMessageUnread, false);
|
||||
}
|
||||
mMessageUnread.setLayoutParams(params);
|
||||
}
|
||||
|
||||
private void setHintLayoutParams(TextView textView, boolean isRedDot) {
|
||||
ViewGroup.LayoutParams params = textView.getLayoutParams();
|
||||
if (isRedDot) {
|
||||
params.width = DisplayUtils.dip2px(6F);
|
||||
params.height = DisplayUtils.dip2px(6F);
|
||||
((ViewGroup.MarginLayoutParams) params).rightMargin = DisplayUtils.dip2px(-4F);
|
||||
((ViewGroup.MarginLayoutParams) params).topMargin = 0;
|
||||
textView.setPadding(0, 0, 0, 0);
|
||||
textView.setMinWidth(0);
|
||||
} else {
|
||||
params.width = RelativeLayout.LayoutParams.WRAP_CONTENT;
|
||||
params.height = DisplayUtils.dip2px(14F);
|
||||
((ViewGroup.MarginLayoutParams) params).rightMargin = DisplayUtils.dip2px(-8F);
|
||||
((ViewGroup.MarginLayoutParams) params).topMargin = DisplayUtils.dip2px(-4F);
|
||||
textView.setPadding(DisplayUtils.dip2px(4F), 0, DisplayUtils.dip2px(4F), 0);
|
||||
textView.setMinWidth(DisplayUtils.dip2px(14F));
|
||||
}
|
||||
textView.setLayoutParams(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -343,15 +364,11 @@ public class SearchToolbarFragment extends BaseLazyFragment implements View.OnCl
|
||||
mDownloadHintTv.setVisibility(View.VISIBLE);
|
||||
mDownloadHintTv.setText(count);
|
||||
|
||||
ViewGroup.LayoutParams params = mDownloadHintTv.getLayoutParams();
|
||||
if (TextUtils.isEmpty(count)) {
|
||||
params.width = DisplayUtils.dip2px(6);
|
||||
params.height = DisplayUtils.dip2px(6);
|
||||
setHintLayoutParams(mDownloadHintTv, true);
|
||||
} else {
|
||||
params.width = DisplayUtils.dip2px(12);
|
||||
params.height = DisplayUtils.dip2px(12);
|
||||
setHintLayoutParams(mDownloadHintTv, false);
|
||||
}
|
||||
mDownloadHintTv.setLayoutParams(params);
|
||||
} else {
|
||||
mDownloadHintTv.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
117
app/src/main/java/com/gh/gamecenter/game/BaseGameViewModel.kt
Normal file
117
app/src/main/java/com/gh/gamecenter/game/BaseGameViewModel.kt
Normal file
@ -0,0 +1,117 @@
|
||||
package com.gh.gamecenter.game
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.util.GameSubstituteRepositoryHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.entity.ExposureEntity
|
||||
import com.gh.gamecenter.core.iinterface.IOffsetable
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.game.data.GameItemData
|
||||
import com.gh.gamecenter.home.BlankDividerViewHolder
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2DownloadStateUpdateHelper
|
||||
|
||||
abstract class BaseGameViewModel(application: Application, open var blockData: SubjectRecommendEntity?) : AndroidViewModel(application), IOffsetable {
|
||||
|
||||
private var mOffsetMap: HashMap<Int, Int> = hashMapOf()
|
||||
|
||||
protected val mItemDataListCache: MutableList<GameItemData> = ArrayList()
|
||||
|
||||
val loadStatus = MutableLiveData<LoadStatus>()
|
||||
val commandScrollTop = MutableLiveData<Any>()
|
||||
|
||||
var itemDataList: MediatorLiveData<List<GameItemData>> = MediatorLiveData()
|
||||
|
||||
var entrance: String = ""
|
||||
|
||||
var positionAndPackageMap = HashMap<String, Int>() // key: packageName + position, value: position
|
||||
|
||||
private var mHomeGameTestV2DownloadStateUpdateHelper: HomeGameTestV2DownloadStateUpdateHelper? = null
|
||||
|
||||
override fun getOffset(position: Int) = mOffsetMap[position] ?: 0
|
||||
|
||||
override fun updateOffset(position: Int, offset: Int) {
|
||||
mOffsetMap[position] = offset
|
||||
}
|
||||
|
||||
override fun resetOffset() {
|
||||
mOffsetMap.clear()
|
||||
}
|
||||
|
||||
fun initData() {
|
||||
onInitData()
|
||||
}
|
||||
|
||||
fun isGameRepo(): Boolean {
|
||||
return blockData?.name?.contains("游戏库") == true
|
||||
}
|
||||
|
||||
fun setHomeGameTestV2DownloadStateUpdateHelper(helper: HomeGameTestV2DownloadStateUpdateHelper) {
|
||||
mHomeGameTestV2DownloadStateUpdateHelper = helper
|
||||
mHomeGameTestV2DownloadStateUpdateHelper?.setOnGameListAddCallback { position, gameEntities ->
|
||||
gameEntities.forEach {
|
||||
addGamePositionAndPackage(it, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun addGamePositionAndPackage(game: GameEntity, position: Int) {
|
||||
var packages = ""
|
||||
for (apkEntity in game.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
positionAndPackageMap[packages + position] = position
|
||||
game.gameLocation = GameEntity.GameLocation.INDEX
|
||||
game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
|
||||
}
|
||||
|
||||
protected fun addGamePositionAndPackage(game: GameEntity) {
|
||||
var packages = ""
|
||||
for (apkEntity in game.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
positionAndPackageMap[packages + (mItemDataListCache.size - 1)] = mItemDataListCache.size - 1
|
||||
game.gameLocation = GameEntity.GameLocation.INDEX
|
||||
game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
|
||||
}
|
||||
|
||||
protected fun appendAdditionalInfoToSubjectGame(subject: SubjectEntity, outerPosition: Int) {
|
||||
subject.outerSequence = outerPosition
|
||||
subject.data?.let {
|
||||
for ((index, game) in it.withIndex()) {
|
||||
// 开测表不是专题不需要补充专题 id
|
||||
if (subject.tag != "test") {
|
||||
game.subjectId = subject.id
|
||||
}
|
||||
game.sequence = index
|
||||
game.containerId = blockData?.link
|
||||
game.containerType = ExposureEntity.BLOCK_ID
|
||||
game.outerSequence = outerPosition
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取填充间距的空白 item
|
||||
*/
|
||||
protected fun getBlankSpacingItem() =
|
||||
GameItemData().apply { blankDivider = BlankDividerViewHolder.DEFAULT_BLANK_HEIGHT * 2 }
|
||||
|
||||
protected abstract fun onInitData()
|
||||
|
||||
abstract fun getSubjectList()
|
||||
|
||||
abstract fun replaceRefreshData(itemData: GameItemData): Boolean
|
||||
|
||||
abstract fun changeSubjectGame(subjectId: String)
|
||||
|
||||
abstract fun refreshDiscoverCardData()
|
||||
|
||||
abstract fun changeGameCollectionRefresh(collectionId: String, isRefreshClick: Boolean): Boolean
|
||||
|
||||
}
|
||||
@ -11,6 +11,7 @@ import com.ethanhua.skeleton.Skeleton
|
||||
import com.ethanhua.skeleton.ViewSkeletonScreen
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.HomeBottomBarHelper
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
import com.gh.download.DownloadManager
|
||||
@ -44,9 +45,9 @@ import com.lightgame.download.DownloadEntity
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class GameFragment : LazyFragment() {
|
||||
open class GameFragment : LazyFragment() {
|
||||
|
||||
private lateinit var mViewModel: GameViewModel
|
||||
private lateinit var mViewModel: BaseGameViewModel
|
||||
private lateinit var mHomeGameTestV2ViewModel: HomeGameTestV2ViewModel
|
||||
|
||||
private lateinit var mBinding: FragmentGameBinding
|
||||
@ -74,11 +75,7 @@ class GameFragment : LazyFragment() {
|
||||
override fun getRealLayoutId() = R.layout.fragment_game
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
val factory = GameViewModel.Factory(
|
||||
HaloApp.getInstance().application,
|
||||
arguments?.getParcelable(EntranceConsts.KEY_BLOCK_DATA)
|
||||
)
|
||||
mViewModel = viewModelProvider(factory)
|
||||
mViewModel = provideViewModel()
|
||||
mViewModel.entrance = mEntrance
|
||||
//新游开测模块
|
||||
mHomeGameTestV2ViewModel = viewModelProvider()
|
||||
@ -364,4 +361,12 @@ class GameFragment : LazyFragment() {
|
||||
mBinding.gameList.setBackgroundColor(R.color.background_white.toColor(requireContext()))
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun provideViewModel(): BaseGameViewModel {
|
||||
val factory = GameViewModel.Factory(
|
||||
HaloApp.getInstance().application,
|
||||
arguments?.getParcelable(EntranceConsts.KEY_BLOCK_DATA)
|
||||
)
|
||||
return viewModelProvider(factory)
|
||||
}
|
||||
}
|
||||
@ -25,6 +25,7 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.ImagePagerAdapter
|
||||
import com.gh.gamecenter.adapter.viewholder.*
|
||||
import com.gh.gamecenter.category.CategoryDirectoryActivity
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.callback.OnViewClickListener
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
@ -82,6 +83,7 @@ import com.gh.gamecenter.home.test_v2.HomeGameTestV2GameListRvAdapter
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2ViewModel
|
||||
import com.gh.gamecenter.home.test_v2.HomeItemGameTestV2ViewHolder
|
||||
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
|
||||
import com.gh.gamecenter.qgame.QGameHorizontalSlideListViewHolder
|
||||
import com.gh.gamecenter.servers.gametest2.GameServerTestV2Activity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
@ -89,7 +91,7 @@ import com.lightgame.download.DownloadEntity
|
||||
|
||||
class GameFragmentAdapter(
|
||||
context: Context,
|
||||
model: GameViewModel,
|
||||
model: BaseGameViewModel,
|
||||
private val mLifecycleOwner: LifecycleOwner,
|
||||
private val mHomeGameTestV2ViewModel: HomeGameTestV2ViewModel,
|
||||
private val mBasicExposureSource: ArrayList<ExposureSource>,
|
||||
@ -97,7 +99,7 @@ class GameFragmentAdapter(
|
||||
private val mScrollCalculatorHelper: ScrollCalculatorHelper? = null
|
||||
) : BaseRecyclerAdapter<ViewHolder>(context), IExposable {
|
||||
|
||||
private val mViewModel: GameViewModel = model
|
||||
private val mViewModel: BaseGameViewModel = model
|
||||
|
||||
private var mLoadStatus: LoadStatus? = null
|
||||
|
||||
@ -132,6 +134,7 @@ class GameFragmentAdapter(
|
||||
if (itemData.image != null) return ItemViewType.GAME_IMAGE
|
||||
if (itemData.horizontalColumn != null) return ItemViewType.GAME_SUBJECT
|
||||
if (itemData.horizontalSlide != null) return ItemViewType.GAME_SUBJECT_SLIDE
|
||||
if (itemData.qqHorizontalSlide != null) return ItemViewType.QQ_GAME_SUBJECT_SLIDE
|
||||
if (itemData.imageSlide != null) return ItemViewType.IMAGE_SLIDE_ITEM
|
||||
if (itemData.verticalSlide != null) return ItemViewType.VERTICAL_SLIDE_ITEM
|
||||
if (itemData.columnCollection != null) return ItemViewType.COLUMN_COLLECTION
|
||||
@ -177,6 +180,7 @@ class GameFragmentAdapter(
|
||||
|
||||
ItemViewType.GAME_SUBJECT -> GameHorizontalListViewHolder(parent.toBinding())
|
||||
ItemViewType.GAME_SUBJECT_SLIDE -> GameHorizontalSlideListViewHolder(parent.toBinding())
|
||||
ItemViewType.QQ_GAME_SUBJECT_SLIDE -> QGameHorizontalSlideListViewHolder(parent.toBinding())
|
||||
ItemViewType.GAME_NORMAL -> GameItemViewHolder(parent.toBinding())
|
||||
ItemViewType.GAME_IMAGE -> GameImageViewHolder(parent.toBinding())
|
||||
ItemViewType.COLUMN_HEADER -> GameHeadViewHolder(parent.toBinding())
|
||||
@ -223,6 +227,7 @@ class GameFragmentAdapter(
|
||||
is FooterViewHolder -> bindFooterView(holder)
|
||||
is GameImageViewHolder -> bindGameImageView(holder, position)
|
||||
is GameHorizontalListViewHolder -> bindGameHorizontalListView(holder, position)
|
||||
is QGameHorizontalSlideListViewHolder -> bindQGameHorizontalSlideListView(holder, position)
|
||||
is GameHorizontalSlideListViewHolder -> bindGameHorizontalSlideListView(holder, position)
|
||||
is GameImageSlideViewHolder -> bindGameImageSlide(holder, position)
|
||||
is GameVerticalSlideViewHolder -> bindVerticalSlide(holder, position)
|
||||
@ -267,7 +272,7 @@ class GameFragmentAdapter(
|
||||
holder.cell.binding?.root?.setOnClickListener {
|
||||
setPageSwitchData()
|
||||
DirectUtils.directToSubject(
|
||||
it.context, gallery.id ?: "", gallery.name, "(游戏-专题)"
|
||||
it.context, gallery.id ?: "", gallery.name, "(游戏-专题)", null, gallery.isQQColumn
|
||||
)
|
||||
NewLogUtils.logColumnPictureClick(
|
||||
"显示图集", gallery.name ?: "", gallery.id ?: "", gallery.id ?: "", "column",
|
||||
@ -513,17 +518,24 @@ class GameFragmentAdapter(
|
||||
val clickClosure: (Int, GameEntity) -> Unit = { _, gameEntity ->
|
||||
val subjectData = gameEntity.subjectData
|
||||
DataCollectionUtils.uploadClick(mContext, subjectData?.name + "-列表", "游戏-专题", gameEntity.name)
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext, gameEntity,
|
||||
StringUtils.buildString(
|
||||
"(游戏-专题:",
|
||||
subjectData?.name,
|
||||
"-列表[",
|
||||
(subjectData?.position).toString(),
|
||||
"])"
|
||||
),
|
||||
traceEvent = gameEntity.exposureEvent
|
||||
)
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
|
||||
GlobalActivityManager.currentActivity?.let {
|
||||
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
|
||||
}
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext, gameEntity,
|
||||
StringUtils.buildString(
|
||||
"(游戏-专题:",
|
||||
subjectData?.name,
|
||||
"-列表[",
|
||||
(subjectData?.position).toString(),
|
||||
"])"
|
||||
),
|
||||
traceEvent = gameEntity.exposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val verticalSlide = mItemDataList[position].verticalSlide!!
|
||||
@ -689,6 +701,64 @@ class GameFragmentAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindQGameHorizontalSlideListView(holder: QGameHorizontalSlideListViewHolder, position: Int) {
|
||||
val subject = mItemDataList[position].qqHorizontalSlide
|
||||
holder.bindHorizontalSlideList(subject!!)
|
||||
|
||||
holder.binding.moreTv.setOnClickListener {
|
||||
val buttonType = when (subject.home) {
|
||||
"change" -> "换一批"
|
||||
"more" -> "更多"
|
||||
else -> "全部"
|
||||
}
|
||||
val moreLink = subject.moreLink
|
||||
NewLogUtils.logColumnListClickButton(
|
||||
buttonType, subject.name ?: "", subject.id ?: "", moreLink?.type ?: "",
|
||||
moreLink?.name ?: "", "版块", mViewModel.blockData?.name ?: ""
|
||||
)
|
||||
when (subject.home) {
|
||||
"change" -> {
|
||||
MtaHelper.onEvent("游戏专题", "换一批", subject.name)
|
||||
holder.binding.moreTv.visibility = View.VISIBLE
|
||||
mViewModel.changeSubjectGame(subject.id!!)
|
||||
}
|
||||
|
||||
"more" -> {
|
||||
setPageSwitchData()
|
||||
subject.moreLink?.let { link ->
|
||||
DirectUtils.directToLinkPage(it.context, link, "(板块)", "(游戏-专题:" + subject.name + "-全部)")
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
setPageSwitchData()
|
||||
if (subject.indexRightTopLink != null) {
|
||||
val link = subject.indexRightTopLink!!
|
||||
|
||||
// ugly ugly ugly as hell
|
||||
if (holder.binding.moreTv.text.contains("更多")) {
|
||||
LogUtils.logServerTestClickMoreEvent(link.text, subject.remark, link.type, link.link)
|
||||
} else {
|
||||
LogUtils.logServerTestClickAllEvent(link.text, subject.remark)
|
||||
}
|
||||
DirectUtils.directToLinkPage(mContext, link, "(游戏-专题:" + subject.name + "-全部)", "")
|
||||
} else {
|
||||
SubjectActivity.startSubjectActivity(
|
||||
mContext,
|
||||
subject.id,
|
||||
subject.getFilterName(),
|
||||
subject.isOrder,
|
||||
mBasicExposureSource,
|
||||
"(游戏-专题:" + subject.name + "-全部)",
|
||||
subject.isQQColumn
|
||||
)
|
||||
}
|
||||
MtaHelper.onEvent("游戏专题", "全部", subject.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindGameImageView(holder: GameImageViewHolder, position: Int) {
|
||||
val entity = mItemDataList[position].image
|
||||
holder.bindImage(entity!!)
|
||||
@ -1127,10 +1197,17 @@ class GameFragmentAdapter(
|
||||
!gameEntity.isPluggable,
|
||||
subjectData.briefStyle
|
||||
)
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
|
||||
DataCollectionUtils.uploadClick(mContext, subjectData.name + "-列表", "游戏-专题", gameEntity.name)
|
||||
|
||||
if (gameEntity.isPluggable) {
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
GlobalActivityManager.currentActivity?.let {
|
||||
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
|
||||
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
|
||||
}
|
||||
} else if (gameEntity.isPluggable) {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity.id,
|
||||
@ -1283,14 +1360,26 @@ class GameFragmentAdapter(
|
||||
}
|
||||
DirectUtils.directToLinkPage(mContext, link, "(游戏-专题:" + column.name + "-全部)", "")
|
||||
} else {
|
||||
SubjectActivity.startSubjectActivity(
|
||||
mContext,
|
||||
column.id,
|
||||
column.getFilterName(),
|
||||
column.isOrder,
|
||||
mBasicExposureSource,
|
||||
"(游戏-专题:" + column.name + "-全部)"
|
||||
)
|
||||
if (column.isQQColumn) {
|
||||
SubjectActivity.startSubjectActivity(
|
||||
mContext,
|
||||
column.id,
|
||||
column.getFilterName(),
|
||||
column.isOrder,
|
||||
mBasicExposureSource,
|
||||
"(游戏-专题:" + column.name + "-全部)",
|
||||
column.isQQColumn
|
||||
)
|
||||
} else {
|
||||
SubjectActivity.startSubjectActivity(
|
||||
mContext,
|
||||
column.id,
|
||||
column.getFilterName(),
|
||||
column.isOrder,
|
||||
mBasicExposureSource,
|
||||
"(游戏-专题:" + column.name + "-全部)"
|
||||
)
|
||||
}
|
||||
}
|
||||
MtaHelper.onEvent("游戏专题", "全部", column.name)
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ import androidx.collection.ArrayMap
|
||||
import androidx.lifecycle.*
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
@ -19,7 +18,6 @@ import com.gh.gamecenter.common.utils.countOccurrences
|
||||
import com.gh.gamecenter.common.utils.debugOnly
|
||||
import com.gh.gamecenter.common.utils.observableToMain
|
||||
import com.gh.gamecenter.common.utils.singleToMain
|
||||
import com.gh.gamecenter.core.iinterface.IOffsetable
|
||||
import com.gh.gamecenter.core.utils.RandomUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
@ -32,7 +30,6 @@ import com.gh.gamecenter.game.rank.RankCollectionAdapter
|
||||
import com.gh.gamecenter.gamecollection.square.GameCollectionListItemData
|
||||
import com.gh.gamecenter.home.BlankDividerViewHolder
|
||||
import com.gh.gamecenter.home.LegacyHomeFragmentAdapterAssistant
|
||||
import com.gh.gamecenter.home.test_v2.HomeGameTestV2DownloadStateUpdateHelper
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
@ -44,17 +41,13 @@ import retrofit2.HttpException
|
||||
import kotlin.collections.set
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class GameViewModel(application: Application, var blockData: SubjectRecommendEntity?) : AndroidViewModel(application),
|
||||
IOffsetable {
|
||||
|
||||
private var mHomeGameTestV2DownloadStateUpdateHelper: HomeGameTestV2DownloadStateUpdateHelper? = null
|
||||
class GameViewModel(application: Application, override var blockData: SubjectRecommendEntity?) : BaseGameViewModel(application, blockData) {
|
||||
|
||||
private var mSlideList = ArrayList<LinkEntity>() // 轮播图
|
||||
private var mNavigationList = ArrayList<GameNavigationEntity>() // 导航栏
|
||||
private var mSubjectList: MutableList<SubjectEntity> = ArrayList() // 专题
|
||||
private var mSubjectDigestList = ArrayList<SubjectRecommendEntity>() // 专题入口
|
||||
|
||||
private val mItemDataListCache: MutableList<GameItemData> = ArrayList()
|
||||
private val mSubjectChangedMap: ArrayMap<String, List<GameEntity>> = ArrayMap() // 存储换一换的数据
|
||||
private val mSubjectRefreshMap: ArrayMap<String, MutableList<GameEntity>> = ArrayMap() // 存储专题刷新数据
|
||||
private val mRefreshGameCollectionMap: ArrayMap<String, List<HomeGameCollectionEntity>> = ArrayMap() // 存储刷新轮换游戏单的数据
|
||||
@ -71,15 +64,6 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
|
||||
private val mSensitiveApi = RetrofitManager.getInstance().api
|
||||
|
||||
private var mOffsetMap: HashMap<Int, Int> = hashMapOf()
|
||||
|
||||
var entrance: String = ""
|
||||
var itemDataList: MediatorLiveData<List<GameItemData>> = MediatorLiveData()
|
||||
val loadStatus = MutableLiveData<LoadStatus>()
|
||||
val commandScrollTop = MutableLiveData<Any>()
|
||||
|
||||
var positionAndPackageMap = HashMap<String, Int>() // key: packageName + position, value: position
|
||||
|
||||
// 所有专题里的所有游戏 ID 的集合,供替换时排重用
|
||||
private var mSubjectGameIdList = hashSetOf<String>()
|
||||
|
||||
@ -97,7 +81,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
/**
|
||||
* 初始化加载数据
|
||||
*/
|
||||
fun initData() {
|
||||
override fun onInitData() {
|
||||
mSubjectPage = 1
|
||||
|
||||
mSlideList = arrayListOf()
|
||||
@ -188,7 +172,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
})
|
||||
}
|
||||
|
||||
fun getSubjectList() {
|
||||
override fun getSubjectList() {
|
||||
if (mIsLoading || loadStatus.value == LoadStatus.LIST_OVER) return
|
||||
|
||||
mIsLoading = true
|
||||
@ -311,7 +295,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
}
|
||||
|
||||
// 目前只需替换横向专题和横向滑动专题
|
||||
fun replaceRefreshData(itemData: GameItemData): Boolean {
|
||||
override fun replaceRefreshData(itemData: GameItemData): Boolean {
|
||||
val horizontalColumn = itemData.horizontalColumn
|
||||
if (horizontalColumn != null) {
|
||||
return replaceHorizontalSubjectRefreshData(horizontalColumn)
|
||||
@ -378,7 +362,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
return true
|
||||
}
|
||||
|
||||
fun changeSubjectGame(subjectId: String) {
|
||||
override fun changeSubjectGame(subjectId: String) {
|
||||
val list = mSubjectChangedMap[subjectId]
|
||||
if (list != null) {
|
||||
initRandomGame(subjectId, ArrayList(list))
|
||||
@ -512,7 +496,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshDiscoverCardData() {
|
||||
override fun refreshDiscoverCardData() {
|
||||
if (mDiscoveryGameCard != null) {
|
||||
val paramsMap = if (SPUtils.getBoolean(Constants.SP_DISCOVER_FORCE_REFRESH)) {
|
||||
mapOf("refresh" to "true")
|
||||
@ -598,7 +582,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
}
|
||||
}
|
||||
|
||||
fun changeGameCollectionRefresh(collectionId: String, isRefreshClick: Boolean): Boolean {
|
||||
override fun changeGameCollectionRefresh(collectionId: String, isRefreshClick: Boolean): Boolean {
|
||||
val page = (mRefreshGameCollectionPageMap[collectionId] ?: 1) + 1
|
||||
return if (page != 0) {
|
||||
getGameCollectionRefresh(collectionId, page, isRefreshClick)
|
||||
@ -1125,67 +1109,6 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
itemDataList.postValue(mItemDataListCache)
|
||||
}
|
||||
|
||||
private fun addGamePositionAndPackage(game: GameEntity, position: Int) {
|
||||
var packages = ""
|
||||
for (apkEntity in game.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
positionAndPackageMap[packages + position] = position
|
||||
game.gameLocation = GameEntity.GameLocation.INDEX
|
||||
game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
|
||||
}
|
||||
|
||||
private fun addGamePositionAndPackage(game: GameEntity) {
|
||||
var packages = ""
|
||||
for (apkEntity in game.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
positionAndPackageMap[packages + (mItemDataListCache.size - 1)] = mItemDataListCache.size - 1
|
||||
game.gameLocation = GameEntity.GameLocation.INDEX
|
||||
game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
|
||||
}
|
||||
|
||||
fun setHomeGameTestV2DownloadStateUpdateHelper(helper: HomeGameTestV2DownloadStateUpdateHelper) {
|
||||
mHomeGameTestV2DownloadStateUpdateHelper = helper
|
||||
mHomeGameTestV2DownloadStateUpdateHelper?.setOnGameListAddCallback { position, gameEntities ->
|
||||
gameEntities.forEach {
|
||||
addGamePositionAndPackage(it, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取填充间距的空白 item
|
||||
*/
|
||||
private fun getBlankSpacingItem() =
|
||||
GameItemData().apply { blankDivider = BlankDividerViewHolder.DEFAULT_BLANK_HEIGHT * 2 }
|
||||
|
||||
override fun getOffset(position: Int) = mOffsetMap[position] ?: 0
|
||||
|
||||
override fun updateOffset(position: Int, offset: Int) {
|
||||
mOffsetMap[position] = offset
|
||||
}
|
||||
|
||||
override fun resetOffset() {
|
||||
mOffsetMap.clear()
|
||||
}
|
||||
|
||||
private fun appendAdditionalInfoToSubjectGame(subject: SubjectEntity, outerPosition: Int) {
|
||||
subject.outerSequence = outerPosition
|
||||
subject.data?.let {
|
||||
for ((index, game) in it.withIndex()) {
|
||||
// 开测表不是专题不需要补充专题 id
|
||||
if (subject.tag != "test") {
|
||||
game.subjectId = subject.id
|
||||
}
|
||||
game.sequence = index
|
||||
game.containerId = blockData?.link
|
||||
game.containerType = ExposureEntity.BLOCK_ID
|
||||
game.outerSequence = outerPosition
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun appendAdditionalInfoToRankSubjectGame(subject: SubjectEntity, outerPosition: Int) {
|
||||
subject.columns.forEach {
|
||||
it.data?.forEachIndexed { index, game ->
|
||||
@ -1201,13 +1124,6 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否显示为游戏库
|
||||
*/
|
||||
fun isGameRepo(): Boolean {
|
||||
return blockData?.name?.contains("游戏库") == true
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@ class GameItemData : ExposureItemData {
|
||||
var navigationList: List<GameNavigationEntity>? = null
|
||||
var verticalSlide: SubjectEntity? = null
|
||||
var horizontalSlide: SubjectEntity? = null
|
||||
var qqHorizontalSlide: SubjectEntity? = null
|
||||
var imageSlide: GameEntity? = null
|
||||
var columnCollection: SubjectEntity? = null
|
||||
var commonLinkCollection: SubjectEntity? = null
|
||||
|
||||
@ -5,18 +5,21 @@ import android.view.ViewGroup
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.databinding.GameGallerySlideItemBinding
|
||||
import com.gh.gamecenter.databinding.ItemWithinGameGallerySlideBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class GameGallerySlideViewHolder(val binding: GameGallerySlideItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
@ -131,12 +134,19 @@ class GameGallerySlideViewHolder(val binding: GameGallerySlideItemBinding) : Bas
|
||||
fun bindView(gameEntity: GameEntity) {
|
||||
binding.iconIv.displayGameIcon(gameEntity)
|
||||
binding.iconIv.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
binding.root.context,
|
||||
gameEntity.id,
|
||||
mEntrance,
|
||||
gameEntity.exposureEvent
|
||||
)
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
|
||||
GlobalActivityManager.currentActivity?.let {
|
||||
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
|
||||
}
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
binding.root.context,
|
||||
gameEntity.id,
|
||||
mEntrance,
|
||||
gameEntity.exposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,10 +2,12 @@ package com.gh.gamecenter.game.gallery
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.utils.safelyGetInRelease
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.view.AsyncCell
|
||||
@ -37,20 +39,36 @@ class GameGalleryViewHolder(val cell: GameGalleryItemCell) :
|
||||
)
|
||||
|
||||
for ((index, gameIcon) in gameIconList.withIndex()) {
|
||||
val gameEntity = subjectEntity.data?.safelyGetInRelease(index) ?: continue
|
||||
val dataSize = subjectEntity.data?.size ?: 0
|
||||
if (index >= dataSize) {
|
||||
gameIcon.visibility = View.GONE
|
||||
} else {
|
||||
val gameEntity = subjectEntity.data?.safelyGetInRelease(index) ?: continue
|
||||
|
||||
gameEntity.subjectId = subjectEntity.id
|
||||
gameEntity.subjectId = subjectEntity.id
|
||||
|
||||
gameIcon.rotation = 35F
|
||||
gameIcon.displayGameIcon(gameEntity)
|
||||
gameIcon.visibility = View.VISIBLE
|
||||
gameIcon.rotation = 35F
|
||||
gameIcon.displayGameIcon(gameEntity)
|
||||
|
||||
runOnIoThread(true) {
|
||||
val exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity,
|
||||
basicExposureSource,
|
||||
listOf(ExposureSource("专题", "${subjectEntity.name}-图集"))
|
||||
)
|
||||
exposureClosure.invoke(exposureEvent)
|
||||
if (subjectEntity.isQQColumn) {
|
||||
gameIcon.setOnClickListener {
|
||||
GlobalActivityManager.currentActivity?.let {
|
||||
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gameIcon.setOnClickListener(null)
|
||||
}
|
||||
|
||||
runOnIoThread(true) {
|
||||
val exposureEvent = ExposureEvent.createEventWithSourceConcat(
|
||||
gameEntity,
|
||||
basicExposureSource,
|
||||
listOf(ExposureSource("专题", "${subjectEntity.name}-图集"))
|
||||
)
|
||||
exposureClosure.invoke(exposureEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,14 +3,19 @@ package com.gh.gamecenter.game.horizontal
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.DataCollectionUtils
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.toPx
|
||||
import com.gh.gamecenter.core.provider.IQGameProvider
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
@ -55,6 +60,8 @@ class GameHorizontalAdapter(
|
||||
val size = mSubjectEntity.data!!.size - getIndex()
|
||||
return if (type == GameHorizontalListType.GameDetailHorizontalType) {
|
||||
size
|
||||
} else if (type == GameHorizontalListType.QGameSubjectHorizontalType){
|
||||
mSubjectEntity.data!!.size
|
||||
} else {
|
||||
when {
|
||||
size < 4 -> size
|
||||
@ -123,12 +130,19 @@ class GameHorizontalAdapter(
|
||||
)
|
||||
}
|
||||
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity.id,
|
||||
entranceResult,
|
||||
exposureEventList?.get(position)
|
||||
)
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
|
||||
GlobalActivityManager.currentActivity?.let {
|
||||
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
|
||||
}
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity.id,
|
||||
entranceResult,
|
||||
exposureEventList?.get(position)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (mSubjectEntity.showDownload && type != GameHorizontalListType.GameDetailHorizontalType) {
|
||||
@ -202,4 +216,6 @@ class GameHorizontalAdapter(
|
||||
sealed class GameHorizontalListType {
|
||||
object GameDetailHorizontalType : GameHorizontalListType()
|
||||
object SubjectHorizontalType : GameHorizontalListType()
|
||||
|
||||
object QGameSubjectHorizontalType : GameHorizontalListType()
|
||||
}
|
||||
@ -17,7 +17,16 @@ class GameHorizontalListViewHolder(val binding: GameHorizontalListBinding) :
|
||||
if (subjectAdapter == null) {
|
||||
binding.recyclerView.setPadding(5F.dip2px(), 8F.dip2px(), 5F.dip2px(), 8F.dip2px())
|
||||
binding.recyclerView.layoutManager = GridLayoutManager(context, 4)
|
||||
subjectAdapter = GameHorizontalAdapter(context, subjectEntity)
|
||||
subjectAdapter = GameHorizontalAdapter(
|
||||
context,
|
||||
subjectEntity,
|
||||
if (subjectEntity.isQQColumn) {
|
||||
GameHorizontalListType.QGameSubjectHorizontalType
|
||||
}
|
||||
else {
|
||||
GameHorizontalListType.SubjectHorizontalType
|
||||
}
|
||||
)
|
||||
(binding.recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
binding.recyclerView.adapter = subjectAdapter
|
||||
binding.recyclerView.isNestedScrollingEnabled = false
|
||||
|
||||
@ -2,12 +2,18 @@ package com.gh.gamecenter.game.horizontal
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.provider.IQGameProvider
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.GameHorizontalItemBinding
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
@ -67,19 +73,26 @@ class GameHorizontalSlideAdapter(
|
||||
}
|
||||
holder.bindGameHorizontalItem(gameEntity, mSubjectEntity)
|
||||
holder.itemView.setOnClickListener {
|
||||
val exposureEvent = exposureEventList?.safelyGetInRelease(position)
|
||||
if (exposureEvent != null) {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity.id,
|
||||
StringUtils.buildString("(游戏-专题:", mSubjectEntity.name, "-列表[", (position + 1).toString(), "])"),
|
||||
traceEvent = exposureEvent
|
||||
)
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
|
||||
GlobalActivityManager.currentActivity?.let {
|
||||
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
|
||||
}
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext, gameEntity.id,
|
||||
StringUtils.buildString("(游戏-专题:", mSubjectEntity.name, "-列表[", (position + 1).toString(), "])")
|
||||
)
|
||||
val exposureEvent = exposureEventList?.safelyGetInRelease(position)
|
||||
if (exposureEvent != null) {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity.id,
|
||||
StringUtils.buildString("(游戏-专题:", mSubjectEntity.name, "-列表[", (position + 1).toString(), "])"),
|
||||
traceEvent = exposureEvent
|
||||
)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext, gameEntity.id,
|
||||
StringUtils.buildString("(游戏-专题:", mSubjectEntity.name, "-列表[", (position + 1).toString(), "])")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,12 +5,18 @@ import android.graphics.drawable.Drawable
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.common.databind.BindingAdapters
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.AsyncUi
|
||||
import com.gh.gamecenter.core.provider.IQGameProvider
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.GameSubjectData
|
||||
|
||||
@ -7,6 +7,7 @@ import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.databinding.GameVerticalSlideItemBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import kotlin.math.min
|
||||
|
||||
class GameVerticalSlideViewHolder(val binding: GameVerticalSlideItemBinding) :
|
||||
BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
@ -17,7 +18,7 @@ class GameVerticalSlideViewHolder(val binding: GameVerticalSlideItemBinding) :
|
||||
transparentBackground: Boolean = false,
|
||||
): SpanCountPagerSnapHelper {
|
||||
val context = binding.root.context
|
||||
val spanCount = verticalSlide.list
|
||||
val spanCount = min(verticalSlide.list, verticalSlide.data!!.size)
|
||||
val snapHelper = SpanCountPagerSnapHelper(spanCount, true)
|
||||
binding.recyclerView.run {
|
||||
clearOnScrollListeners()
|
||||
|
||||
@ -5,6 +5,7 @@ import android.animation.ValueAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.*
|
||||
import android.text.SpannableStringBuilder
|
||||
@ -403,7 +404,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
mGameEntity,
|
||||
mNewGameDetailEntity?.shortId ?: "",
|
||||
mShowConcernOnMenu,
|
||||
mNewGameDetailEntity!!.me.isGameConcerned
|
||||
mNewGameDetailEntity!!.me?.isGameConcerned ?: false
|
||||
)
|
||||
MtaHelper.onEvent("游戏详情_新", "更多按钮", mViewModel.game?.name ?: "")
|
||||
}
|
||||
@ -1152,7 +1153,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
private fun updateGameDetailTopArea(updateUserRelatedViewOnly: Boolean = false) {
|
||||
if (updateUserRelatedViewOnly) {
|
||||
updateConcernMenuIcon(mNewGameDetailEntity!!.me.isGameConcerned)
|
||||
updateConcernMenuIcon(mNewGameDetailEntity!!.me?.isGameConcerned ?: false)
|
||||
return
|
||||
}
|
||||
|
||||
@ -1167,7 +1168,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
}
|
||||
|
||||
updateConcernMenuIcon(mNewGameDetailEntity!!.me.isGameConcerned)
|
||||
updateConcernMenuIcon(mNewGameDetailEntity!!.me?.isGameConcerned ?: false)
|
||||
mBaseHandler.postDelayed({
|
||||
mGameEntity?.gameType = mNewGameDetailEntity?.tagStyle?.joinToString("-") { it.name } ?: ""
|
||||
mBodyBinding.gamedetailGametag.setTags(mNewGameDetailEntity?.tagStyle!!)
|
||||
@ -1705,7 +1706,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(changed: EBConcernChanged) {
|
||||
if (mNewGameDetailEntity != null && mGameEntity != null && changed.isSingle && changed.gameId == mGameEntity!!.id) {
|
||||
mNewGameDetailEntity!!.me.isGameConcerned = changed.isConcern
|
||||
mNewGameDetailEntity!!.me?.isGameConcerned = changed.isConcern
|
||||
updateGameDetailTopArea()
|
||||
}
|
||||
}
|
||||
@ -1739,7 +1740,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
}
|
||||
mDownloadBinding.ivConcern.setOnClickListener {
|
||||
ifLogin("游戏详情-[关注]") {
|
||||
if (mNewGameDetailEntity != null && mNewGameDetailEntity!!.me.isGameConcerned) {
|
||||
if (mNewGameDetailEntity != null && mNewGameDetailEntity!!.me?.isGameConcerned == true) {
|
||||
DialogHelper.showCancelDialog(requireContext(), {
|
||||
mViewModel.concernCommand(false)
|
||||
})
|
||||
@ -1826,18 +1827,28 @@ class GameDetailFragment : ToolbarFragment(), IScrollable {
|
||||
|
||||
val downloadMenuView = mBodyBinding.toolbar.menu.findItem(R.id.menu_download).actionView
|
||||
mDownloadCountHint = downloadMenuView?.findViewById(R.id.menu_download_count_hint)
|
||||
mDownloadCountHint?.typeface =
|
||||
Typeface.createFromAsset(requireContext().assets, "fonts/d_din_bold_only_number.ttf")
|
||||
}
|
||||
|
||||
private fun updateDownloadCountHint(updateList: List<GameUpdateEntity>?) {
|
||||
val count = DownloadManager.getInstance().getDownloadOrUpdateCount(updateList)
|
||||
val params = mDownloadCountHint?.layoutParams
|
||||
if (TextUtils.isEmpty(count)) {
|
||||
params?.width = DisplayUtils.dip2px(6f)
|
||||
params?.height = DisplayUtils.dip2px(6f)
|
||||
} else {
|
||||
params?.width = DisplayUtils.dip2px(12f)
|
||||
params?.height = DisplayUtils.dip2px(12f)
|
||||
}
|
||||
params?.width = if (count.isNullOrEmpty()) 6F.dip2px() else ConstraintLayout.LayoutParams.WRAP_CONTENT
|
||||
params?.height = if (count.isNullOrEmpty()) 6F.dip2px() else 14F.dip2px()
|
||||
(params as? ViewGroup.MarginLayoutParams)?.setMargins(
|
||||
0,
|
||||
if (count.isNullOrEmpty()) 0 else (-4F).dip2px(),
|
||||
if (count.isNullOrEmpty()) (-4F).dip2px() else (-8F).dip2px(),
|
||||
0
|
||||
)
|
||||
mDownloadCountHint?.setPadding(
|
||||
if (count.isNullOrEmpty()) 0 else 4F.dip2px(),
|
||||
0,
|
||||
if (count.isNullOrEmpty()) 0 else 4F.dip2px(),
|
||||
0
|
||||
)
|
||||
mDownloadCountHint?.minWidth = if (count.isNullOrEmpty()) 0 else 14F.dip2px()
|
||||
mDownloadCountHint?.layoutParams = params
|
||||
|
||||
mDownloadCountHint?.goneIf(count == null)
|
||||
|
||||
@ -19,7 +19,7 @@ class NewGameDetailEntity(
|
||||
@SerializedName("top_video")
|
||||
var topVideo: Video? = null,
|
||||
@SerializedName("me")
|
||||
var me: MeEntity = MeEntity(),
|
||||
var me: MeEntity? = null,
|
||||
var event: BigEvent? = null,//游戏大事件
|
||||
@SerializedName("detail_dialogs")
|
||||
var detailDialogs: ArrayList<GameEntity.Dialog> = arrayListOf(),
|
||||
|
||||
@ -6,13 +6,16 @@ import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.gamecenter.common.utils.throwExceptionInDebug
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.toRequestBody
|
||||
import com.gh.gamecenter.feature.entity.GameDetailServer
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.MeEntity
|
||||
import com.gh.gamecenter.feature.entity.ServerCalendarEntity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.SingleEmitter
|
||||
@ -22,12 +25,11 @@ import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
|
||||
class ServersCalendarViewModel(
|
||||
application: Application,
|
||||
val game: GameEntity,
|
||||
val gameServer: GameDetailServer,
|
||||
val meEntity: MeEntity?
|
||||
var meEntity: MeEntity?
|
||||
) : AndroidViewModel(application) {
|
||||
|
||||
val calendarLiveData: MutableLiveData<List<CalendarEntity>> = MutableLiveData()
|
||||
@ -50,6 +52,11 @@ class ServersCalendarViewModel(
|
||||
} else {
|
||||
loadServerData(false)
|
||||
}
|
||||
|
||||
// 登录状态下,且用户信息为空时尝试请求接口判断是否为兼职
|
||||
if (meEntity == null && CheckLoginUtils.isLogin()) {
|
||||
requestPartTimeInfo()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@ -69,6 +76,27 @@ class ServersCalendarViewModel(
|
||||
})
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun requestPartTimeInfo() {
|
||||
val requestMap = hashMapOf<String, List<String>>()
|
||||
requestMap["game"] = arrayListOf(game.id)
|
||||
|
||||
RetrofitManager.getInstance().api.getUserRelatedInfoByPost(UserManager.getInstance().userId, requestMap.toRequestBody())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<UnifiedUserTrendEntity>() {
|
||||
override fun onSuccess(data: UnifiedUserTrendEntity) {
|
||||
data.game?.let {
|
||||
if (data.game.isNullOrEmpty()) return@let
|
||||
for (game in it) {
|
||||
meEntity = game.me
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// private fun checkExistCurSerer() {
|
||||
// isExistCurServer = true // 此参数控制是否显示当月开服表(无论有没有开服信息),为防止需求变更先设死这个参数
|
||||
// val curDate = System.currentTimeMillis()
|
||||
|
||||
@ -27,6 +27,7 @@ import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.common.view.OffsetLinearLayoutManager
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.provider.IFloatingWindowProvider
|
||||
import com.gh.gamecenter.core.provider.IQGameProvider
|
||||
import com.gh.gamecenter.core.provider.ICsjAdProvider
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
|
||||
@ -7,10 +7,12 @@ import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
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.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.RandomUtils
|
||||
import com.gh.gamecenter.databinding.HomeGameItemBinding
|
||||
@ -92,12 +94,19 @@ class HomeGameItemViewHolder(val binding: HomeGameItemBinding) : BaseRecyclerVie
|
||||
}
|
||||
}
|
||||
holder.itemView.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
binding.root.context,
|
||||
game.id,
|
||||
"(${entrance}-游戏[" + game.name + "])",
|
||||
exposureEvent
|
||||
)
|
||||
if (game.isQQMiniGame()) {
|
||||
NewFlatLogUtils.logQGameClick(game.qqMiniGameAppId, game.name)
|
||||
GlobalActivityManager.currentActivity?.let {
|
||||
DirectUtils.directToQGameById(it, game.qqMiniGameAppId)
|
||||
}
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
binding.root.context,
|
||||
game.id,
|
||||
"(${entrance}-游戏[" + game.name + "])",
|
||||
exposureEvent
|
||||
)
|
||||
}
|
||||
if (holder.binding.autoVideoView.isInPlayingState) {
|
||||
holder.binding.autoVideoView.uploadVideoStreamingPlaying(
|
||||
"游戏详情-播放点击",
|
||||
|
||||
@ -3,10 +3,13 @@ package com.gh.gamecenter.personal
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.database.sqlite.SQLiteException
|
||||
import android.graphics.Typeface
|
||||
import android.os.*
|
||||
import android.text.TextUtils
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.content.ContextCompat
|
||||
@ -57,6 +60,7 @@ import com.tencent.connect.common.Constants
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import splitties.views.dsl.core.endMargin
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.abs
|
||||
@ -426,10 +430,18 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
mStubBinding.loginMessageHint.text = ""
|
||||
params.width = 6F.dip2px()
|
||||
params.height = 6F.dip2px()
|
||||
(params as ViewGroup.MarginLayoutParams).topMargin = 0
|
||||
params.endMargin = (-4F).dip2px()
|
||||
mStubBinding.loginMessageHint.setPadding(0, 0, 0, 0)
|
||||
mStubBinding.loginMessageHint.minWidth = 0
|
||||
} else {
|
||||
BindingAdapters.setMessageUnread(mStubBinding.loginMessageHint, it)
|
||||
params.width = 12F.dip2px()
|
||||
params.height = 12F.dip2px()
|
||||
params.width = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
params.height = 14F.dip2px()
|
||||
(params as ViewGroup.MarginLayoutParams).topMargin = (-4F).dip2px()
|
||||
params.endMargin = (-8F).dip2px()
|
||||
mStubBinding.loginMessageHint.setPadding(4F.dip2px(), 0, 4F.dip2px(), 0)
|
||||
mStubBinding.loginMessageHint.minWidth = 14F.dip2px()
|
||||
}
|
||||
mStubBinding.loginMessageHint.layoutParams = params
|
||||
} else {
|
||||
@ -570,6 +582,8 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
mStubBinding.darkModeIv.goneIf(!(Config.getNightModeSetting()?.icon ?: false))
|
||||
mStubBinding.darkModeIv.setImageResource(if (mIsDarkModeOn) R.drawable.ic_personal_light_mode else R.drawable.ic_personal_dark_mode)
|
||||
mStubBinding.ivArrow.enlargeTouchArea()
|
||||
mStubBinding.loginMessageHint.typeface =
|
||||
Typeface.createFromAsset(requireContext().assets, "fonts/d_din_bold_only_number.ttf")
|
||||
|
||||
mStubBinding.motionLayout.setOnClickListener(this)
|
||||
mStubBinding.toolbarContainer.setOnClickListener(this)
|
||||
|
||||
23
app/src/main/java/com/gh/gamecenter/qgame/QGameFragment.kt
Normal file
23
app/src/main/java/com/gh/gamecenter/qgame/QGameFragment.kt
Normal file
@ -0,0 +1,23 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.game.GameFragment
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
/**
|
||||
* QQ小游戏-专题页面
|
||||
*/
|
||||
class QGameFragment : GameFragment() {
|
||||
|
||||
/**
|
||||
* 只替换ViewModel,UI显示与GameFragment完全相同
|
||||
*/
|
||||
override fun provideViewModel(): QGameViewModel {
|
||||
val factory = QGameViewModel.Factory(
|
||||
HaloApp.getInstance().application,
|
||||
SubjectRecommendEntity(text = "QQ小游戏")
|
||||
)
|
||||
return viewModelProvider(factory)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.updateStatusBarColor
|
||||
import com.gh.gamecenter.forum.search.ForumOrUserSearchActivity
|
||||
import com.gh.gamecenter.setting.R
|
||||
|
||||
/**
|
||||
* QQ小游戏-首页
|
||||
*/
|
||||
class QGameHomeWrapperActivity : ToolBarActivity() {
|
||||
|
||||
override fun provideNormalIntent(): Intent {
|
||||
return getTargetIntent(this, QGameHomeWrapperActivity::class.java, QGameHomeWrapperFragment::class.java)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
updateStatusBarColor(R.color.background_white, R.color.background_white)
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
updateStatusBarColor(R.color.background_white, R.color.background_white)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context): Intent {
|
||||
val intent = Intent(context, QGameHomeWrapperActivity::class.java)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.SearchActivity
|
||||
import com.gh.gamecenter.SearchType
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
import com.gh.gamecenter.databinding.FragmentQgameHomeBinding
|
||||
|
||||
class QGameHomeWrapperFragment : ToolbarFragment() {
|
||||
|
||||
private lateinit var viewBinding: FragmentQgameHomeBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setNavigationTitle(getString(R.string.qgame_title))
|
||||
val contentFragment = childFragmentManager.findFragmentById(R.id.wrapper_content) ?: QGameFragment()
|
||||
childFragmentManager.beginTransaction().replace(R.id.wrapper_content, contentFragment).commitAllowingStateLoss()
|
||||
}
|
||||
|
||||
override fun getInflatedLayout(): View =
|
||||
FragmentQgameHomeBinding.inflate(layoutInflater).also { viewBinding = it }.root
|
||||
|
||||
override fun initView(view: View?) {
|
||||
super.initView(view)
|
||||
viewBinding.searchBar.root.setOnClickListener {
|
||||
DirectUtils.directToQGameSearch(it.context, "请输入小游戏关键词", "QQ小游戏")
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int = 0
|
||||
}
|
||||
@ -0,0 +1,168 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.baselist.DiffUtilAdapter
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.utils.visibleIf
|
||||
import com.gh.gamecenter.common.view.GridSpacingItemColorDecoration
|
||||
import com.gh.gamecenter.databinding.ItemHomeRecentVgameBinding
|
||||
import com.gh.gamecenter.databinding.ItemHomeVgameBinding
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
|
||||
class QGameHorizontalSlideListViewHolder(var binding: ItemHomeRecentVgameBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bindHorizontalSlideList(subject: SubjectEntity) {
|
||||
binding.vspaceIv.visibility = View.GONE
|
||||
binding.divider.visibility = View.GONE
|
||||
|
||||
if (subject.showName) {
|
||||
binding.titleTv.visibility = View.VISIBLE
|
||||
binding.titleTv.text = subject.getFilterName()
|
||||
} else {
|
||||
binding.titleTv.visibility = View.GONE
|
||||
}
|
||||
|
||||
val text = if ("change" == subject.home) {
|
||||
"换一批"
|
||||
} else {
|
||||
when (subject.home) {
|
||||
"more" -> "更多"
|
||||
"hide" -> ""
|
||||
else -> "全部"
|
||||
}
|
||||
}
|
||||
binding.moreTv.text = text
|
||||
|
||||
if (subject.indexRightTop != null && subject.indexRightTop != "none") {
|
||||
// 开测表用到的
|
||||
binding.moreTv.visibility = View.VISIBLE
|
||||
if (subject.indexRightTop == "all") {
|
||||
binding.moreTv.text = "全部"
|
||||
} else {
|
||||
binding.moreTv.text = "更多"
|
||||
}
|
||||
} else if (text == "全部"
|
||||
&& subject.data != null
|
||||
&& subject.data!!.size >= (subject.more ?: 0)
|
||||
) {
|
||||
binding.moreTv.visibility = View.GONE
|
||||
} else if (subject.home == "hide") {
|
||||
binding.moreTv.visibility = View.GONE
|
||||
} else {
|
||||
binding.moreTv.visibility = View.VISIBLE
|
||||
}
|
||||
if (binding.moreTv.visibility == View.VISIBLE && (binding.moreTv.text == "更多" || binding.moreTv.text == "全部")) {
|
||||
binding.moreTv.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
val subjectAdapter = if (binding.recyclerView.adapter == null) {
|
||||
val layoutManager =
|
||||
LinearLayoutManager(binding.root.context, RecyclerView.HORIZONTAL, false)
|
||||
|
||||
binding.recyclerView.layoutManager = layoutManager
|
||||
binding.recyclerView.itemAnimator = null
|
||||
val adapter = QGameHorizontalSlideAdapter(binding.root.context)
|
||||
binding.recyclerView.adapter = adapter
|
||||
binding.recyclerView.addItemDecoration(
|
||||
GridSpacingItemColorDecoration(binding.root.context, 4, 0, R.color.transparent)
|
||||
)
|
||||
|
||||
binding.recyclerView.addOnScrollListener(object : OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
if (dx == 0) {
|
||||
val scrollToEnd =
|
||||
layoutManager.findLastCompletelyVisibleItemPosition() == (binding.recyclerView.adapter!!.itemCount - 1)
|
||||
// 当游戏数量超过一屏时,需去除列表右侧的分隔线;去除后,列表最后一个游戏图标与卡片右侧的边距应为16dp
|
||||
if (scrollToEnd) {
|
||||
binding.recyclerViewContainer.post {
|
||||
binding.recyclerViewContainer.layoutParams =
|
||||
(binding.recyclerViewContainer.layoutParams as MarginLayoutParams).apply {
|
||||
rightMargin = 10F.dip2px()
|
||||
}
|
||||
}
|
||||
binding.divider.visibility = View.VISIBLE
|
||||
|
||||
} else {
|
||||
binding.recyclerViewContainer.post {
|
||||
binding.recyclerViewContainer.layoutParams =
|
||||
(binding.recyclerViewContainer.layoutParams as MarginLayoutParams).apply {
|
||||
rightMargin = 0
|
||||
}
|
||||
}
|
||||
binding.divider.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
adapter
|
||||
} else {
|
||||
binding.recyclerView.adapter as QGameHorizontalSlideAdapter
|
||||
}
|
||||
|
||||
subjectAdapter.submitList(subject.data)
|
||||
}
|
||||
}
|
||||
|
||||
class QGameHorizontalSlideAdapter(context: Context) : DiffUtilAdapter<GameEntity>(context) {
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
): QGameHorizontalSlideViewHolder {
|
||||
return QGameHorizontalSlideViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
(holder as QGameHorizontalSlideViewHolder).bindView(mDataList[position])
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mDataList.size
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
|
||||
class QGameHorizontalSlideViewHolder(private var mBinding: ItemHomeVgameBinding) :
|
||||
RecyclerView.ViewHolder(mBinding.root) {
|
||||
|
||||
fun bindView(entity: GameEntity) {
|
||||
mBinding.gameIconIv.displayGameIcon(entity)
|
||||
|
||||
mBinding.maskView.visibility = View.GONE
|
||||
mBinding.controlTv.visibility = View.GONE
|
||||
mBinding.progressBar.visibility = View.GONE
|
||||
mBinding.dotView.visibility = View.GONE
|
||||
mBinding.updateHintIv.visibility = View.GONE
|
||||
mBinding.controlTv.visibility = View.GONE
|
||||
mBinding.progressBar.visibility = View.GONE
|
||||
|
||||
mBinding.root.setOnClickListener {
|
||||
NewFlatLogUtils.logQGameClick(entity.qqMiniGameAppId, entity.name)
|
||||
GlobalActivityManager.currentActivity?.let {
|
||||
DirectUtils.directToQGameById(it, entity.qqMiniGameAppId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.DisplayType
|
||||
import com.gh.gamecenter.SearchActivity
|
||||
import com.gh.gamecenter.SearchType
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.login.R
|
||||
import com.gh.gamecenter.search.SearchGameIndexFragment
|
||||
import com.lightgame.utils.Util_System_Keyboard
|
||||
|
||||
/**
|
||||
* QQ小游戏-搜索页面
|
||||
*/
|
||||
class QGameSearchActivity : SearchActivity() {
|
||||
|
||||
override fun updateDisplayType(type: DisplayType) {
|
||||
val transaction = supportFragmentManager.beginTransaction()
|
||||
when(type) {
|
||||
DisplayType.GAME_DETAIL -> {
|
||||
val digestListFragment =
|
||||
supportFragmentManager.findFragmentByTag(QGameSearchResultFragment::class.java.name) as? QGameSearchResultFragment
|
||||
?: QGameSearchResultFragment()
|
||||
digestListFragment.setParams(mSearchKey ?: "", mSearchType.value)
|
||||
transaction.replace(com.gh.gamecenter.R.id.search_result, digestListFragment, SearchGameIndexFragment::class.java.name)
|
||||
}
|
||||
else -> {
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
Util_System_Keyboard.showSoftKeyboard(this)
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
mDisplayType = type
|
||||
transaction.commitAllowingStateLoss()
|
||||
}
|
||||
|
||||
override fun handleBackPressed(): Boolean {
|
||||
Util_System_Keyboard.hideSoftKeyboard(this)
|
||||
finish()
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun getIntent(
|
||||
context: Context,
|
||||
hint: String,
|
||||
sourceEntrance: String
|
||||
): Intent {
|
||||
val intent = Intent(context, QGameSearchActivity::class.java)
|
||||
intent.putExtra(EntranceConsts.KEY_HINT, hint)
|
||||
intent.putExtra(EntranceConsts.KEY_SOURCE_ENTRANCE, sourceEntrance)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.search.SearchGameResultFragment
|
||||
import com.gh.gamecenter.search.SearchGameResultViewModel
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
/**
|
||||
* QQ小游戏-搜索结果页面
|
||||
*/
|
||||
class QGameSearchResultFragment : SearchGameResultFragment() {
|
||||
|
||||
/**
|
||||
* 仅替换搜索游戏的API,搜索结果页面样式与首页的完全一致
|
||||
*/
|
||||
override fun provideListViewModel(): SearchGameResultViewModel {
|
||||
val factory = SearchGameResultViewModel.Factory(
|
||||
HaloApp.getInstance().application,
|
||||
mKey,
|
||||
true,
|
||||
QGameSearchResultRepository()
|
||||
)
|
||||
return viewModelProvider(factory)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import com.gh.gamecenter.common.utils.EnvHelper
|
||||
import com.gh.gamecenter.entity.SearchSubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import com.gh.gamecenter.search.ISearchGameResultRepository
|
||||
import io.reactivex.Observable
|
||||
import java.net.URLEncoder
|
||||
|
||||
class QGameSearchResultRepository(
|
||||
private val api: ApiService = RetrofitManager.getInstance().newApi
|
||||
) : ISearchGameResultRepository {
|
||||
|
||||
override fun getSearchGame(
|
||||
key: String?,
|
||||
page: Int
|
||||
): Observable<List<GameEntity>> {
|
||||
// 可能会有特殊字符,需要 encode 处理
|
||||
val encodedKey = URLEncoder.encode(key, "utf-8")
|
||||
return api.getSearchQGame(
|
||||
EnvHelper.getNewHost() + "games/qq_mini/columns/game_search?keyword=" +
|
||||
encodedKey + "&page=" + page + "&page_size=20"
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>> {
|
||||
return Observable.just(emptyList())
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import com.gh.gamecenter.subject.ISubjectListRepository
|
||||
import io.reactivex.Single
|
||||
|
||||
class QGameSubjectListRepository(
|
||||
private val api: ApiService = RetrofitManager.getInstance().newApi
|
||||
) : ISubjectListRepository {
|
||||
|
||||
override fun getColumn(column_id: String?, page: Int, sort: String?, order: String?): Single<MutableList<GameEntity>> {
|
||||
return api.getQGameColumn(column_id, order, page, 20)
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import com.gh.gamecenter.subject.ISubjectRepository
|
||||
import io.reactivex.Observable
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.ResponseBody
|
||||
|
||||
class QGameSubjectRepository(
|
||||
private val api: ApiService = RetrofitManager.getInstance().newApi
|
||||
) : ISubjectRepository {
|
||||
|
||||
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {
|
||||
return api.getQGameColumnSettings(column_id)
|
||||
|
||||
}
|
||||
|
||||
override fun getSubjectName(column_id: String?): Observable<ResponseBody> {
|
||||
return Observable.just(ResponseBody.create(MediaType.parse("application/json"), "{\"name\": \"专题\"}"))
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
class QGameSubjectUpdateEvent {
|
||||
}
|
||||
583
app/src/main/java/com/gh/gamecenter/qgame/QGameViewModel.kt
Normal file
583
app/src/main/java/com/gh/gamecenter/qgame/QGameViewModel.kt
Normal file
@ -0,0 +1,583 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import androidx.collection.ArrayMap
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.util.GameSubstituteRepositoryHelper
|
||||
import com.gh.common.util.GameUtils
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.core.provider.IQGameProvider
|
||||
import com.gh.gamecenter.core.utils.RandomUtils
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.GameSubjectData
|
||||
import com.gh.gamecenter.feature.utils.ApkActiveUtils
|
||||
import com.gh.gamecenter.game.BaseGameViewModel
|
||||
import com.gh.gamecenter.game.GameViewModel
|
||||
import com.gh.gamecenter.game.data.GameItemData
|
||||
import com.gh.gamecenter.game.rank.RankCollectionAdapter
|
||||
import com.gh.gamecenter.home.BlankDividerViewHolder
|
||||
import com.gh.gamecenter.home.LegacyHomeFragmentAdapterAssistant
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import retrofit2.HttpException
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class QGameViewModel(application: Application, blockData: SubjectRecommendEntity?) :
|
||||
BaseGameViewModel(application, blockData) {
|
||||
|
||||
private val mSensitiveApi = RetrofitManager.getInstance().newApi
|
||||
|
||||
private var mSubjectList: MutableList<SubjectEntity> = ArrayList() // 专题
|
||||
|
||||
private val mSubjectChangedMap: ArrayMap<String, List<GameEntity>> = ArrayMap() // 存储换一换的数据
|
||||
|
||||
// 所有专题里的所有游戏 ID 的集合,供替换时排重用
|
||||
private var mSubjectGameIdList = hashSetOf<String>()
|
||||
|
||||
private var mIsLoading = false
|
||||
|
||||
init {
|
||||
initQQMiniGameSDK(application)
|
||||
initData()
|
||||
EventBus.getDefault().register(this)// 为了减少对原有逻辑的影响,把EventBus注册在这里
|
||||
}
|
||||
|
||||
override fun onInitData() {
|
||||
mSubjectList = arrayListOf()
|
||||
loadStatus.postValue(LoadStatus.INIT_LOADING)
|
||||
getQGameSubjectList()
|
||||
}
|
||||
|
||||
override fun changeSubjectGame(subjectId: String) {
|
||||
mSensitiveApi
|
||||
.getSubjectQGame(subjectId)
|
||||
.map(RegionSettingHelper.filterGame)
|
||||
.map(ApkActiveUtils.filterMapperList)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<List<GameEntity>>() {
|
||||
override fun onResponse(response: List<GameEntity>?) {
|
||||
if (response != null) {
|
||||
mSubjectChangedMap[subjectId] = response
|
||||
initRandomGame(subjectId, java.util.ArrayList(response))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
Utils.toast(getApplication(), "网络异常")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun getQGameSubjectList() {
|
||||
if (mIsLoading) return
|
||||
|
||||
mSensitiveApi
|
||||
.subjectQGameList
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<List<SubjectEntity>>() {
|
||||
override fun onResponse(response: List<SubjectEntity>?) {
|
||||
if (response != null) {
|
||||
when {
|
||||
response.isEmpty() -> {
|
||||
loadStatus.postValue(LoadStatus.LIST_OVER)
|
||||
}
|
||||
|
||||
else -> {
|
||||
mSubjectList.addAll(response)
|
||||
loadStatus.postValue(LoadStatus.LIST_OVER)
|
||||
transformItemData()
|
||||
}
|
||||
}
|
||||
}
|
||||
mIsLoading = false
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
loadStatus.postValue(LoadStatus.LIST_FAILED)
|
||||
mIsLoading = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 随机产生专题数据(换一换)
|
||||
private fun initRandomGame(subjectId: String, sourceList: List<GameEntity>?) {
|
||||
|
||||
var rawList: MutableList<GameEntity>? = null
|
||||
for (entity in mSubjectList) {
|
||||
if (entity.id == subjectId) rawList = entity.data
|
||||
}
|
||||
if (rawList == null) return
|
||||
|
||||
var sourceList = sourceList
|
||||
|
||||
var size = rawList.size // 判断是否有大图
|
||||
|
||||
var i = 0
|
||||
while (i < rawList.size) { //删除原数据,排除大图
|
||||
if (TextUtils.isEmpty(rawList[i].image)) {
|
||||
rawList.removeAt(i)
|
||||
i--
|
||||
} else {
|
||||
size--
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if (size * 2 <= sourceList!!.size) {
|
||||
sourceList = GameUtils.removeDuplicateData(rawList, sourceList)//排除重复
|
||||
}
|
||||
|
||||
val indexes = RandomUtils.getRandomArray(size, sourceList!!.size)
|
||||
for (index in indexes) {
|
||||
val gameEntity = sourceList[index]
|
||||
rawList.add(gameEntity)
|
||||
}
|
||||
transformItemData()
|
||||
}
|
||||
|
||||
private fun transformItemData() {
|
||||
mItemDataListCache.clear()
|
||||
positionAndPackageMap.clear()
|
||||
|
||||
val iterator = mSubjectList.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val item = iterator.next()
|
||||
// 双列卡片专题过滤掉无封面图游戏
|
||||
if (item.type == "game_double_card") {
|
||||
item.data = item.data?.filter { it.columnImage.isNotBlank() }?.toMutableList()
|
||||
// 游戏数量小于2个不显示专题,所以直接去掉
|
||||
if ((item.data?.size ?: 0) < 2) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
//过滤掉游戏数量小于2个的视频横屏滑动专题
|
||||
if (item.type == "game_video_horizontal_slide") {
|
||||
if ((item.data?.size ?: 0) < 2) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 专题 "type": "image/game_vertical/game_horizontal"
|
||||
for ((index, subjectEntity) in mSubjectList.withIndex()) {
|
||||
var containsImageBeforeHead = false // 在专题名上面是否有大图
|
||||
|
||||
val data = subjectEntity.data
|
||||
|
||||
// 这个 for 循环主要功能是用来标识替换已安装的游戏
|
||||
if (!data.isNullOrEmpty()) {
|
||||
for (game in data) {
|
||||
mSubjectGameIdList.add(game.id)
|
||||
// 应用专题是否显示游戏名后缀的配置
|
||||
game.shouldShowNameSuffix = subjectEntity.showSuffix
|
||||
}
|
||||
}
|
||||
|
||||
if (!data.isNullOrEmpty()) {
|
||||
subjectEntity.relatedColumnId?.let {
|
||||
GameSubstituteRepositoryHelper.replaceGames(data, mSubjectGameIdList, it, false)
|
||||
}
|
||||
}
|
||||
val shouldShowDivider = subjectEntity.type == "game" || subjectEntity.type == "video"
|
||||
// 是否不显示专题标题
|
||||
val hideSubjectName = !subjectEntity.showName
|
||||
|
||||
// 判断是否添加顶部间距
|
||||
// 顶部 & 显示了分割线的 & 隐藏了专题标题的 item 不添加顶部间距
|
||||
if (index != 0
|
||||
&& !shouldShowDivider
|
||||
&& !hideSubjectName
|
||||
&& !(subjectEntity.type == "game_list_collection" && subjectEntity.style == LegacyHomeFragmentAdapterAssistant.GAME_COLLECTION_VERTICAL_REFRESH_STYLE)
|
||||
) {
|
||||
mItemDataListCache.add(getBlankSpacingItem())
|
||||
}
|
||||
|
||||
if (shouldShowDivider) {
|
||||
mItemDataListCache.add(GameItemData().apply { lineDivider = GameViewModel.DEFAULT_DIVIDER })
|
||||
}
|
||||
|
||||
if (!data.isNullOrEmpty() && !data[0].image.isNullOrEmpty() && subjectEntity.type != "column_collection") {
|
||||
val itemDataImage = GameItemData()
|
||||
val gameEntity = data[0]
|
||||
var isBigImageWithGame = false
|
||||
|
||||
if (gameEntity.id.isNullOrEmpty()) gameEntity.id = gameEntity.link ?: ""
|
||||
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
|
||||
// 图片专题样式(后台操作->只显示(滑动))
|
||||
if (data[0].type == "column" && subjectEntity.type == "image_slide") {
|
||||
itemDataImage.imageSlide = gameEntity
|
||||
gameEntity.games?.let {
|
||||
for ((i, g) in it.withIndex()) {
|
||||
g.sequence = i
|
||||
g.outerSequence = index
|
||||
}
|
||||
}
|
||||
} else {
|
||||
itemDataImage.image = gameEntity
|
||||
itemDataImage.image?.subjectData =
|
||||
GameSubjectData(id = subjectEntity.id, name = subjectEntity.name, isOrder = false)
|
||||
if (gameEntity.type == "game") {
|
||||
isBigImageWithGame = true
|
||||
}
|
||||
}
|
||||
|
||||
containsImageBeforeHead = true
|
||||
mItemDataListCache.add(itemDataImage)
|
||||
|
||||
// 确保下载按钮更新
|
||||
if (isBigImageWithGame) {
|
||||
addGamePositionAndPackage(gameEntity)
|
||||
}
|
||||
|
||||
mItemDataListCache.add(getBlankSpacingItem()) // 图片风格 item 后需要空白间距
|
||||
if (subjectEntity.type == "image" || subjectEntity.type == "image_slide") continue
|
||||
}
|
||||
|
||||
// 专题名
|
||||
if (!hideSubjectName
|
||||
&& (subjectEntity.type != "column_collection"
|
||||
&& subjectEntity.type != "column_test_v2"
|
||||
&& subjectEntity.type != "community_article"
|
||||
&& subjectEntity.type != "question"
|
||||
&& subjectEntity.type != "bbs_video"
|
||||
&& subjectEntity.type != "news"
|
||||
&& subjectEntity.type != "game"
|
||||
&& subjectEntity.type != "video"
|
||||
&& subjectEntity.type != "game_explore"
|
||||
&& subjectEntity.type != "game_list_collection"
|
||||
&& subjectEntity.type != "qq_game_horizontal_slide"
|
||||
&& subjectEntity.type != "gallery")
|
||||
|| (subjectEntity.type == "column_collection" && subjectEntity.style != "top")
|
||||
) {
|
||||
val itemDataHead = GameItemData()
|
||||
|
||||
// 专题名称与大图间需要额外的空白间距
|
||||
if (containsImageBeforeHead) {
|
||||
mItemDataListCache.add(getBlankSpacingItem())
|
||||
}
|
||||
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
|
||||
itemDataHead.columnHead = subjectEntity
|
||||
mItemDataListCache.add(itemDataHead)
|
||||
}
|
||||
|
||||
// 裁剪排行榜数据数量
|
||||
if (subjectEntity.type == "column_collection" && subjectEntity.style == "top") {
|
||||
subjectEntity.columns.let { columns ->
|
||||
for (column in columns) {
|
||||
column.data =
|
||||
ArrayList(column.data?.take(RankCollectionAdapter.MAX_RANK_ITEM_COUNT) ?: listOf())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!data.isNullOrEmpty()) {
|
||||
if (subjectEntity.type == "game_vertical_slide") {
|
||||
val itemVerticalSlide = GameItemData()
|
||||
itemVerticalSlide.verticalSlide = subjectEntity
|
||||
mItemDataListCache.add(itemVerticalSlide)
|
||||
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
|
||||
for (i in 0 until data.size) {
|
||||
val game = data[i]
|
||||
if (!game.image.isNullOrEmpty()) continue
|
||||
game.subjectData = GameSubjectData(
|
||||
id = subjectEntity.id,
|
||||
name = subjectEntity.name,
|
||||
tag = subjectEntity.tag,
|
||||
position = i + if (data[0].image.isNullOrEmpty()) 1 else 0,
|
||||
isOrder = subjectEntity.isOrder,
|
||||
briefStyle = subjectEntity.briefStyle,
|
||||
isShowSuffix = subjectEntity.showSuffix
|
||||
)
|
||||
|
||||
addGamePositionAndPackage(game)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "game_horizontal_slide") {
|
||||
val itemHorizontalSlide = GameItemData()
|
||||
itemHorizontalSlide.horizontalSlide = subjectEntity
|
||||
|
||||
// 开测表数据,把全部转化为右上角跳转
|
||||
if (subjectEntity.indexRightTop == "all") {
|
||||
subjectEntity.indexRightTopLink =
|
||||
LinkEntity(text = subjectEntity.name, link = subjectEntity.id, type = "column_test")
|
||||
}
|
||||
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
mItemDataListCache.add(itemHorizontalSlide)
|
||||
continue
|
||||
}
|
||||
|
||||
// QQ小游戏-横屏滑动
|
||||
if (subjectEntity.type == "qq_game_horizontal_slide") {
|
||||
val itemQQHorizontalSlide = GameItemData()
|
||||
itemQQHorizontalSlide.qqHorizontalSlide = subjectEntity
|
||||
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
mItemDataListCache.add(itemQQHorizontalSlide)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "game_horizontal") {
|
||||
val itemDataSubject = GameItemData()
|
||||
itemDataSubject.horizontalColumn = subjectEntity
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
mItemDataListCache.add(itemDataSubject)
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "column_collection" && subjectEntity.style != "top") {
|
||||
val itemColumnCollection = GameItemData()
|
||||
itemColumnCollection.columnCollection = subjectEntity
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
mItemDataListCache.add(itemColumnCollection)
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "common_collection") {
|
||||
if (subjectEntity.homePageStyle == "1-2") {
|
||||
// 样式为一行两个的时候把数据拆分为若干个一行两个的小item,根据 offset 来在原数据中的获取数据
|
||||
var lineCount = (((subjectEntity.commonCollectionList?.size ?: 0).toDouble()) / 2).roundToInt()
|
||||
if (!TextUtils.isEmpty(subjectEntity.verticalLine)) {
|
||||
val serverSideLineCount = subjectEntity.verticalLine.toInt()
|
||||
if (lineCount == 0 || serverSideLineCount < lineCount) {
|
||||
lineCount = serverSideLineCount
|
||||
}
|
||||
}
|
||||
|
||||
for (i in 0 until lineCount) {
|
||||
if (i == 0) {
|
||||
mItemDataListCache.add(GameItemData().apply { blankDivider = 12F })
|
||||
} else {
|
||||
if (subjectEntity.style == "img-list") {
|
||||
mItemDataListCache.add(GameItemData().apply { blankDivider = 12F })
|
||||
}
|
||||
}
|
||||
|
||||
val itemDataSubject = GameItemData()
|
||||
itemDataSubject.commonLinkCollection12 = subjectEntity
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
itemDataSubject.offset = i * 2
|
||||
mItemDataListCache.add(itemDataSubject)
|
||||
}
|
||||
} else {
|
||||
val itemCommonCollection = GameItemData()
|
||||
itemCommonCollection.commonLinkCollection = subjectEntity
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
mItemDataListCache.add(itemCommonCollection)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "gallery") {
|
||||
val itemItemData = GameItemData()
|
||||
itemItemData.gallery = subjectEntity
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
// 小于3就不要滚动了
|
||||
if (subjectEntity.data != null && subjectEntity.data!!.size > 3) {
|
||||
for ((index, game) in subjectEntity.data!!.withIndex()) {
|
||||
game.sequence = index
|
||||
}
|
||||
mItemDataListCache.add(itemItemData)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "gallery" || subjectEntity.type == "gallery_slide") {
|
||||
val itemItemData = GameItemData()
|
||||
itemItemData.gallerySlide = subjectEntity
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
// 小于3就不要滚动了
|
||||
if (subjectEntity.data != null && subjectEntity.data!!.size > 3) {
|
||||
for ((index, game) in subjectEntity.data!!.withIndex()) {
|
||||
game.sequence = index
|
||||
}
|
||||
mItemDataListCache.add(itemItemData)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "game_double_card") {
|
||||
val gameCount = subjectEntity.data?.size ?: continue
|
||||
|
||||
for (i in 0 until gameCount) {
|
||||
if (i % 2 == 0) {
|
||||
if (i == 0) {
|
||||
mItemDataListCache.add(GameItemData().apply { blankDivider = 12F })
|
||||
}
|
||||
|
||||
val itemDataSubject = GameItemData()
|
||||
itemDataSubject.doubleCardColumn = subjectEntity
|
||||
itemDataSubject.offset = i
|
||||
mItemDataListCache.add(itemDataSubject)
|
||||
}
|
||||
}
|
||||
|
||||
mItemDataListCache.add(GameItemData().apply { blankDivider = 12F })
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "community_article"
|
||||
|| subjectEntity.type == "question"
|
||||
|| subjectEntity.type == "bbs_video"
|
||||
|| subjectEntity.type == "news"
|
||||
) {
|
||||
val itemDataSubject = GameItemData()
|
||||
itemDataSubject.bigImageRecommend = subjectEntity
|
||||
mItemDataListCache.add(itemDataSubject)
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "game_video_horizontal_slide") {
|
||||
val itemItemData = GameItemData().apply {
|
||||
horizontalSlideVideo = subjectEntity
|
||||
}
|
||||
mItemDataListCache.add(itemItemData)
|
||||
itemItemData.horizontalSlideVideo?.data?.forEach {
|
||||
addGamePositionAndPackage(it)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (!data.isNullOrEmpty()) {
|
||||
for (i in 0 until data.size) {
|
||||
val game = data[i]
|
||||
if (!game.image.isNullOrEmpty()) continue
|
||||
|
||||
// 第一个普通游戏顶部需要增加半高的填充间距
|
||||
if (i == 0) {
|
||||
mItemDataListCache.add(GameItemData().apply {
|
||||
blankDivider = BlankDividerViewHolder.DEFAULT_BLANK_HEIGHT
|
||||
})
|
||||
}
|
||||
|
||||
game.subjectData = GameSubjectData(
|
||||
id = subjectEntity.id,
|
||||
name = subjectEntity.name,
|
||||
tag = subjectEntity.tag,
|
||||
position = i + if (data[0].image.isNullOrEmpty()) 1 else 0,
|
||||
isOrder = subjectEntity.isOrder,
|
||||
briefStyle = subjectEntity.briefStyle,
|
||||
isShowSuffix = subjectEntity.showSuffix
|
||||
)
|
||||
val itemDataGame = GameItemData()
|
||||
itemDataGame.game = game
|
||||
mItemDataListCache.add(itemDataGame)
|
||||
addGamePositionAndPackage(game)
|
||||
}
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "column_test_v2") {
|
||||
//新游开测 标题和全部按钮
|
||||
val head = GameItemData()
|
||||
val rightTopLink = subjectEntity.testV2Data?.rightTop?.link
|
||||
val indexRightTop = subjectEntity.testV2Data?.rightTop?.text
|
||||
head.columnHead =
|
||||
SubjectEntity(
|
||||
type = subjectEntity.type,
|
||||
name = "新游开测",
|
||||
indexRightTop = indexRightTop,
|
||||
indexRightTopLink = rightTopLink
|
||||
)
|
||||
mItemDataListCache.add(head)
|
||||
//新游开测 条目
|
||||
val item = GameItemData()
|
||||
item.gameTestV2Entity = subjectEntity.testV2Data
|
||||
mItemDataListCache.add(item)
|
||||
continue
|
||||
}
|
||||
|
||||
if (subjectEntity.type == "game" || subjectEntity.type == "video") {
|
||||
val itemItemData = GameItemData()
|
||||
itemItemData.attachGame = subjectEntity
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
mItemDataListCache.add(itemItemData)
|
||||
subjectEntity.linkGame?.let {
|
||||
addGamePositionAndPackage(it)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
appendAdditionalInfoToSubjectGame(subjectEntity, index)
|
||||
}
|
||||
|
||||
itemDataList.postValue(mItemDataListCache)
|
||||
}
|
||||
|
||||
override fun getSubjectList() {
|
||||
loadStatus.postValue(LoadStatus.LIST_OVER)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onQGameSubjectUpdate(event: QGameSubjectUpdateEvent) {
|
||||
onInitData()
|
||||
}
|
||||
|
||||
override fun replaceRefreshData(itemData: GameItemData): Boolean = false
|
||||
|
||||
override fun refreshDiscoverCardData() = Unit
|
||||
|
||||
override fun changeGameCollectionRefresh(collectionId: String, isRefreshClick: Boolean): Boolean = false
|
||||
|
||||
class Factory(val mApplication: Application, val blockData: SubjectRecommendEntity?) :
|
||||
ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return QGameViewModel(mApplication, blockData) as T
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private var isQQMiniSDKInit = false
|
||||
|
||||
/**
|
||||
* QQ小游戏SDK初始化
|
||||
*/
|
||||
private fun initQQMiniGameSDK(context: Context) {
|
||||
if (isQQMiniSDKInit) return
|
||||
val provider = ARouter
|
||||
.getInstance()
|
||||
.build(RouteConsts.provider.qGame)
|
||||
.navigation() as IQGameProvider<*>
|
||||
provider.init(context, Config.WECHAT_APPID, Config.TENCENT_APPID)
|
||||
isQQMiniSDKInit = true
|
||||
}
|
||||
|
||||
fun notifyQGameSubjectUpdate() {
|
||||
EventBus.getDefault().post(QGameSubjectUpdateEvent())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ import android.content.Context;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.retrofit.BaseRetrofitManager;
|
||||
import com.gh.gamecenter.common.utils.EnvHelper;
|
||||
import com.gh.gamecenter.retrofit.service.ApiService;
|
||||
import com.gh.gamecenter.retrofit.service.VApiService;
|
||||
import com.halo.assistant.HaloApp;
|
||||
|
||||
@ -1343,14 +1343,14 @@ public interface ApiService {
|
||||
*/
|
||||
@POST("question/{question_id}:set-top")
|
||||
Observable<ResponseBody> topCommunityQuestion(@Path("question_id") String questionId,
|
||||
@Body RequestBody body);
|
||||
@Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 提问帖-取消置顶
|
||||
*/
|
||||
@POST("question/{question_id}:cancel-top")
|
||||
Observable<ResponseBody> cancelTopCommunityQuestion(@Path("question_id") String questionId,
|
||||
@Body RequestBody body);
|
||||
@Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 视频帖-置顶
|
||||
@ -3143,6 +3143,45 @@ public interface ApiService {
|
||||
@GET("blocks/{block_id}/tabs")
|
||||
Single<List<SubjectRecommendEntity>> getBlockTab(@Path("block_id") String blockId);
|
||||
|
||||
/**
|
||||
* QQ小游戏-专题列表
|
||||
*/
|
||||
@GET("games/qq_mini/columns")
|
||||
Observable<List<SubjectEntity>> getSubjectQGameList();
|
||||
|
||||
/**
|
||||
* QQ小游戏-专题-换一换
|
||||
*/
|
||||
@GET("games/qq_mini/columns/{column_id}/games?page=1&page_size=30")
|
||||
Observable<List<GameEntity>> getSubjectQGame(@Path("column_id") String columnId);
|
||||
|
||||
/**
|
||||
* QQ小游戏-专题游戏列表
|
||||
*/
|
||||
@GET("games/qq_mini/columns/{column_id}/games")
|
||||
Single<List<GameEntity>> getQGameColumn(@Path("column_id") String columnId,
|
||||
@Query("filter") String order,
|
||||
@Query("page") int page,
|
||||
@Query("page_size") int pageSize);
|
||||
|
||||
/**
|
||||
* QQ小游戏-搜索
|
||||
*/
|
||||
@GET
|
||||
Observable<List<GameEntity>> getSearchQGame(@Url String url);
|
||||
|
||||
/**
|
||||
* QQ小游戏-游玩记录
|
||||
*/
|
||||
@POST("/games/qq_mini/{appid}/user/{user_id}")
|
||||
Single<ResponseBody> postQGamePlay(@Path("appid") String qqGameId, @Path("user_id") String userId);
|
||||
|
||||
/**
|
||||
* QQ小游戏-专题数据详情
|
||||
*/
|
||||
@GET("/games/qq_mini/columns/{column_id}/setting")
|
||||
Observable<SubjectSettingEntity> getQGameColumnSettings(@Path("column_id") String column_id);
|
||||
|
||||
/**
|
||||
* 获取广告配置
|
||||
*/
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
package com.gh.gamecenter.search
|
||||
|
||||
import com.gh.gamecenter.entity.SearchSubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import io.reactivex.Observable
|
||||
|
||||
interface ISearchGameResultRepository {
|
||||
fun getSearchGame(key: String?, page: Int): Observable<List<GameEntity>>
|
||||
|
||||
fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>>
|
||||
}
|
||||
@ -67,7 +67,8 @@ class SearchGameIndexFragment : ListFragment<GameEntity, SearchGameResultViewMod
|
||||
SearchGameResultViewModel.Factory(
|
||||
HaloApp.getInstance(),
|
||||
mKey,
|
||||
false
|
||||
false,
|
||||
SearchGameResultRepository()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@ -49,6 +49,7 @@ import kotlin.collections.MutableList
|
||||
import kotlin.collections.forEach
|
||||
import kotlin.collections.isNotEmpty
|
||||
import kotlin.collections.set
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
|
||||
class SearchGameResultAdapter(
|
||||
context: Context,
|
||||
@ -451,15 +452,21 @@ class SearchGameResultAdapter(
|
||||
EventBus.getDefault().post(EBSearch("click", gameEntity.id, gameEntity.name))
|
||||
}
|
||||
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext, gameEntity,
|
||||
StringUtils.buildString(
|
||||
entrance, "+(搜索-列表[", key, "=", type, "=",
|
||||
(holder.adapterPosition + 1).toString(), "])"
|
||||
),
|
||||
traceEvent = exposureEvent
|
||||
)
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
GlobalActivityManager.currentActivity?.let {
|
||||
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
|
||||
}
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext, gameEntity,
|
||||
StringUtils.buildString(
|
||||
entrance, "+(搜索-列表[", key, "=", type, "=",
|
||||
(holder.adapterPosition + 1).toString(), "])"
|
||||
),
|
||||
traceEvent = exposureEvent
|
||||
)
|
||||
// mDao.add(gameEntity.nameWithoutSuffix)
|
||||
}
|
||||
|
||||
LogUtils.uploadSearchClick(
|
||||
"search_click",
|
||||
|
||||
@ -40,7 +40,7 @@ import com.lightgame.utils.Util_System_Keyboard
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultViewModel>() {
|
||||
open class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultViewModel>() {
|
||||
|
||||
private var mAdapter: SearchGameResultAdapter? = null
|
||||
private var mExposureListener: ExposureListener? = null
|
||||
@ -49,7 +49,7 @@ class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultViewMo
|
||||
private var mIsFirstLoad = true
|
||||
private val mBinding by lazy { FragmentSearchResultBinding.inflate(layoutInflater) }
|
||||
|
||||
private var mKey: String = ""
|
||||
protected var mKey: String = ""
|
||||
private var mType: String = ""
|
||||
private var mLoadingAnimation = false
|
||||
private var mScrollIng = false
|
||||
@ -72,7 +72,14 @@ class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultViewMo
|
||||
override fun getInflatedLayout() = mBinding.root
|
||||
|
||||
override fun provideListViewModel() =
|
||||
viewModelProvider<SearchGameResultViewModel>(SearchGameResultViewModel.Factory(HaloApp.getInstance(), mKey, true))
|
||||
viewModelProvider<SearchGameResultViewModel>(
|
||||
SearchGameResultViewModel.Factory(
|
||||
HaloApp.getInstance(),
|
||||
mKey,
|
||||
true,
|
||||
SearchGameResultRepository()
|
||||
)
|
||||
)
|
||||
|
||||
override fun provideListAdapter(): SearchGameResultAdapter {
|
||||
if (mAdapter == null) {
|
||||
@ -264,7 +271,12 @@ class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultViewMo
|
||||
|
||||
R.id.container_menu_close -> {
|
||||
if (mScrollIng) return
|
||||
LogUtils.uploadSearchGame("open_floating_window", "搜索页", mKey, SearchType.fromString(mType).toChinese())
|
||||
LogUtils.uploadSearchGame(
|
||||
"open_floating_window",
|
||||
"搜索页",
|
||||
mKey,
|
||||
SearchType.fromString(mType).toChinese()
|
||||
)
|
||||
showOpenMenuView()
|
||||
}
|
||||
|
||||
@ -282,7 +294,12 @@ class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultViewMo
|
||||
R.id.seek_game_btn -> {
|
||||
Util_System_Keyboard.hideSoftKeyboard(requireActivity())
|
||||
MtaHelper.onEvent("游戏搜索", "求游戏", mKey)
|
||||
LogUtils.uploadSearchGame("ask_more_games", " 搜索页-悬浮按钮", mKey, SearchType.fromString(mType).toChinese())
|
||||
LogUtils.uploadSearchGame(
|
||||
"ask_more_games",
|
||||
" 搜索页-悬浮按钮",
|
||||
mKey,
|
||||
SearchType.fromString(mType).toChinese()
|
||||
)
|
||||
HelpAndFeedbackBridge.startSuggestionActivity(context, SuggestType.gameCollect, "", "求游戏:$mKey")
|
||||
showCloseMenuView()
|
||||
}
|
||||
@ -290,7 +307,12 @@ class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultViewMo
|
||||
R.id.seek_function_btn -> {
|
||||
Util_System_Keyboard.hideSoftKeyboard(requireActivity())
|
||||
MtaHelper.onEvent("游戏搜索", "求功能", mKey)
|
||||
LogUtils.uploadSearchGame("ask_more_func", " 搜索页-悬浮按钮", mKey, SearchType.fromString(mType).toChinese())
|
||||
LogUtils.uploadSearchGame(
|
||||
"ask_more_func",
|
||||
" 搜索页-悬浮按钮",
|
||||
mKey,
|
||||
SearchType.fromString(mType).toChinese()
|
||||
)
|
||||
HelpAndFeedbackBridge.startSuggestionActivity(context, SuggestType.functionSuggest, "", "求功能:$mKey")
|
||||
showCloseMenuView()
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
package com.gh.gamecenter.search
|
||||
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.entity.SearchSubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.Observable
|
||||
import java.net.URLEncoder
|
||||
|
||||
class SearchGameResultRepository(
|
||||
private val mApi: ApiService = RetrofitManager.getInstance().api
|
||||
) : ISearchGameResultRepository {
|
||||
|
||||
override fun getSearchGame(
|
||||
key: String?,
|
||||
page: Int
|
||||
): Observable<List<GameEntity>> {
|
||||
// 可能会有特殊字符,需要 encode 处理
|
||||
val encodedKey = URLEncoder.encode(key, "utf-8")
|
||||
return mApi.getSearchGame(
|
||||
Config.API_HOST + "games:search?keyword=" +
|
||||
encodedKey + "&view=digest&page=" + page +
|
||||
"&channel=" + HaloApp.getInstance().channel +
|
||||
"&version=" + BuildConfig.VERSION_NAME
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>> {
|
||||
return mApi.getSearchSubject(key, page)
|
||||
}
|
||||
}
|
||||
@ -11,23 +11,20 @@ import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.common.baselist.LoadParams
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SearchSubjectEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.net.URLEncoder
|
||||
|
||||
class SearchGameResultViewModel(
|
||||
application: Application,
|
||||
private var mSearchKey: String?,
|
||||
private var mIsManuallySearch: Boolean) : ListViewModel<GameEntity, SearchItemData>(application) {
|
||||
private var mIsManuallySearch: Boolean,
|
||||
private val repository: ISearchGameResultRepository) : ListViewModel<GameEntity, SearchItemData>(application) {
|
||||
|
||||
private var mApi = RetrofitManager.getInstance().api
|
||||
private var mPage = 0
|
||||
private var mSearchSubjects = arrayListOf<SearchSubjectEntity>()
|
||||
|
||||
@ -61,7 +58,7 @@ class SearchGameResultViewModel(
|
||||
@SuppressLint("CheckResult")
|
||||
private fun decorateListAndPost(list: MutableList<GameEntity>) {
|
||||
var itemDataList = ArrayList(list.map { SearchItemData(game = it) })
|
||||
mApi.getSearchSubject(mSearchKey, mPage)
|
||||
repository.getSearchSubject(mSearchKey, mPage)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ mutableList ->
|
||||
@ -150,24 +147,18 @@ class SearchGameResultViewModel(
|
||||
}
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<GameEntity>> {
|
||||
// 可能会有特殊字符,需要 encode 处理
|
||||
val encodedKey = URLEncoder.encode(mSearchKey, "utf-8")
|
||||
mPage = page
|
||||
return mApi.getSearchGame(
|
||||
Config.API_HOST + "games:search?keyword=" +
|
||||
encodedKey + "&view=digest&page=" + page +
|
||||
"&channel=" + HaloApp.getInstance().channel +
|
||||
"&version=" + BuildConfig.VERSION_NAME
|
||||
)
|
||||
return repository.getSearchGame(mSearchKey, page)
|
||||
}
|
||||
|
||||
class Factory(
|
||||
private val mApplication: Application,
|
||||
private val mSearchKey: String?,
|
||||
private val mIsManuallySearch: Boolean
|
||||
private val mIsManuallySearch: Boolean,
|
||||
private val repository: ISearchGameResultRepository
|
||||
) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return SearchGameResultViewModel(mApplication, mSearchKey, mIsManuallySearch) as T
|
||||
return SearchGameResultViewModel(mApplication, mSearchKey, mIsManuallySearch, repository) as T
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package com.gh.gamecenter.subject
|
||||
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import io.reactivex.Single
|
||||
|
||||
interface ISubjectListRepository {
|
||||
|
||||
fun getColumn(
|
||||
column_id: String?,
|
||||
page: Int,
|
||||
sort: String?,
|
||||
order: String?,
|
||||
): Single<MutableList<GameEntity>>
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.gh.gamecenter.subject
|
||||
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import io.reactivex.Observable
|
||||
import okhttp3.ResponseBody
|
||||
|
||||
interface ISubjectRepository {
|
||||
|
||||
fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity>
|
||||
|
||||
fun getSubjectName(column_id: String?): Observable<ResponseBody>
|
||||
}
|
||||
@ -11,7 +11,7 @@ import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.feature.exposure.ExposureSource
|
||||
|
||||
class SubjectActivity : DownloadToolbarActivity() {
|
||||
open class SubjectActivity : DownloadToolbarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -51,12 +51,14 @@ class SubjectActivity : DownloadToolbarActivity() {
|
||||
name: String?,
|
||||
isOrder: Boolean,
|
||||
exposureSourceList: ArrayList<ExposureSource>? = null,
|
||||
entrance: String?) {
|
||||
entrance: String?,
|
||||
isQQMiniGame: Boolean = false
|
||||
) {
|
||||
MtaHelper.onEvent("详情页面", "专题详情", name)
|
||||
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
val subjectData = SubjectData(subjectId = id, subjectName = name, isOrder = isOrder)
|
||||
val subjectData = SubjectData(subjectId = id, subjectName = name, isOrder = isOrder, isQQMiniGame = isQQMiniGame)
|
||||
bundle.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, subjectData)
|
||||
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
if (exposureSourceList != null) {
|
||||
|
||||
@ -17,6 +17,7 @@ import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.GameImageViewHolder
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.baselist.ListAdapter
|
||||
import com.gh.gamecenter.common.constant.ItemViewType
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
@ -213,21 +214,27 @@ class SubjectAdapter(
|
||||
holder.itemView.setOnClickListener {
|
||||
DataCollectionUtils.uploadClick(mContext, "列表", subjectData.subjectName, gameEntity.name)
|
||||
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity,
|
||||
StringUtils.buildString(
|
||||
mEntrance,
|
||||
"+(",
|
||||
subjectData.subjectName,
|
||||
":列表[", subjectData.filter,
|
||||
"=",
|
||||
if (subjectData.sort.contains("publish")) "最新"
|
||||
else "最热",
|
||||
"=", (humanReadablePosition).toString(), "])"
|
||||
),
|
||||
traceEvent = exposureEvent
|
||||
)
|
||||
if (gameEntity.isQQMiniGame()) {
|
||||
GlobalActivityManager.currentActivity?.let {
|
||||
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
|
||||
}
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity,
|
||||
StringUtils.buildString(
|
||||
mEntrance,
|
||||
"+(",
|
||||
subjectData.subjectName,
|
||||
":列表[", subjectData.filter,
|
||||
"=",
|
||||
if (subjectData.sort.contains("publish")) "最新"
|
||||
else "最热",
|
||||
"=", (humanReadablePosition).toString(), "])"
|
||||
),
|
||||
traceEvent = exposureEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
DownloadItemUtils.setOnClickListener(
|
||||
|
||||
@ -15,7 +15,7 @@ import com.gh.gamecenter.subject.tab.SubjectTabFragment
|
||||
import com.gh.gamecenter.subject.tile.SubjectTileFragment
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
class SubjectFragment : LazyFragment() {
|
||||
open class SubjectFragment : LazyFragment() {
|
||||
|
||||
private var mBinding: FragmentSubjectBinding? = null
|
||||
private var mViewModel: SubjectViewModel? = null
|
||||
@ -29,11 +29,8 @@ class SubjectFragment : LazyFragment() {
|
||||
|
||||
override fun onFragmentFirstVisible() {
|
||||
initMenu(R.menu.menu_download)
|
||||
val factory = SubjectViewModel.Factory(
|
||||
HaloApp.getInstance().application,
|
||||
arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_DATA)
|
||||
)
|
||||
mViewModel = ViewModelProviders.of(this, factory).get(SubjectViewModel::class.java)
|
||||
|
||||
mViewModel = provideViewModel()
|
||||
|
||||
super.onFragmentFirstVisible()
|
||||
|
||||
@ -97,6 +94,14 @@ class SubjectFragment : LazyFragment() {
|
||||
transaction.commitAllowingStateLoss()
|
||||
}
|
||||
|
||||
protected open fun provideViewModel(): SubjectViewModel {
|
||||
val factory = SubjectViewModel.Factory(
|
||||
HaloApp.getInstance().application,
|
||||
arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_DATA),
|
||||
)
|
||||
return ViewModelProviders.of(this, factory).get(SubjectViewModel::class.java)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val LAST_PAGE_DATA = "last_page_data"
|
||||
}
|
||||
|
||||
@ -10,19 +10,19 @@ import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.baselist.LazyListFragment
|
||||
import com.gh.gamecenter.common.baselist.LoadType
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.common.view.SpacingItemDecoration
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.OnTitleClickListener
|
||||
import com.lightgame.download.DataWatcher
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
package com.gh.gamecenter.subject
|
||||
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import io.reactivex.Single
|
||||
|
||||
class SubjectListRepository(
|
||||
private val api: ApiService = RetrofitManager.getInstance().api
|
||||
) : ISubjectListRepository {
|
||||
|
||||
override fun getColumn(column_id: String?, page: Int, sort: String?, order: String?): Single<MutableList<GameEntity>> {
|
||||
return api.getColumn(column_id, sort, order, page)
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,7 @@ import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.qgame.QGameSubjectListRepository
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
@ -33,14 +34,16 @@ class SubjectListViewModel(
|
||||
|
||||
var lastPageDataMap: HashMap<String, String>? = null
|
||||
|
||||
private val repository = if (subjectData.isQQMiniGame) QGameSubjectListRepository() else SubjectListRepository()
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<GameEntity>>? = null
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<MutableList<GameEntity>> {
|
||||
return RetrofitManager.getInstance().api.getColumn(
|
||||
return repository.getColumn(
|
||||
subjectData.subjectId,
|
||||
page,
|
||||
subjectData.sort,
|
||||
if (subjectData.filter.isEmpty()) "type:全部" else subjectData.filter,
|
||||
page
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package com.gh.gamecenter.subject
|
||||
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import io.reactivex.Observable
|
||||
import okhttp3.ResponseBody
|
||||
|
||||
class SubjectRepository(
|
||||
private val api: ApiService = RetrofitManager.getInstance().api
|
||||
) : ISubjectRepository {
|
||||
|
||||
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {
|
||||
return api.getColumnSettings(column_id)
|
||||
}
|
||||
|
||||
override fun getSubjectName(column_id: String?): Observable<ResponseBody> {
|
||||
return api.getSubjectName(column_id)
|
||||
}
|
||||
}
|
||||
@ -7,21 +7,26 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.common.retrofit.JSONObjectResponse
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.qgame.QGameSubjectRepository
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
|
||||
class SubjectViewModel(application: Application, var subjectData: SubjectData?) : AndroidViewModel(application) {
|
||||
class SubjectViewModel(
|
||||
application: Application,
|
||||
var subjectData: SubjectData?
|
||||
) : AndroidViewModel(application) {
|
||||
|
||||
val subjectNameLD = MutableLiveData<String>()
|
||||
val subjectSettingLD = MutableLiveData<SubjectSettingEntity>()
|
||||
|
||||
private val repository = if (subjectData?.isQQMiniGame == true) QGameSubjectRepository() else SubjectRepository()
|
||||
|
||||
init {
|
||||
initData()
|
||||
}
|
||||
@ -40,7 +45,7 @@ class SubjectViewModel(application: Application, var subjectData: SubjectData?)
|
||||
}
|
||||
|
||||
private fun loadSubjectName() {
|
||||
RetrofitManager.getInstance().api
|
||||
repository
|
||||
.getSubjectName(subjectData?.subjectId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -65,7 +70,7 @@ class SubjectViewModel(application: Application, var subjectData: SubjectData?)
|
||||
}
|
||||
|
||||
private fun loadSubjectType() {
|
||||
RetrofitManager.getInstance().api
|
||||
repository
|
||||
.getColumnSettings(subjectData?.subjectId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -90,7 +95,10 @@ class SubjectViewModel(application: Application, var subjectData: SubjectData?)
|
||||
}
|
||||
|
||||
|
||||
class Factory(private val mApplication: Application, private val subjectData: SubjectData?) :
|
||||
class Factory(
|
||||
private val mApplication: Application,
|
||||
private val subjectData: SubjectData?
|
||||
) :
|
||||
ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return SubjectViewModel(mApplication, subjectData) as T
|
||||
|
||||
@ -55,6 +55,7 @@ import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.gamecenter.common.utils.PackageFlavorHelper;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.core.iinterface.IApplication;
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
@ -63,7 +64,6 @@ import com.gh.gamecenter.fragment.MainWrapperRepository;
|
||||
import com.gh.gamecenter.login.user.UserRepository;
|
||||
import com.gh.gamecenter.oaid.OAIDHelper;
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository;
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider;
|
||||
import com.gh.gamecenter.provider.FlavorProviderImp;
|
||||
import com.gh.gamecenter.receiver.ActivitySkipReceiver;
|
||||
import com.gh.gamecenter.receiver.DownloadReceiver;
|
||||
|
||||
11
app/src/main/res/drawable/bg_red_stroke_radius_999.xml
Normal file
11
app/src/main/res/drawable/bg_red_stroke_radius_999.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@color/theme_red" />
|
||||
<corners android:radius="999dp" />
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/white" />
|
||||
</shape>
|
||||
@ -185,7 +185,8 @@
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/personal_msg"
|
||||
@ -196,17 +197,20 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_message_hint"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_alignTop="@id/personal_msg"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="@drawable/oval_hint_red_stroke_bg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="14dp"
|
||||
android:layout_alignTop="@+id/personal_msg"
|
||||
android:layout_alignEnd="@+id/personal_msg"
|
||||
android:layout_alignRight="@+id/personal_msg"
|
||||
android:layout_marginTop="-4dp"
|
||||
android:layout_marginEnd="-8dp"
|
||||
android:background="@drawable/bg_red_stroke_radius_999"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="8sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="12" />
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@ -81,19 +81,16 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/menu_download_count_hint"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_alignTop="@+id/menu_download_iv"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:background="@drawable/oval_hint_red_stroke_bg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="14dp"
|
||||
android:background="@drawable/bg_red_stroke_radius_999"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="8sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/menu_download_iv" />
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="@+id/menu_download_iv"
|
||||
app:layout_constraintTop_toTopOf="@+id/menu_download_iv" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
||||
|
||||
31
app/src/main/res/layout/fragment_qgame.xml
Normal file
31
app/src/main/res/layout/fragment_qgame.xml
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/game_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.gh.gamecenter.common.view.TouchSlopRecyclerView
|
||||
android:id="@+id/game_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/background_white"
|
||||
android:clipToPadding="false" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/reuse_no_connection"
|
||||
layout="@layout/reuse_no_connection" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/game_skeleton_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</RelativeLayout>
|
||||
18
app/src/main/res/layout/fragment_qgame_home.xml
Normal file
18
app/src/main/res/layout/fragment_qgame_home.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<include
|
||||
android:id="@+id/search_bar"
|
||||
layout="@layout/layout_qgame_search_bar" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/wrapper_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/search_bar"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/home_actionbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/appbar_height"
|
||||
@ -47,7 +48,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="102dp"
|
||||
android:layout_marginRight="100dp"
|
||||
android:layout_marginTop="9dp"
|
||||
android:layout_marginBottom="9dp"
|
||||
android:layout_weight="1"
|
||||
@ -89,13 +90,12 @@
|
||||
android:src="@drawable/toolbar_search" />
|
||||
|
||||
<RelativeLayout
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:id="@+id/actionbar_rl_download"
|
||||
android:layout_width="36dp"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="@dimen/appbar_height"
|
||||
android:layout_marginRight="52dp">
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/actionbar_notification"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/actionbar_download"
|
||||
@ -106,29 +106,36 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/action_tip"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_alignTop="@id/actionbar_download"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="2dp"
|
||||
android:background="@drawable/oval_hint_red_stroke_bg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="14dp"
|
||||
android:layout_alignTop="@+id/actionbar_download"
|
||||
android:layout_alignEnd="@+id/actionbar_download"
|
||||
android:layout_alignRight="@+id/actionbar_download"
|
||||
android:layout_marginTop="-4dp"
|
||||
android:layout_marginEnd="-8dp"
|
||||
android:background="@drawable/bg_red_stroke_radius_999"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="8sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone" />
|
||||
android:visibility="gone"
|
||||
tools:minWidth="14dp"
|
||||
tools:text="99+"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:id="@+id/actionbar_notification"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="@dimen/appbar_height"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:id="@+id/actionbar_notification"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="@dimen/appbar_height"
|
||||
android:layout_marginRight="12dp">
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/actionbar_message"
|
||||
@ -140,17 +147,23 @@
|
||||
<TextView
|
||||
android:id="@+id/message_unread_hint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@id/actionbar_message"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="2dp"
|
||||
android:background="@drawable/oval_hint_red_stroke_bg"
|
||||
android:layout_height="14dp"
|
||||
android:layout_alignTop="@+id/actionbar_message"
|
||||
android:layout_alignEnd="@+id/actionbar_message"
|
||||
android:layout_alignRight="@+id/actionbar_message"
|
||||
android:layout_marginTop="-4dp"
|
||||
android:layout_marginEnd="-8dp"
|
||||
android:background="@drawable/bg_red_stroke_radius_999"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="8dp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone" />
|
||||
android:textSize="8sp"
|
||||
android:visibility="gone"
|
||||
tools:minWidth="14dp"
|
||||
tools:visibility="visible"
|
||||
tools:text="9" />
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -21,6 +21,7 @@
|
||||
app:srcCompat="@drawable/ic_vgame_recent_hint" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/titleTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
@ -41,6 +42,7 @@
|
||||
android:drawablePadding="4dp"
|
||||
android:includeFontPadding="false"
|
||||
android:text="更多"
|
||||
android:visibility="gone"
|
||||
android:textColor="@color/theme_font"
|
||||
android:textSize="@dimen/secondary_size"
|
||||
app:drawableEndCompat="@drawable/ic_home_head_arrow"
|
||||
|
||||
68
app/src/main/res/layout/layout_qgame_search_bar.xml
Normal file
68
app/src/main/res/layout/layout_qgame_search_bar.xml
Normal file
@ -0,0 +1,68 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/background_white"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="12dp"
|
||||
app:layout_scrollFlags="scroll">
|
||||
|
||||
<View
|
||||
android:id="@+id/search_background"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:background="@drawable/actionbar_search_bg"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@id/tv_search"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/et_search"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@null"
|
||||
android:hint="请输入小游戏关键词"
|
||||
android:imeOptions="actionSearch"
|
||||
android:paddingStart="36dp"
|
||||
android:paddingLeft="36dp"
|
||||
android:paddingEnd="40dp"
|
||||
android:paddingRight="40dp"
|
||||
android:singleLine="true"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="@color/text_title"
|
||||
android:textColorHint="@color/text_body"
|
||||
android:textCursorDrawable="@drawable/cursor_color"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/search_background"
|
||||
app:layout_constraintLeft_toLeftOf="@id/search_background"
|
||||
app:layout_constraintRight_toRightOf="@id/search_background"
|
||||
app:layout_constraintTop_toTopOf="@id/search_background" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/searchIv"
|
||||
android:layout_width="14dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
app:srcCompat="@drawable/toolbar_search_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/search_background"
|
||||
app:layout_constraintLeft_toLeftOf="@id/search_background"
|
||||
app:layout_constraintTop_toTopOf="@id/search_background" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:text="搜索"
|
||||
android:textColor="@color/theme_font"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/search_background"
|
||||
app:layout_constraintLeft_toRightOf="@id/search_background"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/search_background" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -8,26 +8,23 @@
|
||||
android:id="@+id/menu_download_iv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/toolbar_download"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/toolbar_download" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/menu_download_count_hint"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_alignTop="@id/menu_download_iv"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="@drawable/oval_hint_red_stroke_bg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="14dp"
|
||||
android:background="@drawable/bg_red_stroke_radius_999"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="8sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/menu_download_iv" />
|
||||
app:layout_constraintEnd_toEndOf="@+id/menu_download_iv"
|
||||
app:layout_constraintTop_toTopOf="@+id/menu_download_iv" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -469,4 +469,5 @@
|
||||
<string name="update_all_has_land_page_address_dialog_content">部分游戏下载资源由第三方提供,此类游戏无法自动更新,请手动点击游戏【更新】按钮前往第三方网址更新游戏</string>
|
||||
<string name="update_all_has_land_page_address_dialog_confirm">我知道了</string>
|
||||
<string name="miui_open_adb_hint">请查看关闭教程,先开启开发者模式</string>
|
||||
<string name="qgame_title">QQ小游戏</string>
|
||||
</resources>
|
||||
|
||||
@ -137,4 +137,9 @@ ext {
|
||||
documentfile = "1.0.1"
|
||||
|
||||
csjVersion = "5.4.1.6"
|
||||
|
||||
csjVersion = "5.4.1.6"
|
||||
|
||||
qGameVersion = "1.57.14"
|
||||
qGameAdVersion = "4.520.1390"
|
||||
}
|
||||
1
feature/qq_game/.gitignore
vendored
Normal file
1
feature/qq_game/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
||||
72
feature/qq_game/build.gradle
Normal file
72
feature/qq_game/build.gradle
Normal file
@ -0,0 +1,72 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'org.jetbrains.kotlin.android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'kotlin-parcelize'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdk rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode rootProject.ext.versionCode
|
||||
versionName rootProject.ext.versionName
|
||||
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'src/main/AndroidManifest.xml'
|
||||
java {
|
||||
exclude 'manifest/**'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kapt {
|
||||
arguments {
|
||||
arg("AROUTER_MODULE_NAME", project.name)
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
|
||||
kapt "com.alibaba:arouter-compiler:$arouterVersion"
|
||||
|
||||
implementation(project(path: ":module_common")) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
|
||||
implementation(project(':feature:realname-window'))
|
||||
|
||||
implementation "com.tencent.qqmini:minigame:${qGameVersion}"
|
||||
implementation ("com.tencent.qqmini:minigame_external:${qGameVersion}") {
|
||||
exclude group: 'com.squareup.okhttp3'
|
||||
}
|
||||
implementation "com.tencent.qqmini:minigame_open_sdk_all:${qGameVersion}"
|
||||
|
||||
// 优量汇广告 SDK https://developers.adnet.qq.com/doc/android/union/union_version
|
||||
implementation "com.qq.e.union:union:${qGameAdVersion}"
|
||||
implementation "com.tencent.qqmini:extra_union_ad:${qGameVersion}"
|
||||
}
|
||||
100
feature/qq_game/proguard-rules.pro
vendored
Normal file
100
feature/qq_game/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
# Keep class members annotated with @MiniKepp
|
||||
# 保护代码中的注解不被混淆
|
||||
-keepattributes *Annotation*
|
||||
-keep,allowobfuscation @interface com.tencent.qqmini.sdk.annotation.MiniKeep
|
||||
-keep @com.tencent.qqmini.sdk.annotation.MiniKeep class *
|
||||
-keepclassmembers @com.tencent.qqmini.sdk.annotation.MiniKeep class ** {
|
||||
public <methods>; <fields>;
|
||||
}
|
||||
-keepclassmembers class * {
|
||||
@com.tencent.qqmini.sdk.annotation.MiniKeep *;
|
||||
}
|
||||
|
||||
# Keep class members annotated with @JsEvent
|
||||
-keep,allowobfuscation @interface com.tencent.qqmini.sdk.annotation.JsEvent
|
||||
-keepclassmembers class * {
|
||||
@com.tencent.qqmini.sdk.annotation.JsEvent *;
|
||||
}
|
||||
|
||||
# Keep minigame triton
|
||||
-keep interface com.tencent.mobileqq.triton.** { *; }
|
||||
-keep class com.tencent.mobileqq.triton.** { *; }
|
||||
-keep @interface com.tencent.mobileqq.triton.jni.TTNativeModule, com.tencent.mobileqq.triton.jni.TTNativeCall
|
||||
-keep @com.tencent.mobileqq.triton.jni.TTNativeModule class ** {
|
||||
@com.tencent.mobileqq.triton.jni.TTNativeCall <methods>;
|
||||
@com.tencent.mobileqq.triton.jni.TTNativeCall <fields>;
|
||||
}
|
||||
-keep @interface io.github.landerlyoung.jenny.NativeClass, io.github.landerlyoung.jenny.NativeFieldProxy, io.github.landerlyoung.jenny.NativeMethodProxy
|
||||
-keep @io.github.landerlyoung.jenny.NativeClass class ** {
|
||||
@io.github.landerlyoung.jenny.NativeFieldProxy <fields>;
|
||||
@io.github.landerlyoung.jenny.NativeMethodProxy <methods>;
|
||||
}
|
||||
|
||||
# Keep minigame sdk
|
||||
-keep class * extends com.tencent.qqmini.sdk.launcher.ui.MiniActivity
|
||||
-keep class com.tencent.qqmini.sdk.core.generated.** { *; }
|
||||
-keep class com.tencent.qqmini.sdk.launcher.** { *; }
|
||||
-keep class com.tencent.qqmini.sdk.MiniSDK { *; }
|
||||
-keep class com.tencent.qqmini.sdk.MiniSDK$* { *; }
|
||||
-keep class com.tencent.qqmini.sdk.BuildConfig { *; }
|
||||
-keep class com.tencent.qqmini.sdk.annotation.** {* ;}
|
||||
-keep class com.tencent.qqmini.sdk.utils.MiniSDKConst$AdConst{*;}
|
||||
-keep class com.tencent.qqmini.sdk.receiver.** {* ;}
|
||||
-keepclassmembers class com.tencent.qqmini.sdk.** {
|
||||
@android.webkit.JavascriptInterface <methods>;
|
||||
}
|
||||
-keep class com.tencent.qqmini.sdk.core.proxy.service.ChannelProxyDefault { *; }
|
||||
|
||||
# protocol: should keep field name because reflection
|
||||
-keep class cooperation.** { *; }
|
||||
-keep class com.tencent.mobileqq.pb.MessageMicro { *; }
|
||||
-keepclassmembers class * extends com.tencent.mobileqq.pb.MessageMicro {
|
||||
<fields>;
|
||||
}
|
||||
|
||||
# extra_ad
|
||||
-keep class com.tencent.qqmini.ad.** {* ;}
|
||||
|
||||
# ad
|
||||
-keep class com.qq.e.** {* ;}
|
||||
|
||||
# extraad模块直接引用了协议,先keep
|
||||
-keep class NS_MINI_AD.** { *; }
|
||||
-keep class NS_QWEB_PROTOCAL.** { *; }
|
||||
-keep class com.tencent.mobileqq.pb.PBStringField {*;}
|
||||
-keep class com.tencent.qqmini.sdk.request.ProtoBufRequest {
|
||||
public *;
|
||||
}
|
||||
|
||||
# 微信互联登录
|
||||
-keep class com.tencent.mm.opensdk.** {
|
||||
*;
|
||||
}
|
||||
-keep class com.tencent.wxop.** {
|
||||
*;
|
||||
}
|
||||
-keep class com.tencent.mm.sdk.** {
|
||||
*;
|
||||
}
|
||||
38
feature/qq_game/src/main/AndroidManifest.xml
Normal file
38
feature/qq_game/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.gh.gamecenter.qqgame">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<application>
|
||||
|
||||
<activity android:name="com.gh.gamecenter.qgame.WXDelegateEntryActivity" />
|
||||
|
||||
<!-- QQ小游戏广告相关页面,默认进程为光环客户端进程,这里将进程修改为QQ小游戏的进程,解决关闭广告页面未跳转回QQ小游戏的问题 -->
|
||||
|
||||
<activity
|
||||
android:name="com.qq.e.ads.ADActivity"
|
||||
android:taskAffinity=".mini1" />
|
||||
<activity
|
||||
android:name="com.qq.e.ads.PortraitADActivity"
|
||||
android:taskAffinity=".mini1" />
|
||||
<activity
|
||||
android:name="com.qq.e.ads.LandscapeADActivity"
|
||||
android:taskAffinity=".mini1" />
|
||||
<!-- 用于激励视频可选广告的竖屏透明背景activity -->
|
||||
<activity
|
||||
android:name="com.qq.e.ads.RewardvideoPortraitADActivity"
|
||||
android:taskAffinity=".mini1" />
|
||||
<!-- 用于激励视频可选广告的横屏透明背景activity -->
|
||||
<activity
|
||||
android:name="com.qq.e.ads.RewardvideoLandscapeADActivity"
|
||||
android:taskAffinity=".mini1" />
|
||||
<activity
|
||||
android:name="com.qq.e.ads.DialogActivity"
|
||||
android:taskAffinity=".mini1" />
|
||||
|
||||
<!-- QQ小游戏广告相关页面,默认进程为光环客户端进程,这里将进程修改为QQ小游戏的进程,解决关闭广告页面未跳转回QQ小游戏的问题 -->
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -0,0 +1,66 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import android.app.Application
|
||||
import android.content.res.Configuration
|
||||
import android.util.Log
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.iinterface.IApplication
|
||||
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
|
||||
import com.gh.gamecenter.core.provider.IRealNameProvider
|
||||
import com.google.auto.service.AutoService
|
||||
|
||||
@AutoService(IApplication::class)
|
||||
class HaloApp : IApplication {
|
||||
|
||||
override fun attachBaseContext() {
|
||||
|
||||
}
|
||||
|
||||
override fun onCreate(application: Application) {
|
||||
|
||||
MiniGameWebViewUtils.handleWebViewDir(application)
|
||||
|
||||
doOnlyOnMiniProcess(application) {
|
||||
val provider = ARouter
|
||||
.getInstance()
|
||||
.build(RouteConsts.provider.realName)
|
||||
.navigation() as IRealNameProvider
|
||||
provider.init(application)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onLowMemory() {
|
||||
|
||||
}
|
||||
|
||||
override fun onTerminate() {
|
||||
|
||||
}
|
||||
|
||||
override fun onTrimMemory(level: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
|
||||
}
|
||||
|
||||
private fun doOnlyOnMiniProcess(application: Application, callback: () -> Unit) {
|
||||
val processName = getProcessName(application)
|
||||
val processNameSplits = processName.split(":")
|
||||
if (processNameSplits.size < 2) return
|
||||
val processNameSuffix = processNameSplits[1]
|
||||
if (processNameSuffix.startsWith("mini")) {
|
||||
Log.d("HaloApp", "doOnlyOnMiniProcess -> $processName")
|
||||
callback.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getProcessName(application: Application): String {
|
||||
val packageUtilsConfig =
|
||||
ARouter.getInstance().build(RouteConsts.provider.packageUtils).navigation() as? IPackageUtilsProvider
|
||||
return packageUtilsConfig?.obtainProcessName(application) ?: application.packageName
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.gh.gamecenter.qgame;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
import com.tencent.qqmini.sdk.launcher.core.proxy.LogProxy;
|
||||
|
||||
@Keep
|
||||
public class LogProxyImpl extends LogProxy {
|
||||
@Override
|
||||
public void log(int logLevel, String tag, String msg, Throwable t) {
|
||||
switch (logLevel) {
|
||||
case com.tencent.qqmini.sdk.launcher.log.Log.DEBUG:
|
||||
if (t == null) {
|
||||
Log.d(tag, msg);
|
||||
} else {
|
||||
Log.d(tag, msg, t);
|
||||
}
|
||||
break;
|
||||
case com.tencent.qqmini.sdk.launcher.log.Log.INFO:
|
||||
if (t == null) {
|
||||
Log.i(tag, msg);
|
||||
} else {
|
||||
Log.i(tag, msg, t);
|
||||
}
|
||||
break;
|
||||
case com.tencent.qqmini.sdk.launcher.log.Log.WARN:
|
||||
if (t == null) {
|
||||
Log.w(tag, msg);
|
||||
} else {
|
||||
Log.w(tag, msg, t);
|
||||
}
|
||||
break;
|
||||
case com.tencent.qqmini.sdk.launcher.log.Log.ERROR:
|
||||
if (t == null) {
|
||||
Log.e(tag, msg);
|
||||
} else {
|
||||
Log.e(tag, msg, t);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (t == null) {
|
||||
Log.v(tag, msg);
|
||||
} else {
|
||||
Log.v(tag, msg, t);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IRealNameProvider
|
||||
import com.tencent.qqmini.sdk.launcher.AppLoaderFactory
|
||||
import com.tencent.qqmini.sdk.launcher.core.proxy.MiniCustomizedProxy
|
||||
import com.tencent.qqmini.sdk.launcher.model.AppState
|
||||
import com.tencent.qqmini.sdk.launcher.model.MiniAppInfo
|
||||
|
||||
class MiniCustomizedProxyImpl : MiniCustomizedProxy() {
|
||||
|
||||
override fun onAppStateChange(info: MiniAppInfo, appState: Int) {
|
||||
val provider = ARouter
|
||||
.getInstance()
|
||||
.build(RouteConsts.provider.realName)
|
||||
.navigation() as IRealNameProvider
|
||||
|
||||
when(appState) {
|
||||
AppState.STATE_SHOW -> provider.setAppInfo(info.appId, info.name) {
|
||||
QGameHelper.stopMiniApp(AppLoaderFactory.g().context, info, true)
|
||||
}
|
||||
|
||||
AppState.STATE_HIDE -> {}
|
||||
|
||||
AppState.STATE_STOP -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package com.gh.gamecenter.qgame;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.gh.gamecenter.common.constant.RouteConsts;
|
||||
import com.gh.gamecenter.common.utils.PackageFlavorHelper;
|
||||
import com.gh.gamecenter.core.provider.IAppProvider;
|
||||
import com.tencent.qqmini.minigame.external.proxy.IMiniGameChannelInfoProxy;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Keep
|
||||
public class MiniGameChannelInfoProxyImpl extends IMiniGameChannelInfoProxy {
|
||||
|
||||
/**
|
||||
* 接入方在小游戏平台上注册的PlatformID。
|
||||
*/
|
||||
@Override
|
||||
public String getPlatformId() {
|
||||
return "2042";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取宿主APP的名称
|
||||
*
|
||||
* @return 应用名
|
||||
*/
|
||||
@Override
|
||||
public String getAppName() {
|
||||
return "光环助手";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取宿主APP的版本信息
|
||||
*
|
||||
* @return 版本号
|
||||
*/
|
||||
@Override
|
||||
public String getAppVersion() {
|
||||
IAppProvider appProvider = (IAppProvider) ARouter.getInstance().build(RouteConsts.provider.app).navigation();
|
||||
return appProvider.getAppVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断宿主APP是否为debug版本,debug版log输出比较全,但是对性能有影响,建议上线前检查。
|
||||
*
|
||||
* @return true: debug版本; false: release版本
|
||||
*/
|
||||
@Override
|
||||
public boolean isDebugVersion() {
|
||||
return PackageFlavorHelper.IS_TEST_FLAVOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 腾讯广告的AppId,如果以前申请过建议填写,会针对当前应用出广告。
|
||||
* 如果没有也不影响广告功能。
|
||||
*/
|
||||
@Override
|
||||
public String getAmsAppId() {
|
||||
return "1203549148";
|
||||
}
|
||||
|
||||
/**
|
||||
* 扩展字段,会透传给到接入方后台,接入方可以自定义。
|
||||
* @return 接入方自定义内容
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getExtInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.gh.gamecenter.qgame;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.tencent.qqmini.minigame.opensdk.proxy.IWXRequestListener;
|
||||
import com.tencent.qqmini.minigame.opensdk.proxy.MiniGameOpenSdkProxy;
|
||||
import com.tencent.qqmini.minigame.opensdk.wx.WXHttpsRequest;
|
||||
|
||||
public class MiniGameOpenSdkProxyImpl implements MiniGameOpenSdkProxy {
|
||||
|
||||
private static final String TAG = "MiniGameOpenSdkProxyDefault";
|
||||
private static final String wxAppId = "wx3ffd0785fad18396";
|
||||
private static final String appSecret = "368b49e8471857575a033b206218f9fb";
|
||||
|
||||
public void wxAuth(Context context, String code, @Nullable IWXRequestListener listener) {
|
||||
WXHttpsRequest.wxAuth(context, wxAppId, code, appSecret, listener);
|
||||
}
|
||||
|
||||
public void wxRefreshToken(Context context, @Nullable IWXRequestListener listener) {
|
||||
WXHttpsRequest.wxRefreshToken(context, wxAppId, listener);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.gh.gamecenter.qgame;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.tencent.qqmini.minigame.opensdk.proxy.MimiGameOpenSdkInfoProxyImpl;
|
||||
import com.tencent.qqmini.sdk.launcher.core.proxy.AsyncResult;
|
||||
import com.tencent.qqmini.sdk.launcher.model.MiniAppInfo;
|
||||
|
||||
public class MiniGameProxyImpl extends MimiGameOpenSdkInfoProxyImpl {
|
||||
@Override
|
||||
public boolean needCheckAntiAddictionToken() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleTokenInvalid(Context context, @Nullable MiniAppInfo miniAppInfo, int i, @Nullable AsyncResult asyncResult) {
|
||||
return super.handleTokenInvalid(context, miniAppInfo, i, asyncResult);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.webkit.WebView
|
||||
import java.io.File
|
||||
import java.io.RandomAccessFile
|
||||
|
||||
object MiniGameWebViewUtils {
|
||||
fun handleWebViewDir(application: Application) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
return
|
||||
}
|
||||
|
||||
// Android P需要手动设置Data文件夹所在的进程,否则会触发以下异常:
|
||||
// java.lang.RuntimeException: Using WebView from more than one process at once with the same data directory is not supported.
|
||||
try {
|
||||
val processName = Application.getProcessName()
|
||||
val suffix = if (application.packageName != processName) {//判断不等于默认进程名称
|
||||
val process = processName.ifEmpty { application.packageName }
|
||||
WebView.setDataDirectorySuffix(process)
|
||||
"_$process"
|
||||
} else ""
|
||||
tryLockOrRecreateFile(application,suffix)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
private fun tryLockOrRecreateFile(context: Context, suffix: String) {
|
||||
val sb = context.dataDir.absolutePath +
|
||||
"/app_webview"+suffix+"/webview_data.lock"
|
||||
val file = File(sb)
|
||||
if (file.exists()) {
|
||||
try {
|
||||
val tryLock = RandomAccessFile(file, "rw").channel.tryLock()
|
||||
if (tryLock != null) {
|
||||
tryLock.close()
|
||||
} else {
|
||||
createFile(file, file.delete());
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
val deleted = if (file.exists()) {
|
||||
file.delete()
|
||||
} else false
|
||||
createFile(file, deleted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFile(file: File, deleted: Boolean){
|
||||
try {
|
||||
if (deleted && !file.exists()) {
|
||||
file.createNewFile()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.ResultReceiver
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.google.gson.Gson
|
||||
import com.tencent.qqmini.minigame.opensdk.OpenSdkLoginManager
|
||||
import com.tencent.qqmini.minigame.opensdk.config.OpenSdkConfig
|
||||
import com.tencent.qqmini.sdk.MiniSDK
|
||||
import com.tencent.qqmini.sdk.launcher.model.AccountInfo
|
||||
import com.tencent.qqmini.sdk.launcher.model.ExtParams
|
||||
import com.tencent.qqmini.sdk.launcher.model.LaunchParam
|
||||
import com.tencent.qqmini.sdk.launcher.model.MiniAppInfo
|
||||
import com.tencent.tauth.Tencent
|
||||
|
||||
/**
|
||||
* QQ 游戏管理类
|
||||
*/
|
||||
internal object QGameHelper {
|
||||
|
||||
fun init(context: Context, wxAppId: String, qqAppId: String) {
|
||||
// 若 Android 系统版本低于 5.0 不用初始化
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return
|
||||
}
|
||||
|
||||
MiniSDK.init(context)
|
||||
OpenSdkLoginManager.init(
|
||||
OpenSdkConfig.Builder()
|
||||
.setUseOauth(false)
|
||||
.setQqOpenAppId(qqAppId) // QQ互联平台AppId,若不想接入QQ互联,则不设置
|
||||
.setWxOpenAppId(wxAppId) // 微信互联平台AppId,若不想接入微信互联,则不设置
|
||||
.setIsDebugEnv(true)
|
||||
.build()
|
||||
)
|
||||
Tencent.setIsPermissionGranted(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权完成后设置用户帐号信息
|
||||
*/
|
||||
fun setLoginInfo(context: Context, userId: String, userName: String, token: String) {
|
||||
MiniSDK.setLoginInfo(context, AccountInfo(userId, userName, token.toByteArray()), null)
|
||||
}
|
||||
|
||||
fun launchGame(
|
||||
activity: Activity,
|
||||
gameId: String,
|
||||
resultCallback: (resultCode: Int, resultData: Bundle?) -> Unit
|
||||
) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
ToastUtils.toast("该游戏仅支持安卓5.0及以上设备")
|
||||
return
|
||||
}
|
||||
|
||||
val extParam = ExtParams().apply {
|
||||
customInfo = "" // 心跳透传字段
|
||||
resultReceiver = object : ResultReceiver(Handler(Looper.getMainLooper())) {
|
||||
override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
|
||||
resultCallback.invoke(resultCode, resultData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MiniSDK.startMiniAppById(activity, gameId, extParam)
|
||||
}
|
||||
|
||||
fun launchGameByLink(
|
||||
activity: Activity,
|
||||
gameLink: String,
|
||||
resultCallback: (resultCode: Int, resultData: Bundle?) -> Unit
|
||||
) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
ToastUtils.toast("该游戏仅支持安卓5.0及以上设备")
|
||||
return
|
||||
}
|
||||
|
||||
val extParam = ExtParams().apply {
|
||||
customInfo = "" // 心跳透传字段
|
||||
resultReceiver = object : ResultReceiver(Handler(Looper.getMainLooper())) {
|
||||
override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
|
||||
resultCallback.invoke(resultCode, resultData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MiniSDK.startMiniAppByLink(activity, gameLink, extParam)
|
||||
}
|
||||
|
||||
fun stopAllMiniApp(context: Context, force: Boolean) {
|
||||
MiniSDK.stopAllMiniApp(context, force)
|
||||
}
|
||||
|
||||
fun stopMiniApp(context: Context, info: MiniAppInfo, force: Boolean) {
|
||||
MiniSDK.stopMiniApp(context, info, force)
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IQGameProvider
|
||||
import com.tencent.mm.opensdk.modelmsg.SendAuth
|
||||
import com.tencent.qqmini.minigame.opensdk.wx.BaseWXEntryActivity
|
||||
import com.tencent.qqmini.sdk.launcher.AppLoaderFactory
|
||||
import com.tencent.qqmini.sdk.launcher.model.ShareData
|
||||
|
||||
@Route(path = RouteConsts.provider.qGame, name = "QQ小游戏暴露服务")
|
||||
class QGameProviderImpl : IQGameProvider<SendAuth.Resp> {
|
||||
|
||||
override fun init(context: Context, wxAppId: String, qqAppId: String) {
|
||||
QGameHelper.init(context, wxAppId, qqAppId)
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun setLoginInfo(context: Context, userId: String, userName: String, token: String) {
|
||||
QGameHelper.setLoginInfo(context, userId, userName, token)
|
||||
}
|
||||
|
||||
override fun launchGame(
|
||||
activity: Activity,
|
||||
qqGameId: String,
|
||||
resultCallback: (resultCode: Int, resultData: Bundle?) -> Unit
|
||||
) {
|
||||
QGameHelper.launchGame(activity, qqGameId, resultCallback)
|
||||
}
|
||||
|
||||
override fun launchGameByLink(
|
||||
activity: Activity,
|
||||
qqGameLink: String,
|
||||
resultCallback: (resultCode: Int, resultData: Bundle?) -> Unit
|
||||
) {
|
||||
QGameHelper.launchGameByLink(activity, qqGameLink, resultCallback)
|
||||
}
|
||||
|
||||
override fun onWechatLogin(context: Context, resp: SendAuth.Resp) {
|
||||
// 这里用 WXDelegateEntryActivity 类做了个中转,把数据传递到了底层的 Activity
|
||||
val bundle = Bundle()
|
||||
resp.toBundle(bundle)
|
||||
|
||||
val intent = Intent(context, WXDelegateEntryActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信分享结果回调
|
||||
* @param resultType 结果 0 代表失败, -1 代表取消, 1 代表成功
|
||||
*/
|
||||
override fun onWechatShare(context: Context, resultType: Int) {
|
||||
val tempShareData = BaseWXEntryActivity.sShareData
|
||||
BaseWXEntryActivity.sShareData = null
|
||||
|
||||
if (tempShareData != null) {
|
||||
when (resultType) {
|
||||
-1 -> tempShareData.notifyShareResult(context, ShareData.ShareResult.CANCEL)
|
||||
0 -> tempShareData.notifyShareResult(context, ShareData.ShareResult.FAIL)
|
||||
1 -> tempShareData.notifyShareResult(context, ShareData.ShareResult.SUCCESS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun stopAllMiniApp(force: Boolean) {
|
||||
QGameHelper.stopAllMiniApp(AppLoaderFactory.g().context, force)
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,146 @@
|
||||
package com.gh.gamecenter.qgame;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
import com.tencent.connect.share.QzoneShare;
|
||||
import com.tencent.qqmini.minigame.opensdk.share.OpenSdkShareHelper;
|
||||
import com.tencent.qqmini.sdk.MiniSDK;
|
||||
import com.tencent.qqmini.sdk.annotation.ProxyService;
|
||||
import com.tencent.qqmini.sdk.launcher.core.proxy.ShareProxy;
|
||||
import com.tencent.qqmini.sdk.launcher.model.ShareData;
|
||||
import com.tencent.qqmini.sdk.launcher.ui.MoreItem;
|
||||
import com.tencent.qqmini.sdk.launcher.ui.MoreItemList;
|
||||
import com.tencent.qqmini.sdk.manager.LoginManager;
|
||||
import com.tencent.qqmini.sdk.widget.MiniToast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Keep
|
||||
@ProxyService(proxy = ShareProxy.class)
|
||||
public class ShareProxyImpl extends ShareProxy {
|
||||
|
||||
private static final String TAG = "ShareProxyImpl";
|
||||
|
||||
// 扩展按钮的ID需要设置为[100, 200]这个区间中的值,否则,添加无效。
|
||||
public static final int OTHER_MORE_ITEM_1 = 101;
|
||||
public static final int OTHER_MORE_ITEM_2 = 102;
|
||||
|
||||
private final OpenSdkShareHelper mShareHelper = new OpenSdkShareHelper();
|
||||
|
||||
/**
|
||||
* 获取默认的分享目标,即默认的宿主分享渠道。
|
||||
*/
|
||||
@Override
|
||||
public int getDefaultShareTarget() {
|
||||
int loginType = LoginManager.getInstance().getOpenSdkLoginInfo().getLoginType();
|
||||
switch (loginType) {
|
||||
case MiniSDK.LoginType.LOGIN_FROM_WX:
|
||||
return ShareData.ShareTarget.WECHAT_FRIEND;
|
||||
default:
|
||||
return ShareData.ShareTarget.QQ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在share之前回调
|
||||
* 可以用于决定分享的target是否可进行分享行为
|
||||
*/
|
||||
@Override
|
||||
public boolean isShareTargetAvailable(Context context, int shareTarget) {
|
||||
return mShareHelper.isShareTargetAvailable(context, shareTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<MoreItem> createMoreItems(MoreItemList.Builder builder) {
|
||||
// 自行调整顺序。不支持删除关于,举报。
|
||||
builder
|
||||
.addShareQQ("QQ", com.tencent.qqmini.sdk.R.drawable.mini_sdk_channel_qq)
|
||||
.addShareQzone("QQ空间", com.tencent.qqmini.sdk.R.drawable.mini_sdk_channel_qzone)
|
||||
.addShareWxFriends("微信好友", com.tencent.qqmini.sdk.R.drawable.mini_sdk_channel_wx_friend)
|
||||
.addShareWxMoments("微信朋友圈", com.tencent.qqmini.sdk.R.drawable.mini_sdk_channel_wx_moment)
|
||||
.addRestart("重启小程序", com.tencent.qqmini.sdk.R.drawable.mini_sdk_restart_miniapp)
|
||||
.addSettings("设置", com.tencent.qqmini.sdk.R.drawable.mini_sdk_about);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享
|
||||
* @param activity
|
||||
* @param shareData 分享数据
|
||||
*/
|
||||
@Override
|
||||
public void share(Activity activity, ShareData shareData) {
|
||||
switch (shareData.shareTarget) {
|
||||
case ShareData.ShareTarget.QQ:
|
||||
case ShareData.ShareTarget.SHARE_CHAT:
|
||||
case ShareData.ShareTarget.QQ_DIRECTLY:
|
||||
case ShareData.ShareTarget.FRIEND_LIST:
|
||||
mShareHelper.shareToQQ(activity, shareData);
|
||||
break;
|
||||
|
||||
case ShareData.ShareTarget.QZONE:
|
||||
mShareHelper.shareToQZone(activity, shareData);
|
||||
break;
|
||||
|
||||
case ShareData.ShareTarget.WECHAT_FRIEND:
|
||||
mShareHelper.shareToWxSession(activity, shareData);
|
||||
break;
|
||||
|
||||
case ShareData.ShareTarget.WECHAT_MOMENTS:
|
||||
mShareHelper.shareToWxTimeline(activity, shareData);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (MoreItem.isValidExtendedItemId(shareData.shareTarget)) {
|
||||
shareToOther(activity, shareData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动第三方分享结果的返回
|
||||
* 这里wx分享不会回调这里,需要渠道自己在IWXAPIEventHandler#onResp根据rsp处理
|
||||
*/
|
||||
@Override
|
||||
public void onShareActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Log.d(TAG, "requestCode=" + requestCode + ",resultCode=" + resultCode);
|
||||
mShareHelper.onShareActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用第三方分享
|
||||
*/
|
||||
public void shareToOther(Activity activity, ShareData shareData) {
|
||||
switch (shareData.shareItemId) {
|
||||
case OTHER_MORE_ITEM_1:
|
||||
if (shareData.shareInMiniProcess) {
|
||||
activity.runOnUiThread(() -> MiniToast.makeText(activity, "模拟第三方实现", Toast.LENGTH_LONG).show());
|
||||
shareToOtherItem1(activity, shareData);
|
||||
}
|
||||
break;
|
||||
case OTHER_MORE_ITEM_2:
|
||||
default:
|
||||
MiniToast.makeText(activity, "待第三方实现", Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void shareToOtherItem1(Activity activity, ShareData shareData) {
|
||||
Bundle params = new Bundle();
|
||||
params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE, QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT );
|
||||
params.putString(QzoneShare.SHARE_TO_QQ_TITLE, shareData.title);//必填
|
||||
params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, shareData.summary);//选填
|
||||
params.putString(QzoneShare.SHARE_TO_QQ_TARGET_URL, shareData.targetUrl);//必填
|
||||
ArrayList<String> imageUrlList = new ArrayList<>();
|
||||
imageUrlList.add(shareData.sharePicPath);
|
||||
params.putStringArrayList(QzoneShare.SHARE_TO_QQ_IMAGE_URL, imageUrlList);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.gh.gamecenter.qgame
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.Keep
|
||||
import com.tencent.mm.opensdk.modelmsg.SendAuth
|
||||
import com.tencent.qqmini.minigame.opensdk.wx.BaseWXEntryActivity
|
||||
import com.tencent.qqmini.minigame.opensdk.wx.WXLoginHelper
|
||||
|
||||
@Keep
|
||||
internal class WXDelegateEntryActivity : BaseWXEntryActivity() {
|
||||
override fun onCreate(p0: Bundle?) {
|
||||
// 将数据转移给 BaseWXEntryActivity 来规避需要继承 BaseWXEntryActivity 的问题
|
||||
// TODO 第二次会无法登录,可能某些地方还需要处理
|
||||
val resp = SendAuth.Resp()
|
||||
resp.fromBundle(intent.extras)
|
||||
|
||||
WXLoginHelper.loginState = resp.state
|
||||
|
||||
onResp(resp)
|
||||
|
||||
super.onCreate(p0)
|
||||
|
||||
finish()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.tencent.qqmini.sdk.core.generated;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
import com.gh.gamecenter.qgame.LogProxyImpl;
|
||||
import com.gh.gamecenter.qgame.MiniCustomizedProxyImpl;
|
||||
import com.gh.gamecenter.qgame.MiniGameChannelInfoProxyImpl;
|
||||
import com.gh.gamecenter.qgame.MiniGameOpenSdkProxyImpl;
|
||||
import com.gh.gamecenter.qgame.MiniGameProxyImpl;
|
||||
import com.gh.gamecenter.qgame.ShareProxyImpl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Keep
|
||||
public final class ExtProxyServiceScope {
|
||||
public static final Map<Class, Class> PROXY_SERVICES = new HashMap<>();
|
||||
|
||||
static {
|
||||
PROXY_SERVICES.put(com.tencent.qqmini.sdk.launcher.core.proxy.ShareProxy.class, ShareProxyImpl.class);
|
||||
PROXY_SERVICES.put(com.tencent.qqmini.minigame.external.proxy.IMiniGameChannelInfoProxy.class, MiniGameChannelInfoProxyImpl.class);
|
||||
PROXY_SERVICES.put(com.tencent.qqmini.sdk.launcher.core.proxy.LogProxy.class, LogProxyImpl.class);
|
||||
PROXY_SERVICES.put(com.tencent.qqmini.sdk.launcher.core.proxy.MiniGameProxy.class, MiniGameProxyImpl.class);
|
||||
PROXY_SERVICES.put(com.tencent.qqmini.minigame.opensdk.proxy.MiniGameOpenSdkProxy.class, MiniGameOpenSdkProxyImpl.class);
|
||||
PROXY_SERVICES.put(com.tencent.qqmini.sdk.launcher.core.proxy.MiniCustomizedProxy.class, MiniCustomizedProxyImpl.class);
|
||||
}
|
||||
}
|
||||
1
feature/realname-window/.gitignore
vendored
Normal file
1
feature/realname-window/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
||||
43
feature/realname-window/build.gradle
Normal file
43
feature/realname-window/build.gradle
Normal file
@ -0,0 +1,43 @@
|
||||
apply plugin: "com.android.library"
|
||||
apply plugin: "org.jetbrains.kotlin.android"
|
||||
apply plugin: "kotlin-kapt"
|
||||
|
||||
android {
|
||||
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdk rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode rootProject.ext.versionCode
|
||||
versionName rootProject.ext.versionName
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
kapt {
|
||||
arguments {
|
||||
arg("AROUTER_MODULE_NAME", project.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
kapt "com.alibaba:arouter-compiler:$arouterVersion"
|
||||
|
||||
implementation(project(path: ":module_common")) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
}
|
||||
21
feature/realname-window/proguard-rules.pro
vendored
Normal file
21
feature/realname-window/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
6
feature/realname-window/src/main/AndroidManifest.xml
Normal file
6
feature/realname-window/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.lg.realname">
|
||||
|
||||
|
||||
</manifest>
|
||||
@ -0,0 +1,199 @@
|
||||
package com.lg.realname
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.*
|
||||
import com.gh.gamecenter.common.eventbus.EBFloatWindow
|
||||
import com.gh.gamecenter.common.json.json
|
||||
import com.gh.gamecenter.common.utils.setTextChangedListener
|
||||
import com.gh.gamecenter.common.utils.toRequestBody
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.lg.realname.databinding.DialogInputRealNameBinding
|
||||
import com.lg.realname.retrofit.RetrofitManager
|
||||
import com.lg.realname.utils.NewFlatLogUtils
|
||||
import com.lg.realname.utils.SensorsLogUtils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
|
||||
class InputRealNameDialog(context: Context) : Dialog(context) {
|
||||
|
||||
private val mBinding by lazy { DialogInputRealNameBinding.inflate(LayoutInflater.from(context)) }
|
||||
private var mCallBack: ((realName: String, idCard: String, isMinor: Boolean) -> Unit)? = null
|
||||
private var mQQGameId : String = ""
|
||||
private var mQQGameName = "1.0"
|
||||
private var mInputCount = 0
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
setCancelable(false)
|
||||
setCanceledOnTouchOutside(false)
|
||||
setContentView(mBinding.root)
|
||||
initUI()
|
||||
|
||||
SensorsLogUtils.logEvent("HaloFunVerificationDialogShow")
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
val height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
window?.setGravity(Gravity.CENTER)
|
||||
window?.setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL)
|
||||
window?.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
)
|
||||
window?.decorView?.systemUiVisibility =
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
window?.setLayout(width, height)
|
||||
}
|
||||
|
||||
//动态去修改提交认证按钮的高度去强制更新editText的内容 在某些(小米安卓12 MIUI13)机型下横屏输入的情况下 键盘是半屏的 输入的时候editText没有即时更新内容
|
||||
private fun changeContinueTvHeight() {
|
||||
if (DisplayUtils.getScreenWidth() > DisplayUtils.getScreenHeight()) {
|
||||
mInputCount++
|
||||
val param = mBinding.continueTv.layoutParams
|
||||
if (mInputCount % 2 == 0) {
|
||||
param.height = DisplayUtils.dip2px(40F)
|
||||
} else {
|
||||
param.height = DisplayUtils.dip2px(39.5F)
|
||||
}
|
||||
mBinding.continueTv.layoutParams = param
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun initUI() {
|
||||
|
||||
mBinding.apply {
|
||||
contentTv.text = context.getString(R.string.input_content)
|
||||
realNameEt.setTextChangedListener { realName, _, _, _ ->
|
||||
changeContinueTvHeight()
|
||||
clearRealNameIv.visibility = if (realName.isEmpty()) View.GONE else View.VISIBLE
|
||||
updateSubmitStatus()
|
||||
}
|
||||
idCardEt.setTextChangedListener { idCard, _, _, _ ->
|
||||
changeContinueTvHeight()
|
||||
clearIdCardIv.visibility = if (idCard.isEmpty()) View.GONE else View.VISIBLE
|
||||
updateSubmitStatus()
|
||||
}
|
||||
clearRealNameIv.setOnClickListener {
|
||||
realNameEt.setText("")
|
||||
}
|
||||
clearIdCardIv.setOnClickListener {
|
||||
idCardEt.setText("")
|
||||
}
|
||||
continueTv.setOnClickListener {
|
||||
SensorsLogUtils.logEvent("HaloFunVerificationDialogClick")
|
||||
checkInput()
|
||||
}
|
||||
realNameEt.setOnFocusChangeListener { _, isFoucs ->
|
||||
if (isFoucs) {
|
||||
postDismissFloatWindow()
|
||||
}
|
||||
}
|
||||
idCardEt.setOnFocusChangeListener { _, isFoucs ->
|
||||
if (isFoucs) {
|
||||
postDismissFloatWindow()
|
||||
}
|
||||
}
|
||||
this.root.setOnClickListener {
|
||||
postDismissFloatWindow()
|
||||
}
|
||||
}
|
||||
updateSubmitStatus()
|
||||
|
||||
}
|
||||
private fun postDismissFloatWindow(){
|
||||
EventBus.getDefault().post(EBFloatWindow())
|
||||
}
|
||||
|
||||
private fun checkInput() {
|
||||
val realName = mBinding.realNameEt.text.toString()
|
||||
val idCard = mBinding.idCardEt.text.toString()
|
||||
if (!TextUtils.isEmpty(realName) && !TextUtils.isEmpty(idCard)) {
|
||||
NewFlatLogUtils.logCwCertificationDialogClick(mQQGameId, mQQGameName)
|
||||
postCerfication(realName, idCard)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//实名认证
|
||||
@SuppressLint("CheckResult")
|
||||
private fun postCerfication(realName: String, idCard: String) {
|
||||
|
||||
val json = json {
|
||||
"id_card" to json {
|
||||
"id" to idCard
|
||||
"name" to realName
|
||||
}
|
||||
}
|
||||
|
||||
RetrofitManager.getInstance().api.postCertification(json.toRequestBody())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ success ->
|
||||
val result = JSONObject(success.string())
|
||||
dismiss()
|
||||
val isMinor = result.getBoolean("minor")
|
||||
mCallBack?.invoke(realName, idCard, isMinor)
|
||||
SensorsLogUtils.logEvent(
|
||||
"HaloFunVerificationResult",
|
||||
"attestation_result",
|
||||
if (isMinor) "未成年人" else "成年人"
|
||||
)
|
||||
}, { error ->
|
||||
NewFlatLogUtils.logCwCertificationResult(mQQGameId, "认证失败")
|
||||
val errorBody = (error as HttpException).response()?.errorBody()
|
||||
val errorResult = JSONObject(errorBody?.string())
|
||||
TipBottomDialog.show(context, false, errorResult.optString("toast", "认证失败"))
|
||||
SensorsLogUtils.logEvent(
|
||||
"HaloFunVerificationResult",
|
||||
"defeated_reason",
|
||||
errorResult.optString("toast", "1"),
|
||||
"attestation_result",
|
||||
"认证失败"
|
||||
)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun updateSubmitStatus() {
|
||||
if (!TextUtils.isEmpty(mBinding.realNameEt.text) && !TextUtils.isEmpty(mBinding.idCardEt.text) && mBinding.idCardEt.text.length == 18) {
|
||||
mBinding.continueTv.isEnabled = true
|
||||
mBinding.continueTv.alpha = 1f
|
||||
} else {
|
||||
mBinding.continueTv.isEnabled = false
|
||||
mBinding.continueTv.alpha = 0.3f
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun show(
|
||||
context: Context,
|
||||
qqGameId:String,
|
||||
qqGameName:String,
|
||||
callBack: ((realName: String, idCard: String, isMinor: Boolean) -> Unit)?
|
||||
): Dialog {
|
||||
val dialog = InputRealNameDialog(context)
|
||||
dialog.mQQGameId = qqGameId
|
||||
dialog.mQQGameName = qqGameName
|
||||
dialog.mCallBack = callBack
|
||||
dialog.show()
|
||||
return dialog
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
package com.lg.realname
|
||||
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.TextPaint
|
||||
import android.text.style.ClickableSpan
|
||||
import android.view.*
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.lg.realname.databinding.DialogRealNameBinding
|
||||
|
||||
class RealNameDialog(context: Context) : Dialog(context) {
|
||||
|
||||
private val mBinding by lazy { DialogRealNameBinding.inflate(LayoutInflater.from(context)) }
|
||||
private var isMplay = false
|
||||
private var mCallBack: ((isPlay: Boolean) -> Unit)? = null
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
setContentView(mBinding.root)
|
||||
setCancelable(false)
|
||||
setCanceledOnTouchOutside(false)
|
||||
initUI()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
val height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
window?.setGravity(Gravity.CENTER)
|
||||
window?.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
)
|
||||
window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
window?.setLayout(width, height)
|
||||
}
|
||||
|
||||
private fun initUI() {
|
||||
|
||||
val spannString = if (isMplay) SpannableStringBuilder(
|
||||
context.getString(R.string.real_name_content_play)
|
||||
) else SpannableStringBuilder(
|
||||
context.getString(R.string.real_name_content)
|
||||
)
|
||||
val start = if (!isMplay) 12 else 13
|
||||
spannString.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(tp: TextPaint) {
|
||||
super.updateDrawState(tp)
|
||||
tp.color =
|
||||
ContextCompat.getColor(context, R.color.color_1383EB)
|
||||
tp.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(tv: View) {
|
||||
|
||||
}
|
||||
}, 4, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
spannString.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(tp: TextPaint) {
|
||||
super.updateDrawState(tp)
|
||||
tp.color =
|
||||
ContextCompat.getColor(context, R.color.color_1383EB)
|
||||
tp.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(tv: View) {
|
||||
|
||||
}
|
||||
}, spannString.length - start, spannString.length - 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
mBinding.apply {
|
||||
contentTv.text = spannString
|
||||
if (isMplay) {
|
||||
backGameTv.text = "进入游戏"
|
||||
backGameTv.setTextColor(Color.WHITE)
|
||||
backGameTv.setBackgroundResource(R.drawable.bg_blue_radius_20)
|
||||
backGameTv.setOnClickListener {
|
||||
dismiss()
|
||||
mCallBack?.invoke(true)
|
||||
}
|
||||
} else {
|
||||
backGameTv.setOnClickListener {
|
||||
mCallBack?.invoke(false)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun show(
|
||||
context: Context,
|
||||
isPlay: Boolean,
|
||||
callBack: ((isPlay: Boolean) -> Unit)?
|
||||
): Dialog {
|
||||
val dialog = RealNameDialog(context)
|
||||
dialog.isMplay = isPlay
|
||||
dialog.mCallBack = callBack
|
||||
dialog.show()
|
||||
return dialog
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,302 @@
|
||||
package com.lg.realname
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.app.Application.ActivityLifecycleCallbacks
|
||||
import android.app.Dialog
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Base64
|
||||
import android.view.WindowManager
|
||||
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.lg.realname.retrofit.RetrofitManager
|
||||
import com.lg.realname.utils.NewFlatLogUtils
|
||||
import com.lg.realname.utils.SensorsLogUtils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.json.JSONObject
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
|
||||
// Application 的 context 不用管泄漏警告
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object RealNameHelper : ActivityLifecycleCallbacks {
|
||||
|
||||
private var timer = Timer()
|
||||
private var timerTask: TimerTask? = null
|
||||
private var mIsValid = false
|
||||
private var mIsAdult = false//未成年人为false 成年人true
|
||||
|
||||
private var mExitClosure: (() -> Unit)? = null
|
||||
|
||||
private var mIsSuccessDialogShowed = false
|
||||
|
||||
private var mApplication: Application? = null
|
||||
|
||||
private var mIsDialogShown = false
|
||||
|
||||
private var mCurrentActivityRef = WeakReference<Activity>(null)
|
||||
private var mIsCertificated = false
|
||||
private var mLastIsHealthyTime = false // 上一次是否是健康时间段
|
||||
private var currentRealNameDialog: Dialog? = null
|
||||
private var currentInputRealNameDialog: Dialog? = null
|
||||
private var mIsAgoShowRealNameDialog = false // 是否已经弹起过RealNameDialog
|
||||
private var mStartAppShowHeath: Boolean = false//是否是在启动游戏的时候弹出健康时间弹窗
|
||||
private var mSubmitCertification: Boolean = false//是否是在提交认证的时候触发健康时间弹窗
|
||||
private var mQQGameId: String = ""
|
||||
private var mQQGameName: String = ""
|
||||
private var mIsAgoShowInputRealNameDialog = false // 是否已经弹起过实名认证弹窗InputRealNameDialog
|
||||
|
||||
@JvmStatic
|
||||
fun init(application: Application) {
|
||||
mApplication = application
|
||||
|
||||
application.registerActivityLifecycleCallbacks(this)
|
||||
validateRealNameInfo(application)
|
||||
}
|
||||
|
||||
fun setAppInfo(qqGameId: String, qqGameName: String, exitClosure: (() -> Unit)) {
|
||||
if (mQQGameId != qqGameId || !mIsDialogShown) {
|
||||
startGameShowDialog()
|
||||
mIsDialogShown = true
|
||||
}
|
||||
mQQGameId = qqGameId
|
||||
mQQGameName = qqGameName
|
||||
mExitClosure = exitClosure
|
||||
}
|
||||
|
||||
override fun onActivityCreated(p0: Activity, p1: Bundle?) {
|
||||
mStartAppShowHeath = true
|
||||
mLastIsHealthyTime = false
|
||||
mIsAgoShowRealNameDialog = false
|
||||
mIsAgoShowInputRealNameDialog = false
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
p0.window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||
}
|
||||
}
|
||||
|
||||
//获取是否在健康时间段内
|
||||
@SuppressLint("CheckResult")
|
||||
fun checkHealthyTime() {
|
||||
|
||||
RetrofitManager.getInstance().newApi.postHealthyTimeCheck()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ success ->
|
||||
val result = JSONObject(success.string())
|
||||
if (!result.getBoolean("is_healthy_time")) {//不在健康时间段
|
||||
showSuccessRealNameDialog(mCurrentActivityRef.get(), false)
|
||||
mLastIsHealthyTime = false
|
||||
} else {
|
||||
showSuccessRealNameDialog(mCurrentActivityRef.get(), true)
|
||||
mLastIsHealthyTime = true
|
||||
}
|
||||
}, {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
override fun onActivityStarted(p0: Activity) {
|
||||
}
|
||||
|
||||
override fun onActivityResumed(p0: Activity) {
|
||||
mCurrentActivityRef = WeakReference(p0)
|
||||
}
|
||||
|
||||
private fun startGameShowDialog(){
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
if (mIsValid) {
|
||||
if (!mIsSuccessDialogShowed) {
|
||||
val activity = mCurrentActivityRef.get()
|
||||
if (activity != null) {
|
||||
showSuccessDialog(activity, "光环快速实名认证成功,正在开始游戏~")
|
||||
NewFlatLogUtils.logCwCertificationToastShow(mQQGameId)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val activity = mCurrentActivityRef.get()
|
||||
if (activity != null) {
|
||||
if (mIsCertificated) {//已经认证
|
||||
showSuccessDialogOrScheduleHealthyCheck(activity)
|
||||
} else {
|
||||
showInputRealNameDialog(activity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
private fun showInputRealNameDialog(activity: Activity) {
|
||||
if (mIsAgoShowInputRealNameDialog){
|
||||
return
|
||||
}
|
||||
tryWithDefaultCatch {
|
||||
currentInputRealNameDialog?.dismiss()
|
||||
}
|
||||
currentInputRealNameDialog =
|
||||
InputRealNameDialog.show(activity, mQQGameId, mQQGameName) { realName, idCard, isMinor ->
|
||||
mIsAdult = !isMinor
|
||||
mSubmitCertification = true
|
||||
mStartAppShowHeath = false
|
||||
mIsCertificated = true
|
||||
NewFlatLogUtils.logCwCertificationResult(mQQGameId, if (isMinor) "未成年人" else "成年人")
|
||||
syncCertification(realName, idCard)
|
||||
showSuccessDialogOrScheduleHealthyCheck(activity)
|
||||
|
||||
}
|
||||
NewFlatLogUtils.logCwCertificationDialogShow(mQQGameId, mQQGameName)
|
||||
mIsAgoShowInputRealNameDialog = true
|
||||
}
|
||||
|
||||
private fun showSuccessDialogOrScheduleHealthyCheck(activity: Activity) {
|
||||
if (mIsAdult) {//如果是成年人
|
||||
if (!mIsSuccessDialogShowed){
|
||||
showSuccessDialog(activity, "光环实名认证成功,正在开始游戏~")
|
||||
}
|
||||
} else {//未成年人
|
||||
timerTask?.cancel()//取消上一次的任务
|
||||
timerTask = MyTimerTask()
|
||||
//这里需要每一分钟请求一次当前时间是否是健康时间段
|
||||
timer.schedule(timerTask, 0, 1 * 60 * 1000)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class MyTimerTask : TimerTask() {
|
||||
override fun run() {
|
||||
checkHealthyTime()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private fun syncCertification(realName: String, idCard: String) {
|
||||
if (mApplication != null) {
|
||||
val resolver = mApplication!!.contentResolver
|
||||
val insertUri = Uri.parse("content://com.gh.gamecenter.provider/sync_certification")
|
||||
val values = ContentValues()
|
||||
values.put("real_name", Base64.encodeToString(realName.toByteArray(), Base64.DEFAULT))
|
||||
values.put("id_card", Base64.encodeToString(idCard.toByteArray(), Base64.DEFAULT))
|
||||
resolver.insert(insertUri, values)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityPaused(p0: Activity) {
|
||||
mCurrentActivityRef.clear()
|
||||
mStartAppShowHeath = false
|
||||
}
|
||||
|
||||
override fun onActivityStopped(p0: Activity) {
|
||||
|
||||
}
|
||||
|
||||
override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) {
|
||||
|
||||
}
|
||||
|
||||
override fun onActivityDestroyed(p0: Activity) {
|
||||
currentRealNameDialog?.dismiss()
|
||||
mIsSuccessDialogShowed = false
|
||||
}
|
||||
|
||||
private fun validateRealNameInfo(context: Context) {
|
||||
// 检查光环实名
|
||||
val uri = Uri.parse("content://com.gh.gamecenter.provider/certification")
|
||||
val cursor = context.contentResolver?.query(
|
||||
uri,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
|
||||
if (cursor == null) {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("ghzhushou://invoke_only"))
|
||||
if (context !is Activity) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
if (cursor != null && cursor.count > 0) {
|
||||
cursor.moveToFirst()
|
||||
do {
|
||||
if (cursor.getInt(1) == 1) {
|
||||
mIsCertificated = true
|
||||
if (cursor.getInt(2) == 1) {
|
||||
//如果是成年人 那肯定是认证了???
|
||||
mIsValid = true
|
||||
mIsAdult = true
|
||||
}
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
cursor.close()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSuccessRealNameDialog(activity: Activity?, isPlay: Boolean) {
|
||||
if (activity != null) {
|
||||
if (isPlay == mLastIsHealthyTime && mIsAgoShowRealNameDialog) {
|
||||
return
|
||||
}
|
||||
tryWithDefaultCatch {
|
||||
currentRealNameDialog?.dismiss()
|
||||
}
|
||||
|
||||
// 羊了个羊游戏在广告页面退出游戏会导致应用进程再次被唤起,这里做一个弹窗延时
|
||||
if (!isPlay && activity.packageName.equals("com.hlys.hcrcq.ylgy.gzgw27")
|
||||
&& activity.localClassName.equals("com.jygame.ui.SplashActivity")) {
|
||||
return
|
||||
}
|
||||
|
||||
currentRealNameDialog = RealNameDialog.show(activity, isPlay) { play ->
|
||||
if (play) {
|
||||
//进入游戏
|
||||
uploadHealthTipsEvent(activity, isPlay, "进入游戏")
|
||||
mSubmitCertification = false
|
||||
mStartAppShowHeath = false
|
||||
} else {
|
||||
//退出游戏
|
||||
uploadHealthTipsEvent(activity, isPlay, "退出游戏")
|
||||
mExitClosure?.invoke()
|
||||
}
|
||||
}
|
||||
uploadHealthTipsEvent(activity, isPlay, "")
|
||||
mIsAgoShowRealNameDialog = true
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun uploadHealthTipsEvent(activity: Activity, isPlay: Boolean, operation: String) {
|
||||
var entrance = ""
|
||||
val heath = if (isPlay) "健康时间" else "非健康时间"
|
||||
if (mStartAppShowHeath) {
|
||||
entrance = "启动游戏"
|
||||
} else if (mSubmitCertification) {
|
||||
entrance = "提交认证"
|
||||
mStartAppShowHeath = false
|
||||
} else {
|
||||
entrance = "未在健康时间段"
|
||||
mSubmitCertification = false
|
||||
mStartAppShowHeath = false
|
||||
}
|
||||
NewFlatLogUtils.logCwHeathTipShow(mQQGameId, heath, entrance, operation)
|
||||
SensorsLogUtils.logEvent(
|
||||
"HaloFunHealthTipsShow",
|
||||
"dialog_type", if (isPlay) "健康时间内" else "非健康时间",
|
||||
"result", operation,
|
||||
"source_entrance", entrance
|
||||
)
|
||||
}
|
||||
|
||||
private fun showSuccessDialog(activity: Activity, message: String) {
|
||||
TipBottomDialog.show(activity, true, message)
|
||||
mIsSuccessDialogShowed = true
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package com.lg.realname
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.lg.realname.databinding.DialogTipBinding
|
||||
|
||||
class TipBottomDialog(context: Context) : Dialog(context) {
|
||||
|
||||
private val mBinding by lazy { DialogTipBinding.inflate(LayoutInflater.from(context)) }
|
||||
private var mShouldShowIcon = false
|
||||
private var mContentMessage: String = ""
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
window?.setGravity(Gravity.BOTTOM)
|
||||
setCanceledOnTouchOutside(false)
|
||||
setContentView(mBinding.root)
|
||||
initUI()
|
||||
|
||||
mBinding.root.postDelayed({
|
||||
tryWithDefaultCatch {
|
||||
dismiss()
|
||||
}
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
val height = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
window?.setLayout(width, height)
|
||||
}
|
||||
|
||||
private fun initUI() {
|
||||
mBinding.tipTv.text = mContentMessage
|
||||
if (!mShouldShowIcon) {
|
||||
mBinding.tipIconIv.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun show(
|
||||
context: Context,
|
||||
showIcon: Boolean = true,
|
||||
contentMessage: String
|
||||
) {
|
||||
val dialog = TipBottomDialog(context)
|
||||
dialog.mShouldShowIcon = showIcon
|
||||
dialog.mContentMessage = contentMessage
|
||||
var params = dialog.window?.attributes
|
||||
params?.y = DisplayUtils.dip2px(40F)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.lg.realname.provider
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IRealNameProvider
|
||||
import com.lg.realname.RealNameHelper
|
||||
|
||||
@Route(path = RouteConsts.provider.realName, name = "实名认证暴露服务")
|
||||
class RealNameProviderImpl : IRealNameProvider {
|
||||
|
||||
override fun init(application: Application) {
|
||||
RealNameHelper.init(application)
|
||||
}
|
||||
|
||||
override fun setAppInfo(qqGameId: String, qqGameName: String, exitClosure: (() -> Unit)) {
|
||||
RealNameHelper.setAppInfo(qqGameId, qqGameName, exitClosure)
|
||||
}
|
||||
|
||||
override fun init(context: Context?) {}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user