Compare commits
25 Commits
v5.32.2-99
...
v5.32.7-99
| Author | SHA1 | Date | |
|---|---|---|---|
| 36e9bd20ac | |||
| cc4ef16e10 | |||
| 0911cd146b | |||
| 8e255b1803 | |||
| ae0f4c948b | |||
| d650739632 | |||
| 6f6a734cb5 | |||
| e510146775 | |||
| 8b863955a3 | |||
| 37155b96dd | |||
| e55d4d3332 | |||
| 10572e7b0b | |||
| 0c807922d6 | |||
| d7f5b573c6 | |||
| f9d624b077 | |||
| a22fa59975 | |||
| e68ad6489a | |||
| ccd3a98799 | |||
| 96026ef9fa | |||
| 777e05733c | |||
| cbf6f34a9c | |||
| 23c0f12ed3 | |||
| da91dcab59 | |||
| ee846bc620 | |||
| aa3db9330e |
@ -826,6 +826,8 @@
|
||||
<!-- tools:node="remove" />-->
|
||||
<!-- </provider>-->
|
||||
|
||||
<service android:name = "com.gh.gamecenter.install.InstallService" />
|
||||
|
||||
<receiver
|
||||
android:name="com.gh.gamecenter.receiver.DownloadReceiver"
|
||||
android:exported="false">
|
||||
|
||||
@ -5,6 +5,7 @@ import android.os.Build;
|
||||
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.NewsDetailEntity;
|
||||
@ -54,7 +55,7 @@ public class DataCollectionUtils {
|
||||
map.put("location", downloadEntity.getLocation());
|
||||
map.put(EntranceConsts.KEY_ENTRANCE, downloadEntity.getEntrance());
|
||||
map.put("installed", downloadEntity.getInstalled());
|
||||
map.put("network", NetworkUtils.getConnectedType(context));
|
||||
map.put("network", MetaUtil.getMeta().getNetwork());
|
||||
DataCollectionManager.onEvent(context, "download", map);
|
||||
}
|
||||
|
||||
@ -118,7 +119,7 @@ public class DataCollectionUtils {
|
||||
map.put("key", args[0]);
|
||||
map.put("game_id", args[3]);
|
||||
map.put("game_name", args[4]);
|
||||
map.put("netword", NetworkUtils.getConnectedType(context));
|
||||
map.put("netword", MetaUtil.getMeta().getNetwork());
|
||||
map.put("type", "search");
|
||||
map.put("device_type", android.os.Build.MODEL);
|
||||
map.put("device_system", android.os.Build.VERSION.SDK_INT + "=" + android.os.Build.VERSION.RELEASE);
|
||||
@ -136,7 +137,7 @@ public class DataCollectionUtils {
|
||||
map.put("key", args[0]);
|
||||
map.put("game_id", args[3]);
|
||||
map.put("game_name", args[4]);
|
||||
map.put("netword", NetworkUtils.getConnectedType(context));
|
||||
map.put("netword", MetaUtil.getMeta().getNetwork());
|
||||
map.put("type", "click");
|
||||
map.put("device_type", android.os.Build.MODEL);
|
||||
map.put("device_system", android.os.Build.VERSION.SDK_INT + "=" + android.os.Build.VERSION.RELEASE);
|
||||
|
||||
@ -920,9 +920,9 @@ object DirectUtils {
|
||||
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
context.startActivity(browserIntent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Utils.toast(context, "跳转地址无效")
|
||||
url.copyTextAndToast(context.getString(R.string.direct_to_external_browser_failed_toast))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -62,60 +62,60 @@ object DownloadNotificationHelper {
|
||||
} else {
|
||||
intent.action = ACTION_DOWNLOAD
|
||||
}
|
||||
val pendingIntent = PendingIntent.getBroadcast(
|
||||
HaloApp.getInstance().application,
|
||||
downloadNotificationId,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel =
|
||||
NotificationChannel(DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
val whenTime = 1000 * 60 * (System.currentTimeMillis() / 1000 / 60)
|
||||
val builder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
|
||||
.setContentTitle(entity.name)
|
||||
.setSmallIcon(getNotificationIcon())
|
||||
.setContentIntent(pendingIntent)
|
||||
.setGroup(DOWNLOAD_GROUP_KEY)
|
||||
.setWhen(whenTime)
|
||||
|
||||
if (xapkStatus == XapkUnzipStatus.FAILURE.name) {
|
||||
builder.setContentText("《" + entity.name + "》解压失败,点击查看详情~")
|
||||
} else {
|
||||
when (entity.status) {
|
||||
DownloadStatus.downloading -> builder.setContentText(
|
||||
String.format(
|
||||
"%s(剩%s)",
|
||||
SpeedUtils.getSpeed(entity.speed),
|
||||
SpeedUtils.getRemainTime(entity.size, entity.progress, entity.speed * 1024)
|
||||
)
|
||||
)
|
||||
DownloadStatus.done -> builder.setContentText("下载完成,点击立即安装")
|
||||
DownloadStatus.waiting -> builder.setContentText("等待中")
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.diskisfull,
|
||||
DownloadStatus.diskioerror,
|
||||
DownloadStatus.neterror -> builder.setContentText("已暂停,连接WiFi自动下载")
|
||||
else -> builder.setContentText("暂停中")
|
||||
}
|
||||
builder.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
|
||||
}
|
||||
|
||||
when (entity.status) {
|
||||
DownloadStatus.done -> {
|
||||
builder.setSortKey("A")
|
||||
builder.setOngoing(true) // 垃圾华为 sortKey 不起效 priority 也不起效,要将下载完成任务的通知置顶只能设置为 ongoing,喷了
|
||||
}
|
||||
DownloadStatus.downloading -> builder.setSortKey("B")
|
||||
else -> builder.setSortKey("C")
|
||||
}
|
||||
|
||||
tryCatchInRelease {
|
||||
val pendingIntent = PendingIntent.getBroadcast(
|
||||
HaloApp.getInstance().application,
|
||||
downloadNotificationId,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel =
|
||||
NotificationChannel(DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
val whenTime = 1000 * 60 * (System.currentTimeMillis() / 1000 / 60)
|
||||
val builder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
|
||||
.setContentTitle(entity.name)
|
||||
.setSmallIcon(getNotificationIcon())
|
||||
.setContentIntent(pendingIntent)
|
||||
.setGroup(DOWNLOAD_GROUP_KEY)
|
||||
.setWhen(whenTime)
|
||||
|
||||
if (xapkStatus == XapkUnzipStatus.FAILURE.name) {
|
||||
builder.setContentText("《" + entity.name + "》解压失败,点击查看详情~")
|
||||
} else {
|
||||
when (entity.status) {
|
||||
DownloadStatus.downloading -> builder.setContentText(
|
||||
String.format(
|
||||
"%s(剩%s)",
|
||||
SpeedUtils.getSpeed(entity.speed),
|
||||
SpeedUtils.getRemainTime(entity.size, entity.progress, entity.speed * 1024)
|
||||
)
|
||||
)
|
||||
DownloadStatus.done -> builder.setContentText("下载完成,点击立即安装")
|
||||
DownloadStatus.waiting -> builder.setContentText("等待中")
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.diskisfull,
|
||||
DownloadStatus.diskioerror,
|
||||
DownloadStatus.neterror -> builder.setContentText("已暂停,连接WiFi自动下载")
|
||||
else -> builder.setContentText("暂停中")
|
||||
}
|
||||
builder.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
|
||||
}
|
||||
|
||||
when (entity.status) {
|
||||
DownloadStatus.done -> {
|
||||
builder.setSortKey("A")
|
||||
builder.setOngoing(true) // 垃圾华为 sortKey 不起效 priority 也不起效,要将下载完成任务的通知置顶只能设置为 ongoing,喷了
|
||||
}
|
||||
DownloadStatus.downloading -> builder.setSortKey("B")
|
||||
else -> builder.setSortKey("C")
|
||||
}
|
||||
|
||||
val notification = builder.build() // 可能会抛出异常
|
||||
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
|
||||
if (xapkStatus == XapkUnzipStatus.FAILURE.name) {
|
||||
|
||||
@ -19,6 +19,7 @@ import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.CurrentActivityHolder
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.install.InstallService
|
||||
import com.gh.gamecenter.vpn.VpnHelper
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
@ -159,6 +160,13 @@ object PackageInstaller {
|
||||
*/
|
||||
private fun install(context: Context, pkgPath: String) {
|
||||
HaloApp.put(Constants.LAST_INSTALL_GAME, pkgPath)
|
||||
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU && Build.MANUFACTURER.lowercase().contains("xiaomi")) {
|
||||
val foregroundServiceIntent = Intent(context, InstallService::class.java)
|
||||
foregroundServiceIntent.putExtra(InstallService.KEY_SERVICE_ACTION, InstallService.START_FOREGROUND)
|
||||
context.startForegroundService(foregroundServiceIntent)
|
||||
}
|
||||
|
||||
val installIntent = getInstallIntent(context, pkgPath)
|
||||
context.startActivity(installIntent)
|
||||
}
|
||||
|
||||
@ -728,6 +728,13 @@ public class PackageUtils {
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
// 这里的 pm.getApplicationLabel 有极小机率会返回 null 值 (明明方法标示了返回值 nonnull)
|
||||
// Attempt to invoke interface method 'java.lang.String java.lang.CharSequence.toString()' on a null object reference
|
||||
// 所以要是为空就 continue,忽略掉它
|
||||
if (pm.getApplicationLabel(packageInfo.applicationInfo) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
jsonObject.put("name", pm.getApplicationLabel(packageInfo.applicationInfo).toString());
|
||||
jsonObject.put("package", packageInfo.packageName);
|
||||
jsonObject.put("version", packageInfo.versionName);
|
||||
|
||||
@ -883,6 +883,7 @@ public class MainActivity extends BaseActivity {
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NotNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.clear();
|
||||
outState.putInt(CURRENT_PAGE, mMainWrapperFragment.getCurrentItem());
|
||||
if (mMainWrapperFragment != null) {
|
||||
outState.putInt(BaseFragment_ViewPager.ARGS_INDEX, mMainWrapperFragment.getCurrentItem());
|
||||
|
||||
@ -1,17 +1,22 @@
|
||||
package com.gh.gamecenter.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.SparseIntArray
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.util.forEach
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentPagerAdapter
|
||||
import com.gh.gamecenter.common.BuildConfig
|
||||
|
||||
/***
|
||||
* 支持替换Fragment的FragmentPagerAdapter
|
||||
*/
|
||||
class MainFragmentPagerAdapter(
|
||||
private val mContext: Context,
|
||||
private val mFragmentManager: FragmentManager,
|
||||
private val mFragmentsList: ArrayList<Fragment>
|
||||
private val mFragmentsList: ArrayList<Fragment>,
|
||||
) : FragmentPagerAdapter(mFragmentManager) {
|
||||
private val mFragmentPositionSparseArray = SparseIntArray() // 记录Fragment的位置
|
||||
private val mFragmentPositionUpdateSparseArray = SparseIntArray() // 记录更新后Fragment的位置
|
||||
@ -76,4 +81,24 @@ class MainFragmentPagerAdapter(
|
||||
override fun getItem(position: Int): Fragment = mFragmentsList[position]
|
||||
|
||||
override fun getItemId(position: Int): Long = mFragmentsList[position].hashCode().toLong()
|
||||
|
||||
override fun finishUpdate(container: ViewGroup) {
|
||||
// 替换Fragment闪退关联问题(REPLACE_FRAGMENT_CRASH)
|
||||
try {
|
||||
super.finishUpdate(container)
|
||||
} catch (e: Throwable) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
throw e
|
||||
} else {
|
||||
e.printStackTrace()
|
||||
|
||||
// 重启APP
|
||||
val pm = mContext.packageManager
|
||||
val intent = pm?.getLaunchIntentForPackage(mContext.packageName)
|
||||
val mainIntent = Intent.makeRestartActivityTask(intent!!.component)
|
||||
mContext.startActivity(mainIntent)
|
||||
Runtime.getRuntime().exit(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -45,6 +45,7 @@ import com.gh.gamecenter.common.syncpage.SyncPageRepository
|
||||
import com.gh.gamecenter.common.tracker.TrackerLogger
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.SentryHelper
|
||||
import com.gh.gamecenter.databinding.FragmentMainBinding
|
||||
import com.gh.gamecenter.discovery.DiscoveryFragment
|
||||
import com.gh.gamecenter.entity.HomeDataEntity
|
||||
@ -96,13 +97,15 @@ class MainWrapperFragment : BaseFragment_ViewPager_Checkable(), OnBackPressedLis
|
||||
|
||||
private val mPriorityChain by lazy { PriorityChain() }
|
||||
|
||||
private var mVideoNavBarEntity: SubjectRecommendEntity? = null
|
||||
|
||||
override fun getLayoutId(): Int = 0
|
||||
override fun getInflatedLayout() = mBinding.root
|
||||
override fun getCheckableGroupId(): Int = R.id.lightgame_tab_container
|
||||
override fun getViewPagerId(): Int = R.id.lightgame_tab_viewpager
|
||||
override fun getCurrentItem() = mViewPager.currentItem
|
||||
override fun getChildCount(): Int = 5
|
||||
override fun provideAdapter(): PagerAdapter = MainFragmentPagerAdapter(childFragmentManager, mFragmentsList as ArrayList<Fragment>)
|
||||
override fun provideAdapter(): PagerAdapter = MainFragmentPagerAdapter(requireContext(), childFragmentManager, mFragmentsList as ArrayList<Fragment>)
|
||||
|
||||
override fun initFragmentList(fragments: MutableList<Fragment>) {
|
||||
mHomeFragment = HomeSearchToolWrapperFragment()
|
||||
@ -182,20 +185,40 @@ class MainWrapperFragment : BaseFragment_ViewPager_Checkable(), OnBackPressedLis
|
||||
}
|
||||
|
||||
else -> {
|
||||
val homeArgs = Bundle()
|
||||
putFragmentBundle(entity, homeArgs, false)
|
||||
mFourthFragment = HomeToolbarWrapperFragment()
|
||||
mFourthFragment!!.arguments = homeArgs
|
||||
mFourthFragment
|
||||
// 新页面与旧页面类型不同或链接不同时才进行替换
|
||||
if (mFourthFragment !is HomeToolbarWrapperFragment || mVideoNavBarEntity?.type != entity.type || mVideoNavBarEntity?.link != entity.link) {
|
||||
val homeArgs = Bundle()
|
||||
putFragmentBundle(entity, homeArgs, false)
|
||||
mFourthFragment = HomeToolbarWrapperFragment()
|
||||
mFourthFragment!!.arguments = homeArgs
|
||||
mFourthFragment
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fourthFragment != null) {
|
||||
if (mFragmentsList.size > 3) {
|
||||
// 替换第4个Fragment
|
||||
(mAdapter as MainFragmentPagerAdapter).replaceFragment(3, fourthFragment)
|
||||
try {
|
||||
(mAdapter as MainFragmentPagerAdapter).replaceFragment(3, fourthFragment)
|
||||
} catch (e: Exception) {
|
||||
SentryHelper.onEvent(
|
||||
"REPLACE_FRAGMENT_CRASH",
|
||||
"new_fragment_type",
|
||||
entity.type,
|
||||
"old_fragment_type",
|
||||
mVideoNavBarEntity?.type,
|
||||
"new_link",
|
||||
entity.link,
|
||||
"old_link",
|
||||
mVideoNavBarEntity?.link
|
||||
)
|
||||
}
|
||||
} else {
|
||||
fragments.add(fourthFragment)
|
||||
}
|
||||
mVideoNavBarEntity = entity
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,21 +330,7 @@ class MainWrapperFragment : BaseFragment_ViewPager_Checkable(), OnBackPressedLis
|
||||
homeArgs.putBoolean(EntranceConsts.KEY_IS_HOME, true)
|
||||
}
|
||||
|
||||
override fun restoreFragments(): ArrayList<Fragment> {
|
||||
val restoreFragments = super.restoreFragments()
|
||||
for (fragment in restoreFragments) {
|
||||
if (fragment is SearchToolWrapperFragment && fragment !is HomeSearchToolWrapperFragment) {
|
||||
mGameWrapperFragment = fragment
|
||||
} else if (fragment is HomeVideoFragment || fragment is HomeToolbarWrapperFragment || fragment is AmwayFragment || fragment is ForumDetailFragment) {
|
||||
mFourthFragment = fragment as ToolbarFragment?
|
||||
} else if (fragment is CommunityHomeFragment) {
|
||||
mCommunityHomeFragment = fragment
|
||||
} else if (fragment is HomeSearchToolWrapperFragment) {
|
||||
mHomeFragment = fragment
|
||||
}
|
||||
}
|
||||
return restoreFragments
|
||||
}
|
||||
override fun restoreFragments(): ArrayList<Fragment> = ArrayList()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mViewModel = viewModelProviderFromParent(MainWrapperViewModel.Factory(HaloApp.getInstance()))
|
||||
|
||||
@ -199,6 +199,8 @@ public class SearchToolbarFragment extends BaseLazyFragment implements View.OnCl
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null && getArguments().getString(EntranceConsts.KEY_LOCATION) != null) {
|
||||
mLocation = getArguments().getString(EntranceConsts.KEY_LOCATION);
|
||||
} else {
|
||||
mLocation = "";
|
||||
}
|
||||
mHintIndex = 0;
|
||||
if (savedInstanceState != null) {
|
||||
|
||||
@ -325,6 +325,7 @@ open class GameFragment : LazyFragment() {
|
||||
mListAdapter.notifyChildItem(gameAndPosition.position, busFour.packageName)
|
||||
}
|
||||
}
|
||||
(mViewModel as GameViewModel).refreshRecentVGameIfNeeded()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
@ -332,6 +333,7 @@ open class GameFragment : LazyFragment() {
|
||||
if (::mListAdapter.isInitialized && "Refresh" == reuse.type) {
|
||||
mListAdapter.notifyDataSetChanged()
|
||||
}
|
||||
(mViewModel as GameViewModel).refreshRecentVGameIfNeeded()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
|
||||
@ -87,6 +87,7 @@ 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.gh.vspace.HomeRecentVGameAdapter
|
||||
import com.gh.vspace.HomeRecentVGameViewHolder
|
||||
import com.gh.vspace.VHelper
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
@ -1754,6 +1755,7 @@ class GameFragmentAdapter(
|
||||
|| getItemViewType(gameAndPosition.position) == ItemViewType.HORIZONTAL_SLIDE_VIDEO
|
||||
|| getItemViewType(gameAndPosition.position) == ItemViewType.GAME_COLLECTION_BIG_SLIDE
|
||||
|| getItemViewType(gameAndPosition.position) == ItemViewType.GAME_COLLECTION_VERTICAL_REFRESH
|
||||
|| getItemViewType(gameAndPosition.position) == ItemViewType.RECENT_V_GAME
|
||||
) {
|
||||
val view = mLayoutManager?.findViewByPosition(gameAndPosition.position)
|
||||
val recyclerView = view?.findViewById<RecyclerView>(R.id.recycler_view)
|
||||
@ -1765,6 +1767,7 @@ class GameFragmentAdapter(
|
||||
is HomeHorizontalSlideVideoAdapter -> adapter.notifyItemByDownload(download)
|
||||
is HomeGameCollectionSlideAdapter -> adapter.notifyItemByDownload(download)
|
||||
is HomeGameCollectionRefreshAdapter -> adapter.notifyItemByDownload(download)
|
||||
is HomeRecentVGameAdapter -> adapter.notifyItemByDownload(download)
|
||||
}
|
||||
} else {
|
||||
notifyItemChanged(gameAndPosition.position)
|
||||
@ -1907,6 +1910,12 @@ class GameFragmentAdapter(
|
||||
continue
|
||||
}
|
||||
|
||||
val recentVGame = mItemDataList[position].recentVGame
|
||||
if (recentVGame != null) {
|
||||
positionList.add(GameAndPosition(null, position))
|
||||
continue
|
||||
}
|
||||
|
||||
val image = mItemDataList[position].image
|
||||
if (image != null) positionList.add(GameAndPosition(image, position))
|
||||
}
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
package com.gh.gamecenter.install
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.gh.gamecenter.R
|
||||
import com.lightgame.download.ForegroundNotificationManager
|
||||
import com.lightgame.utils.Utils
|
||||
import java.util.*
|
||||
|
||||
class InstallService : Service() {
|
||||
|
||||
private var mForegroundTimer: Timer? = null
|
||||
private var mForegroundNotificationManager: ForegroundNotificationManager? = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
mForegroundNotificationManager = ForegroundNotificationManager(this, this.application)
|
||||
Utils.log(InstallService::class.java.simpleName, "onCreate")
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
Utils.log(InstallService::class.java.simpleName, "onStartCommand")
|
||||
val notificationId = 9999
|
||||
if (intent != null && intent.extras != null) {
|
||||
val serviceAction = intent.getStringExtra(KEY_SERVICE_ACTION)
|
||||
if (START_FOREGROUND == serviceAction) {
|
||||
startForegroundIfNeeded(notificationId)
|
||||
} else if (STOP_FOREGROUND == serviceAction) {
|
||||
startForegroundIfNeeded(notificationId)
|
||||
stopForegroundIfNeeded(notificationId)
|
||||
}
|
||||
} else {
|
||||
startForegroundIfNeeded(notificationId)
|
||||
stopForegroundIfNeeded(notificationId)
|
||||
}
|
||||
|
||||
// 不需要 intent 为空的重建
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun startForegroundIfNeeded(notificationId: Int) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel =
|
||||
NotificationChannel(SERVICE_CHANNEL_ID, SERVICE_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
|
||||
val manager = applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
manager.createNotificationChannel(channel)
|
||||
val notification: Notification = NotificationCompat.Builder(this, SERVICE_CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_download_notification)
|
||||
.setContentTitle("光环助手安装服务")
|
||||
.build()
|
||||
mForegroundNotificationManager?.notify(notificationId, notification)
|
||||
|
||||
mForegroundTimer?.cancel()
|
||||
mForegroundTimer = Timer()
|
||||
|
||||
val task: TimerTask = object : TimerTask() {
|
||||
override fun run() {
|
||||
stopForegroundIfNeeded(notificationId)
|
||||
}
|
||||
}
|
||||
|
||||
mForegroundTimer?.schedule(task, FOREGROUND_COUNT_DOWN_TIME)
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopForegroundIfNeeded(notificationId: Int) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
mForegroundNotificationManager?.cancel(notificationId)
|
||||
|
||||
mForegroundTimer?.cancel()
|
||||
mForegroundTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private const val SERVICE_CHANNEL_ID = "安装服务"
|
||||
private const val FOREGROUND_COUNT_DOWN_TIME = 20 * 1000L
|
||||
|
||||
const val START_FOREGROUND = "start_foreground"
|
||||
const val STOP_FOREGROUND = "stop_foreground"
|
||||
const val KEY_SERVICE_ACTION = "service_action"
|
||||
}
|
||||
}
|
||||
@ -541,6 +541,7 @@ public class UpdateManager {
|
||||
downloadEntity.setPath(path);
|
||||
downloadEntity.setPlatform("官方版");
|
||||
downloadEntity.setGameId(Constants.GHZS_GAME_ID);
|
||||
downloadEntity.setFormat("apk");
|
||||
downloadEntity.setExposureTrace(GsonUtils.toJson(event));
|
||||
|
||||
if (isSilentUpdate) {
|
||||
|
||||
@ -6,6 +6,7 @@ import android.content.MutableContextWrapper
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebResourceResponse
|
||||
import android.webkit.WebView
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.view.RichEditor
|
||||
import com.gh.gamecenter.common.utils.EnvHelper
|
||||
import com.gh.gamecenter.common.utils.removeFromParent
|
||||
@ -40,6 +41,10 @@ object ArticleDetailWebCacheManager {
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun init(applicationContext: Context) {
|
||||
if (!PackageUtils.checkWebViewIsAvailable(applicationContext)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (isInit) return
|
||||
|
||||
isInit = true
|
||||
@ -98,6 +103,10 @@ object ArticleDetailWebCacheManager {
|
||||
* 预初始化 WebView
|
||||
*/
|
||||
fun preInitRichEditor(context: Context) {
|
||||
if (!PackageUtils.checkWebViewIsAvailable(context)) {
|
||||
return
|
||||
}
|
||||
|
||||
// 避免未正常初始化的情况
|
||||
if (!isInit) {
|
||||
init(context.applicationContext)
|
||||
|
||||
@ -3,6 +3,7 @@ package com.gh.gamecenter.receiver;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import com.gh.common.util.InstallUtils;
|
||||
import com.gh.common.util.PackageHelper;
|
||||
@ -17,13 +18,17 @@ import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.gh.gamecenter.eventbus.EBPackage;
|
||||
import com.gh.gamecenter.feature.entity.GameInstall;
|
||||
import com.gh.gamecenter.install.InstallService;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.gh.ndownload.NDownloadService;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
* 监听应用安装和卸载的广播
|
||||
@ -39,6 +44,14 @@ public class InstallAndUninstallReceiver extends BroadcastReceiver {
|
||||
PackageUtils.dumpInstalledListCache();
|
||||
ExtensionsKt.doOnMainProcessOnly(context, () -> {
|
||||
Utils.log("InstallAndUninstallReceiver:: onReceive->" + intent.getAction() + "==" + intent.getDataString());
|
||||
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU
|
||||
&& Build.MANUFACTURER.toLowerCase(Locale.CHINA).contains("xiaomi")) {
|
||||
Intent foregroundServiceIntent = new Intent(context, InstallService.class);
|
||||
foregroundServiceIntent.putExtra(InstallService.KEY_SERVICE_ACTION, InstallService.STOP_FOREGROUND);
|
||||
context.startForegroundService(foregroundServiceIntent);
|
||||
}
|
||||
|
||||
// 接收安装广播
|
||||
if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) {
|
||||
String packageName = intent.getDataString();
|
||||
|
||||
@ -10,6 +10,7 @@ import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.eventbus.EBNetworkState;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils;
|
||||
import com.halo.assistant.HaloApp;
|
||||
@ -23,6 +24,7 @@ public class NetworkStateReceiver extends BroadcastReceiver {
|
||||
// 网络变更这里会被主进程和推送进程分别调用,这里只对主进程响应,
|
||||
// 奇怪,初次注册监听就会有回调,会导致部分接口短时间内触发两次调用
|
||||
ExtensionsKt.doOnMainProcessOnly(context, () -> {
|
||||
MetaUtil.updateCachedNetwork();
|
||||
if (NetworkUtils.isNetworkConnected(context)) {
|
||||
AdDelegateHelper.INSTANCE.requestAdConfig(true, "", null);
|
||||
RegionSettingHelper.getRegionSetting();
|
||||
|
||||
@ -192,11 +192,13 @@ class HomeVideoFragment : BaseLazyFragment() {
|
||||
fun getCurrentFragment(): VideoDetailContainerFragment? {
|
||||
val mIsHomeVideo = arguments?.getBoolean(EntranceConsts.KEY_IS_HOME_VIDEO, false) ?: false
|
||||
return if (mIsHomeVideo) {
|
||||
if (mBinding.mViewPager.currentItem == 0) {
|
||||
newestVideoDetailFragment
|
||||
} else {
|
||||
recommendVideoDetailFragment
|
||||
}
|
||||
if (::mBinding.isInitialized) {
|
||||
if (mBinding.mViewPager.currentItem == 0) {
|
||||
newestVideoDetailFragment
|
||||
} else {
|
||||
recommendVideoDetailFragment
|
||||
}
|
||||
} else null
|
||||
} else {
|
||||
recommendVideoDetailFragment
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.ndownload
|
||||
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import com.lg.download.httpclient.DefaultHttpClient
|
||||
import com.lightgame.download.HttpDnsManager
|
||||
@ -24,6 +25,7 @@ class NHttpClient : DefaultHttpClient() {
|
||||
HttpDnsManager.metaMap[HttpDnsManager.ANDROID_SDK_VERSION]
|
||||
)
|
||||
mConnection.setRequestProperty(HttpDnsManager.REFERER, HttpDnsManager.DEFAULT_REFERER)
|
||||
mConnection.setRequestProperty("androidmodel", Build.MODEL)
|
||||
|
||||
val isEmulator = meta?.get("is_emulator")
|
||||
val isForcedRealName = meta?.get("force_real_name")
|
||||
|
||||
@ -91,7 +91,11 @@ class HomeRecentVGameAdapter(context: Context) : DiffUtilAdapter<VGameItemData>(
|
||||
notifyDataSetChanged()
|
||||
} else {
|
||||
for (position in mDataList.indices) {
|
||||
if (downloadEntity.name == mDataList[position].downloadEntity.name) {
|
||||
val oldDownloadEntity = mDataList[position].downloadEntity
|
||||
if (downloadEntity.name == oldDownloadEntity.name) {
|
||||
// 防止覆盖游戏最后打开的时间为0
|
||||
if (VHelper.getLastPlayedTime(oldDownloadEntity) != 0L && VHelper.getLastPlayedTime(downloadEntity) == 0L)
|
||||
return
|
||||
mDataList[position].downloadEntity = downloadEntity
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
|
||||
@ -1705,17 +1705,17 @@ object VHelper {
|
||||
val sortedEntityList = arrayListOf<VGameItemData>()
|
||||
|
||||
val distinctIdSet = hashSetOf<String>()
|
||||
// 将下载任务的实体放进待排序列表里
|
||||
for (rawDownloadEntity in rawDownloadEntityList) {
|
||||
distinctIdSet.add(rawDownloadEntity.gameId)
|
||||
rawEntityList.add(rawDownloadEntity)
|
||||
}
|
||||
// 将已安装任务的实体放进待排序列表里
|
||||
for (rawInstalledEntity in rawInstalledEntityList) {
|
||||
if (distinctIdSet.contains(rawInstalledEntity.downloadEntity.gameId)) {
|
||||
distinctIdSet.add(rawInstalledEntity.downloadEntity.gameId)
|
||||
rawEntityList.add(rawInstalledEntity.downloadEntity)
|
||||
}
|
||||
// 将下载任务的实体放进待排序列表里
|
||||
for (rawDownloadEntity in rawDownloadEntityList) {
|
||||
if (distinctIdSet.contains(rawDownloadEntity.gameId)) {
|
||||
continue
|
||||
}
|
||||
rawEntityList.add(rawInstalledEntity.downloadEntity)
|
||||
rawEntityList.add(rawDownloadEntity)
|
||||
}
|
||||
distinctIdSet.clear()
|
||||
|
||||
|
||||
@ -520,4 +520,5 @@
|
||||
<string name="servers_calendar_no_remind_checked_hint">至少勾选一种提醒方式</string>
|
||||
<string name="servers_calendar_time_out_of_date">区服已开服,不能设置提醒</string>
|
||||
<string name="network_error_hint">网络异常,请检查手机网络状态</string>
|
||||
<string name="direct_to_external_browser_failed_toast">打开外部浏览器失败,已复制链接到粘贴板,请自行打开链接</string>
|
||||
</resources>
|
||||
|
||||
@ -7,8 +7,8 @@ ext {
|
||||
targetSdkVersion = 28
|
||||
|
||||
// application info (每个大版本之间的 versionCode 增加 20)
|
||||
versionCode = 992
|
||||
versionName = "5.32.2"
|
||||
versionCode = 997
|
||||
versionName = "5.32.7"
|
||||
applicationId = "com.gh.gamecenter"
|
||||
|
||||
// AndroidX
|
||||
|
||||
@ -55,5 +55,4 @@ dependencies {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
implementation "com.pangle.ad:oppo:$csjVersion"
|
||||
implementation "com.pangle.ad:oppo_tools:$csjVersion"
|
||||
}
|
||||
@ -14,7 +14,7 @@ data class Meta(
|
||||
val dia: String? = "",
|
||||
val android_sdk: Int? = -1,
|
||||
val android_version: String? = "",
|
||||
val network: String? = "",
|
||||
var network: String? = "",
|
||||
val os: String? = "",
|
||||
val gid: String? = "",
|
||||
val oaid: String? = "",
|
||||
|
||||
@ -6,6 +6,7 @@ import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.ConnectivityManager
|
||||
import android.os.Build
|
||||
import android.os.DeadObjectException
|
||||
import android.provider.Settings
|
||||
import android.telephony.TelephonyManager
|
||||
import android.text.TextUtils
|
||||
@ -56,6 +57,7 @@ object MetaUtil {
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getMeta(): Meta {
|
||||
if (m == null) {
|
||||
refreshMeta()
|
||||
@ -199,39 +201,52 @@ object MetaUtil {
|
||||
return Build.VERSION.RELEASE
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新通用 meta 里缓存的 network 字段
|
||||
*/
|
||||
@JvmStatic
|
||||
fun updateCachedNetwork() {
|
||||
m?.network = getNetwork()
|
||||
}
|
||||
|
||||
fun getNetwork(): String? {
|
||||
// 有一定机率在 getActiveNetworkInfo 时触发 DeadSystemException,所以这里进行简单 try catch
|
||||
try {
|
||||
if (application.checkCallingOrSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)
|
||||
return "unknown"
|
||||
|
||||
if (application.checkCallingOrSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)
|
||||
return "unknown"
|
||||
val activeNetwork =
|
||||
(application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
|
||||
?: return "unknown"
|
||||
|
||||
val activeNetwork =
|
||||
(application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
|
||||
?: return "unknown"
|
||||
|
||||
return when (activeNetwork.type) {
|
||||
ConnectivityManager.TYPE_WIFI -> "WIFI"
|
||||
ConnectivityManager.TYPE_WIMAX -> "WIMAX"
|
||||
ConnectivityManager.TYPE_MOBILE -> {
|
||||
val telephonyManager = application.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||
if (telephonyManager.simState != TelephonyManager.SIM_STATE_READY) return "unknown"
|
||||
when (telephonyManager.networkType) {
|
||||
// Unknown
|
||||
TelephonyManager.NETWORK_TYPE_UNKNOWN -> "unknown"
|
||||
// Cellular Data–2G
|
||||
TelephonyManager.NETWORK_TYPE_EDGE, TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_CDMA,
|
||||
TelephonyManager.NETWORK_TYPE_IDEN, TelephonyManager.NETWORK_TYPE_1xRTT -> "2G"
|
||||
// Cellular Data–3G
|
||||
TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_HSPA,
|
||||
TelephonyManager.NETWORK_TYPE_HSPAP, TelephonyManager.NETWORK_TYPE_HSUPA, TelephonyManager.NETWORK_TYPE_EVDO_0,
|
||||
TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_EVDO_B -> "3G"
|
||||
// Cellular Data–4G
|
||||
TelephonyManager.NETWORK_TYPE_LTE -> "4G"
|
||||
TelephonyManager.NETWORK_TYPE_NR -> "5G"
|
||||
else -> "unknown"
|
||||
return when (activeNetwork.type) {
|
||||
ConnectivityManager.TYPE_WIFI -> "WIFI"
|
||||
ConnectivityManager.TYPE_WIMAX -> "WIMAX"
|
||||
ConnectivityManager.TYPE_MOBILE -> {
|
||||
val telephonyManager = application.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||
if (telephonyManager.simState != TelephonyManager.SIM_STATE_READY) return "unknown"
|
||||
when (telephonyManager.networkType) {
|
||||
// Unknown
|
||||
TelephonyManager.NETWORK_TYPE_UNKNOWN -> "unknown"
|
||||
// Cellular Data–2G
|
||||
TelephonyManager.NETWORK_TYPE_EDGE, TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_CDMA,
|
||||
TelephonyManager.NETWORK_TYPE_IDEN, TelephonyManager.NETWORK_TYPE_1xRTT -> "2G"
|
||||
// Cellular Data–3G
|
||||
TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_HSPA,
|
||||
TelephonyManager.NETWORK_TYPE_HSPAP, TelephonyManager.NETWORK_TYPE_HSUPA, TelephonyManager.NETWORK_TYPE_EVDO_0,
|
||||
TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_EVDO_B -> "3G"
|
||||
// Cellular Data–4G
|
||||
TelephonyManager.NETWORK_TYPE_LTE -> "4G"
|
||||
TelephonyManager.NETWORK_TYPE_NR -> "5G"
|
||||
else -> "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
else -> "unknown"
|
||||
}
|
||||
else -> "unknown"
|
||||
} catch (e: DeadObjectException) {
|
||||
e.printStackTrace()
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -93,49 +93,6 @@ public class NetworkUtils {
|
||||
return quickLoginHelper.isOpenMobileData(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前网络连接的类型信息
|
||||
*
|
||||
* @param context 上下文
|
||||
* @return 当前网络连接的类型信息
|
||||
*/
|
||||
public static String getConnectedType(Context context) {
|
||||
if (context != null) {
|
||||
context = context.getApplicationContext();
|
||||
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo mNetworkInfo = mConnectivityManager
|
||||
.getActiveNetworkInfo();
|
||||
if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {
|
||||
switch (mNetworkInfo.getType()) {
|
||||
case ConnectivityManager.TYPE_BLUETOOTH:
|
||||
return "BLUETOOTH";
|
||||
case ConnectivityManager.TYPE_DUMMY:
|
||||
return "DUMMY";
|
||||
case ConnectivityManager.TYPE_ETHERNET:
|
||||
return "ETHERNET";
|
||||
case ConnectivityManager.TYPE_MOBILE:
|
||||
return "MOBILE";
|
||||
case ConnectivityManager.TYPE_MOBILE_DUN:
|
||||
return "MOBILE_DUN";
|
||||
case ConnectivityManager.TYPE_MOBILE_HIPRI:
|
||||
return "MOBILE_HIPRI";
|
||||
case ConnectivityManager.TYPE_MOBILE_MMS:
|
||||
return "MOBILE_MMS";
|
||||
case ConnectivityManager.TYPE_MOBILE_SUPL:
|
||||
return "MOBILE_SUPL";
|
||||
case ConnectivityManager.TYPE_WIFI:
|
||||
return "WIFI";
|
||||
case ConnectivityManager.TYPE_WIMAX:
|
||||
return "WIMAX";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "NONE";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前移动网络连接的类型信息(当连接的网络是移动网络时使用)
|
||||
*
|
||||
|
||||
@ -115,7 +115,7 @@ data class GameEntity(
|
||||
|
||||
// 额外的下载方式,用于双下载类型时使用。可能的值为 "off/on/smooth/smooth_32",分别为关闭/畅玩64位/畅玩32位
|
||||
@SerializedName("download_extra_status")
|
||||
private var mDownloadStatusExtra: String = "",
|
||||
private var mDownloadStatusExtra: String = "off",
|
||||
// 优先的下载方式,用于双下载类型时使用。可能的值为 "smooth/local",分别为 畅玩下载/普通下载
|
||||
@SerializedName("download_default")
|
||||
private var mDefaultDownloadType: String = "",
|
||||
|
||||
Reference in New Issue
Block a user