Merge remote-tracking branch 'origin/dev' into dev-5.26.0

This commit is contained in:
chenjuntao
2023-05-22 11:27:59 +08:00
71 changed files with 643 additions and 95 deletions

View File

@ -54,6 +54,7 @@ android_build:
- offline-test
stage: build&analyze
image: hub.shanqu.cc/library/ci-android:jdk11-sdk31-33
resource_group: android_build
variables:
GIT_SUBMODULE_STRATEGY: recursive
KUBERNETES_CPU_LIMIT: "10"

View File

@ -11,6 +11,7 @@ android {
String CONFIG_ID = ""
String FIRST_LAUNCH = ""
int ACTIVATE_REPORTING_RATIO = 0
buildFeatures {
viewBinding true
@ -76,6 +77,8 @@ android {
// 首次启动的跳转配置
buildConfigField "String", "FIRST_LAUNCH", "\"${FIRST_LAUNCH}\""
buildConfigField "int", "ACTIVATE_REPORTING_RATIO", "${ACTIVATE_REPORTING_RATIO}"
// All third-party appid/appkey
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
buildConfigField "String", "NEW_API_HOST", "\"${NEW_API_HOST}\""
@ -329,6 +332,7 @@ dependencies {
// implementation(project(':feature:vpn'))
implementation(project(':feature:pkg'))
implementation(project(':feature:floating-window'))
implementation(project(':feature:beizi_startup_ad'))
}
File propFile = file('sign.properties')

View File

@ -26,7 +26,7 @@ class FlavorProviderImp : IFlavorProvider {
return channel
}
override fun init(application: Application, activity: Activity) {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
// do nothing
}

View File

@ -12,7 +12,7 @@ import com.leon.channel.helper.ChannelReaderUtil
class FlavorProviderImp : IFlavorProvider {
override fun init(application: Application, activity: Activity) {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
GdtHelper.init(application, getChannelStr(application))
if (HaloApp.getInstance().isBrandNewInstall) {

View File

@ -12,7 +12,7 @@ import com.kwai.monitor.payload.TurboHelper
class FlavorProviderImp : IFlavorProvider {
override fun init(application: Application, activity: Activity) {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
KuaishouHelper.init(application, getChannelStr(application))
if (HaloApp.getInstance().isBrandNewInstall) {

View File

@ -46,7 +46,8 @@
<!-- 如果有视频相关的广告且使用textureView播放请务必添加否则黑屏 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-sdk tools:overrideLibrary="com.shuyu.gsyvideoplayer,
<uses-sdk tools:overrideLibrary="
com.shuyu.gsyvideoplayer,
com.shuyu.gsyvideoplayer.lib,
com.haroldadmin.whatthestack,
com.shuyu.gsyvideoplayer.armv7a,
@ -120,7 +121,7 @@
android:name="io.sentry.breadcrumbs.system-events"
android:value="false" />
<service android:name = "com.gh.ndownload.NDownloadService" />
<service android:name="com.gh.ndownload.NDownloadService" />
<activity
android:name="com.gh.gamecenter.SplashScreenActivity"

View File

@ -455,7 +455,7 @@ public class BindingAdapters {
}
if (gameEntity.isVGame()) {
VHelper.installOrLaunch((AppCompatActivity) v.getContext(), gameEntity.getApk().get(0).getPackageName());
VHelper.installOrLaunch((AppCompatActivity) v.getContext(), gameEntity);
return;
}
@ -473,10 +473,9 @@ public class BindingAdapters {
case INSTALL_NORMAL:
if (gameEntity.getApk().size() == 1) {
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);
String packageName = gameEntity.getApk().get(0).getPackageName();
if (gameEntity.isVGame()) {
VHelper.installOrLaunch(v.getContext(), packageName);
VHelper.installOrLaunch(v.getContext(), gameEntity);
return;
}

View File

@ -114,7 +114,7 @@ public class DetailDownloadUtils {
if (downloadEntity == null && viewHolder.gameEntity.isVGame()) {
String packageName = viewHolder.gameEntity.getUniquePackageName();
if (!TextUtils.isEmpty(packageName)) {
downloadEntity = VHelper.getDownloadEntitySnapshot(viewHolder.gameEntity.getId(), packageName);
downloadEntity = VHelper.getVDownloadEntitySnapshot(viewHolder.gameEntity.getId(), packageName);
}
}
@ -214,7 +214,7 @@ public class DetailDownloadUtils {
if (downloadEntity == null && viewHolder.gameEntity.isVGame()) {
String packageName = viewHolder.gameEntity.getUniquePackageName();
if (!TextUtils.isEmpty(packageName)) {
downloadEntity = VHelper.getDownloadEntitySnapshot(viewHolder.gameEntity.getId(), packageName);
downloadEntity = VHelper.getVDownloadEntitySnapshot(viewHolder.gameEntity.getId(), packageName);
}
}

View File

@ -266,7 +266,7 @@ object DownloadItemUtils {
var downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
if (downloadEntity == null && gameEntity.isVGame()) {
downloadEntity = VHelper.getDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
downloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
}
if (downloadEntity == null) {
@ -884,7 +884,7 @@ object DownloadItemUtils {
}
if (gameEntity.isVGame()) {
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity.getUniquePackageName() ?: "")
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
} else {
install(context, gameEntity, position, adapter, refreshCallback)
}
@ -909,7 +909,7 @@ object DownloadItemUtils {
}
if (gameEntity.isVGame()) {
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity.getUniquePackageName() ?: "")
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
return
}

View File

@ -298,7 +298,7 @@ object GameActivityDownloadHelper {
}
if (gameEntity.isVGame()) {
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity.getUniquePackageName() ?: "")
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
} else {
downloadEntity?.run {
install(context, gameEntity, apk, this)
@ -336,7 +336,7 @@ object GameActivityDownloadHelper {
}
if (gameEntity.isVGame()) {
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity.getUniquePackageName() ?: "")
VHelper.installOrLaunch((context as AppCompatActivity), gameEntity)
return
}

View File

@ -107,7 +107,7 @@ public class GameUtils {
// 在下载管理找不到下载实体,并且为畅玩游戏的时候到畅玩数据库里找
if (downloadEntity == null && gameEntity.isVGame()) {
downloadEntity = VHelper.getDownloadEntitySnapshot(gameEntity.getId(), apkEntity.getPackageName());
downloadEntity = VHelper.getVDownloadEntitySnapshot(gameEntity.getId(), apkEntity.getPackageName());
}
if (downloadEntity != null) {

View File

@ -627,7 +627,7 @@ public class DownloadManager implements DownloadStatusListener {
}
/**
* 根据 url 获取下载任务快照 (仅保证下载状态一致)
* 根据包名获取下载任务快照 (仅保证下载状态一致)
*
* @param packageName 包名 (多包名一样时取第一个,若使用场景里有多包名,请使用 url 获取下载任务)
* @return null 表示下载列表中不存在该任务,否则返回下载任务

View File

@ -861,7 +861,7 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
imageView.setOnLongClickListener {
// 下滑的时候不弹
if (imageView.isDragging()) {
return@setOnLongClickListener false
return@setOnLongClickListener true
}
val dialog = Dialog(this@ImageViewerActivity)
@ -897,7 +897,7 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
}
dialog.cancel()
}
false
true
}
view.tag = position
container.addView(view)

View File

@ -26,7 +26,6 @@ import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.preference.PreferenceManager;
@ -34,6 +33,7 @@ import android.text.Html;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
@ -43,6 +43,7 @@ import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
import com.alibaba.android.arouter.launcher.ARouter;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.common.DefaultUrlHandler;
import com.gh.common.constant.Config;
@ -76,6 +77,7 @@ import com.gh.gamecenter.common.base.fragment.ToolbarFragment;
import com.gh.gamecenter.common.constant.CommonConsts;
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.entity.NotificationUgc;
import com.gh.gamecenter.common.entity.SuggestType;
@ -90,6 +92,7 @@ import com.gh.gamecenter.common.utils.ImageUtils;
import com.gh.gamecenter.common.utils.NotificationHelper;
import com.gh.gamecenter.common.utils.ShareUtils;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.core.provider.IStartUpAdProvider;
import com.gh.gamecenter.core.utils.ClassUtils;
import com.gh.gamecenter.core.utils.DisplayUtils;
import com.gh.gamecenter.core.utils.GsonUtils;
@ -189,6 +192,8 @@ public class MainActivity extends BaseActivity {
private final Handler handler = new Handler();
public boolean showAd = false; // 是否显示广告
private IStartUpAdProvider mStartUpAdProvider;
@Override
protected void onCreate(Bundle savedInstanceState) {
showAd = getIntent().getBooleanExtra(SHOW_AD, false) && savedInstanceState == null;
@ -495,6 +500,7 @@ public class MainActivity extends BaseActivity {
if (!showAd) {
hideStartUp();
hideStartUpAd();
hideSDKStartUpAd();
return;
}
final StartupAdEntity startUp = AdHelper.getStartUp();
@ -502,8 +508,17 @@ public class MainActivity extends BaseActivity {
showStartUp(startUp);
AppExecutor.getUiExecutor().executeWithDelay(() -> {
hideStartUp();
observeStartUpAd();
initStartUpAd();
}, 2000);
} else {
initStartUpAd();
}
}
private void initStartUpAd() {
mStartUpAdProvider = (IStartUpAdProvider) ARouter.getInstance().build(RouteConsts.provider.adSdk).navigation();
if (mStartUpAdProvider != null && mStartUpAdProvider.shouldEnableSDK(HaloApp.getInstance().getChannel())) {
initSDKStartUpAd();
} else {
observeStartUpAd();
}
@ -600,6 +615,18 @@ public class MainActivity extends BaseActivity {
checkDialog();
}
private void hideSDKStartUpAd() {
showAd = false;
getIntent().putExtra(SHOW_AD, false);
View startAdContainer = findViewById(R.id.sdkStartAdContainer);
if (startAdContainer != null) {
startAdContainer.setVisibility(View.GONE);
ExtensionsKt.removeFromParent(startAdContainer);
if (mStartUpAdProvider != null) mStartUpAdProvider.cancelStartUpAd(this);
}
checkDialog();
}
private void checkDialog() {
// 检查通知权限
checkNotificationPermission();
@ -654,6 +681,18 @@ public class MainActivity extends BaseActivity {
mBaseHandler.sendEmptyMessageDelayed(COUNTDOWN_AD, 1000);
}
private void initSDKStartUpAd() {
View startAdContainer = findViewById(R.id.sdkStartAdContainer);
startAdContainer.setVisibility(View.VISIBLE);
FrameLayout adsFl = findViewById(R.id.adsFl);
if (mStartUpAdProvider != null) {
mStartUpAdProvider.initStartUpAd(startAdContainer, adsFl, showAd, () -> {
hideSDKStartUpAd();
return null;
});
}
}
private void showStartUp(StartupAdEntity ad) {
TextView adContentTv = findViewById(R.id.adContentTv);
View containerView = findViewById(R.id.maskContainer);

View File

@ -21,7 +21,6 @@ import com.alibaba.android.arouter.launcher.ARouter
import com.g00fy2.versioncompare.Version
import com.gh.common.dialog.NewPrivacyPolicyDialogFragment
import com.gh.common.util.*
import com.gh.common.util.DialogUtils
import com.gh.common.util.GameSubstituteRepositoryHelper.updateGameSubstituteRepository
import com.gh.common.util.UsageStatsHelper.checkAndPostUsageStats
import com.gh.download.DownloadManager
@ -29,10 +28,12 @@ import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.callback.SimpleCallback
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.common.tracker.TrackerLogger
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
import com.gh.gamecenter.core.provider.IStartUpAdProvider
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.entity.PrivacyPolicyEntity
@ -62,6 +63,9 @@ class SplashScreenActivity : BaseActivity() {
private var mStartMainActivityDirectly = false // 是否不需要用户点击立即体验就直接跳转首页
private var mViewModel: SplashScreenViewModel? = null
private var mShouldPrefetchData = true
private val mStartUpAdProvider by lazy {
ARouter.getInstance().build(RouteConsts.provider.adSdk).navigation() as? IStartUpAdProvider
}
private val mPermissions = arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
@ -294,19 +298,45 @@ class SplashScreenActivity : BaseActivity() {
overridePendingTransition(0, 0)
startActivity(intent)
doFlavorInit()
initStartUpAdSDK()
logAppLaunch()
finish()
}
private fun doFlavorInit() {
HaloApp.getInstance().flavorProvider.init(HaloApp.getInstance(), this)
HaloApp.getInstance().flavorProvider.init(HaloApp.getInstance(), this, PkgHelper.getActivateRatio())
// 仅官网渠道和测试包启用神策
if ("GH_206" == HaloApp.getInstance().channel || PackageFlavorHelper.IS_TEST_FLAVOR) {
val whiteListChannel = arrayListOf<String>(
"GH_206",
"KS-GHZS-KY1",
"KS-GHZS-MC1",
"GDT_GHZS_MC1",
"T11-GH-APPDY-ZC01",
"T7-GH-APPDY-KY03",
"T8-GH-APPUX-KY04",
"T1-GHZS-MC01",
"T4-GHZS-MC03"
)
if (whiteListChannel.contains(HaloApp.getInstance().channel) || PackageFlavorHelper.IS_TEST_FLAVOR) {
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
}
}
private fun initStartUpAdSDK() {
mStartUpAdProvider?.run {
if (shouldEnableSDK(HaloApp.getInstance().channel)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
initOAID(applicationContext) {
HaloApp.getInstance().oaid = it
MetaUtil.refreshMeta()
}
}
initSDK(applicationContext)
}
}
}
private fun getGitLogString(): String {
if (com.gh.gamecenter.common.BuildConfig.BUILD_TIME != 0L) {
val stringBuilder = StringBuilder()

View File

@ -346,7 +346,7 @@ public class DetailViewHolder {
}
if (mGameEntity.isVGame()) {
VHelper.installOrLaunch(mViewHolder.context, mGameEntity.getApk().get(0).getPackageName());
VHelper.installOrLaunch(mViewHolder.context, mGameEntity);
return;
}
@ -388,7 +388,7 @@ public class DetailViewHolder {
}
if (mGameEntity.isVGame()) {
VHelper.installOrLaunch(v.getContext(), mGameEntity.getApk().get(0).getPackageName());
VHelper.installOrLaunch(v.getContext(), mGameEntity);
return;
}

View File

@ -210,7 +210,7 @@ class AuthorizationActivity : ToolBarActivity() {
private fun backToLaunchApp(showLoading: Boolean = true) {
val gamePkg = mGamePkg
if (gamePkg != null) { // 跳转回游戏
VHelper.launch(this, gamePkg, showLoading = showLoading)
VHelper.launch(this, gamePkg, ignoreGApps = true, showLoading = showLoading)
return
}
val remotePkgName = this.mRemotePkgName

View File

@ -338,7 +338,7 @@ class CloudArchiveManagerActivity : BaseActivity_TabLayout() {
btnText = getString(R.string.launch)
setOnClickListener {
CurrentActivityHolder.getCurrentActivity()?.let {
VHelper.installOrLaunch(it, downloadEntity.packageName)
VHelper.installOrLaunch(it, downloadEntity)
}
}
}

View File

@ -463,7 +463,7 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
mViewModel?.sectionListLiveData?.observe(this) {
if (!it.isNullOrEmpty() && it.size >= 2) {
mShowSections = true
mBinding.sectionContainer.visibility = View.VISIBLE
mBinding.sectionContainer.goneIf(mViewPager.currentItem != INDEX_ALL)
if (mSectionId.isNotEmpty()) {
it.forEachIndexed { index, section ->
if (section.id == mSectionId) {

View File

@ -197,7 +197,8 @@ class HomeSearchToolWrapperFragment : SearchToolWrapperFragment() {
topMaskView.layoutParams = topMaskView.layoutParams.apply {
height = DisplayUtils.getStatusBarHeight(requireContext().resources) + 48F.dip2px()
}
mTwoLevelOpenOffset = 312F.dip2px() - DisplayUtils.getStatusBarHeight(requireContext().resources)
mTwoLevelOpenOffset =
DisplayUtils.getScreenWidth() - 48F.dip2px() - DisplayUtils.getStatusBarHeight(requireContext().resources)
mShowTwoLevelStartOffset = 139F.dip2px() - DisplayUtils.getStatusBarHeight(requireContext().resources)
tabBackground.setOnlyTopRoundedColorBackground(R.color.background_white.toColor(requireContext()), 8F)
classicsHeader.setArrowResource(R.drawable.icon_arrow)
@ -527,6 +528,7 @@ class HomeSearchToolWrapperFragment : SearchToolWrapperFragment() {
fun popUpHomePushIfNeeded() {
mBinding?.run {
if (mFragmentList.safelyGetInRelease(viewPager.currentItem) !is HomeFragment) return
mHomePush?.run {
val homePushSet = HashSet(SPUtils.getStringSet(Constants.SP_HOME_PUSH_POP_UP_SET))
if (popSwitch == "on" && !homePushSet.contains(id)) {

View File

@ -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.IStartUpAdProvider
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.SPUtils
@ -103,7 +104,10 @@ class HomeFragment : LazyFragment() {
reuseLoading.root.goneIf(loadStatus != LoadStatus.INIT_LOADING)
}
mListAdapter.setLoadStatus(it)
val startAdContainerView = requireActivity().findViewById<View>(R.id.startAdContainer)
val startUpAdProvider =
ARouter.getInstance().build(RouteConsts.provider.adSdk).navigation() as? IStartUpAdProvider
val startAdContainerView =
requireActivity().findViewById<View>(if (startUpAdProvider != null) R.id.sdkStartAdContainer else R.id.startAdContainer)
if (it == LoadStatus.INIT_LOADED && startAdContainerView == null) {
AppExecutor.uiExecutor.executeWithDelay({
scroll()
@ -195,7 +199,9 @@ class HomeFragment : LazyFragment() {
}
fun setScrollEnabled(isScrollEnabled: Boolean) {
mAutomaticLayoutManager.isScrollEnabled = isScrollEnabled
if (::mAutomaticLayoutManager.isInitialized) {
mAutomaticLayoutManager.isScrollEnabled = isScrollEnabled
}
}
fun onRefresh() {
@ -217,7 +223,10 @@ class HomeFragment : LazyFragment() {
* 2. 过早显示悬浮窗,出现首页还未显示悬浮窗就在广告页显示的情况
*/
private fun listenStartAdViewRemoved() {
val startAdContainerView = requireActivity().findViewById<View>(R.id.startAdContainer)
val startUpAdProvider =
ARouter.getInstance().build(RouteConsts.provider.adSdk).navigation() as? IStartUpAdProvider
val startAdContainerView =
requireActivity().findViewById<View>(if (startUpAdProvider != null) R.id.sdkStartAdContainer else R.id.startAdContainer)
val parentView = startAdContainerView?.parent as? ViewGroup
if (parentView == null) {

View File

@ -32,9 +32,10 @@ class HomeGameCollectionAdapter(
override fun onBindViewHolder(holder: HomeGameCollectionCardViewHolder, position: Int) {
if (gameCollectionItemDataList.isNotEmpty()) {
val gameCollectionItemData = gameCollectionItemDataList.safelyGetInRelease(position)
(holder.itemView as HomeGameCollectionItemCell).bindWhenInflated {
(holder.itemView as HomeGameCollectionItemCell).binding?.run {
holder.bindGameCollectionCard(this, gameCollectionItemDataList[position], entrance)
gameCollectionItemData?.let { holder.bindGameCollectionCard(this, it, entrance) }
}
}
}

View File

@ -5,6 +5,7 @@ import android.view.View
import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.core.utils.DisplayUtils
/**
* @author : liujiarui
@ -13,6 +14,9 @@ import com.gh.gamecenter.common.utils.dip2px
* 仅用于新游开测,让条目右侧漏出部分,或者最后一列左侧条目漏出部分
*/
class HomeGameTestV2Decoration : RecyclerView.ItemDecoration() {
private val mParentWidth = DisplayUtils.getScreenWidth() - 32F.dip2px()
companion object {
private const val SPAN_COUNT = 3
}
@ -24,7 +28,7 @@ class HomeGameTestV2Decoration : RecyclerView.ItemDecoration() {
if (lastModPosition == 0) lastModPosition = SPAN_COUNT
val isLastRow = (itemCount - position) <= lastModPosition
view.updateLayoutParams {
width = parent.width - if (isLastRow) {
width = mParentWidth - if (isLastRow) {
8F.dip2px()
} else {
24F.dip2px()

View File

@ -185,7 +185,8 @@ class HomeGameTestV2ViewModel(application: Application) : AndroidViewModel(appli
timeType = response.timeType,
pageId = response.pageId,
action = Action.getActionByCommand(response.action),
isRefresh = false
isRefresh = false,
isSameTimeType = timeType == loadTimeType
)
}
@ -289,7 +290,8 @@ class HomeGameTestV2ViewModel(application: Application) : AndroidViewModel(appli
pageId: String,
action: Action,
firstIndex: Int = 0, //首页推荐列表左侧剩余游戏数
isRefresh: Boolean = false
isRefresh: Boolean = false,
isSameTimeType: Boolean = false //当前时间轴类型与预加载时间轴类型是否相同
) {
val currentData = getCurrentData().toMutableList()
val gameList = getFilterGameAndTrimList(currentData, list)
@ -324,7 +326,7 @@ class HomeGameTestV2ViewModel(application: Application) : AndroidViewModel(appli
gameList.reverse()
}
gameList.forEach {
addGameItemWithAction(currentData, it, action)
addGameItemWithAction(currentData, it, action, isSameTimeType)
}
}
mDataLiveData.value = currentData.toMutableList()
@ -341,11 +343,20 @@ class HomeGameTestV2ViewModel(application: Application) : AndroidViewModel(appli
dataList: MutableList<GameDataWrapper>,
gameDataWrapper: GameDataWrapper,
action: Action,
isSameTimeType: Boolean
) {
val gameTimeType = gameDataWrapper.timeType
val firstLoadedRecommendPosition =
dataList.indexOfFirst { it.timeType == "recommend" && !it.isPlaceHolder && !it.isSpace } // 推荐类型第一个非占位的位置
val lastLoadedRecommendPosition =
dataList.indexOfLast { it.timeType == "recommend" && !it.isPlaceHolder && !it.isSpace } // 推荐类型最后一个非占位的位置
val shouldInsertLoadedRecommendFront =
gameTimeType == "recommend" && isSameTimeType && firstLoadedRecommendPosition > 0 // 推荐定位不是第一个时需要插入到已加载位置的前面
val shouldInsertLoadedRecommendBehind =
gameTimeType == "recommend" && isSameTimeType && lastLoadedRecommendPosition > 0 // 推荐定位不是第一个时需要插入到已加载位置的后面
val insertPosition = when (action) {
Action.LEFT -> dataList.indexOfFirst { it.timeType == gameTimeType && it.isPlaceHolder }
Action.RIGHT -> dataList.indexOfLast { it.timeType == gameTimeType && it.isPlaceHolder }
Action.LEFT -> if (shouldInsertLoadedRecommendBehind) lastLoadedRecommendPosition + 1 else dataList.indexOfFirst { it.timeType == gameTimeType && it.isPlaceHolder }
Action.RIGHT -> if (shouldInsertLoadedRecommendFront) firstLoadedRecommendPosition - 1 else dataList.indexOfLast { it.timeType == gameTimeType && it.isPlaceHolder }
}
val exist = dataList.find { it.timeType == gameTimeType && it.gameData?.id == gameDataWrapper.gameData?.id }
if (exist != null) {

View File

@ -212,7 +212,8 @@ class HomeItemGameTestV2ViewHolder(
pageId = data.pageId,
action = HomeGameTestV2ViewModel.Action.getActionByCommand(data.action),
firstIndex = recommendLeftSurplusNum,
isRefresh = true
isRefresh = true,
isSameTimeType = true
)
//数据填充完毕后滑动到推荐列表指定位置
if (recommendLeftSurplusNum > 0) {

View File

@ -43,7 +43,7 @@ class HaloPersonalFunctionAdapter(context: Context) : BaseRecyclerAdapter<Recycl
}
mEntityList.clear()
mEntityList.addAll(functionList)
notifyItemRangeChanged(0, itemCount)
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =

View File

@ -44,7 +44,7 @@ class HaloPersonalRecommendAdapter(val context: Context) : BaseRecyclerAdapter<R
}
mEntityList.clear()
mEntityList.addAll(recommendList)
notifyItemRangeChanged(0, itemCount)
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =

View File

@ -15,10 +15,23 @@ object PkgHelper {
private var mPkgConfigLink: PkgConfigEntity.PkgLinkEntity? = null
private const val SP_PKG_CONFIG_IS_USED = "pkg_config_is_used"
private var mActivateRatioFromInternet = 0
private val mPkgProvider by lazy {
ARouter.getInstance().build(RouteConsts.provider.pkg).navigation() as? IPkgProvider<PkgConfigEntity>
}
/**
* 获取激活比例
*/
fun getActivateRatio() : Int {
return if (mActivateRatioFromInternet > 0) {
mActivateRatioFromInternet
} else {
BuildConfig.ACTIVATE_REPORTING_RATIO
}
}
fun getPkgConfig(isFromHomeTopTab: Boolean): PkgConfigEntity.PkgLinkEntity? {
if (mPkgConfigLink == null
&& !SPUtils.getBoolean(SP_PKG_CONFIG_IS_USED, false)
@ -56,7 +69,9 @@ object PkgHelper {
mPkgProvider?.requestPkgConfig(configId) {
mPkgConfigLink = it.data?.link
mActivateRatioFromInternet = it.data?.activateRatio ?: 0
}
}
}

View File

@ -149,10 +149,7 @@ class HomeRecentVGameAdapter(context: Context) : DiffUtilAdapter<VGameItemData>(
}
} else {
binding.root.setOnClickListener {
VHelper.installOrLaunch(
binding.root.context,
downloadEntity.packageName
)
VHelper.installOrLaunch(binding.root.context, downloadEntity)
}
}
}

View File

@ -180,7 +180,7 @@ class VDownloadManagerAdapter(
}
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
?: VHelper.getDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
?: VHelper.getVDownloadEntitySnapshot(gameEntity.id, gameEntity.getUniquePackageName())
updateDownloadBtnAndDes(
mContext,
@ -527,7 +527,7 @@ class VDownloadManagerAdapter(
btnText = context.getString(R.string.launch)
setOnClickListener {
CurrentActivityHolder.getCurrentActivity()?.let {
VHelper.installOrLaunch(it, downloadEntity.packageName)
VHelper.installOrLaunch(it, downloadEntity)
}
}
}

View File

@ -133,6 +133,9 @@ object VHelper {
// 是否已经尝试过重连
private var mHasAlreadyTriedReConnect = false
// 临时的用来临时匹配安装完成时包名对应的游戏 ID 的 Map
private var mTempPackageNameAndGameIdMap = hashMapOf<String, String>()
val vGameLiveData by lazy { mVGameDao.getAllLiveData() }
private val mVGameObserver by lazy {
@ -415,7 +418,7 @@ object VHelper {
@JvmStatic
fun getVGameSnapshot(gameId: String? = null, packageName: String? = null): VGameEntity? {
return mVGameSnapshotList.find {
it.packageName == packageName && (gameId == null || it.downloadEntity.gameId == gameId)
it.packageName == packageName && (gameId.isNullOrEmpty() || it.downloadEntity.gameId == gameId)
}
}
@ -631,6 +634,9 @@ object VHelper {
)
) return
// 更新此包名对应的 gameId Map
mTempPackageNameAndGameIdMap[downloadEntity.packageName] = downloadEntity.gameId
// 当且仅当
// 1. 全局安装完成启动游戏开关打开
// 2. 服务连接不成功或是手动触发的安装
@ -759,7 +765,9 @@ object VHelper {
*/
fun onInstallFinished(packageName: String, result: VGameInstallerResult) {
runOnIoThread {
val downloadEntity = getDownloadEntityByPackageName(packageName)
val gameId = mTempPackageNameAndGameIdMap[packageName] ?: ""
val downloadEntity = getVDownloadEntity(gameId = gameId, packageName = packageName)
if (downloadEntity != null) {
// 去掉更新标记
@ -835,13 +843,19 @@ object VHelper {
* 游戏是否正在安装中
*/
fun isInstalling(packageName: String): Boolean {
val downloadEntity = getDownloadEntityByPackageName(packageName) ?: return false
val gameId = mTempPackageNameAndGameIdMap[packageName] ?: ""
val downloadEntity = getVDownloadEntity(gameId = gameId, packageName = packageName) ?: return false
return (mInstallingVaPathSet.contains(downloadEntity.path))
}
private fun getDownloadEntityByPackageName(packageName: String): DownloadEntity? {
return DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName)
?: getDownloadEntitySnapshot(gameId = null, packageName = packageName)
/**
* 获取实体 (虽然实体是 DownloadEntity 其实就是游戏实体)
* 优先从下载管理里获取(根据 gameId 获取)
* 下载管理不存在时从畅玩游戏数据库的里获取
*/
private fun getVDownloadEntity(gameId: String, packageName: String): DownloadEntity? {
return DownloadManager.getInstance().getDownloadEntitySnapshot("", gameId, true)
?: getVDownloadEntitySnapshot(gameId = gameId, packageName = packageName)
}
private fun insertInstalledGameToProvider(downloadEntity: DownloadEntity, fromRetry: Boolean = false) {
@ -873,11 +887,23 @@ object VHelper {
}
}
fun installOrLaunch(context: Context, downloadEntity: DownloadEntity) {
Utils.log(LOG_TAG, "检测是需要安装还是启动 ${downloadEntity.gameId}")
installOrLaunch(context, downloadEntity.packageName, downloadEntity.gameId)
}
@JvmStatic
fun installOrLaunch(context: Context, gameEntity: GameEntity) {
Utils.log(LOG_TAG, "检测是需要安装还是启动 ${gameEntity.id}")
installOrLaunch(context, gameEntity.getUniquePackageName() ?: "", gameEntity.id)
}
/**
* 安装或启动应用
*/
@JvmStatic
fun installOrLaunch(context: Context, packageName: String) {
private fun installOrLaunch(context: Context, packageName: String, gameId: String) {
Utils.log(LOG_TAG, "检测是需要安装还是启动 $packageName")
validateVSpaceBeforeAction(context, null) {
@ -891,7 +917,7 @@ object VHelper {
}
// 检查下载管理是否有下载实体,有实体表明未安装成功
val downloadEntity = getDownloadEntityByPackageName(packageName)
val downloadEntity = getVDownloadEntity(gameId = gameId, packageName = packageName)
if (downloadEntity != null) {
val downloadedFile = File(downloadEntity.path)
@ -919,7 +945,7 @@ object VHelper {
// 置空下载挂起回调(能 launch 游戏说明畅玩组件已安装)
mPendingDownloadCallback = null
val downloadEntity = getDownloadEntityByPackageName(packageName)
val downloadEntity = getVDownloadEntity(gameId = "", packageName = packageName)
val gameId = downloadEntity?.gameId ?: "unknown"
val gameName = downloadEntity?.name ?: "unknown"
@ -1075,10 +1101,10 @@ object VHelper {
}
/**
* 根据游戏 ID 和包名获取下载快照
* 根据游戏 ID 和包名获取畅玩游戏的实体快照
*/
@JvmStatic
fun getDownloadEntitySnapshot(gameId: String?, packageName: String?): DownloadEntity? {
fun getVDownloadEntitySnapshot(gameId: String?, packageName: String?): DownloadEntity? {
return getVGameSnapshot(gameId, packageName)?.downloadEntity
}

View File

@ -153,10 +153,7 @@ object VLoadCompleteWindowHelper {
"启动",
mAdapter.gameEntityList[mBinding.viewPager.currentItem].id
)
VHelper.installOrLaunch(
activity,
mAdapter.gameEntityList[mBinding.viewPager.currentItem].getApk()[0].packageName
)
VHelper.installOrLaunch(activity, mAdapter.gameEntityList[mBinding.viewPager.currentItem])
}
}
}

View File

@ -80,7 +80,7 @@ class ShortcutManager private constructor() {
*/
fun tryCreateShortCut(context: Context, gameId: String, gamePkg: String, result: OnCreateShortcutResult) {
VHelper.postOnInitialized {
val downloadEntity = VHelper.getDownloadEntitySnapshot(gameId, gamePkg)
val downloadEntity = VHelper.getVDownloadEntitySnapshot(gameId, gamePkg)
runOnUiThread {
if (downloadEntity == null) {
result.failed()

View File

@ -70,7 +70,7 @@
android:layout_height="match_parent"
android:background="@color/background"
android:visibility="gone"
tools:visibility="visible">
tools:visibility="gone">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/adImage"
@ -129,4 +129,23 @@
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/sdkStartAdContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/launcher_background"
android:visibility="gone"
tools:visibility="visible">
<FrameLayout
android:id="@+id/adsFl"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -34,13 +34,14 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/headerContainer"
android:layout_width="match_parent"
android:layout_height="360dp"
android:layout_height="wrap_content"
android:background="@color/black">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/gameImageIv"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -51,6 +52,7 @@
android:layout_width="0dp"
android:layout_height="0dp"
app:avRadius="0"
app:layout_constraintDimensionRatio="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
<debug-overrides>
<trust-anchors>
<!-- Trust user added CAs while debuggable only -->

View File

@ -2,6 +2,7 @@ package com.gh.gamecenter.provider
import android.app.Activity
import android.app.Application
import android.os.Environment
import android.text.TextUtils
import com.gh.gamecenter.BuildConfig
import com.bytedance.hume.readapk.HumeSDK
@ -10,30 +11,34 @@ import com.gh.gamecenter.core.provider.IFlavorProvider
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeUtils
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import java.io.File
class FlavorProviderImp : IFlavorProvider {
private var mIsLuckyEnoughToUseTea = true
override fun init(application: Application, activity: Activity) {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
mIsLuckyEnoughToUseTea = amILucky(BuildConfig.ACTIVATE_REPORTING_RATIO)
mIsLuckyEnoughToUseTea = amILucky(activateRatio)
if (mIsLuckyEnoughToUseTea) {
TeaHelper.init(application, activity, getChannelStr(application))
if (HaloApp.getInstance().isBrandNewInstall) {
SPUtils.setLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000)
SPUtils.setLong(KEY_TIME_OF_BRAND_NEW_INSTALL, System.currentTimeMillis() / 1000)
} else {
val shouldSendRetentionLogEvent =
SPUtils.getBoolean("SHOULD_SEND_RETENTION_EVENT", true)
SPUtils.getBoolean(KEY_SHOULD_SEND_RETENTION_EVENT, true)
val installTimeNotToday =
!TimeUtils.isToday(SPUtils.getLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000))
!TimeUtils.isToday(SPUtils.getLong(KEY_TIME_OF_BRAND_NEW_INSTALL, System.currentTimeMillis() / 1000))
if (shouldSendRetentionLogEvent && installTimeNotToday) {
logEvent("retention_2d")
SPUtils.setBoolean("SHOULD_SEND_RETENTION_EVENT", false)
logEvent(RETENTION_2D)
SPUtils.setBoolean(KEY_SHOULD_SEND_RETENTION_EVENT, false)
}
}
} else {
SPUtils.setBoolean(KEY_UNLUCKY, true)
}
}
@ -52,8 +57,19 @@ class FlavorProviderImp : IFlavorProvider {
}
private fun amILucky(percentage: Int = 100): Boolean {
// 若上一次已经标记不幸运了,那就不再进行是否足够幸运的判断
if (SPUtils.getBoolean(KEY_UNLUCKY)) return false
val randomNumber = (0..100).random()
return randomNumber <= percentage
}
companion object {
const val RETENTION_2D = "retention_2d"
const val KEY_UNLUCKY = "UNLUCKY"
const val KEY_TIME_OF_BRAND_NEW_INSTALL = "TIME_OF_BRAND_NEW_INSTALL"
const val KEY_SHOULD_SEND_RETENTION_EVENT = "SHOULD_SEND_RETENTION_EVENT"
}
}

View File

@ -6,6 +6,7 @@ import com.android.build.api.transform.Transform
import com.android.build.api.transform.TransformInvocation
import com.android.build.gradle.AppExtension
import com.android.build.gradle.internal.pipeline.TransformManager
import com.gh.gamecenter.plugin.transform.ActivityTransformer
import com.gh.gamecenter.plugin.transform.DiskLruCacheTransformer
import com.gh.gamecenter.plugin.transform.ExoSourceManagerTransformer
import com.gh.gamecenter.plugin.transform.RoomTransformer
@ -49,6 +50,7 @@ class GhTransform(var project: Project) : Transform() {
mTransformHelper.addTransformer(ExoSourceManagerTransformer())
mTransformHelper.addTransformer(DiskLruCacheTransformer())
mTransformHelper.addTransformer(RoomTransformer())
mTransformHelper.addTransformer(ActivityTransformer())
}
/**

View File

@ -1,9 +1,7 @@
package com.gh.gamecenter.plugin
import com.gh.gamecenter.plugin.transform.Transformer
import javassist.CtClass
import org.apache.commons.io.IOUtils
import org.gradle.plugins.ide.idea.model.FilePath
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.util.jar.JarOutputStream

View File

@ -0,0 +1,45 @@
package com.gh.gamecenter.plugin.transform
import javassist.ClassPool
import javassist.CtClass
import javassist.NotFoundException
import javassist.bytecode.ClassFile
import java.io.BufferedInputStream
import java.io.DataInputStream
import java.io.InputStream
class ActivityTransformer : Transformer {
private val classPool = ClassPool.getDefault()
override fun getModifyClassName(): String {
return "ComponentActivity.class"
}
override fun modifyClass(filePath: String, inputStream: InputStream): CtClass? {
if (filePath.contains(getModifyClassName())) {
val classFile = ClassFile(DataInputStream(BufferedInputStream(inputStream)))
val ctClass = classPool.get(classFile.name)
if (ctClass.isFrozen) {
ctClass.defrost()
}
// 使用 try catch 包裹找到的第一个 startActivityForResult 方法 (若能找到的话)
// https://sentry.shanqu.cc/organizations/lightgame/issues/221480/?project=22&query=level%3Afatal+is%3Aunresolved&sort=freq&statsPeriod=14d
try {
val ctMethod = ctClass.getDeclaredMethod("startActivityForResult")
val exceptionType: CtClass = ClassPool.getDefault().get("java.lang.NullPointerException")
val catchBody = "{ System.out.println(\$e); return null; }"
ctMethod.addCatch(catchBody, exceptionType)
} catch (e: NotFoundException) {
e.printStackTrace()
}
return ctClass
}
return null
}
}

View File

@ -31,7 +31,7 @@ ext {
localbroadcastmanager = "1.0.0"
webkit = "1.4.0"
collection = "1.2.0"
activity = "1.2.3"
activity = "1.2.4"
material = "1.2.1"

1
feature/beizi_lib/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,4 @@
configurations.maybeCreate("default")
artifacts.add("default", file('beizi_ad_sdk_3.4.20.23.aar'))
artifacts.add("default", file('beizi_fusion_sdk_4.90.2.27.aar'))
artifacts.add("default", file('oaid_sdk_1.0.25.aar'))

Binary file not shown.

1
feature/beizi_startup_ad/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,90 @@
if (isRelease.toBoolean()) {
apply plugin: 'com.android.library'
} else {
apply plugin: 'com.android.application'
}
apply plugin: 'org.jetbrains.kotlin.android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-parcelize'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
if (!isRelease.toBoolean()) {
applicationId "com.gh.gamecenter.beiziad"
multiDexEnabled true
}
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 {
if (isRelease.toBoolean()) {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
exclude 'manifest/**'
}
} else {
java {
srcDirs = ['src/main/java']
}
manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
res.srcDirs = ['src/main/res']
}
}
}
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.name)
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildTypes {
debug {
if (!isRelease.toBoolean()) {
buildConfigField "String", "DEV_API_HOST", "\"${DEV_API_HOST}\""
}
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
if (!isRelease.toBoolean()) {
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
}
}
}
}
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
kapt "com.alibaba:arouter-compiler:$arouterVersion"
if (!isRelease.toBoolean()) {
implementation "androidx.multidex:multidex:${multiDex}"
}
implementation(project(path: ":module_common")) {
exclude group: 'androidx.swiperefreshlayout'
}
api project(":feature:beizi_lib")
}

View File

@ -0,0 +1,42 @@
# 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
# 倍孜广告SDK混淆
-dontwarn com.beizi.fusion.**
-dontwarn com.beizi.ad.**
-keep class com.beizi.fusion.** {*; }
-keep class com.beizi.ad.** {*; }
# 移动安全联盟oaid混淆
-keep class XI.CA.XI.**{*;}
-keep class XI.K0.XI.**{*;}
-keep class XI.XI.K0.**{*;}
-keep class XI.xo.XI.XI.**{*;}
-keep class com.asus.msa.SupplementaryDID.**{*;}
-keep class com.asus.msa.sdid.**{*;}
-keep class com.bun.lib.**{*;}
-keep class com.bun.miitmdid.**{*;}
-keep class com.huawei.hms.ads.identifier.**{*;}
-keep class com.samsung.android.deviceidservice.**{*;}
-keep class com.zui.opendeviceidlibrary.**{*;}
-keep class org.json.**{*;}
-keep public class com.netease.nis.sdkwrapper.Utils {public <methods>;}

View File

@ -0,0 +1,10 @@
<?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.beiziad">
<uses-permission android:name="android.permission.INTERNET" />
<uses-sdk tools:overrideLibrary="com.bun.miitmdid" />
<application></application>
</manifest>

View File

@ -0,0 +1,10 @@
{
"supplier": {
"vivo": {
"appid": "100215079"
},
"xiaomi": {},
"huawei": {},
"oppo": {}
}
}

View File

@ -0,0 +1,79 @@
package com.gh.gamecenter.beiziad
import android.content.Context
import android.view.View
import android.widget.FrameLayout
import com.beizi.fusion.AdListener
import com.beizi.fusion.BeiZiCustomController
import com.beizi.fusion.BeiZis
import com.beizi.fusion.SplashAd
import com.bun.miitmdid.core.MdidSdkHelper
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.lightgame.utils.Utils
import java.lang.ref.WeakReference
object BeiziAdHelper {
private const val BEIZI_APP_ID = "21425"
private const val BEIZI_START_UP_AD_ID = "105706"
private const val START_UP_AD_TOTAL_TIME = 3000L
private val mChannelList = listOf("GH_206")
private var mSplashAd: WeakReference<SplashAd>? = null
fun initBeiziSDK(context: Context) {
BeiZis.setSupportPersonalized(SPUtils.getBoolean(Constants.SP_PERSONAL_RECOMMEND, true))
BeiZis.init(context, BEIZI_APP_ID, object : BeiZiCustomController() {
override fun isCanUsePhoneState(): Boolean = false
override fun isCanUseGaid(): Boolean = false
})
}
fun initOAID(context: Context, callback: (String) -> Unit) {
MdidSdkHelper.InitSdk(context, true) { _, idSupplier ->
Utils.log("OAID: ${idSupplier.oaid}")
callback(idSupplier.oaid)
}
}
fun initBeiziStartUpAd(startAdContainer: View, adsFl: FrameLayout, showAd: Boolean, hideCallback: () -> Unit) {
startAdContainer.visibility = View.VISIBLE
mSplashAd = WeakReference(SplashAd(startAdContainer.context, null, BEIZI_START_UP_AD_ID, object : AdListener {
override fun onAdLoaded() {
if (showAd) {
mSplashAd?.get()?.show(adsFl)
}
}
override fun onAdShown() {
// do nothing
}
override fun onAdFailedToLoad(i: Int) {
hideCallback()
}
override fun onAdClosed() {
hideCallback()
}
override fun onAdTick(l: Long) {
// do nothing
}
override fun onAdClicked() {
// do nothing
}
}, START_UP_AD_TOTAL_TIME))
mSplashAd?.get()?.loadAd(DisplayUtils.getScreenWidth(), DisplayUtils.getScreenHeight())
}
fun cancelBeiziStartUpAd(context: Context) {
mSplashAd?.get()?.cancel(context)
}
fun shouldEnableSDK(channel: String) = mChannelList.contains(channel)
}

View File

@ -0,0 +1,35 @@
package com.gh.gamecenter.beiziad
import android.content.Context
import android.view.View
import android.widget.FrameLayout
import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IStartUpAdProvider
@Route(path = RouteConsts.provider.adSdk, name = "开屏广告暴露服务")
class StartUpAdProviderImpl : IStartUpAdProvider {
override fun initSDK(context: Context) {
BeiziAdHelper.initBeiziSDK(context)
}
override fun initOAID(context: Context, callback: (String) -> Unit) {
BeiziAdHelper.initOAID(context, callback)
}
override fun initStartUpAd(startAdContainer: View, adsFl: FrameLayout, showAd: Boolean, hideCallback: () -> Unit) {
BeiziAdHelper.initBeiziStartUpAd(startAdContainer, adsFl, showAd, hideCallback)
}
override fun cancelStartUpAd(context: Context) {
BeiziAdHelper.cancelBeiziStartUpAd(context)
}
override fun shouldEnableSDK(channel: String): Boolean {
return BeiziAdHelper.shouldEnableSDK(channel)
}
override fun init(context: Context?) {
// Do nothing
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="BeiZi_BackArrowView">
<!-- 箭头颜色 -->
<attr format="color" name="beizi_bav_color" />
<!-- 箭头线宽 -->
<attr format="integer|float|dimension" name="beizi_bav_stroke_width" />
<!-- 模式 -->
<attr format="enum" name="beizi_bav_arrow_style">
<!-- Google Material Design -->
<enum name="beizi_material_design" value="1" />
<!-- 微信风格 -->
<enum name="beizi_wechat_design" value="2" />
</attr>
</declare-styleable>
</resources>

View File

@ -74,7 +74,7 @@ class AppProviderImpl : IAppProvider {
return ""
}
override fun init(application: Application, activity: Activity) {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
// do nothing
}

View File

@ -70,7 +70,7 @@ class AppProviderImpl : IAppProvider {
return ""
}
override fun init(application: Application, activity: Activity) {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
// do nothing
}

View File

@ -70,7 +70,7 @@ class AppProviderImpl : IAppProvider {
return ""
}
override fun init(application: Application, activity: Activity) {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
// do nothing
}

View File

@ -83,6 +83,7 @@ dependencies {
api "androidx.room:room-rxjava2:${room}"
kapt "androidx.room:room-compiler:${room}"
api "androidx.collection:collection-ktx:${collection}"
api "androidx.activity:activity:${activity}"
api "androidx.activity:activity-ktx:${activity}"
api "com.aliyun.openservices:aliyun-log-android-sdk:${aliyunLog}"
debugApi "com.lg:chucker:${chucker}"

View File

@ -79,6 +79,8 @@ object RouteConsts {
const val exposureManager = "/exposure/exposureManager"
const val sensors = "/sensors/sensors"
const val adSdk = "/adSdk/adSdk"
}
}

View File

@ -8,6 +8,7 @@ class PkgConfigEntity(
) {
data class Data(
@SerializedName("first_lanuch_jump") var link: PkgLinkEntity? = PkgLinkEntity(),
@SerializedName("activate_reporting_ratio") var activateRatio: Int? = 0,
)
class PkgLinkEntity(

View File

@ -14,7 +14,7 @@ import com.scwang.smartrefresh.layout.constant.RefreshState;
import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener;
public class HomeSmartRefreshLayout extends SmartRefreshLayout {
private final int mFloorHeight = DisplayUtils.dip2px(312F) - DisplayUtils.getStatusBarHeight(getContext().getResources());
private final int mFloorHeight = DisplayUtils.getScreenWidth() - DisplayUtils.dip2px(48F) - DisplayUtils.getStatusBarHeight(getContext().getResources());
public HomeSmartRefreshLayout(Context context) {
super(context);

View File

@ -7,7 +7,12 @@ interface IFlavorProvider {
fun getChannelStr(application: Application): String
fun init(application: Application, activity: Activity)
/**
* 初始化对应 SDK
*
* @param activateRatio 调用初始化的概率,取值为 0 ~ 100如传入 60 时,代表有 60% 的概率进行 SDK 初始化
*/
fun init(application: Application, activity: Activity, activateRatio: Int)
fun logEvent(content: String)

View File

@ -0,0 +1,19 @@
package com.gh.gamecenter.core.provider
import android.content.Context
import android.view.View
import android.widget.FrameLayout
import com.alibaba.android.arouter.facade.template.IProvider
interface IStartUpAdProvider : IProvider {
fun initSDK(context: Context)
fun initOAID(context: Context, callback: (String) -> Unit)
fun initStartUpAd(startAdContainer: View, adsFl: FrameLayout, showAd: Boolean, hideCallback: () -> Unit)
fun cancelStartUpAd(context: Context)
fun shouldEnableSDK(channel: String): Boolean
}

View File

@ -518,13 +518,13 @@ data class GameEntity(
@IgnoredOnParcel
val decoratedDes: String?
get() = if (
(apk != null && apk!!.size > 0)
getApk().size > 0
&& !hideSizeInsideDes
&& ((TextUtils.isEmpty(subjectData?.briefStyle)
|| subjectData?.briefStyle?.contains("size") == true)
|| subjectData?.briefStyle?.contains("recommend") == true)
) {
apk?.firstOrNull()?.size + " " + brief
getApk().firstOrNull()?.size + " " + brief
} else {
brief
}

View File

@ -74,7 +74,7 @@ class AppProviderImpl : IAppProvider {
return ""
}
override fun init(application: Application, activity: Activity) {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
// do nothing
}

View File

@ -62,7 +62,7 @@ class AppProviderImpl : IAppProvider {
return ""
}
override fun init(application: Application, activity: Activity) {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
// do nothing
}

View File

@ -62,7 +62,7 @@ class AppProviderImpl : IAppProvider {
return ""
}
override fun init(application: Application, activity: Activity) {
override fun init(application: Application, activity: Activity, activateRatio: Int) {
// do nothing
}

View File

@ -11,6 +11,8 @@ build_time=$(TZ=Asia/Shanghai date +'%Y-%m%d-%H%M')
git checkout app/build.gradle
# 重置 module_common build.gradle
git checkout module_common/build.gradle
# 重置 module_sensors_data build.gradle
git checkout module_sensors_data/build.gradle
# 开启 mapping 上传
if [[ "$OSTYPE" == "darwin"* ]]; then
@ -57,4 +59,6 @@ cp -R app/build/outputs/apk/publish/release/app-publish-release.apk release-app/
# 重置 app build.gradle
git checkout app/build.gradle
# 重置 module_common build.gradle
git checkout module_common/build.gradle
git checkout module_common/build.gradle
# 重置 module_sensors_data build.gradle
git checkout module_sensors_data/build.gradle

View File

@ -14,12 +14,16 @@ apk_release_path=""
git checkout app/build.gradle
# 重置 module_common build.gradle
git checkout module_common/build.gradle
# 重置 module_sensors_data build.gradle
git checkout module_sensors_data/build.gradle
# 开启 mapping 上传
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' '1 a plugins { id "io.sentry.android.gradle" version "2.1.5" }' app/build.gradle
sed -i '' 's/var isTestBuild = true/var isTestBuild = false/g' module_sensors_data/build.gradle
else
sed -i '1 a plugins { id "io.sentry.android.gradle" version "2.1.5" }' app/build.gradle
sed -i 's/var isTestBuild = true/var isTestBuild = false/g' module_sensors_data/build.gradle
fi
./gradlew --stop
@ -89,14 +93,14 @@ if [ "${sdk_platform}" != "" ]; then
activate_reporting_ratio="100"
fi
# 调整上报比例
sed -i "75i buildConfigField "\"int\"", "\"ACTIVATE_REPORTING_RATIO\"", \""${activate_reporting_ratio}"\"" app/build.gradle
sed -i "s/int ACTIVATE_REPORTING_RATIO = 0/int ACTIVATE_REPORTING_RATIO = ${activate_reporting_ratio}/g" app/build.gradle
if [ "${sdk_version}" == "5.3.0" ]; then
sed -i "s/bytedanceApplog = \"6.14.1\"/bytedanceApplog = \"${sdk_version}\"/g" dependencies.gradle
sed -i "s/bytedanceApplog = \"6.14.3\"/bytedanceApplog = \"${sdk_version}\"/g" dependencies.gradle
rm app/src/tea/java/com/gh/gamecenter/TeaHelper.kt
mv app/src/tea/java/com/gh/gamecenter/TeaHelper app/src/tea/java/com/gh/gamecenter/TeaHelper.kt
else
sed -i "s/bytedanceApplog = \"6.14.1\"/bytedanceApplog = \"${sdk_version}\"/g" dependencies.gradle
sed -i "s/bytedanceApplog = \"6.14.3\"/bytedanceApplog = \"${sdk_version}\"/g" dependencies.gradle
fi
./gradlew aTR -I init.gradle
@ -128,4 +132,6 @@ fi
# 重置 app build.gradle
git checkout app/build.gradle
# 重置 module_common build.gradle
git checkout module_common/build.gradle
git checkout module_common/build.gradle
# 重置 module_sensors_data build.gradle
git checkout module_sensors_data/build.gradle

View File

@ -16,3 +16,5 @@ include ':module_sensors_data'
include ':feature:vpn'
include ':feature:pkg'
include ':feature:floating-window'
include ':feature:beizi_startup_ad'
include ':feature:beizi_lib'