Compare commits
32 Commits
pack/test-
...
v5.35.1-10
| Author | SHA1 | Date | |
|---|---|---|---|
| ad3a3c1341 | |||
| ba320f7740 | |||
| f3dbc0b779 | |||
| 0c518ac40e | |||
| bf57118900 | |||
| b80a14f2b1 | |||
| 1450064640 | |||
| 90e19d5099 | |||
| 383124dc36 | |||
| 6d6ce2613a | |||
| 8569264b82 | |||
| 59667abf09 | |||
| b651ef8617 | |||
| 76e17eddd7 | |||
| f01e08aec9 | |||
| faddf5d7b6 | |||
| 81cf2f0ddc | |||
| 198561d15a | |||
| 1e721b699c | |||
| 8f48dfd347 | |||
| bc811a2882 | |||
| bfd986fdfd | |||
| a2bd5e01e0 | |||
| 844d227f19 | |||
| 8b1f92e9c4 | |||
| f5834d440b | |||
| f982bf6478 | |||
| 33d7afec71 | |||
| 37ef50f323 | |||
| 4c6acdee3a | |||
| 6beb060e63 | |||
| d11ccba0b7 |
@ -401,7 +401,7 @@ dependencies {
|
||||
implementation(project(':feature:pkg'))
|
||||
implementation(project(':feature:oaid'))
|
||||
implementation(project(':feature:floating-window'))
|
||||
implementation(project(':feature:csj_ad'))
|
||||
// implementation(project(':feature:csj_ad'))
|
||||
// implementation(project(':feature:beizi_startup_ad'))
|
||||
implementation(project(':feature:xapk-installer'))
|
||||
implementation(project(':feature:qq_game')) {
|
||||
@ -409,12 +409,13 @@ dependencies {
|
||||
}
|
||||
internalImplementation(project(':module_internal_test'))
|
||||
|
||||
// 根据BUILD_PUSH_TYPE决定使用哪个推送SDK,目前默认使用阿里云推送
|
||||
def pushProject = findProperty('BUILD_PUSH_TYPE') == 'jg'
|
||||
? project(':feature:jg_push') : project(':feature:acloud_push')
|
||||
implementation(pushProject) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
// def pushProperty = findProperty('BUILD_PUSH_TYPE')
|
||||
// // 根据BUILD_PUSH_TYPE决定使用哪个推送SDK,目前默认使用极光推送
|
||||
// def pushProject = (pushProperty == null || pushProperty == 'jg')
|
||||
// ? project(':feature:jg_push') : project(':feature:acloud_push')
|
||||
// implementation(pushProject) {
|
||||
// exclude group: 'androidx.swiperefreshlayout'
|
||||
// }
|
||||
}
|
||||
|
||||
File propFile = file('sign.properties')
|
||||
|
||||
@ -191,10 +191,11 @@ object AdDelegateHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 热启动是否需要显示开屏广告
|
||||
* 热启动是否需要显示开屏广告(目前只展示第三方广告)
|
||||
*/
|
||||
private fun shouldShowStartUpAdWhenHotLaunch() =
|
||||
mSplashAd?.displayRule?.hotStartSplashAd?.type == AD_TYPE_SDK && mSplashAd?.hotStartThirdPartyAd != null
|
||||
private fun shouldShowStartUpAdWhenHotLaunch() = (mCsjAdImpl != null || mBeiziAdImpl != null)
|
||||
&& mSplashAd?.displayRule?.hotStartSplashAd?.type == AD_TYPE_SDK
|
||||
&& mSplashAd?.hotStartThirdPartyAd != null
|
||||
|
||||
/**
|
||||
* 是否需要显示下载管理广告
|
||||
|
||||
@ -45,6 +45,14 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
}
|
||||
isFromBackgroundToForeground = false
|
||||
}
|
||||
|
||||
if (activityCount == 1) {
|
||||
// 清除桌面角标
|
||||
if (activity !is SplashScreenActivity && activity !is AuthorizationActivity) {
|
||||
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
|
||||
pushProvider?.cleanBadgeNumber(activity.applicationContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResumed(activity: Activity) {
|
||||
@ -84,10 +92,6 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
}
|
||||
|
||||
XapkInstaller.updateCurrentInstallStatus()
|
||||
|
||||
// 清除桌面角标
|
||||
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
|
||||
pushProvider?.cleanBadgeNumber(activity.applicationContext)
|
||||
}
|
||||
|
||||
override fun onActivityPaused(activity: Activity) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.constant;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
@ -28,6 +29,7 @@ import com.gh.gamecenter.entity.VSetting;
|
||||
import com.gh.gamecenter.feature.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity;
|
||||
import com.gh.gamecenter.feature.utils.ContentBlockedHelper;
|
||||
import com.gh.gamecenter.receiver.PackageChangeBroadcastReceiver;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.vspace.VHelper;
|
||||
import com.halo.assistant.HaloApp;
|
||||
@ -94,8 +96,7 @@ public class Config {
|
||||
getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply();
|
||||
mSettingsEntity = settingsEntity;
|
||||
|
||||
// 加载完设置后刷新下
|
||||
PackageHelper.initList();
|
||||
PackageHelper.refreshList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -332,8 +333,31 @@ public class Config {
|
||||
if (mNewApiSettingsEntity.getGameShieldContents() != null) {
|
||||
ContentBlockedHelper.INSTANCE.init(mNewApiSettingsEntity.getGameShieldContents());
|
||||
}
|
||||
|
||||
// 更新安装列表是否开启的配置
|
||||
// if (mNewApiSettingsEntity.getInstalledComplianceSwitch() != null) {
|
||||
// PackageHelper.INSTANCE.updateIsGetInstalledPackagesApiAgreedRequired(mNewApiSettingsEntity.getInstalledComplianceSwitch());
|
||||
// } else {
|
||||
// PackageHelper.INSTANCE.updateIsGetInstalledPackagesApiAgreedRequired(false);
|
||||
// }
|
||||
|
||||
// 更新包名监听是否开启
|
||||
if (mNewApiSettingsEntity.isPackageObserveEnable()) {
|
||||
observePackageChange(mNewApiSettingsEntity.getPackageObserveActions());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void observePackageChange(NewApiSettingsEntity.PackageObserveActions packageObserveActions) {
|
||||
PackageChangeBroadcastReceiver receiver = new PackageChangeBroadcastReceiver(packageObserveActions);
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(packageObserveActions.getAdd());
|
||||
intentFilter.addAction(packageObserveActions.getRem());
|
||||
intentFilter.addAction(packageObserveActions.getRep());
|
||||
intentFilter.addDataScheme("package");
|
||||
HaloApp.getInstance().registerReceiver(receiver, intentFilter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.LogUtils
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
@ -59,7 +60,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
private val mDuration = 3000
|
||||
private var mDisposable: Disposable? = null
|
||||
private var mAdapter: PackageCheckAdapter? = null
|
||||
private var mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
|
||||
private var mAllInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
|
||||
var gameEntity: GameEntity? = null
|
||||
var callBack: ConfirmListener? = null
|
||||
|
||||
@ -325,7 +326,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
|
||||
mAllInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
|
||||
gameEntity?.packageDialog?.let {
|
||||
if (isAllPackageInstalled(mAllInstalledPackages, it)) {
|
||||
callBack?.onConfirm()
|
||||
@ -363,7 +364,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busFour: EBPackage) {
|
||||
if (busFour.isInstalledOrUninstalled()) {
|
||||
mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
|
||||
mAllInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
@ -416,7 +417,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
return
|
||||
}
|
||||
|
||||
val allInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
|
||||
val allInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
|
||||
if (isAllPackageInstalled(allInstalledPackages, packageDialogEntity)) {
|
||||
callBack.onConfirm()
|
||||
return
|
||||
|
||||
@ -9,10 +9,12 @@ import androidx.fragment.app.FragmentActivity
|
||||
import com.gh.common.iinterface.ISuperiorChain
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.gamecenter.SplashAdActivity
|
||||
import com.gh.gamecenter.SplashScreenActivity
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.entity.DialogEntity
|
||||
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
|
||||
@ -42,12 +44,13 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
return activity is FragmentActivity
|
||||
&& !activity.isFinishing
|
||||
&& activity !is SplashScreenActivity
|
||||
&& activity !is SplashAdActivity
|
||||
}
|
||||
|
||||
/**
|
||||
* 预启动所有的优先级弹窗管理链
|
||||
*/
|
||||
fun preStart() {
|
||||
fun preStart(withSpecialDelay: Boolean) {
|
||||
val launchRedirectHandler = LaunchRedirectHandler(-101)
|
||||
val updateDialogHandler = UpdateDialogHandler(-100)
|
||||
val privacyPolicyDialogHandler = PrivacyPolicyDialogHandler(-99)
|
||||
@ -64,8 +67,13 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
|
||||
launchRedirectHandler.doPreProcess()
|
||||
updateDialogHandler.doPreProcess()
|
||||
requestOpeningDialogData(welcomeDialogHandler, privacyPolicyDialogHandler)
|
||||
requestReserveDialogData(reserveDialogHandler)
|
||||
|
||||
// 首次启动延迟 300ms,保证请求首次启动时已经获取到了 GID 、 OAID 等标记
|
||||
val requestDelay = if (withSpecialDelay) 300L else 0L
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
requestOpeningDialogData(welcomeDialogHandler, privacyPolicyDialogHandler)
|
||||
requestReserveDialogData(reserveDialogHandler)
|
||||
}, requestDelay)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,6 +131,17 @@ object GlobalPriorityChainHelper : ISuperiorChain {
|
||||
mainChain.resume()
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加新的 handler 到优先级弹窗管理链 (插队!)
|
||||
*/
|
||||
fun queueNewHandler(handler: PriorityChainHandler) {
|
||||
if (mainChain.isHandlerQueueEmpty()) {
|
||||
observeLifecycle()
|
||||
}
|
||||
|
||||
mainChain.addHandler(handler)
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求首页启动弹窗相关的数据并执行相关 handler 的 preProcess
|
||||
*/
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
package com.gh.common.prioritychain
|
||||
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
|
||||
class RequestInstalledListPermissionHandler : PriorityChainHandler(-1000) {
|
||||
|
||||
init {
|
||||
updateStatus(STATUS_VALID)
|
||||
}
|
||||
|
||||
override fun onProcess(): Boolean {
|
||||
val currentActivity = GlobalActivityManager.currentActivity ?: return false
|
||||
|
||||
if (currentActivity !is FragmentActivity) return false
|
||||
|
||||
PackageHelper.showGetInstallAppsListDialogAndRequestPermissionIfNeeded(
|
||||
activity = currentActivity,
|
||||
ignorePermanentlyDenied = true
|
||||
) {
|
||||
processNext()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.gh.common.provider
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageInfo
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
|
||||
@ -23,7 +24,7 @@ class PackageUtilsProviderImpl : IPackageUtilsProvider {
|
||||
}
|
||||
|
||||
override fun getInstalledPackages(context: Context, flag: Int): List<PackageInfo> {
|
||||
return PackageUtils.getInstalledPackages(context, flag)
|
||||
return PackageHelper.getInstalledPackages(context, flag)
|
||||
}
|
||||
|
||||
override fun getApkSignatureByPackageName(context: Context, packageName: String): Array<String> {
|
||||
@ -38,6 +39,10 @@ class PackageUtilsProviderImpl : IPackageUtilsProvider {
|
||||
return PackageUtils.isSignedByGh(context, packageName)
|
||||
}
|
||||
|
||||
override fun isInstalledWithLauncherIcon(context: Context, packageName: String): Boolean {
|
||||
return PackageUtils.isInstalled(context, packageName)
|
||||
}
|
||||
|
||||
override fun getInstalledTime(context: Context, packageName: String): Long {
|
||||
return PackageUtils.getInstalledTime(context, packageName)
|
||||
}
|
||||
|
||||
@ -166,162 +166,160 @@ class SimulatorDownloadManager private constructor() {
|
||||
this.gameName = gameName
|
||||
this.gameType = gameCategoryChinese
|
||||
|
||||
PermissionHelper.checkGetInstalledAppsListBeforeAction(context, object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
val isInstalledNewSimulator =
|
||||
SimulatorGameManager.isNewSimulatorInstalled(HaloApp.getInstance().application)
|
||||
//当没有安装新版本模拟器时候 判断是否隐藏
|
||||
if (simulator?.active == false && !isInstalledNewSimulator) {
|
||||
showNoneEmulatorDialog(context)
|
||||
return
|
||||
}
|
||||
var isInstalled = PackageUtils.isInstalledFromAllPackage(
|
||||
context,
|
||||
simulator?.apk?.packageName
|
||||
)
|
||||
//模拟器管理界面还是用之前的逻辑
|
||||
if (isInstalledNewSimulator && location != SimulatorLocation.SIMULATOR_MANAGE) {
|
||||
isInstalled = isInstalledNewSimulator
|
||||
}
|
||||
// val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator?.apk?.packageName)
|
||||
val shouldShowUpdate =
|
||||
PackageUtils.isInstalledApkMatchedMd5(simulator?.apk?.packageName, simulator?.apk?.md5)
|
||||
val showAlertTag = SPUtils.getString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, "") //当天是否弹过
|
||||
val todayIsShow = showAlertTag == TimeUtils.getToday()
|
||||
downloadType = if (shouldShowUpdate && isInstalled) "update" else "download"
|
||||
if (downloadType == "update" && todayIsShow && location != SimulatorLocation.SIMULATOR_MANAGE) {
|
||||
return
|
||||
}
|
||||
if (downloadType == "download" && isInstalled) {
|
||||
return
|
||||
}
|
||||
val title = if (shouldShowUpdate && isInstalled) "更新模拟器" else "安装模拟器"
|
||||
val message =
|
||||
if (shouldShowUpdate && isInstalled) "检测到模拟器存在更高版本,是否前往更新" else "模拟器游戏需要先下载安装对应的模拟器,才可以运行"
|
||||
val positiveText =
|
||||
if (shouldShowUpdate && isInstalled) "更新(${simulator?.apk?.size})" else "下载(${simulator?.apk?.size})"
|
||||
val negativeText = if (shouldShowUpdate && isInstalled) "下次再说" else "取消"
|
||||
val trackableEntity = TrackableEntity(
|
||||
"模拟器下载",
|
||||
key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗",
|
||||
logShowEvent = true
|
||||
)
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
NewFlatLogUtils.logSimulatorUpdateAlertShow()
|
||||
}
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
SensorsBridge.trackSimulatorUpdateDialogShow(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
} else {
|
||||
SensorsBridge.trackSimulatorInstallDialogShow(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
DialogHelper.showDialog(
|
||||
context,
|
||||
title,
|
||||
message,
|
||||
positiveText,
|
||||
negativeText,
|
||||
trackMtaEvent = true,
|
||||
cancelClickCallback = {
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
cancelCallback?.invoke()
|
||||
NewFlatLogUtils.logSimulatorUpdateAlertClick("取消")
|
||||
MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说")
|
||||
SensorsBridge.trackSimulatorUpdateDialogClick(
|
||||
buttonName = negativeText,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
} else {
|
||||
SensorsBridge.trackSimulatorInstallDialogClick(
|
||||
buttonName = negativeText,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
},
|
||||
confirmClickCallback = {
|
||||
showDownloadingDialog(context, simulator, gameId, gameName, gameCategoryChinese)
|
||||
NewFlatLogUtils.logSimulatorUpdateAlertClick("更新")
|
||||
MtaHelper.onEvent(
|
||||
trackableEntity.event,
|
||||
trackableEntity.key,
|
||||
if (shouldShowUpdate && isInstalled) "点击更新" else "点击下载"
|
||||
)
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
SensorsBridge.trackSimulatorUpdateDialogClick(
|
||||
buttonName = positiveText,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
} else {
|
||||
SensorsBridge.trackSimulatorInstallDialogClick(
|
||||
buttonName = positiveText,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
},
|
||||
touchOutsideCallback = {
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
SensorsBridge.trackSimulatorUpdateDialogClick(
|
||||
buttonName = "关闭弹窗",
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
} else {
|
||||
SensorsBridge.trackSimulatorInstallDialogClick(
|
||||
buttonName = "关闭弹窗",
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
},
|
||||
mtaEvent = trackableEntity.event, mtaKey = trackableEntity.key,
|
||||
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
if (downloadType == "update" && location != SimulatorLocation.SIMULATOR_MANAGE) {
|
||||
SPUtils.setString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, TimeUtils.getToday())
|
||||
}
|
||||
PermissionHelper.checkGetInstalledAppsListBeforeAction(context) { _ ->
|
||||
val isInstalledNewSimulator =
|
||||
SimulatorGameManager.isNewSimulatorInstalled(HaloApp.getInstance().application)
|
||||
//当没有安装新版本模拟器时候 判断是否隐藏
|
||||
if (simulator?.active == false && !isInstalledNewSimulator) {
|
||||
showNoneEmulatorDialog(context)
|
||||
return@checkGetInstalledAppsListBeforeAction
|
||||
}
|
||||
})
|
||||
var isInstalled = PackageUtils.isInstalledFromAllPackage(
|
||||
context,
|
||||
simulator?.apk?.packageName
|
||||
)
|
||||
//模拟器管理界面还是用之前的逻辑
|
||||
if (isInstalledNewSimulator && location != SimulatorLocation.SIMULATOR_MANAGE) {
|
||||
isInstalled = isInstalledNewSimulator
|
||||
}
|
||||
// val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator?.apk?.packageName)
|
||||
val shouldShowUpdate =
|
||||
PackageUtils.isInstalledApkMatchedMd5(simulator?.apk?.packageName, simulator?.apk?.md5)
|
||||
val showAlertTag = SPUtils.getString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, "") //当天是否弹过
|
||||
val todayIsShow = showAlertTag == TimeUtils.getToday()
|
||||
downloadType = if (shouldShowUpdate && isInstalled) "update" else "download"
|
||||
if (downloadType == "update" && todayIsShow && location != SimulatorLocation.SIMULATOR_MANAGE) {
|
||||
return@checkGetInstalledAppsListBeforeAction
|
||||
}
|
||||
if (downloadType == "download" && isInstalled) {
|
||||
return@checkGetInstalledAppsListBeforeAction
|
||||
}
|
||||
val title = if (shouldShowUpdate && isInstalled) "更新模拟器" else "安装模拟器"
|
||||
val message =
|
||||
if (shouldShowUpdate && isInstalled) "检测到模拟器存在更高版本,是否前往更新" else "模拟器游戏需要先下载安装对应的模拟器,才可以运行"
|
||||
val positiveText =
|
||||
if (shouldShowUpdate && isInstalled) "更新(${simulator?.apk?.size})" else "下载(${simulator?.apk?.size})"
|
||||
val negativeText = if (shouldShowUpdate && isInstalled) "下次再说" else "取消"
|
||||
val trackableEntity = TrackableEntity(
|
||||
"模拟器下载",
|
||||
key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗",
|
||||
logShowEvent = true
|
||||
)
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
NewFlatLogUtils.logSimulatorUpdateAlertShow()
|
||||
}
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
SensorsBridge.trackSimulatorUpdateDialogShow(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
} else {
|
||||
SensorsBridge.trackSimulatorInstallDialogShow(
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
DialogHelper.showDialog(
|
||||
context,
|
||||
title,
|
||||
message,
|
||||
positiveText,
|
||||
negativeText,
|
||||
trackMtaEvent = true,
|
||||
cancelClickCallback = {
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
cancelCallback?.invoke()
|
||||
NewFlatLogUtils.logSimulatorUpdateAlertClick("取消")
|
||||
MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说")
|
||||
SensorsBridge.trackSimulatorUpdateDialogClick(
|
||||
buttonName = negativeText,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
} else {
|
||||
SensorsBridge.trackSimulatorInstallDialogClick(
|
||||
buttonName = negativeText,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
},
|
||||
confirmClickCallback = {
|
||||
showDownloadingDialog(context, simulator, gameId, gameName, gameCategoryChinese)
|
||||
NewFlatLogUtils.logSimulatorUpdateAlertClick("更新")
|
||||
MtaHelper.onEvent(
|
||||
trackableEntity.event,
|
||||
trackableEntity.key,
|
||||
if (shouldShowUpdate && isInstalled) "点击更新" else "点击下载"
|
||||
)
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
SensorsBridge.trackSimulatorUpdateDialogClick(
|
||||
buttonName = positiveText,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
} else {
|
||||
SensorsBridge.trackSimulatorInstallDialogClick(
|
||||
buttonName = positiveText,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
},
|
||||
touchOutsideCallback = {
|
||||
if (shouldShowUpdate && isInstalled) {
|
||||
SensorsBridge.trackSimulatorUpdateDialogClick(
|
||||
buttonName = "关闭弹窗",
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
} else {
|
||||
SensorsBridge.trackSimulatorInstallDialogClick(
|
||||
buttonName = "关闭弹窗",
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameCategoryChinese,
|
||||
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
|
||||
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
|
||||
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
|
||||
)
|
||||
}
|
||||
},
|
||||
mtaEvent = trackableEntity.event, mtaKey = trackableEntity.key,
|
||||
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
if (downloadType == "update" && location != SimulatorLocation.SIMULATOR_MANAGE) {
|
||||
SPUtils.setString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, TimeUtils.getToday())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun showDownloadingDialog(
|
||||
|
||||
@ -14,12 +14,10 @@ import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager;
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.gh.gamecenter.core.utils.SentryHelper;
|
||||
import com.gh.gamecenter.login.entity.IdCardEntity;
|
||||
@ -32,8 +30,6 @@ import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.sentry.Sentry;
|
||||
import io.sentry.android.core.SentryAndroid;
|
||||
@ -108,45 +104,51 @@ public class DataUtils {
|
||||
}
|
||||
|
||||
public static void getGid() {
|
||||
GidHelper.getInstance().registerDevice(HaloApp.getInstance().getApplication(), new GidCallback() {
|
||||
@Override
|
||||
public void onSuccess(String gid) {
|
||||
Utils.log("Gid", gid);
|
||||
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit().putString(Constants.DEVICE_KEY, gid).apply();
|
||||
// 默认用 APP 级已存储的 GID 来使用,不使用外部 GID
|
||||
String savedGid = SPUtils.getString(Constants.GID);
|
||||
if (!TextUtils.isEmpty(savedGid)) {
|
||||
HaloApp.getInstance().setGid(savedGid);
|
||||
onGidReceived(savedGid);
|
||||
} else {
|
||||
GidHelper.getInstance().registerDevice(HaloApp.getInstance().getApplication(), new GidCallback() {
|
||||
@Override
|
||||
public void onSuccess(String gid) {
|
||||
Utils.log("Gid", gid);
|
||||
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit().putString(Constants.DEVICE_KEY, gid).apply();
|
||||
|
||||
// 默认用 APP 级已存储的 GID 来使用,不使用外部 GID
|
||||
String savedGid = SPUtils.getString(Constants.GID);
|
||||
if (!TextUtils.isEmpty(savedGid)) {
|
||||
gid = savedGid;
|
||||
} else {
|
||||
SPUtils.setString(Constants.GID, gid);
|
||||
|
||||
onGidReceived(gid);
|
||||
}
|
||||
|
||||
HaloApp.getInstance().setGid(gid);
|
||||
|
||||
// 更新广告配置
|
||||
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
|
||||
|
||||
getDeviceCertification(gid);
|
||||
|
||||
// 避免初始化顺序问题导致 MetaUtil 一直持有空的 gid
|
||||
MetaUtil.INSTANCE.refreshMeta();
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(GhContentProvider.KEY_GID, gid);
|
||||
values.put(GhContentProvider.KEY_ANDROID_ID, MetaUtil.getBase64EncodedAndroidId());
|
||||
try {
|
||||
HaloApp.getInstance().getContentResolver().insert(Uri.parse("content://com.gh.gamecenter.provider/device"), values);
|
||||
} catch (Exception exception) {
|
||||
SentryHelper.INSTANCE.onEvent("DEVICE_INSERT_ERROR", "exception_digest", exception.getLocalizedMessage());
|
||||
exception.printStackTrace();
|
||||
@Override
|
||||
public void onFailure(String s) {
|
||||
// 更新广告配置
|
||||
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String s) {
|
||||
// 更新广告配置
|
||||
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
|
||||
private static void onGidReceived(String gid) {
|
||||
HaloApp.getInstance().setGid(gid);
|
||||
// 更新广告配置
|
||||
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
|
||||
|
||||
getDeviceCertification(gid);
|
||||
|
||||
// 避免初始化顺序问题导致 MetaUtil 一直持有空的 gid
|
||||
MetaUtil.INSTANCE.refreshMeta();
|
||||
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(GhContentProvider.KEY_GID, gid);
|
||||
values.put(GhContentProvider.KEY_ANDROID_ID, MetaUtil.getBase64EncodedAndroidId());
|
||||
try {
|
||||
HaloApp.getInstance().getContentResolver().insert(Uri.parse("content://com.gh.gamecenter.provider/device"), values);
|
||||
} catch (Exception exception) {
|
||||
SentryHelper.INSTANCE.onEvent("DEVICE_INSERT_ERROR", "exception_digest", exception.getLocalizedMessage());
|
||||
exception.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ public class InstallUtils {
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.what == INSTALL_WHAT && packageManager != null) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<PackageInfo> packageInfos = PackageUtils.getInstalledPackages(context, 0);
|
||||
List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
list.add(packageInfo.packageName);
|
||||
|
||||
@ -768,7 +768,7 @@ public class LibaoUtils {
|
||||
}
|
||||
|
||||
public static boolean isAppInstalled(Context context, String packageName) {
|
||||
List<PackageInfo> pinfo = PackageUtils.getInstalledPackages(context, 0);
|
||||
List<PackageInfo> pinfo = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
|
||||
if (pinfo != null) {
|
||||
for (int i = 0; i < pinfo.size(); i++) {
|
||||
String pn = pinfo.get(i).packageName;
|
||||
|
||||
136
app/src/main/java/com/gh/common/util/PackageChangeHelper.kt
Normal file
136
app/src/main/java/com/gh/common/util/PackageChangeHelper.kt
Normal file
@ -0,0 +1,136 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.download.PackageObserver
|
||||
import com.gh.gamecenter.common.utils.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.lightgame.utils.Utils
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
object PackageChangeHelper : DefaultLifecycleObserver {
|
||||
|
||||
private const val TAG = "PackageChangeHelper"
|
||||
|
||||
private const val INSTALL_PENDING = 1
|
||||
private const val UNINSTALL_PENDING = 2
|
||||
private const val UPDATE_PENDING = 3
|
||||
|
||||
// <包名,pending 类型,应用版本> Triple
|
||||
private var pendingPackagePair: Triple<String, Int, String>? = null
|
||||
|
||||
/**
|
||||
* 添加一个等待中,待确定是否已成功安装的应用
|
||||
*/
|
||||
fun addInstallPendingPackage(packageName: String) {
|
||||
val installData = PackagesManager.getInstalledData(packageName)
|
||||
if (installData == null) {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待安装成功")
|
||||
pendingPackagePair = Triple(packageName, INSTALL_PENDING, "")
|
||||
} else {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待安装更新成功")
|
||||
pendingPackagePair = Triple(packageName, UPDATE_PENDING, installData.version)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个等待中,待确定是否已成功卸载的应用
|
||||
*/
|
||||
fun addUninstallPendingPackage(packageName: String) {
|
||||
Utils.log(TAG, "添加了: $packageName 包名等待卸载成功")
|
||||
pendingPackagePair = Triple(packageName, UNINSTALL_PENDING, "")
|
||||
}
|
||||
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
super.onResume(owner)
|
||||
|
||||
if (pendingPackagePair != null) {
|
||||
val packageName = pendingPackagePair?.first ?: return
|
||||
val isInstallPending = pendingPackagePair?.second == INSTALL_PENDING
|
||||
val isUninstallPending = pendingPackagePair?.second == UNINSTALL_PENDING
|
||||
val isUpdatePending = pendingPackagePair?.second == UPDATE_PENDING
|
||||
|
||||
val pendingVersion = pendingPackagePair?.third ?: ""
|
||||
|
||||
val installedVersionName = PackageUtils.getVersionNameByPackageName(packageName)
|
||||
val isInstalled = installedVersionName != null
|
||||
|
||||
if (isInstallPending && isInstalled) {
|
||||
pendingPackagePair = null
|
||||
|
||||
PackageRepository.addInstalledGame(packageName)
|
||||
|
||||
performInstallSuccessAction(packageName)
|
||||
} else if (isUninstallPending && !isInstalled) {
|
||||
pendingPackagePair = null
|
||||
|
||||
performUninstallSuccessAction(packageName)
|
||||
} else if (isUpdatePending
|
||||
&& installedVersionName != pendingVersion) {
|
||||
pendingPackagePair = null
|
||||
|
||||
performUninstallSuccessAction(packageName)
|
||||
performInstallSuccessAction(packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun addInstall(packageName: String) {
|
||||
performInstallSuccessAction(packageName)
|
||||
}
|
||||
|
||||
/**
|
||||
* 对应包名安装成功后的操作,继承至 PackageChangeBroadcastObserver
|
||||
*/
|
||||
private fun performInstallSuccessAction(packageName: String, withLog: Boolean = true) {
|
||||
Utils.log(TAG, "安装了: $packageName 包名的程序")
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName)
|
||||
val gameId = if (downloadEntity != null && downloadEntity.gameId != null) downloadEntity.gameId else ""
|
||||
val gameName = if (downloadEntity != null && downloadEntity.name != null) downloadEntity.name else ""
|
||||
|
||||
if (withLog) {
|
||||
NewFlatLogUtils.logGameInstallComplete(gameId, gameName)
|
||||
SensorsBridge.trackInstallGameFinish(gameId, gameName)
|
||||
}
|
||||
|
||||
InstallUtils.getInstance().removeInstall(packageName)
|
||||
PackageHelper.refreshLocalPackageList()
|
||||
|
||||
val versionName = PackageUtils.getVersionNameByPackageName(packageName)
|
||||
val installEb = EBPackage(EBPackage.TYPE_INSTALLED, packageName, versionName)
|
||||
|
||||
PackageObserver.onPackageChanged(installEb)
|
||||
EventBus.getDefault().post(installEb)
|
||||
}
|
||||
|
||||
fun addUninstall(packageName: String) {
|
||||
performUninstallSuccessAction(packageName)
|
||||
}
|
||||
|
||||
/**
|
||||
* 对应包名卸载成功后的操作,继承至 PackageChangeBroadcastObserver
|
||||
*/
|
||||
private fun performUninstallSuccessAction(packageName: String, withLog: Boolean = true) {
|
||||
Utils.log(TAG, "卸载了: $packageName 包名的程序")
|
||||
val install = PackagesManager.getInstalledData(packageName)
|
||||
val gameId = if (install?.id != null) install.id else ""
|
||||
val gameName = if (install?.name != null) install.name else ""
|
||||
|
||||
if (withLog) {
|
||||
NewFlatLogUtils.logGameUninstallComplete(gameId!!, gameName!!)
|
||||
SensorsBridge.trackUnloadGameFinish(gameId, gameName)
|
||||
}
|
||||
|
||||
InstallUtils.getInstance().removeUninstall(packageName)
|
||||
PackageHelper.refreshLocalPackageList()
|
||||
|
||||
val uninstallEb = EBPackage(EBPackage.TYPE_UNINSTALLED, packageName, "")
|
||||
PackageObserver.onPackageChanged(uninstallEb)
|
||||
EventBus.getDefault().post(uninstallEb)
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,24 +1,80 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PermissionInfo
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.prioritychain.GlobalPriorityChainHelper
|
||||
import com.gh.common.prioritychain.RequestInstalledListPermissionHandler
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.DialogHelper
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper.isGetInstalledListPermissionDisabled
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.entity.WhitePackageListEntity
|
||||
import com.gh.gamecenter.feature.entity.SettingsEntity
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
object PackageHelper {
|
||||
|
||||
private const val TAG = "PackageHelper"
|
||||
|
||||
private const val SP_GET_INSTALLED_API_AGREED = "get_installed_api_agreed"
|
||||
|
||||
private const val UNKNOWN = -1
|
||||
private const val UNSUPPORTED = 0
|
||||
private const val SUPPORTED = 1
|
||||
|
||||
private const val ENABLED = 2
|
||||
private const val DISABLED = 3
|
||||
|
||||
private var lastInstalledPackageListTime = 0L
|
||||
private var cachedInstalledPackagesList: List<PackageInfo> = arrayListOf()
|
||||
|
||||
private var isGetInstalledPackagesApiAgreed = true // 用户是否已经同意使用已安装应用列表 API
|
||||
private var isGetInstalledPackagesApiAgreedRequired = DISABLED // 需要用户手动授权才获取已安装应用列表的功能的开关
|
||||
private var isGetInstalledPackagesPermissionSupported = UNKNOWN // 设备是否支持禁用获取已安装应用列表
|
||||
|
||||
// 评论黑名单包名列表,避免用户安装了 Xposed Installer 这样的工具,也能在包含该安装包的游戏详情页评论
|
||||
var commentPackageNameBlackList = arrayListOf<String>()
|
||||
private var _commentPackageNameBlackList = arrayListOf<String>()
|
||||
val commentPackageNameBlackList: ArrayList<String> = _commentPackageNameBlackList
|
||||
|
||||
// 关闭下载的包列表
|
||||
var downloadPackageNameBlackList = arrayListOf<String>()
|
||||
private var _downloadPackageNameBlackList = arrayListOf<String>()
|
||||
val downloadPackageNameBlackList: ArrayList<String> = _downloadPackageNameBlackList
|
||||
|
||||
// 本地已安装的包去掉关闭下载的包后的列表
|
||||
var validLocalPackageNameSet = hashSetOf<String>()
|
||||
private var _validLocalPackageNameSet = hashSetOf<String>()
|
||||
val validLocalPackageNameSet: HashSet<String> = _validLocalPackageNameSet
|
||||
|
||||
// 游戏包名匹配列表
|
||||
var relatedPackageList = arrayListOf<SettingsEntity.GameWithPackages>()
|
||||
private var _relatedPackageList = arrayListOf<SettingsEntity.GameWithPackages>()
|
||||
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages> = _relatedPackageList
|
||||
|
||||
// 接口控制的已安装应用列表获取开关状态 (UI 显示)
|
||||
private var _installedPackageApiSwitchStatusLiveData = MutableLiveData<Boolean>()
|
||||
val installedPackageApiSwitchStatusLiveData: LiveData<Boolean> = _installedPackageApiSwitchStatusLiveData
|
||||
|
||||
// 本地已安装包的列表
|
||||
var localPackageNameSet = hashSetOf<String>()
|
||||
@ -31,6 +87,22 @@ object PackageHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已安装的白名单列表(为了在没有已安装应用列表获取能力的时候也能正常判断更新、插件化)
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun getInstalledWhiteList() {
|
||||
RetrofitManager.getInstance().newApi.installWhitelist
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<WhitePackageListEntity>() {
|
||||
override fun onSuccess(data: WhitePackageListEntity) {
|
||||
data.data?.let {
|
||||
addInstalledButMissingPackages(it)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun refreshLocalPackageList() {
|
||||
localPackageNameSet = getAllPackageName(HaloApp.getInstance().application)
|
||||
@ -38,33 +110,26 @@ object PackageHelper {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun initList() {
|
||||
Config.getSettings()?.gameCommentBlackList?.let {
|
||||
commentPackageNameBlackList = ArrayList(it)
|
||||
}
|
||||
Config.getSettings()?.gameDownloadBlackList?.let {
|
||||
downloadPackageNameBlackList = ArrayList(it)
|
||||
}
|
||||
Config.getSettings()?.gamePackageMatch?.let {
|
||||
relatedPackageList = ArrayList(it)
|
||||
}
|
||||
fun refreshList() {
|
||||
Config.getSettings()?.gameCommentBlackList?.let { _commentPackageNameBlackList = ArrayList(it) }
|
||||
Config.getSettings()?.gameDownloadBlackList?.let { _downloadPackageNameBlackList = ArrayList(it) }
|
||||
Config.getSettings()?.gamePackageMatch?.let { _relatedPackageList = ArrayList(it) }
|
||||
|
||||
Config.getSettings()?.gameDownloadBlackList
|
||||
updateValidPackageNameList()
|
||||
}
|
||||
|
||||
private fun updateValidPackageNameList() {
|
||||
validLocalPackageNameSet =
|
||||
_validLocalPackageNameSet =
|
||||
localPackageNameSet.filterNot { p -> downloadPackageNameBlackList.contains(p) }.toHashSet()
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* 获取所有已安装的软件的包名、版本(非系统应用)
|
||||
*/
|
||||
private fun getAllPackageName(context: Context): HashSet<String> {
|
||||
val set = HashSet<String>()
|
||||
return try {
|
||||
val packageInfos = PackageUtils.getInstalledPackages(context, 0)
|
||||
val packageInfos = getInstalledPackages(context, 0)
|
||||
for (packageInfo in packageInfos) {
|
||||
if (packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0) {
|
||||
if (context.packageName != packageInfo.packageName) {
|
||||
@ -79,4 +144,341 @@ object PackageHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 弃用已安装列表缓存
|
||||
*/
|
||||
fun dumpInstalledListCache() {
|
||||
lastInstalledPackageListTime = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 在超时后,若后台没有开启获取已安装应用列表的功能,默认以接口不控制的方式获取已安装应用列表
|
||||
*/
|
||||
fun fallbackInstalledPackageApiSwitchAfterTimeout(timeout: Long) {
|
||||
CoroutineScope(SupervisorJob()).launch {
|
||||
delay(timeout)
|
||||
if (isGetInstalledPackagesApiAgreedRequired == UNKNOWN) {
|
||||
Utils.log(TAG, "后台没有开启获取已安装应用列表的功能,超时后默认以接口不控制的方式获取已安装应用列表")
|
||||
updateIsGetInstalledPackagesApiAgreedRequired(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新已安装应用列表获取开关状态
|
||||
*/
|
||||
fun updateIsGetInstalledPackagesApiAgreedRequired(isEnabled: Boolean) {
|
||||
// 若状态不为 unknown 或者用户已经同意使用了,无需再更新
|
||||
if (isGetInstalledPackagesApiAgreedRequired != UNKNOWN || isGetInstalledPackagesApiAgreed()) {
|
||||
Utils.log(TAG, "installedPackageApiSwitchStatus 不为 UNKNOWN,无需再更新")
|
||||
return
|
||||
}
|
||||
|
||||
if (isEnabled) {
|
||||
getInstalledWhiteList()
|
||||
_installedPackageApiSwitchStatusLiveData.postValue(true)
|
||||
isGetInstalledPackagesApiAgreedRequired = ENABLED
|
||||
} else {
|
||||
isGetInstalledPackagesApiAgreedRequired = DISABLED
|
||||
|
||||
if (isSupportGetInstalledAppsPermission(HaloApp.getInstance())) {
|
||||
GlobalPriorityChainHelper.queueNewHandler(RequestInstalledListPermissionHandler())
|
||||
} else {
|
||||
agreeOnGetInstalledPackagesApi()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户是否已经允许了调用获取已安装应用列表接口
|
||||
* 优先用内存的值,没有再从 SP 中获取并更新
|
||||
*/
|
||||
fun isGetInstalledPackagesApiAgreed(): Boolean {
|
||||
return isGetInstalledPackagesApiAgreed
|
||||
|| (SPUtils.getBoolean(SP_GET_INSTALLED_API_AGREED).also { isGetInstalledPackagesApiAgreed = it })
|
||||
}
|
||||
|
||||
fun isGetInstalledPackagesApiAgreedRequired(): Boolean {
|
||||
return isGetInstalledPackagesApiAgreedRequired == ENABLED
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意使用已安装应用列表 API
|
||||
*/
|
||||
private fun agreeOnGetInstalledPackagesApi() {
|
||||
isGetInstalledPackagesApiAgreed = true
|
||||
SPUtils.setBoolean(SP_GET_INSTALLED_API_AGREED, true)
|
||||
|
||||
_installedPackageApiSwitchStatusLiveData.postValue(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已安装应用列表
|
||||
*/
|
||||
fun getInstalledPackages(context: Context?, flags: Int): List<PackageInfo> {
|
||||
Utils.log(TAG, "即将获取已安装应用列表")
|
||||
|
||||
// 用户未同意使用已安装应用列表 API,返回空列表
|
||||
if (!isGetInstalledPackagesApiAgreed()) {
|
||||
Utils.log(TAG, "用户未同意使用已安装应用列表 API,返回空列表")
|
||||
return cachedInstalledPackagesList
|
||||
}
|
||||
|
||||
// 简单 debounce 过于频繁的获取已安装应用列表调用
|
||||
if (System.currentTimeMillis() - lastInstalledPackageListTime < 3000 && cachedInstalledPackagesList.isNotEmpty()) {
|
||||
Utils.log(TAG, "使用了缓存的已安装应用列表")
|
||||
return cachedInstalledPackagesList
|
||||
}
|
||||
|
||||
var shouldGetNewInstalledPackagedList = false
|
||||
|
||||
// 当前设备是否支持限制获取已安装应用列表的功能
|
||||
if (isSupportGetInstalledAppsPermission(context!!)) {
|
||||
Utils.log(TAG, "当前设备支持限制获取已安装应用列表的功能")
|
||||
// 当前设备是否支持禁用了获取已安装应用列表
|
||||
if (!isGetInstalledListPermissionDisabled(context)) {
|
||||
Utils.log(TAG, "当前设备没有限制获取已安装应用列表的功能")
|
||||
shouldGetNewInstalledPackagedList = true
|
||||
} else {
|
||||
Utils.log(TAG, "当前设备已限制获取已安装应用列表的功能")
|
||||
}
|
||||
} else {
|
||||
Utils.log(TAG, "当前设备不支持限制获取已安装应用列表的功能")
|
||||
shouldGetNewInstalledPackagedList = true
|
||||
}
|
||||
|
||||
if (shouldGetNewInstalledPackagedList) {
|
||||
lastInstalledPackageListTime = System.currentTimeMillis()
|
||||
cachedInstalledPackagesList = getInstalledPackagesInternal(context, flags)
|
||||
}
|
||||
|
||||
return cachedInstalledPackagesList
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示获取已安装应用列表的对话框并请求权限
|
||||
*/
|
||||
fun showGetInstallAppsListDialogAndRequestPermissionIfNeeded(
|
||||
activity: FragmentActivity,
|
||||
ignorePermanentlyDenied: Boolean = false,
|
||||
resultClosure: (Boolean) -> Unit
|
||||
) {
|
||||
|
||||
val globalOnPermissionGrantedClosure = {
|
||||
agreeOnGetInstalledPackagesApi()
|
||||
// 进行包名初始化相关的操作
|
||||
PackageRepository.initData()
|
||||
refreshLocalPackageList()
|
||||
refreshList()
|
||||
}
|
||||
|
||||
if (isSupportGetInstalledAppsPermission(activity)) {
|
||||
// 若系统已经授予了获取应用列表的权限,直接进行授权成功回调
|
||||
if (!isGetInstalledListPermissionDisabled(activity)) {
|
||||
globalOnPermissionGrantedClosure.invoke()
|
||||
resultClosure.invoke(true)
|
||||
return
|
||||
}
|
||||
|
||||
PermissionHelper.showGetInstalledAppsListPermissionDialog(
|
||||
activity = activity,
|
||||
requestPermission = true,
|
||||
ignorePermanentlyDenied = ignorePermanentlyDenied
|
||||
) { isGranted ->
|
||||
if (isGranted) {
|
||||
SensorsBridge.trackInstalledListPermissionsResult("成功")
|
||||
globalOnPermissionGrantedClosure.invoke()
|
||||
resultClosure.invoke(true)
|
||||
|
||||
trackInstalledListAfterDelay()
|
||||
} else {
|
||||
resultClosure.invoke(false)
|
||||
SensorsBridge.trackInstalledListPermissionsResult("拒绝")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val hintDialog = PermissionHelper.showGetInstalledAppsListPermissionDialog(
|
||||
activity = activity,
|
||||
requestPermission = false,
|
||||
) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
SensorsBridge.trackInstalledListPermissionsCustomDialogShow()
|
||||
|
||||
val noticeDialog = DialogHelper.showGuideDialog(
|
||||
context = activity,
|
||||
title = "权限申请",
|
||||
content = "是否允许“光环助手”获取已安装的应用信息",
|
||||
confirmText = "开启",
|
||||
cancelText = "拒绝",
|
||||
confirmClickCallback = {
|
||||
SensorsBridge.trackInstalledListPermissionsCustomClick("开启")
|
||||
globalOnPermissionGrantedClosure.invoke()
|
||||
resultClosure.invoke(true)
|
||||
|
||||
trackInstalledListAfterDelay()
|
||||
},
|
||||
cancelClickCallback = {
|
||||
resultClosure.invoke(false)
|
||||
SensorsBridge.trackInstalledListPermissionsCustomClick("拒绝")
|
||||
}
|
||||
)
|
||||
|
||||
noticeDialog?.setOnDismissListener {
|
||||
hintDialog?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟5秒后上报已安装应用列表
|
||||
*/
|
||||
private fun trackInstalledListAfterDelay() {
|
||||
CoroutineScope(SupervisorJob()).launch {
|
||||
delay(5000)
|
||||
SensorsBridge.trackNumberOfInstalledList(localPackageNameSet.size, localPackageNameSet)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持动态获取已安装应用列表权限
|
||||
*/
|
||||
fun isSupportGetInstalledAppsPermission(context: Context): Boolean {
|
||||
// 若存在缓存,直接返回缓存结果。
|
||||
if (isGetInstalledPackagesPermissionSupported != UNKNOWN) {
|
||||
return isGetInstalledPackagesPermissionSupported != UNSUPPORTED
|
||||
}
|
||||
|
||||
try {
|
||||
// 根据官方提供的方法来判定是否支持限制获取已安装应用列表
|
||||
val flag =
|
||||
Settings.Secure.getInt(context.contentResolver, "oem_installed_apps_runtime_permission_enable", 0)
|
||||
if (flag == 1) {
|
||||
isGetInstalledPackagesPermissionSupported = SUPPORTED
|
||||
return true
|
||||
}
|
||||
|
||||
// 部分未升级的手机没有上面配置项,有定义下面危险权限也认为是支持设备软件列表管控
|
||||
val packageManager = context.packageManager
|
||||
val permissionInfo = packageManager.getPermissionInfo("com.android.permission.GET_INSTALLED_APPS", 0)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
if (permissionInfo.protection == PermissionInfo.PROTECTION_DANGEROUS) {
|
||||
isGetInstalledPackagesPermissionSupported = SUPPORTED
|
||||
return true
|
||||
} else {
|
||||
isGetInstalledPackagesPermissionSupported = UNSUPPORTED
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
isGetInstalledPackagesPermissionSupported = UNSUPPORTED
|
||||
return false
|
||||
}
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
isGetInstalledPackagesPermissionSupported = UNSUPPORTED
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保指定包名的应用在已安装了的情况下能正常收录
|
||||
*/
|
||||
fun addInstalledButMissingPackages(packageNameSet: HashSet<String>) {
|
||||
Utils.log(TAG, "addInstalledButMissingPackages 检查已安装但未收录的应用")
|
||||
|
||||
val installedPackageNameSet: HashSet<String> = hashSetOf()
|
||||
|
||||
for (packageName in packageNameSet) {
|
||||
if (!PackagesManager.isInstalled(packageName)
|
||||
&& PackageUtils.getVersionNameByPackageName(packageName) != null
|
||||
) {
|
||||
installedPackageNameSet.add(packageName)
|
||||
}
|
||||
}
|
||||
|
||||
Utils.log(TAG, "addInstalledButMissingPackages 需要请求接口获取的包数量为 ${installedPackageNameSet.size}")
|
||||
|
||||
PackageRepository.addInstalledGames(
|
||||
pkgNameList = ArrayList(installedPackageNameSet),
|
||||
updateInstallStatus = true
|
||||
)
|
||||
}
|
||||
|
||||
fun refreshWrongInstallStatus(packageNameSet: MutableSet<String>) {
|
||||
runOnIoThread {
|
||||
Utils.log(TAG, "refreshWrongInstallStatus 检查安装状态异常的应用")
|
||||
|
||||
val installedButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
|
||||
val uninstalledButKeepingWrongStatusPackageNameSet: HashSet<String> = hashSetOf()
|
||||
|
||||
for (packageName in packageNameSet) {
|
||||
if (!PackagesManager.isInstalled(packageName)
|
||||
&& PackageUtils.getVersionNameByPackageName(packageName) != null
|
||||
) {
|
||||
installedButKeepingWrongStatusPackageNameSet.add(packageName)
|
||||
} else if (PackagesManager.isInstalled(packageName)
|
||||
&& PackageUtils.getVersionNameByPackageName(packageName) == null) {
|
||||
uninstalledButKeepingWrongStatusPackageNameSet.add(packageName)
|
||||
}
|
||||
}
|
||||
|
||||
Utils.log(TAG, "refreshWrongInstallStatus 需要请求接口获取的包数量为 ${installedButKeepingWrongStatusPackageNameSet.size}")
|
||||
Utils.log(TAG, "refreshWrongInstallStatus 需要移除已安装的包数量为 ${uninstalledButKeepingWrongStatusPackageNameSet.size}")
|
||||
|
||||
if (installedButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
|
||||
for (packageName in installedButKeepingWrongStatusPackageNameSet) {
|
||||
PackageChangeHelper.addInstall(packageName)
|
||||
}
|
||||
}
|
||||
|
||||
if (uninstalledButKeepingWrongStatusPackageNameSet.isNotEmpty()) {
|
||||
for (packageName in uninstalledButKeepingWrongStatusPackageNameSet) {
|
||||
PackageChangeHelper.addUninstall(packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在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 fun getInstalledPackagesInternal(context: Context, flags: Int): List<PackageInfo> {
|
||||
Utils.log(TAG, "调用系统 API 获取已安装应用列表")
|
||||
|
||||
val pm = context.packageManager
|
||||
try {
|
||||
return pm.getInstalledPackages(flags)
|
||||
} catch (ignored: java.lang.Exception) {
|
||||
//we don't care why it didn't succeed. We'll do it using an alternative way instead
|
||||
}
|
||||
// use fallback:
|
||||
val process: Process
|
||||
val result: MutableList<PackageInfo> = java.util.ArrayList()
|
||||
var bufferedReader: BufferedReader? = null
|
||||
try {
|
||||
process = Runtime.getRuntime().exec("pm list packages")
|
||||
bufferedReader = BufferedReader(InputStreamReader(process.inputStream))
|
||||
var line: String
|
||||
while ((bufferedReader.readLine().also { line = it }) != null) {
|
||||
val packageName = line.substring(line.indexOf(':') + 1)
|
||||
val packageInfo = pm.getPackageInfo(packageName, flags)
|
||||
result.add(packageInfo)
|
||||
}
|
||||
process.waitFor()
|
||||
} catch (e: java.lang.Exception) {
|
||||
e.printStackTrace()
|
||||
if (e is InterruptedException) {
|
||||
Thread.currentThread().interrupt()
|
||||
}
|
||||
} finally {
|
||||
if (bufferedReader != null) try {
|
||||
bufferedReader.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@ -108,6 +108,9 @@ object PackageInstaller {
|
||||
return
|
||||
}
|
||||
|
||||
val packageName = downloadEntity?.packageName ?: PackageUtils.getPackageNameByPath(context, pkgPath)
|
||||
PackageChangeHelper.addInstallPendingPackage(packageName)
|
||||
|
||||
try {
|
||||
// 判断是否需要使用浏览器来进行安装
|
||||
if (BrowserInstallHelper.isUseBrowserToInstallEnabled()
|
||||
@ -250,6 +253,8 @@ object PackageInstaller {
|
||||
fun uninstallForPackageName(context: Context, pkn: String?) {
|
||||
if (pkn.isNullOrEmpty()) return
|
||||
|
||||
PackageChangeHelper.addUninstallPendingPackage(pkn)
|
||||
|
||||
val uninstallIntent = Intent()
|
||||
uninstallIntent.action = Intent.ACTION_DELETE
|
||||
uninstallIntent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
|
||||
@ -7,14 +7,12 @@ 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,8 +27,6 @@ import com.gh.common.xapk.XapkInstaller;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.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;
|
||||
@ -49,12 +45,10 @@ import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
@ -68,20 +62,14 @@ import java.util.zip.ZipFile;
|
||||
|
||||
public class PackageUtils {
|
||||
|
||||
private static long mLastInstalledPackageListTime = 0L;
|
||||
private static List<PackageInfo> mInstalledPackageList = null;
|
||||
|
||||
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,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).applicationInfo.sourceDir;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
// do nothing
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -319,7 +307,7 @@ public class PackageUtils {
|
||||
return new String[]{null, null};
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
// do nothing
|
||||
}
|
||||
return new String[]{null, null};
|
||||
}
|
||||
@ -599,7 +587,7 @@ public class PackageUtils {
|
||||
.getPackageInfo(packageName, 0);
|
||||
return packageInfo.firstInstallTime;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
// do nothing
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -626,7 +614,7 @@ public class PackageUtils {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager()
|
||||
.getPackageInfo(BuildConfig.APPLICATION_ID, 0).lastUpdateTime;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -640,7 +628,7 @@ public class PackageUtils {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
// do nothing
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -653,7 +641,7 @@ public class PackageUtils {
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionCode;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
// do nothing
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -667,7 +655,7 @@ public class PackageUtils {
|
||||
PackageManager packageManager = context.getApplicationContext().getPackageManager();
|
||||
return packageManager.getApplicationIcon(packageName);
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
// do nothing
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -677,7 +665,7 @@ public class PackageUtils {
|
||||
*/
|
||||
public static ArrayList<String> getAllPackageName(Context context) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<PackageInfo> packageInfos = getInstalledPackages(context, 0);
|
||||
List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
if (!context.getPackageName().equals(packageInfo.packageName)) {
|
||||
@ -690,7 +678,7 @@ public class PackageUtils {
|
||||
|
||||
public static ArrayList<String> getAllPackageNameIncludeGh(Context context) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<PackageInfo> packageInfos = getInstalledPackages(context, 0);
|
||||
List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
list.add(packageInfo.packageName);
|
||||
@ -704,11 +692,9 @@ public class PackageUtils {
|
||||
*/
|
||||
public static ArrayList<String> getAllPackageNameIncludeSystemApps(Context context) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<PackageInfo> packageInfos = getInstalledPackages(context, 0);
|
||||
List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if (!context.getPackageName().equals(packageInfo.packageName)) {
|
||||
list.add(packageInfo.packageName);
|
||||
}
|
||||
list.add(packageInfo.packageName);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@ -717,7 +703,7 @@ public class PackageUtils {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
try {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
List<PackageInfo> packageInfos = getInstalledPackages(context, 0);
|
||||
List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
@ -758,7 +744,6 @@ public class PackageUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 启动应用
|
||||
* 请使用 PackageLauncher.launchApp()
|
||||
@ -778,22 +763,6 @@ public class PackageUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据包名,获取软件名称
|
||||
*/
|
||||
public static String getNameByPackageName(Context context, String packageName) {
|
||||
try {
|
||||
PackageManager pm = context.getApplicationContext().getPackageManager();
|
||||
ApplicationInfo applicationInfo = pm.getApplicationInfo(
|
||||
packageName, 0);
|
||||
return applicationInfo.loadLabel(pm).toString();
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* todo 统一判断
|
||||
* <p>
|
||||
@ -912,8 +881,8 @@ public class PackageUtils {
|
||||
String packageName = context.getApplicationContext().getPackageName();
|
||||
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
|
||||
// The name of the process that this object is associated with.
|
||||
if (appProcess.processName.equals(packageName) && appProcess.importance
|
||||
== ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
|
||||
if (appProcess.processName.equals(packageName)
|
||||
&& appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -924,132 +893,6 @@ public class PackageUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 弃用已安装列表缓存
|
||||
*/
|
||||
public static void dumpInstalledListCache() {
|
||||
mLastInstalledPackageListTime = 0;
|
||||
}
|
||||
|
||||
public static List<PackageInfo> getInstalledPackages(Context context, int flags) {
|
||||
Utils.log(TAG, "即将获取已安装应用列表");
|
||||
|
||||
// 简单 debounce 掉过于频繁的调用获取已安装列表调用
|
||||
if (System.currentTimeMillis() - mLastInstalledPackageListTime < 1000
|
||||
&& mInstalledPackageList != null
|
||||
&& mInstalledPackageList.size() > 0) {
|
||||
Utils.log(TAG, "使用了缓存的已安装应用列表");
|
||||
return new ArrayList<>(mInstalledPackageList);
|
||||
}
|
||||
|
||||
// 是否需要调用系统 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<>();
|
||||
}
|
||||
|
||||
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);
|
||||
} catch (Exception ignored) {
|
||||
//we don't care why it didn't succeed. We'll do it using an alternative way instead
|
||||
}
|
||||
// use fallback:
|
||||
Process process;
|
||||
List<PackageInfo> result = new ArrayList<>();
|
||||
BufferedReader bufferedReader = null;
|
||||
try {
|
||||
process = Runtime.getRuntime().exec("pm list packages");
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
final String packageName = line.substring(line.indexOf(':') + 1);
|
||||
final PackageInfo packageInfo = pm.getPackageInfo(packageName, flags);
|
||||
result.add(packageInfo);
|
||||
}
|
||||
process.waitFor();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof InterruptedException) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
} finally {
|
||||
if (bufferedReader != null)
|
||||
try {
|
||||
bufferedReader.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getWebviewPath(Context context) {
|
||||
final PackageInfo webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(context);
|
||||
return webViewPackageInfo != null ? webViewPackageInfo.applicationInfo.sourceDir : null;
|
||||
|
||||
@ -28,10 +28,10 @@ import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.net.URLEncoder
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
object BrowserInstallHelper {
|
||||
|
||||
// 随便选的 32321 居然在部分 vivo 手机上被占用,喷了
|
||||
private const val PORT = 40705
|
||||
private const val RESERVE_PORT = 40706
|
||||
|
||||
@ -40,15 +40,12 @@ object BrowserInstallHelper {
|
||||
private val mContext by lazy { HaloApp.getInstance().application }
|
||||
private var mUseReservePort = false
|
||||
|
||||
private val mAllInstalledPackageList: ArrayList<String> by lazy {
|
||||
PackageUtils.getAllPackageNameIncludeSystemApps(HaloApp.getInstance().applicationContext).apply {
|
||||
add(HaloApp.getInstance().applicationContext.packageName)
|
||||
}
|
||||
}
|
||||
private var mValidInstalledPackageList: ArrayList<String> = arrayListOf()
|
||||
private var mValidConditionMatchedCache: Boolean? = null
|
||||
|
||||
private fun getServer(port: Int): DownloadServer {
|
||||
val server = DownloadServer(port)
|
||||
for (packageName in mAllInstalledPackageList) {
|
||||
for (packageName in getAllInstalledPackageList()) {
|
||||
if (packageName.contains("com.freeme") || packageName.contains("com.zhuoyi")) {
|
||||
server.isBuggyDevice = true
|
||||
break
|
||||
@ -57,6 +54,23 @@ object BrowserInstallHelper {
|
||||
return server
|
||||
}
|
||||
|
||||
private fun getAllInstalledPackageList(): ArrayList<String> {
|
||||
when {
|
||||
mValidInstalledPackageList.isNotEmpty() -> {
|
||||
return mValidInstalledPackageList
|
||||
}
|
||||
|
||||
else -> {
|
||||
val allInstalledPackageList = PackageUtils.getAllPackageNameIncludeSystemApps(mContext)
|
||||
|
||||
if (allInstalledPackageList.isNotEmpty()) {
|
||||
mValidInstalledPackageList = allInstalledPackageList
|
||||
}
|
||||
return mValidInstalledPackageList
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadFile(filePath: String) {
|
||||
if (!::mServer.isInitialized) mServer = if (mUseReservePort) getServer(RESERVE_PORT) else getServer(PORT)
|
||||
if (!mServer.isAlive && !startServer()) {
|
||||
@ -237,32 +251,43 @@ object BrowserInstallHelper {
|
||||
* 是否满足开启浏览器安装的条件
|
||||
*/
|
||||
private fun isConditionMatched(settingsEntity: NewSettingsEntity): Boolean {
|
||||
if (mValidConditionMatchedCache != null) {
|
||||
return mValidConditionMatchedCache!!
|
||||
}
|
||||
|
||||
val packageList = getAllInstalledPackageList()
|
||||
|
||||
if (packageList.isEmpty()) return false
|
||||
|
||||
settingsEntity.installModel?.whiteList?.let {
|
||||
for (packageName in it) {
|
||||
if (mAllInstalledPackageList.contains(packageName)) {
|
||||
return false
|
||||
if (packageList.contains(packageName)) {
|
||||
mValidConditionMatchedCache = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
settingsEntity.installModel?.packages?.let {
|
||||
for (packageName in it) {
|
||||
if (mAllInstalledPackageList.contains(packageName)) {
|
||||
return true
|
||||
if (packageList.contains(packageName)) {
|
||||
mValidConditionMatchedCache = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// 匹配部分字符串即可
|
||||
settingsEntity.installModel?.regexPackages?.let {
|
||||
for (packageNamePieces in it) {
|
||||
for (installedPackageName in mAllInstalledPackageList) {
|
||||
for (installedPackageName in packageList) {
|
||||
if (installedPackageName.contains(packageNamePieces)) {
|
||||
return true
|
||||
mValidConditionMatchedCache = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return mValidConditionMatchedCache ?: false
|
||||
}
|
||||
|
||||
fun onApkInstalled(path: String?) {
|
||||
|
||||
@ -556,7 +556,10 @@ public class MainActivity extends BaseActivity {
|
||||
} else {
|
||||
TextView jumpBtn = findViewById(R.id.jumpBtn);
|
||||
jumpBtn.setText(String.format(Locale.CHINA, "跳过 %d", COUNTDOWN_MAX_COUNT - mCountdownCount));
|
||||
mBaseHandler.sendEmptyMessageDelayed(COUNTDOWN_AD, 1000);
|
||||
Message newMsg = Message.obtain();
|
||||
newMsg.what = COUNTDOWN_AD;
|
||||
newMsg.obj = msg.obj;
|
||||
mBaseHandler.sendMessageDelayed(newMsg, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ class SplashScreenActivity : BaseActivity() {
|
||||
|
||||
// 尝试获取安装应用列表权限并启动首页(不在乎结果)
|
||||
private fun requestGetInstallListPermissionAndLaunchMainActivity() {
|
||||
if (PackageUtils.isSupportGetInstalledAppsPermission(this)
|
||||
if (PackageHelper.isSupportGetInstalledAppsPermission(this)
|
||||
&& PermissionHelper.isGetInstalledListPermissionDisabled(this)
|
||||
) {
|
||||
PermissionHelper.requestGetInstalledAppsListPermission(this, true) {
|
||||
|
||||
@ -18,6 +18,7 @@ import android.widget.TextView;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.util.PackageHelper;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -188,7 +189,7 @@ public class CleanApkAdapter extends BaseRecyclerAdapter<KcSelectGameViewHolder>
|
||||
}
|
||||
|
||||
private int doType(String packageName) {
|
||||
List<PackageInfo> pakageinfos = PackageUtils.getInstalledPackages(mContext, 0);
|
||||
List<PackageInfo> pakageinfos = PackageHelper.INSTANCE.getInstalledPackages(mContext, 0);
|
||||
for (PackageInfo pi : pakageinfos) {
|
||||
if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
String pi_packageName = pi.packageName;
|
||||
|
||||
@ -21,6 +21,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.ad.AdDelegateHelper
|
||||
import com.gh.common.util.HomePluggableHelper
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.common.util.PackageInstaller
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.DownloadManagerActivity
|
||||
@ -276,6 +277,12 @@ class DownloadFragment : BaseFragment_TabLayout() {
|
||||
if (mBinding.adGameItemContainer.isVisible) {
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
refreshInstallStatus()
|
||||
}
|
||||
|
||||
private fun refreshInstallStatus() {
|
||||
PackageHelper.refreshWrongInstallStatus(PackagesManager.getInstalledSet())
|
||||
}
|
||||
|
||||
override fun onParentActivityFinish() {
|
||||
|
||||
@ -10,8 +10,8 @@ import com.ethanhua.skeleton.ViewSkeletonScreen
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
@ -29,7 +29,6 @@ import com.gh.gamecenter.feature.entity.GameInstall
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel
|
||||
import com.gh.gamecenter.wrapper.MainWrapperFragment
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
@ -147,15 +146,20 @@ class NewInstalledGameFragment : ToolbarFragment() {
|
||||
}
|
||||
|
||||
mBinding.run {
|
||||
if (PermissionHelper.isGetInstalledListPermissionDisabled(requireContext())) {
|
||||
val isGetInstalledListDisagreed = PackageHelper.isGetInstalledPackagesApiAgreedRequired()
|
||||
&& !PackageHelper.isGetInstalledPackagesApiAgreed()
|
||||
val isGetInstalledListPermissionDisabled = PermissionHelper.isGetInstalledListPermissionDisabled(requireContext())
|
||||
|
||||
if (isGetInstalledListDisagreed || isGetInstalledListPermissionDisabled) {
|
||||
reuseNoneData.reuseNoneDataIv.visibility = View.GONE
|
||||
reuseNoneData.reuseNoneDataTv.text = "开启应用列表权限"
|
||||
reuseNoneData.reuseNoneDataDescTv.text = " 及时获悉游戏最新的更新消息"
|
||||
reuseNoneData.reuseResetLoadTv.text = "去开启"
|
||||
reuseNoneData.reuseResetLoadTv.setOnClickListener {
|
||||
PermissionHelper.requestGetInstalledAppsListPermission(requireActivity()) {
|
||||
updateNoDataView()
|
||||
PackageRepository.initData()
|
||||
PackageHelper.showGetInstallAppsListDialogAndRequestPermissionIfNeeded(requireActivity()) { isGranted ->
|
||||
if (isGranted) {
|
||||
updateNoDataView()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -3,8 +3,8 @@ package com.gh.gamecenter.download
|
||||
import android.view.View
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.LazyFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
@ -12,12 +12,10 @@ import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.FixLinearLayoutManager
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.EmptyCallback
|
||||
import com.gh.gamecenter.databinding.FragmentGameUpdatableBinding
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel
|
||||
import com.gh.gamecenter.wrapper.MainWrapperFragment
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
@ -40,7 +38,6 @@ class UpdatableGameFragment : LazyFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun getRealLayoutId() = R.layout.fragment_game_updatable
|
||||
override fun onRealLayoutInflated(inflatedView: View) {
|
||||
mBinding = FragmentGameUpdatableBinding.bind(inflatedView)
|
||||
@ -98,21 +95,21 @@ class UpdatableGameFragment : LazyFragment() {
|
||||
noDataContainer.reuseResetLoadTv.layoutParams = layoutParam
|
||||
noDataContainer.reuseResetLoadTv.visibility = View.VISIBLE
|
||||
noDataContainer.reuseNoneDataDescTv.visibility = View.VISIBLE
|
||||
if (PermissionHelper.isGetInstalledListPermissionDisabled(requireContext())) {
|
||||
|
||||
val isGetInstalledListDisagreed = !PackageHelper.isGetInstalledPackagesApiAgreed()
|
||||
val isGetInstalledListPermissionDisabled = PermissionHelper.isGetInstalledListPermissionDisabled(requireContext())
|
||||
|
||||
if (isGetInstalledListDisagreed || isGetInstalledListPermissionDisabled) {
|
||||
noDataContainer.reuseNoneDataIv.visibility = View.GONE
|
||||
noDataContainer.reuseNoneDataTv.text = "开启应用列表权限"
|
||||
noDataContainer.reuseNoneDataDescTv.text = "及时获悉游戏最新的更新消息"
|
||||
noDataContainer.reuseResetLoadTv.text = "去开启"
|
||||
noDataContainer.reuseResetLoadTv.setOnClickListener {
|
||||
PermissionHelper.requestGetInstalledAppsListPermission(
|
||||
requireActivity(),
|
||||
false,
|
||||
object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
updateNoDataView()
|
||||
PackageRepository.initData()
|
||||
}
|
||||
})
|
||||
PackageHelper.showGetInstallAppsListDialogAndRequestPermissionIfNeeded(requireActivity()) { isGranted ->
|
||||
if (isGranted) {
|
||||
updateNoDataView()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
noDataContainer.reuseNoneDataIv.visibility = View.VISIBLE
|
||||
|
||||
@ -11,6 +11,12 @@ class NewApiSettingsEntity(
|
||||
var startup: StartupAdEntity? = null,//启动文案广告
|
||||
@SerializedName("user_interested_game")
|
||||
var userInterestedGame: Boolean = false, //偏好设置状态开关
|
||||
@SerializedName("installed_compliance_switch")
|
||||
var installedComplianceSwitch: Boolean? = false, //安装合规开关
|
||||
@SerializedName("listen_switch")
|
||||
var isPackageObserveEnable: Boolean = false, // 安装包监听开关
|
||||
@SerializedName("listen_str")
|
||||
var packageObserveActions: PackageObserveActions? = null, // 安装包监听的三个 action
|
||||
var install: Install, // 安装相关的
|
||||
@SerializedName("game_shield_contents")
|
||||
var gameShieldContents: List<String>? = listOf(),//游戏屏蔽内容
|
||||
@ -46,4 +52,13 @@ class NewApiSettingsEntity(
|
||||
val type: String,
|
||||
val link: LinkEntity
|
||||
)
|
||||
|
||||
class PackageObserveActions(
|
||||
@SerializedName("ADD")
|
||||
val add: String,
|
||||
@SerializedName("REM")
|
||||
val rem: String,
|
||||
@SerializedName("REP")
|
||||
val rep: String
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
class WhitePackageListEntity {
|
||||
var data: HashSet<String>? = null
|
||||
}
|
||||
@ -17,11 +17,9 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.gh.common.browse.BrowseTimer
|
||||
import com.gh.common.browse.withLifecycle
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.common.util.ViewPagerFragmentHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.TrackableDialog
|
||||
import com.gh.gamecenter.common.base.adapter.FragmentAdapter
|
||||
@ -74,7 +72,6 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
private var mBottomTabId = ""
|
||||
|
||||
private val browseTimer = BrowseTimer()
|
||||
.withLifecycle(this)
|
||||
.withResult {
|
||||
SensorsBridge.trackCommunityBrowsingDuration(it / 1000.0)
|
||||
}
|
||||
@ -202,13 +199,14 @@ class CommunityHomeFragment : LazyFragment() {
|
||||
mBottomTabId = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_ID, "") ?: ""
|
||||
}
|
||||
|
||||
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
|
||||
super.setUserVisibleHint(isVisibleToUser)
|
||||
if (isVisibleToUser) {
|
||||
browseTimer.start()
|
||||
} else {
|
||||
browseTimer.stop()
|
||||
}
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
browseTimer.start()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
browseTimer.stop()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
|
||||
@ -798,6 +798,8 @@ class GameCollectionDetailFragment :
|
||||
}
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
mListViewModel.refreshPackageStatus()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
||||
@ -10,6 +10,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.util.ErrorHelper
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.baselist.LoadStatus
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
@ -64,6 +65,8 @@ open class GameCollectionDetailViewModel(
|
||||
var videoIsMuted = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
|
||||
var isPostFirstOver = false
|
||||
|
||||
private var packageNameSet = hashSetOf<String>()
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getGameCollectionDetail() {
|
||||
mApi.getGameCollectionDetail(gameCollectionId)
|
||||
@ -128,10 +131,17 @@ open class GameCollectionDetailViewModel(
|
||||
add(mResultLiveData.value!![i])
|
||||
}
|
||||
} else {
|
||||
packageNameSet = hashSetOf()
|
||||
|
||||
games?.forEach {
|
||||
it.isAdData = adIconActive
|
||||
add(CommentItemData(game = it))
|
||||
it.getApk().forEach { apk ->
|
||||
packageNameSet.add(apk.packageName)
|
||||
}
|
||||
}
|
||||
|
||||
refreshPackageStatus()
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,6 +168,12 @@ open class GameCollectionDetailViewModel(
|
||||
override fun getHandleTopCommentCondition(index: Int) =
|
||||
!isHandleTopComment && gameCollectionDetail != null && topCommentId.isNotBlank() && index == 0
|
||||
|
||||
fun refreshPackageStatus() {
|
||||
if (packageNameSet.isNotEmpty()) {
|
||||
PackageHelper.refreshWrongInstallStatus(packageNameSet)
|
||||
}
|
||||
}
|
||||
|
||||
fun followingCommand(userId: String, isFollow: Boolean) {
|
||||
val observable = if (isFollow) {
|
||||
RetrofitManager.getInstance().api.postFollowing(userId)
|
||||
|
||||
@ -2399,6 +2399,8 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|
||||
|
||||
DownloadManager.getInstance().addObserver(dataWatcher)
|
||||
controlInstallHint()
|
||||
|
||||
mViewModel.refreshWrongInstallStatus()
|
||||
}
|
||||
|
||||
override fun onFragmentPause() {
|
||||
|
||||
@ -14,8 +14,8 @@ import com.gh.common.history.HistoryHelper
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.gamecenter.feature.utils.ConcernUtils
|
||||
import com.gh.common.util.LibaoUtils
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.livedata.NonStickyMutableLiveData
|
||||
import com.gh.gamecenter.common.mvvm.Resource
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
@ -184,6 +184,7 @@ class GameDetailViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
refreshWrongInstallStatus()
|
||||
filterGameTags(data)
|
||||
filterBlockedContent(data)
|
||||
replaceWithMirrorInfoIfNeeded(data)
|
||||
@ -256,6 +257,14 @@ class GameDetailViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshWrongInstallStatus() {
|
||||
val packageNameSet = hashSetOf<String>()
|
||||
game?.getApk()?.forEach {
|
||||
packageNameSet.add(it.packageName)
|
||||
}
|
||||
PackageHelper.refreshWrongInstallStatus(packageNameSet)
|
||||
}
|
||||
|
||||
private fun replaceWithMirrorInfoIfNeeded(data: NewGameDetailEntity) {
|
||||
// 获取镜像相关数据,不存在时不替换
|
||||
val mirrorData = getMirrorData(data) ?: return
|
||||
|
||||
@ -168,10 +168,8 @@ class CustomHomeItemGameTestV2ViewHolder(
|
||||
} else {
|
||||
RIGHT_TEXT_MORE
|
||||
}
|
||||
if (tvRight.text.isBlank()) {
|
||||
tvRight.text = rightText
|
||||
}
|
||||
|
||||
tvRight.text = rightText
|
||||
tvRight.setOnClickListener {
|
||||
if (data.rightTop.text == ALL) {
|
||||
NewFlatLogUtils.logGameTestV2MoreClick(rightText, "自定义页面")
|
||||
|
||||
@ -7,6 +7,7 @@ import com.gh.gamecenter.feature.entity.GameInstall
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
/**
|
||||
* todo 整理部分与[PackageUtils]冲突的方法
|
||||
@ -18,11 +19,11 @@ object PackagesManager {
|
||||
private val mInstalledList = ArrayList<GameInstall>()
|
||||
|
||||
// 实时更新(已安装到本地的包名列表,不包括畅玩游戏)
|
||||
private val mInstalledPkgList = Collections.synchronizedList(ArrayList<String>())
|
||||
private val mInstalledPkgSet = Collections.synchronizedSet(HashSet<String>())
|
||||
|
||||
fun initInstallPkgList(list: List<String>) {
|
||||
mInstalledPkgList.clear()
|
||||
mInstalledPkgList.addAll(list)
|
||||
fun initInstallPkgSet(set: Set<String>) {
|
||||
mInstalledPkgSet.clear()
|
||||
mInstalledPkgSet.addAll(set)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,9 +87,11 @@ object PackagesManager {
|
||||
return false
|
||||
}
|
||||
|
||||
return mInstalledPkgList.contains(packageName)
|
||||
return mInstalledPkgSet.contains(packageName)
|
||||
}
|
||||
|
||||
fun getInstalledSet(): MutableSet<String> = HashSet(mInstalledPkgSet)
|
||||
|
||||
/**
|
||||
* 根据包名版本号判断是否已安装相应版本的应用
|
||||
*
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
package com.gh.gamecenter.packagehelper
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.common.utils.toRequestBody
|
||||
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.entity.PackageFilter
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.room.AppDatabase
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
object PackageFilterManager {
|
||||
@ -77,11 +79,20 @@ object PackageFilterManager {
|
||||
if (appendOnly) {
|
||||
mPendingPackageNameSet.addAll(packageList)
|
||||
} else {
|
||||
if (exception is retrofit2.HttpException && exception.code() == 403) {
|
||||
// 403 代表 key 过期,需要重新获取
|
||||
callbackClosure?.invoke(arrayListOf())
|
||||
return
|
||||
}
|
||||
|
||||
// 接口访问失败时从数据库读取上一次缓存的已安装收录列表进行更新
|
||||
val packageEntityList =
|
||||
AppDatabase.getInstance().packageFilterDao().getAllPackageName()
|
||||
for (packageEntity in packageEntityList) {
|
||||
mValidPackageNameSet.add(packageEntity.packageName)
|
||||
// 依然为已安装状态才加入到有效包名列表中
|
||||
if (PackageUtils.isInstalled(HaloApp.getInstance(), packageEntity.packageName)) {
|
||||
mValidPackageNameSet.add(packageEntity.packageName)
|
||||
}
|
||||
}
|
||||
|
||||
callbackClosure?.invoke(ArrayList(mValidPackageNameSet))
|
||||
|
||||
@ -20,9 +20,9 @@ import com.gh.gamecenter.common.utils.tryCatchInRelease
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.GameInstall
|
||||
import com.gh.gamecenter.livedata.Event
|
||||
import com.gh.gamecenter.manager.PackagesManager
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -30,6 +30,7 @@ import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
@ -54,7 +55,7 @@ object PackageRepository {
|
||||
private const val LAST_UPLOAD_APPLIST_TIME = "last_upload_applist_time"
|
||||
private const val PAGE_SIZE = 50
|
||||
|
||||
private val mInstalledPkgList = Collections.synchronizedList(ArrayList<String>())
|
||||
private val mInstalledPkgSet = Collections.synchronizedSet(HashSet<String>())
|
||||
|
||||
@Volatile
|
||||
private var mIsInitialisingData = false
|
||||
@ -86,7 +87,7 @@ object PackageRepository {
|
||||
if (gameInstalled.isNotEmpty()) gameInstalled.clear()
|
||||
if (mInstalledGameList.isNotEmpty()) mInstalledGameList.clear()
|
||||
if (gameUpdate.isNotEmpty()) gameUpdate.clear()
|
||||
if (mInstalledPkgList.isNotEmpty()) mInstalledPkgList.clear()
|
||||
if (mInstalledPkgSet.isNotEmpty()) mInstalledPkgSet.clear()
|
||||
|
||||
val list = PackageUtils.getAllPackageName(mApplication)
|
||||
|
||||
@ -95,7 +96,7 @@ object PackageRepository {
|
||||
initFilterPackage(list) { filteredList ->
|
||||
mIsInitialisingData = false
|
||||
|
||||
mInstalledPkgList.addAll(filteredList)
|
||||
mInstalledPkgSet.addAll(filteredList)
|
||||
notifyInstallPkgData()
|
||||
|
||||
loadInstalledGameDigestAndNotifyData(filteredList)
|
||||
@ -203,12 +204,14 @@ object PackageRepository {
|
||||
* @param filteredList 已安装的游戏包名集合 (仅已收录部分)
|
||||
* @param onWorkerThreadOnly 是否在工作线程执行
|
||||
* @param isVGame 包名列表是否为畅玩游戏
|
||||
* @param updateInstallStatus 更新安装状态 (通过 EventBus 来进行)
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
private fun loadInstalledGameDigestAndNotifyData(
|
||||
filteredList: ArrayList<String>,
|
||||
onWorkerThreadOnly: Boolean = false,
|
||||
isVGame: Boolean = false,
|
||||
updateInstallStatus: Boolean = false
|
||||
) {
|
||||
var isNotifyUpdate = false
|
||||
val maxPageCount = (filteredList.size / PAGE_SIZE) + 1
|
||||
@ -243,9 +246,7 @@ object PackageRepository {
|
||||
|
||||
for (game in validGames) {
|
||||
if (gh_id == null || gh_id == game.id) {
|
||||
gameInstalled.add(
|
||||
GameInstall.transformGameInstall(game, pkgName, isVGame)
|
||||
)
|
||||
gameInstalled.add(GameInstall.transformGameInstall(game, pkgName, isVGame))
|
||||
mInstalledGameList.add(game)
|
||||
val isCanPluggable = checkGamePlugin(game, pkgName)
|
||||
val isCanUpdate = checkGameUpdate(game, isVGame)
|
||||
@ -253,6 +254,10 @@ object PackageRepository {
|
||||
if (!isNotifyUpdate && isCanUpdate || isCanPluggable) {
|
||||
isNotifyUpdate = true
|
||||
}
|
||||
|
||||
if (updateInstallStatus) {
|
||||
EventBus.getDefault().post(EBPackage(EBPackage.TYPE_INSTALLED, pkgName, game.getApk().firstOrNull()?.version))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -400,14 +405,18 @@ object PackageRepository {
|
||||
* 新增已安装的游戏
|
||||
* @param pkgName 已安装的游戏包名
|
||||
*/
|
||||
fun addInstalledGame(pkgName: String) {
|
||||
mInstalledPkgList.add(pkgName)
|
||||
fun addInstalledGame(pkgName: String, updateInstallStatus: Boolean = false) {
|
||||
mInstalledPkgSet.add(pkgName)
|
||||
notifyInstallPkgData()
|
||||
|
||||
val list = arrayListOf(pkgName)
|
||||
|
||||
updateFilterPackage(list) {
|
||||
loadInstalledGameDigestAndNotifyData(list, true)
|
||||
loadInstalledGameDigestAndNotifyData(
|
||||
filteredList = list,
|
||||
onWorkerThreadOnly = true,
|
||||
updateInstallStatus = updateInstallStatus
|
||||
)
|
||||
}
|
||||
changeRecentVaPlayed()
|
||||
}
|
||||
@ -415,18 +424,29 @@ object PackageRepository {
|
||||
/**
|
||||
* 批量新增已安装的游戏数量
|
||||
* @param pkgNameList 数组列表
|
||||
* @param isVGame 是否为畅玩游戏
|
||||
* @param updateInstallStatus 是否更新安装状态
|
||||
*/
|
||||
fun addInstalledGames(pkgNameList: ArrayList<String>, isVGame: Boolean = false) {
|
||||
fun addInstalledGames(pkgNameList: ArrayList<String>,
|
||||
isVGame: Boolean = false,
|
||||
updateInstallStatus: Boolean = false,
|
||||
) {
|
||||
// 畅玩游戏不添加至本地的已安装包名列表中
|
||||
if (!isVGame) {
|
||||
mInstalledPkgList.addAll(pkgNameList)
|
||||
mInstalledPkgSet.addAll(pkgNameList)
|
||||
} else {
|
||||
changeRecentVaPlayed()
|
||||
}
|
||||
notifyInstallPkgData()
|
||||
|
||||
updateFilterPackage(pkgNameList) {
|
||||
loadInstalledGameDigestAndNotifyData(pkgNameList, true, isVGame)
|
||||
loadInstalledGameDigestAndNotifyData(
|
||||
filteredList = pkgNameList,
|
||||
onWorkerThreadOnly = true,
|
||||
isVGame = isVGame,
|
||||
updateInstallStatus = updateInstallStatus
|
||||
)
|
||||
}
|
||||
changeRecentVaPlayed()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -435,9 +455,8 @@ object PackageRepository {
|
||||
* @param isVGame 是否来自于畅玩游戏
|
||||
*/
|
||||
fun addUninstalledGame(pkgName: String, isVGame: Boolean) {
|
||||
// TODO 检查为什么会有两个相同的包名添加到 mInstalledPkgList 里
|
||||
if (!isVGame && mInstalledPkgList.isNotEmpty()) {
|
||||
mInstalledPkgList.removeAll { it == pkgName }
|
||||
if (!isVGame && mInstalledPkgSet.isNotEmpty()) {
|
||||
mInstalledPkgSet.remove(pkgName)
|
||||
}
|
||||
// 尝试从临时的当前版本列表里移除已卸载的条目
|
||||
tryCatchInRelease {
|
||||
@ -493,7 +512,7 @@ object PackageRepository {
|
||||
}
|
||||
|
||||
private fun notifyInstallPkgData() {
|
||||
PackagesManager.initInstallPkgList(mInstalledPkgList)
|
||||
PackagesManager.initInstallPkgSet(mInstalledPkgSet)
|
||||
}
|
||||
|
||||
}
|
||||
@ -16,11 +16,11 @@ import com.gh.gamecenter.common.utils.NewFlatLogUtils;
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge;
|
||||
import com.gh.gamecenter.core.AppExecutor;
|
||||
import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.gh.gamecenter.entity.NewApiSettingsEntity;
|
||||
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;
|
||||
@ -29,21 +29,26 @@ import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
* 监听应用安装和卸载的广播
|
||||
*
|
||||
* @author LGT 黄壮华
|
||||
* 监听安装包变更
|
||||
*/
|
||||
public class InstallAndUninstallReceiver extends BroadcastReceiver {
|
||||
public class PackageChangeBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = "PackageChangeBroadcastReceiver";
|
||||
|
||||
private static final String webviewPackageName = "com.google.android.webview";
|
||||
|
||||
private final NewApiSettingsEntity.PackageObserveActions mActions;
|
||||
|
||||
public PackageChangeBroadcastReceiver(NewApiSettingsEntity.PackageObserveActions actions) {
|
||||
mActions = actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
PackageUtils.dumpInstalledListCache();
|
||||
PackageHelper.INSTANCE.dumpInstalledListCache();
|
||||
ExtensionsKt.doOnMainProcessOnly(() -> {
|
||||
Utils.log("InstallAndUninstallReceiver:: onReceive->" + intent.getAction() + "==" + intent.getDataString());
|
||||
Utils.log(TAG, "onReceive->" + intent.getAction() + "==" + intent.getDataString());
|
||||
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU
|
||||
&& Build.MANUFACTURER.toLowerCase(Locale.CHINA).contains("xiaomi")) {
|
||||
@ -53,10 +58,10 @@ public class InstallAndUninstallReceiver extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
// 接收安装广播
|
||||
if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) {
|
||||
if (intent.getAction().equals(mActions.getAdd())) {
|
||||
String packageName = intent.getDataString();
|
||||
packageName = packageName.substring(packageName.indexOf(":") + 1);
|
||||
Utils.log("安装了:" + packageName + "包名的程序");
|
||||
Utils.log(TAG, "安装了:" + packageName + "包名的程序");
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshotByPackageName(packageName);
|
||||
String gameId = downloadEntity != null && downloadEntity.getGameId() != null ? downloadEntity.getGameId() : "";
|
||||
String gameName = downloadEntity != null && downloadEntity.getName() != null ? downloadEntity.getName() : "";
|
||||
@ -84,10 +89,10 @@ public class InstallAndUninstallReceiver extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
// 接收卸载广播
|
||||
if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
|
||||
if (intent.getAction().equals(mActions.getRem())) {
|
||||
String packageName = intent.getDataString();
|
||||
packageName = packageName.substring(packageName.indexOf(":") + 1);
|
||||
Utils.log("卸载了:" + packageName + "包名的程序");
|
||||
Utils.log(TAG, "卸载了:" + packageName + "包名的程序");
|
||||
GameInstall install = PackagesManager.getInstalledData(packageName);
|
||||
String gameId = install != null && install.getId() != null ? install.getId() : "";
|
||||
String gameName = install != null && install.getName() != null ? install.getName() : "";
|
||||
@ -107,10 +112,10 @@ public class InstallAndUninstallReceiver extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
// 接收替换广播
|
||||
if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) {
|
||||
if (intent.getAction().equals(mActions.getRep())) {
|
||||
String packageName = intent.getData().getSchemeSpecificPart();
|
||||
packageName = packageName.substring(packageName.indexOf(":") + 1);
|
||||
Utils.log("替换了:" + packageName + "包名的程序");
|
||||
Utils.log(TAG, "替换了:" + packageName + "包名的程序");
|
||||
String versionName = PackageUtils.getVersionNameByPackageName(packageName);
|
||||
|
||||
EBPackage updateEb = new EBPackage(EBPackage.TYPE_REPLACED, packageName, versionName);
|
||||
@ -93,6 +93,7 @@ import com.gh.gamecenter.entity.VideoDraftEntity;
|
||||
import com.gh.gamecenter.entity.VideoEntity;
|
||||
import com.gh.gamecenter.entity.VideoTagEntity;
|
||||
import com.gh.gamecenter.entity.VoteEntity;
|
||||
import com.gh.gamecenter.entity.WhitePackageListEntity;
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.feature.entity.ArticleDraftEntity;
|
||||
@ -784,6 +785,9 @@ public interface ApiService {
|
||||
@Query("systemVersion") int systemVersion,
|
||||
@Query("ghVersion") String ghVersion);
|
||||
|
||||
@GET("/settings/game_installed/whitelist")
|
||||
Single<WhitePackageListEntity> getInstallWhitelist();
|
||||
|
||||
/**
|
||||
* 给一个回答新增评论
|
||||
*/
|
||||
|
||||
@ -148,6 +148,8 @@ class SearchGameIndexFragment : ListFragment<GameEntity, SearchGameResultViewMod
|
||||
super.onResume()
|
||||
|
||||
DownloadManager.getInstance().addObserver(dataWatcher)
|
||||
|
||||
mListViewModel.refreshWrongInstallStatus()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
||||
@ -331,6 +331,8 @@ open class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultV
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
DownloadManager.getInstance().addObserver(dataWatcher)
|
||||
|
||||
mListViewModel.refreshWrongInstallStatus()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
||||
@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.ad.AdDelegateHelper
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.gamecenter.SearchActivity
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
@ -45,6 +46,8 @@ class SearchGameResultViewModel(
|
||||
private var mAdPositionSet: HashSet<Int>? = null
|
||||
private val mAdGameMap = ConcurrentHashMap<String, List<GameEntity>>()
|
||||
|
||||
private var mPackageNameSet = hashSetOf<String>()
|
||||
|
||||
fun updateSearchKeyWithType(searchKey: String, searchType: String) {
|
||||
mSearchKey = searchKey
|
||||
mSearchType = searchType
|
||||
@ -67,6 +70,18 @@ class SearchGameResultViewModel(
|
||||
SearchItemData(game = game, isFirst = index == 0)
|
||||
}
|
||||
)
|
||||
|
||||
mPackageNameSet = hashSetOf()
|
||||
|
||||
// 添加所有出现的游戏包名
|
||||
list.forEach {
|
||||
it.getApk().forEach { apk ->
|
||||
mPackageNameSet.add(apk.packageName)
|
||||
}
|
||||
}
|
||||
|
||||
refreshWrongInstallStatus()
|
||||
|
||||
repository.getSearchSubject(mSearchKey, mPage)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -167,6 +182,12 @@ class SearchGameResultViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshWrongInstallStatus() {
|
||||
if (mPackageNameSet.isNotEmpty()) {
|
||||
PackageHelper.refreshWrongInstallStatus(mPackageNameSet)
|
||||
}
|
||||
}
|
||||
|
||||
private fun decorateListWithThirdPartyAdOnly(
|
||||
decoratedItemDataList: ArrayList<SearchItemData>,
|
||||
thirdPartyAdList: List<AdConfig>,
|
||||
|
||||
@ -5,8 +5,8 @@ import android.app.Application
|
||||
import android.content.pm.PackageManager
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.simulator.SimulatorGameManager
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.gamecenter.common.utils.NetworkUtils
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity
|
||||
import com.gh.gamecenter.feature.entity.SimulatorEntity
|
||||
@ -56,7 +56,7 @@ class SimulatorManagementViewModel(application: Application) :
|
||||
return Single.create<List<SimulatorEntity>> { emitter ->
|
||||
val simulatorEntityList = ArrayList<SimulatorEntity>()
|
||||
val allInstalledPackages =
|
||||
PackageUtils.getInstalledPackages(HaloApp.getInstance().application, PackageManager.GET_ACTIVITIES)
|
||||
PackageHelper.getInstalledPackages(HaloApp.getInstance().application, PackageManager.GET_ACTIVITIES)
|
||||
allInstalledPackages.forEach {
|
||||
if (it.packageName.contains("com.gh")) {
|
||||
val activityInfo =
|
||||
|
||||
@ -3,12 +3,15 @@ package com.gh.gamecenter.wrapper
|
||||
import android.graphics.PorterDuff
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.text.color
|
||||
import androidx.core.view.doOnNextLayout
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.ShellActivity
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
@ -77,6 +80,15 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
|
||||
mViewModel?.realNameInfoUpdateLiveData?.observe(viewLifecycleOwner) {
|
||||
updateRealNameErrorContainer()
|
||||
}
|
||||
|
||||
PackageHelper.installedPackageApiSwitchStatusLiveData.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
showInstallApiHintView(mBinding)
|
||||
SensorsBridge.trackInstalledListPermissionsDialogShow()
|
||||
} else {
|
||||
mBinding.installApiContainer.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurrentItem(page: Int) {
|
||||
@ -255,6 +267,39 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
|
||||
}
|
||||
}
|
||||
|
||||
private fun showInstallApiHintView(binding: FragmentMainBinding) {
|
||||
val contentText = SpannableStringBuilder()
|
||||
.color(R.color.text_theme.toColor(requireContext())) { append("您未授予已安装列表权限,可能") }
|
||||
.color(R.color.secondary_red.toColor(requireContext())) { append("导致无法安装及更新") }
|
||||
.color(R.color.text_theme.toColor(requireContext())) { append("建议开启权限!") }
|
||||
|
||||
binding.installApiContainer.visibility = View.VISIBLE
|
||||
binding.installApiContainer.setOnClickListener {
|
||||
// do nothing
|
||||
}
|
||||
binding.installApiCloseIv.enlargeTouchArea()
|
||||
binding.installApiContentTv.text = contentText
|
||||
binding.installApiCloseIv.setOnClickListener {
|
||||
binding.installApiContainer.visibility = View.GONE
|
||||
SensorsBridge.trackInstalledListPermissionsClick("关闭")
|
||||
}
|
||||
binding.installApiBtn.setOnClickListener {
|
||||
SensorsBridge.trackInstalledListPermissionsClick("去开启")
|
||||
|
||||
val callbackClosure: (Boolean) -> Unit = { isGranted ->
|
||||
if (isGranted) {
|
||||
binding.installApiContainer.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
PackageHelper.showGetInstallAppsListDialogAndRequestPermissionIfNeeded(
|
||||
activity = requireActivity(),
|
||||
ignorePermanentlyDenied = false,
|
||||
resultClosure = callbackClosure
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
changeBottomTabStyle(mBinding.viewPager.currentItem)
|
||||
|
||||
@ -3,7 +3,6 @@ package com.halo.assistant;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.net.ConnectivityManager;
|
||||
@ -39,14 +38,15 @@ import com.gh.common.util.DownloadNotificationHelper;
|
||||
import com.gh.common.util.DownloadObserver;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.LunchType;
|
||||
import com.gh.common.util.PackageChangeHelper;
|
||||
import com.gh.common.util.PackageHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.SignatureRepository;
|
||||
import com.gh.common.videolog.VideoRecordUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.simple.DownloadMessageHandler;
|
||||
import com.gh.download.simple.SimpleDownloadDatabase;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.Injection;
|
||||
import com.gh.gamecenter.common.constant.Config;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.RouteConsts;
|
||||
@ -73,7 +73,6 @@ import com.gh.gamecenter.packagehelper.PackageRepository;
|
||||
import com.gh.gamecenter.provider.FlavorProviderImp;
|
||||
import com.gh.gamecenter.receiver.ActivitySkipReceiver;
|
||||
import com.gh.gamecenter.receiver.DownloadReceiver;
|
||||
import com.gh.gamecenter.receiver.InstallAndUninstallReceiver;
|
||||
import com.gh.gamecenter.receiver.InstallReceiver;
|
||||
import com.gh.gamecenter.receiver.NetworkStateReceiver;
|
||||
import com.gh.gamecenter.wrapper.MainWrapperRepository;
|
||||
@ -81,6 +80,8 @@ import com.gh.vspace.VHelper;
|
||||
import com.github.piasy.biv.BigImageViewer;
|
||||
import com.github.piasy.biv.loader.fresco.FrescoImageLoader;
|
||||
import com.lg.ndownload.DownloadCore;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.llew.huawei.verifier.LoadedApkHuaWei;
|
||||
import com.shuyu.gsyvideoplayer.cache.CacheFactory;
|
||||
@ -120,7 +121,7 @@ public class HaloApp extends MultiDexApplication {
|
||||
|
||||
public boolean isSkippingThirdParty = false; // 应用是否处于跳转第三方Activity状态
|
||||
private List<String> webViewAbiList;
|
||||
private IFlavorProvider mFlavorProvider = new FlavorProviderImp();
|
||||
private final IFlavorProvider mFlavorProvider = new FlavorProviderImp();
|
||||
private final ServiceLoader<IApplication> mApplicationList = ServiceLoader.load(IApplication.class, this.getClass().getClassLoader());
|
||||
private LunchType mLaunchType = null;
|
||||
|
||||
@ -331,6 +332,9 @@ public class HaloApp extends MultiDexApplication {
|
||||
// 获取 settings 配置
|
||||
com.gh.common.constant.Config.getGhzsSettings();
|
||||
|
||||
// 5 秒获取后台配置的获取应用列表限制接口结果超时后,回落到关闭状态
|
||||
// PackageHelper.INSTANCE.fallbackInstalledPackageApiSwitchAfterTimeout(5000L);
|
||||
|
||||
String localTemporaryDeviceId = SPUtils.getString(Constants.SP_TEMPORARY_DEVICE_ID);
|
||||
if (!TextUtils.isEmpty(localTemporaryDeviceId)) {
|
||||
HaloApp.getInstance().setLocalTemporaryDeviceId(localTemporaryDeviceId);
|
||||
@ -340,7 +344,7 @@ public class HaloApp extends MultiDexApplication {
|
||||
// 必须放在外面,否则不能及时刷新用户数据
|
||||
UserRepository.getInstance().getLoginUserInfo();
|
||||
|
||||
GlobalPriorityChainHelper.INSTANCE.preStart();
|
||||
GlobalPriorityChainHelper.INSTANCE.preStart(isNewForThisVersion);
|
||||
|
||||
MainWrapperRepository.Companion.getInstance().getDataUnion();
|
||||
|
||||
@ -351,7 +355,7 @@ public class HaloApp extends MultiDexApplication {
|
||||
|
||||
PackageRepository.initData();
|
||||
PackageHelper.refreshLocalPackageList();
|
||||
PackageHelper.initList();
|
||||
PackageHelper.refreshList();
|
||||
|
||||
initReceiver();
|
||||
initPackageChangesReceiver();
|
||||
@ -367,6 +371,9 @@ public class HaloApp extends MultiDexApplication {
|
||||
// 初始化畅玩相关数据
|
||||
retrieveVGameInfoIfNeeded();
|
||||
|
||||
// 移除已安装但还在本地数据库中的包(避免因为没有监听到安装结果导致安装包没有删除的问题)
|
||||
removeInstalledButRemainedPackages();
|
||||
|
||||
// 开发环境不要强制捕获相关异常,这些异常通常是需要处理的
|
||||
if (!BuildConfig.DEBUG) {
|
||||
RxJavaPlugins.setErrorHandler(throwable -> {
|
||||
@ -497,13 +504,7 @@ public class HaloApp extends MultiDexApplication {
|
||||
}
|
||||
|
||||
private void initPackageChangesReceiver() {
|
||||
InstallAndUninstallReceiver receiver = new InstallAndUninstallReceiver();
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
||||
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
intentFilter.addDataScheme("package");
|
||||
this.registerReceiver(receiver, intentFilter);
|
||||
ProcessLifecycleOwner.get().getLifecycle().addObserver(PackageChangeHelper.INSTANCE);
|
||||
}
|
||||
|
||||
private void initConnectivityChangesReceiver() {
|
||||
@ -575,6 +576,32 @@ public class HaloApp extends MultiDexApplication {
|
||||
VHelper.init(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除已安装但还在本地数据库中的包
|
||||
*/
|
||||
private void removeInstalledButRemainedPackages() {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
for (DownloadEntity downloadEntity : DownloadManager.getInstance().getAllDownloadEntity()) {
|
||||
if (downloadEntity.getStatus() != DownloadStatus.done) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
String versionName = downloadEntity.getVersionName();
|
||||
String packageName = downloadEntity.getPackageName();
|
||||
// 这里暴力删除会影响畅玩游戏快速安装功能,但先不管了
|
||||
if (versionName != null
|
||||
&& packageName != null
|
||||
&& versionName.equals(PackageUtils.getVersionNameByPackageName(packageName))) {
|
||||
DownloadManager.getInstance().cancel(downloadEntity.getUrl());
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
// 不在乎删除的结果,尝试即可
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isReinstallTheSameVersion() {
|
||||
return mIsReinstallTheSameVersion;
|
||||
}
|
||||
@ -608,12 +635,6 @@ public class HaloApp extends MultiDexApplication {
|
||||
return mFlavorProvider;
|
||||
}
|
||||
|
||||
// @NonNull
|
||||
// @Override
|
||||
// public Configuration getWorkManagerConfiguration() {
|
||||
// return new Configuration.Builder().build();
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
|
||||
BIN
app/src/main/res/drawable-xxxhdpi/ic_install_api_close.png
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/ic_install_api_close.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 341 B |
@ -1,5 +1,6 @@
|
||||
<com.gh.gamecenter.common.view.MaterializedConstraintLayout 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:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
@ -29,7 +30,7 @@
|
||||
android:layout_height="40dp"
|
||||
android:background="@color/home_realname_error"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/bottomTabContainer"
|
||||
app:layout_constraintBottom_toTopOf="@+id/installApiContainer"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
@ -41,7 +42,8 @@
|
||||
android:src="@drawable/ic_realname_error_hint"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/realNameErrorHintTv"
|
||||
@ -77,6 +79,60 @@
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/installApiContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="52dp"
|
||||
android:background="@color/ui_surface"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/bottomTabContainer"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/primary_theme_10" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/installApiCloseIv"
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:src="@drawable/ic_install_api_close"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/installApiContentTv"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="您未授予已安装列表权限,可能导致无法安装及更新等异常情况,建议开启权限!"
|
||||
android:textSize="@dimen/secondary_size"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/installApiBtn"
|
||||
app:layout_constraintStart_toEndOf="@id/installApiCloseIv"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/installApiBtn"
|
||||
style="@style/BtnSmallStyle"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@drawable/bg_common_button_fill_gradient_blue"
|
||||
android:text="去开启"
|
||||
android:textColor="@color/text_aw_primary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomTabContainer"
|
||||
android:layout_width="0dp"
|
||||
|
||||
@ -7,8 +7,8 @@ ext {
|
||||
targetSdkVersion = 30
|
||||
|
||||
// application info (每个大版本之间的 versionCode 增加 20)
|
||||
versionCode = 1050
|
||||
versionName = "5.35.0"
|
||||
versionCode = 1051
|
||||
versionName = "5.35.1"
|
||||
applicationId = "com.gh.gamecenter"
|
||||
applicationIdGat = "com.gh.gamecenter.intl"
|
||||
|
||||
@ -129,7 +129,7 @@ ext {
|
||||
|
||||
documentfile = "1.0.1"
|
||||
|
||||
csjVersion = "5.6.2.0"
|
||||
csjVersion = "5.8.0.4.0"
|
||||
|
||||
qGameVersion = "1.57.14"
|
||||
qGameAdVersion = "4.520.1390"
|
||||
|
||||
@ -72,18 +72,19 @@ object CsjAdHelper {
|
||||
*/
|
||||
override fun getDevOaid(): String = oaid
|
||||
})
|
||||
.build(),
|
||||
object : TTVfSdk.InitCallback {
|
||||
override fun success() {
|
||||
Utils.log(TAG, "穿山甲初始化成功")
|
||||
mIsInitialed = true
|
||||
}
|
||||
.build())
|
||||
|
||||
override fun fail(p0: Int, p1: String?) {
|
||||
Utils.log(TAG, "穿山甲初始化失败, $p0 $p1")
|
||||
mIsInitialed = false
|
||||
}
|
||||
})
|
||||
TTVfSdk.start(object : TTVfSdk.Callback {
|
||||
override fun success() {
|
||||
Utils.log(TAG, "穿山甲初始化成功")
|
||||
mIsInitialed = true
|
||||
}
|
||||
|
||||
override fun fail(p0: Int, p1: String?) {
|
||||
Utils.log(TAG, "穿山甲初始化失败, $p0 $p1")
|
||||
mIsInitialed = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun updateThemeStatus(isDarkMode: Boolean) {
|
||||
@ -124,8 +125,8 @@ object CsjAdHelper {
|
||||
}
|
||||
|
||||
mTTVfNative.loadSphVs(adSlot, object : TTVfNative.CSJSplashAdListener {
|
||||
override fun onSplashLoadSuccess() {
|
||||
Utils.log(TAG, "开屏广告加载成功")
|
||||
override fun onSplashLoadSuccess(p0: CSJSplashAd?) {
|
||||
Utils.log(TAG, "开屏广告加载成功 $p0")
|
||||
}
|
||||
|
||||
override fun onSplashLoadFail(p0: CSJAdError?) {
|
||||
@ -199,7 +200,7 @@ object CsjAdHelper {
|
||||
.setCodeId(slotId) // 广告位id
|
||||
.setSupportDeepLink(true)
|
||||
.setAdCount(1) // 请求广告数量为1到3条
|
||||
.setExpressViewAcceptedSize(expressViewAcceptedSize, 96F) // 期望模板广告view的size,宽度最低为375,单位dp
|
||||
.setExpressViewAcceptedSize(expressViewAcceptedSize, 0F) // 期望模板广告view的size,宽度最低为375,单位dp
|
||||
.setAdLoadType(TTAdLoadType.LOAD) // 推荐使用,用于标注此次的广告请求用途为预加载(当做缓存)还是实时加载,方便后续为开发者优化相关策略
|
||||
.build()
|
||||
|
||||
|
||||
@ -32,6 +32,12 @@
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<provider
|
||||
android:name="cn.jpush.android.service.InitProvider"
|
||||
android:authorities="${applicationId}.jiguang.InitProvider"
|
||||
android:exported="false"
|
||||
tools:node="remove" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -186,6 +186,9 @@ public class Constants {
|
||||
// 用户是否曾经永久拒绝过存储权限
|
||||
public static final String SP_USER_HAS_PERMANENTLY_DENIED_STORAGE_PERMISSION = "user_has_permanently_denied_storage_permission";
|
||||
|
||||
// 用户是否曾经永久拒绝过获取应用安装列表权限
|
||||
public static final String SP_USER_HAS_PERMANENTLY_DENIED_GET_INSTALL_LIST_PERMISSION = "user_has_permanently_denied_get_install_list_permission";
|
||||
|
||||
// 是否已经填写邀请码
|
||||
public static final String SP_HAS_COMPLETE_INVITE_CODE = "has_complete_invite_code";
|
||||
|
||||
|
||||
@ -18,11 +18,10 @@ import android.text.Spanned
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Window
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.gamecenter.common.R
|
||||
@ -51,41 +50,50 @@ object PermissionHelper {
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun requestGetInstalledAppsListPermission(
|
||||
context: FragmentActivity,
|
||||
ignoreResult: Boolean = false,
|
||||
emptyCallback: EmptyCallback
|
||||
activity: FragmentActivity,
|
||||
ignorePermanentlyDenied: Boolean = false,
|
||||
resultCallback: (Boolean) -> Unit
|
||||
) {
|
||||
try {
|
||||
val rxPermission = RxPermissions(context)
|
||||
val rxPermission = RxPermissions(activity)
|
||||
rxPermission
|
||||
.requestEachCombined(PERMISSION_GET_INSTALLED_LIST)
|
||||
.subscribe { permission ->
|
||||
when {
|
||||
permission.granted -> {
|
||||
emptyCallback.onCallback()
|
||||
resultCallback.invoke(true)
|
||||
}
|
||||
|
||||
permission.shouldShowRequestPermissionRationale -> {
|
||||
if (ignoreResult) {
|
||||
emptyCallback.onCallback()
|
||||
}
|
||||
resultCallback.invoke(false)
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (ignoreResult) {
|
||||
emptyCallback.onCallback()
|
||||
// 忽略永久拒绝的提示跳转响应
|
||||
if (ignorePermanentlyDenied) {
|
||||
resultCallback.invoke(false)
|
||||
return@subscribe
|
||||
}
|
||||
|
||||
if (SPUtils.getBoolean(Constants.SP_USER_HAS_PERMANENTLY_DENIED_GET_INSTALL_LIST_PERMISSION)) {
|
||||
showPermissionPermanentlyDeniedDialog(
|
||||
activity = activity,
|
||||
permissionName = "获取已安装应用列表权限"
|
||||
) {
|
||||
resultCallback.invoke(false)
|
||||
}
|
||||
} else {
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intent.data = Uri.parse("package:" + context.packageName)
|
||||
context.startActivity(intent)
|
||||
SPUtils.setBoolean(
|
||||
Constants.SP_USER_HAS_PERMANENTLY_DENIED_GET_INSTALL_LIST_PERMISSION,
|
||||
true
|
||||
)
|
||||
resultCallback.invoke(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (ignoreResult) {
|
||||
emptyCallback.onCallback()
|
||||
}
|
||||
resultCallback.invoke(false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +163,10 @@ object PermissionHelper {
|
||||
|
||||
else -> {
|
||||
if (SPUtils.getBoolean(Constants.SP_USER_HAS_PERMANENTLY_DENIED_STORAGE_PERMISSION)) {
|
||||
showStoragePermissionPermanentlyDeniedDialog(activity = activity) {
|
||||
showPermissionPermanentlyDeniedDialog(
|
||||
activity = activity,
|
||||
permissionName = "存储权限"
|
||||
) {
|
||||
resultCallback.invoke(false)
|
||||
}
|
||||
} else {
|
||||
@ -168,11 +179,15 @@ object PermissionHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showStoragePermissionPermanentlyDeniedDialog(activity: Activity, callback: () -> Unit) {
|
||||
private fun showPermissionPermanentlyDeniedDialog(
|
||||
activity: Activity,
|
||||
permissionName: String,
|
||||
callback: () -> Unit
|
||||
) {
|
||||
DialogHelper.showDialog(
|
||||
context = activity,
|
||||
title = "权限申请",
|
||||
content = "在设置-应用-光环助手-权限中开启存储权限,以保证能正常使用相关功能",
|
||||
content = "在设置-应用-光环助手-权限中开启${permissionName},以保证能正常使用相关功能",
|
||||
confirmText = "去设置",
|
||||
cancelText = "放弃",
|
||||
confirmClickCallback = {
|
||||
@ -239,9 +254,67 @@ object PermissionHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示获取存储权限提示弹窗并请求存储权限
|
||||
* 展示获取已安装列表权限提示弹窗并请求权限
|
||||
*/
|
||||
private fun showStoragePermissionDialogAndRequestPermission(activity: FragmentActivity, emptyCallback: EmptyCallback) {
|
||||
fun showGetInstalledAppsListPermissionDialog(
|
||||
activity: FragmentActivity,
|
||||
requestPermission: Boolean,
|
||||
ignorePermanentlyDenied: Boolean = false,
|
||||
resultCallback: (Boolean) -> Unit
|
||||
): Dialog? {
|
||||
val solidContext = activity as? Activity ?: AppManager.getInstance().currentActivity() ?: return null
|
||||
val dialog = Dialog(solidContext, R.style.GhAlertDialog)
|
||||
|
||||
val binding = DialogExternalStoragePermissionIntroBinding.inflate(LayoutInflater.from(solidContext))
|
||||
|
||||
binding.container.updateLayoutParams<FrameLayout.LayoutParams> {
|
||||
height = 100F.dip2px()
|
||||
}
|
||||
|
||||
val spannableBuilder = SpannableStringBuilder("当您使用APP时,以下场景向您申请已安装列表权限:\n")
|
||||
|
||||
val liStringList = arrayListOf("游戏更新提醒")
|
||||
|
||||
for (li in liStringList) {
|
||||
val liSpanned = SpannableStringBuilder(li).apply {
|
||||
setSpan(
|
||||
ImprovedBulletSpan(bulletRadius = 1.5F.dip2px(), gapWidth = 14F.dip2px()),
|
||||
0,
|
||||
li.length,
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
}
|
||||
spannableBuilder.append(liSpanned)
|
||||
}
|
||||
|
||||
binding.contentTv.text = spannableBuilder
|
||||
binding.titleTv.text = "权限使用说明"
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog.setContentView(binding.root)
|
||||
dialog.window?.setDimAmount(0F)
|
||||
dialog.window?.setGravity(Gravity.TOP)
|
||||
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
|
||||
dialog.show()
|
||||
|
||||
if (requestPermission) {
|
||||
requestGetInstalledAppsListPermission(activity, ignorePermanentlyDenied) { isGranted ->
|
||||
resultCallback.invoke(isGranted)
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
return dialog
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示获取提示弹窗并请求存储权限
|
||||
*/
|
||||
private fun showStoragePermissionDialogAndRequestPermission(
|
||||
activity: FragmentActivity,
|
||||
emptyCallback: EmptyCallback
|
||||
) {
|
||||
val solidContext = activity as? Activity ?: AppManager.getInstance().currentActivity() ?: return
|
||||
val dialog = Dialog(solidContext, R.style.GhAlertDialog)
|
||||
|
||||
@ -336,18 +409,18 @@ object PermissionHelper {
|
||||
@JvmStatic
|
||||
fun checkGetInstalledAppsListBeforeAction(
|
||||
context: Context,
|
||||
emptyCallback: EmptyCallback
|
||||
resultCallback: (Boolean) -> Unit
|
||||
) {
|
||||
if (context is AppCompatActivity && isGetInstalledListPermissionDisabled(context)) {
|
||||
showDialogBeforeRequestingGetInstalledListDialog(context, emptyCallback)
|
||||
showDialogBeforeRequestingGetInstalledListDialog(context, resultCallback)
|
||||
} else {
|
||||
emptyCallback.onCallback()
|
||||
resultCallback.invoke(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showDialogBeforeRequestingGetInstalledListDialog(
|
||||
context: FragmentActivity,
|
||||
emptyCallback: EmptyCallback
|
||||
resultCallback: (Boolean) -> Unit
|
||||
) {
|
||||
DialogHelper.showDialog(
|
||||
context,
|
||||
@ -356,7 +429,7 @@ object PermissionHelper {
|
||||
cancelText = "放弃",
|
||||
confirmText = "去授权",
|
||||
cancelClickCallback = null,
|
||||
confirmClickCallback = { requestGetInstalledAppsListPermission(context, false, emptyCallback) },
|
||||
confirmClickCallback = { requestGetInstalledAppsListPermission(context, false, resultCallback) },
|
||||
extraConfig = DialogHelper.Config(hint = HINT_CHECK_USAGE),
|
||||
uiModificationCallback = {
|
||||
it.hintTv.setTextColor(ContextCompat.getColor(context, R.color.text_theme))
|
||||
|
||||
@ -103,6 +103,8 @@ object SensorsBridge {
|
||||
private const val KEY_LINK_CONTENT_COLLECTIONE_PATTERN = "link_content_collectione_pattern"
|
||||
private const val KEY_COLUMN_COLLECTIONE_PATTERN = "column_collectione_pattern"
|
||||
private const val KEY_SEQUENCE = "sequence"
|
||||
private const val KEY_NUMBER = "number"
|
||||
private const val KEY_APP_LIST = "app_list"
|
||||
|
||||
|
||||
private const val EVENT_GAME_DETAIL_PAGE_TAB_SELECT = "GameDetailPageTabSelect"
|
||||
@ -216,6 +218,13 @@ object SensorsBridge {
|
||||
private const val EVENT_SUSPENDED_WINDOW_SHOW = "SuspendedWindowShow"
|
||||
private const val EVENT_SUSPENDED_WINDOW_CLICK = "SuspendedWindowClick"
|
||||
|
||||
private const val EVENT_INSTALLED_LIST_PERMISSIONS_DIALOG_SHOW = "InstalledListPermissionsDialogShow"
|
||||
private const val EVENT_INSTALLED_LIST_PERMISSIONS_CLICK = "InstalledListPermissionsClick"
|
||||
private const val EVENT_INSTALLED_LIST_PERMISSIONS_CUSTOM_DIALOG_SHOW = "InstalledListPermissionsCustomDialogShow"
|
||||
private const val EVENT_INSTALLED_LIST_PERMISSIONS_CUSTOM_CLICK = "InstalledListPermissionsCustomClick"
|
||||
private const val EVENT_INSTALLED_LIST_PERMISSIONS_RESULT = "InstalledListPermissionsResult"
|
||||
private const val EVENT_NUMBER_OF_INSTALLED_LIST = "NumberOfInstalledList"
|
||||
|
||||
private var mIsSensorsEnabled = false
|
||||
|
||||
private val mSensor by lazy {
|
||||
@ -3515,4 +3524,73 @@ object SensorsBridge {
|
||||
}
|
||||
trackEvent(EVENT_SUSPENDED_WINDOW_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:InstalledListPermissionsDialogShow
|
||||
* 事件名称:已安装列表权限提示条展示事件
|
||||
* 触发时机: 授权提示条展示时触发 (提示条在底部TAB主页面常驻,各TAB切换时不重复上报展示事件)
|
||||
*/
|
||||
fun trackInstalledListPermissionsDialogShow() {
|
||||
trackEvent(EVENT_INSTALLED_LIST_PERMISSIONS_DIALOG_SHOW)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:InstalledListPermissionsClick
|
||||
* 事件名称:已安装列表权限提示条点击事件
|
||||
* 触发时机:点击对应按钮时触发上报
|
||||
*/
|
||||
fun trackInstalledListPermissionsClick(btnName: String) {
|
||||
val json = json {
|
||||
KEY_BUTTON_NAME to btnName
|
||||
}
|
||||
trackEvent(EVENT_INSTALLED_LIST_PERMISSIONS_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:InstalledListPermissionsCustomDialogShow
|
||||
* 事件名称:已安装列表权限自定义弹窗展示事件
|
||||
* 触发时机:自定义授权提示弹窗展示时触发
|
||||
*/
|
||||
fun trackInstalledListPermissionsCustomDialogShow() {
|
||||
trackEvent(EVENT_INSTALLED_LIST_PERMISSIONS_CUSTOM_DIALOG_SHOW)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:InstalledListPermissionsCustomClick
|
||||
* 事件名称:已安装列表权限自定义弹窗点击事件
|
||||
* 触发时机:点击对应按钮时触发上报
|
||||
*/
|
||||
fun trackInstalledListPermissionsCustomClick(btnName: String) {
|
||||
val json = json {
|
||||
KEY_BUTTON_NAME to btnName
|
||||
}
|
||||
trackEvent(EVENT_INSTALLED_LIST_PERMISSIONS_CUSTOM_CLICK, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:InstalledListPermissionsResult
|
||||
* 事件名称:已安装列表权限获取结果事件
|
||||
* 触发时机:1、用户点击已安装列表自定义弹窗“开启”后,上报权限获取的结果
|
||||
* 2、用户点击授权提示条“去开启”后,上报权限获取的结果
|
||||
*/
|
||||
fun trackInstalledListPermissionsResult(result: String) {
|
||||
val json = json {
|
||||
KEY_RESULT to result
|
||||
}
|
||||
trackEvent(EVENT_INSTALLED_LIST_PERMISSIONS_RESULT, json)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件ID:NumberOfInstalledList
|
||||
* 事件名称:已安装列表数量
|
||||
* 触发时机:客户端检测到获取已安装列表权限5s上报所读取到的已安装应用的数量
|
||||
*/
|
||||
fun trackNumberOfInstalledList(number: Int, packageSet: Set<String>) {
|
||||
val json = json {
|
||||
KEY_NUMBER to number
|
||||
KEY_APP_LIST to packageSet
|
||||
}
|
||||
trackEvent(EVENT_NUMBER_OF_INSTALLED_LIST, json)
|
||||
}
|
||||
|
||||
}
|
||||
@ -26,6 +26,7 @@ import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.alibaba.android.arouter.utils.PackageUtils;
|
||||
import com.gh.gamecenter.common.R;
|
||||
import com.gh.gamecenter.common.callback.BiCallback;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
@ -264,17 +265,10 @@ public class ShareUtils {
|
||||
|
||||
//检查是否安装手机QQ
|
||||
public static boolean isQQClientAvailable(Context context) {
|
||||
IPackageUtilsProvider packageUtilsConfig = (IPackageUtilsProvider) ARouter.getInstance().build(RouteConsts.provider.packageUtils).navigation();
|
||||
List<PackageInfo> pinfo = packageUtilsConfig.getInstalledPackages(context, 0);
|
||||
if (pinfo != null) {
|
||||
for (int i = 0; i < pinfo.size(); i++) {
|
||||
String pn = pinfo.get(i).packageName;
|
||||
if ("com.tencent.mobileqq".equals(pn) || "com.tencent.tim".equals(pn)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
IPackageUtilsProvider packageUtilsImpl = (IPackageUtilsProvider) ARouter.getInstance().build(RouteConsts.provider.packageUtils).navigation();
|
||||
|
||||
return packageUtilsImpl.isInstalledWithLauncherIcon(context, "com.tencent.mobileqq")
|
||||
|| packageUtilsImpl.isInstalledWithLauncherIcon(context, "com.tencent.tim");
|
||||
}
|
||||
|
||||
// 邀请好友(专属链接)
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
android:background="@color/transparent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
|
||||
@ -12,6 +12,8 @@ interface IPackageUtilsProvider : IProvider {
|
||||
|
||||
fun getGhVersionCode(): Int
|
||||
|
||||
fun isInstalledWithLauncherIcon(context: Context, packageName: String): Boolean
|
||||
|
||||
fun getInstalledPackages(context: Context, flag: Int): List<PackageInfo>
|
||||
|
||||
fun getApkSignatureByPackageName(context: Context, packageName: String): Array<String>
|
||||
|
||||
@ -401,9 +401,9 @@ data class GameEntity(
|
||||
@IgnoredOnParcel
|
||||
var name: String?
|
||||
get() = if (shouldUseMirrorInfo()) {
|
||||
obtainMirrorData()?.mName?.removeSuffix(".")
|
||||
obtainMirrorData()?.mName?.removeSuffix(".") ?: "mirror unknown"
|
||||
} else {
|
||||
mName?.removeSuffix(".")
|
||||
mName?.removeSuffix(".") ?: "unknown"
|
||||
}
|
||||
set(value) {
|
||||
mName = value
|
||||
|
||||
Submodule ndownload updated: 66413fae1f...b61908863c
Reference in New Issue
Block a user