Compare commits

...

5 Commits

24 changed files with 650 additions and 428 deletions

View File

@ -71,7 +71,7 @@ android_build:
exit_codes: 137 exit_codes: 137
only: only:
- dev - dev
- release - feat/GHZSCY-5250
# 代码检查 # 代码检查
sonarqube_analysis: sonarqube_analysis:
@ -152,4 +152,4 @@ oss-upload&send-email:
- /usr/local/bin/python /ci-android-mail-jira-comment.py - /usr/local/bin/python /ci-android-mail-jira-comment.py
only: only:
- dev - dev
- release - feat/GHZSCY-5250

View File

@ -94,8 +94,7 @@ public class Config {
getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply(); getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply();
mSettingsEntity = settingsEntity; mSettingsEntity = settingsEntity;
// 加载完设置后刷新下 PackageHelper.refreshList();
PackageHelper.initList();
} }
@Nullable @Nullable

View File

@ -19,6 +19,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.DirectUtils import com.gh.common.util.DirectUtils
import com.gh.common.util.LogUtils import com.gh.common.util.LogUtils
import com.gh.common.util.PackageHelper
import com.gh.common.util.PackageUtils import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager import com.gh.download.DownloadManager
import com.gh.gamecenter.R import com.gh.gamecenter.R
@ -59,7 +60,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
private val mDuration = 3000 private val mDuration = 3000
private var mDisposable: Disposable? = null private var mDisposable: Disposable? = null
private var mAdapter: PackageCheckAdapter? = 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 gameEntity: GameEntity? = null
var callBack: ConfirmListener? = null var callBack: ConfirmListener? = null
@ -325,7 +326,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0) mAllInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
gameEntity?.packageDialog?.let { gameEntity?.packageDialog?.let {
if (isAllPackageInstalled(mAllInstalledPackages, it)) { if (isAllPackageInstalled(mAllInstalledPackages, it)) {
callBack?.onConfirm() callBack?.onConfirm()
@ -363,7 +364,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) { fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) { if (busFour.isInstalledOrUninstalled()) {
mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0) mAllInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
mAdapter?.notifyDataSetChanged() mAdapter?.notifyDataSetChanged()
} }
} }
@ -416,7 +417,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
return return
} }
val allInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0) val allInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
if (isAllPackageInstalled(allInstalledPackages, packageDialogEntity)) { if (isAllPackageInstalled(allInstalledPackages, packageDialogEntity)) {
callBack.onConfirm() callBack.onConfirm()
return return

View File

@ -3,6 +3,7 @@ package com.gh.common.provider
import android.content.Context import android.content.Context
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import com.alibaba.android.arouter.facade.annotation.Route import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.common.util.PackageHelper
import com.gh.common.util.PackageUtils import com.gh.common.util.PackageUtils
import com.gh.gamecenter.common.constant.RouteConsts import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IPackageUtilsProvider import com.gh.gamecenter.core.provider.IPackageUtilsProvider
@ -23,7 +24,7 @@ class PackageUtilsProviderImpl : IPackageUtilsProvider {
} }
override fun getInstalledPackages(context: Context, flag: Int): List<PackageInfo> { 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> { override fun getApkSignatureByPackageName(context: Context, packageName: String): Array<String> {
@ -38,6 +39,10 @@ class PackageUtilsProviderImpl : IPackageUtilsProvider {
return PackageUtils.isSignedByGh(context, packageName) 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 { override fun getInstalledTime(context: Context, packageName: String): Long {
return PackageUtils.getInstalledTime(context, packageName) return PackageUtils.getInstalledTime(context, packageName)
} }

View File

@ -166,162 +166,160 @@ class SimulatorDownloadManager private constructor() {
this.gameName = gameName this.gameName = gameName
this.gameType = gameCategoryChinese this.gameType = gameCategoryChinese
PermissionHelper.checkGetInstalledAppsListBeforeAction(context, object : EmptyCallback { PermissionHelper.checkGetInstalledAppsListBeforeAction(context) { _ ->
override fun onCallback() { val isInstalledNewSimulator =
val isInstalledNewSimulator = SimulatorGameManager.isNewSimulatorInstalled(HaloApp.getInstance().application)
SimulatorGameManager.isNewSimulatorInstalled(HaloApp.getInstance().application) //当没有安装新版本模拟器时候 判断是否隐藏
//当没有安装新版本模拟器时候 判断是否隐藏 if (simulator?.active == false && !isInstalledNewSimulator) {
if (simulator?.active == false && !isInstalledNewSimulator) { showNoneEmulatorDialog(context)
showNoneEmulatorDialog(context) return@checkGetInstalledAppsListBeforeAction
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())
}
} }
}) 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( fun showDownloadingDialog(

View File

@ -50,7 +50,7 @@ public class InstallUtils {
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
if (msg.what == INSTALL_WHAT && packageManager != null) { if (msg.what == INSTALL_WHAT && packageManager != null) {
ArrayList<String> list = new ArrayList<>(); ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = PackageUtils.getInstalledPackages(context, 0); List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
for (PackageInfo packageInfo : packageInfos) { for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
list.add(packageInfo.packageName); list.add(packageInfo.packageName);

View File

@ -768,7 +768,7 @@ public class LibaoUtils {
} }
public static boolean isAppInstalled(Context context, String packageName) { 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) { if (pinfo != null) {
for (int i = 0; i < pinfo.size(); i++) { for (int i = 0; i < pinfo.size(); i++) {
String pn = pinfo.get(i).packageName; String pn = pinfo.get(i).packageName;

View File

@ -2,23 +2,53 @@ package com.gh.common.util
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo 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 com.gh.common.constant.Config import com.gh.common.constant.Config
import com.gh.gamecenter.common.utils.PermissionHelper.isGetInstalledListPermissionDisabled
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.feature.entity.SettingsEntity import com.gh.gamecenter.feature.entity.SettingsEntity
import com.halo.assistant.HaloApp import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import kotlin.collections.ArrayList
import kotlin.collections.HashSet
object PackageHelper { 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 var lastInstalledPackageListTime = 0L
private var installedPackageList: List<PackageInfo> = arrayListOf()
private var isGetInstalledPackagesApiAgreed = false
private var isGetInstalledListPermissionSupported = UNKNOWN // 设备是否支持禁用获取已安装应用列表。-1 代表支持情况未知0 代表不支持, 1 代表支持
// 评论黑名单包名列表,避免用户安装了 Xposed Installer 这样的工具,也能在包含该安装包的游戏详情页评论 // 评论黑名单包名列表,避免用户安装了 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
// 本地已安装包的列表 // 本地已安装包的列表
var localPackageNameSet = hashSetOf<String>() var localPackageNameSet = hashSetOf<String>()
@ -38,33 +68,26 @@ object PackageHelper {
} }
@JvmStatic @JvmStatic
fun initList() { fun refreshList() {
Config.getSettings()?.gameCommentBlackList?.let { Config.getSettings()?.gameCommentBlackList?.let { _commentPackageNameBlackList = ArrayList(it) }
commentPackageNameBlackList = ArrayList(it) Config.getSettings()?.gameDownloadBlackList?.let { _downloadPackageNameBlackList = ArrayList(it) }
} Config.getSettings()?.gamePackageMatch?.let { _relatedPackageList = ArrayList(it) }
Config.getSettings()?.gameDownloadBlackList?.let {
downloadPackageNameBlackList = ArrayList(it)
}
Config.getSettings()?.gamePackageMatch?.let {
relatedPackageList = ArrayList(it)
}
Config.getSettings()?.gameDownloadBlackList
updateValidPackageNameList() updateValidPackageNameList()
} }
private fun updateValidPackageNameList() { private fun updateValidPackageNameList() {
validLocalPackageNameSet = _validLocalPackageNameSet =
localPackageNameSet.filterNot { p -> downloadPackageNameBlackList.contains(p) }.toHashSet() localPackageNameSet.filterNot { p -> downloadPackageNameBlackList.contains(p) }.toHashSet()
} }
/* /**
* 获取所有已安装的软件的包名、版本(非系统应用) * 获取所有已安装的软件的包名、版本(非系统应用)
*/ */
private fun getAllPackageName(context: Context): HashSet<String> { private fun getAllPackageName(context: Context): HashSet<String> {
val set = HashSet<String>() val set = HashSet<String>()
return try { return try {
val packageInfos = PackageUtils.getInstalledPackages(context, 0) val packageInfos = getInstalledPackages(context, 0)
for (packageInfo in packageInfos) { for (packageInfo in packageInfos) {
if (packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0) { if (packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0) {
if (context.packageName != packageInfo.packageName) { if (context.packageName != packageInfo.packageName) {
@ -79,4 +102,154 @@ object PackageHelper {
} }
} }
/**
* 弃用已安装列表缓存
*/
fun dumpInstalledListCache() {
lastInstalledPackageListTime = 0
}
/**
* 用户是否已经允许了调用获取已安装应用列表接口
* 优先用内存的值,没有再从 SP 中获取并更新
*/
fun isGetInstalledPackagesApiAgreed(): Boolean {
return isGetInstalledPackagesApiAgreed
|| (SPUtils.getBoolean(SP_GET_INSTALLED_API_AGREED).also { isGetInstalledPackagesApiAgreed = it })
}
/**
* 同意使用已安装应用列表 API
*/
fun agreeOnGetInstalledPackagesApi() {
isGetInstalledPackagesApiAgreed = true
SPUtils.setBoolean(SP_GET_INSTALLED_API_AGREED, true)
}
/**
* 获取已安装应用列表
*/
fun getInstalledPackages(context: Context?, flags: Int): List<PackageInfo> {
Utils.log(TAG, "即将获取已安装应用列表")
// Utils.log(TAG, "即将获取已安装应用列表" + Thread.currentThread().getStackTrace().contentToString().replace( ',', '\n' ))
// 用户未同意使用已安装应用列表 API返回空列表
if (!isGetInstalledPackagesApiAgreed()) {
Utils.log(TAG, "用户未同意使用已安装应用列表 API返回空列表")
return installedPackageList
}
// 简单 debounce 过于频繁的获取已安装应用列表调用
if (System.currentTimeMillis() - lastInstalledPackageListTime < 3000 && installedPackageList.isNotEmpty()) {
Utils.log(TAG, "使用了缓存的已安装应用列表")
return installedPackageList
}
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()
installedPackageList = getInstalledPackagesInternal(context, flags)
}
return installedPackageList
}
/**
* 是否支持动态获取已安装应用列表权限
*/
fun isSupportGetInstalledAppsPermission(context: Context): Boolean {
// 若存在缓存,直接返回缓存结果。
if (isGetInstalledListPermissionSupported != UNKNOWN) {
return isGetInstalledListPermissionSupported != UNSUPPORTED
}
try {
// 根据官方提供的方法来判定是否支持限制获取已安装应用列表
val flag =
Settings.Secure.getInt(context.contentResolver, "oem_installed_apps_runtime_permission_enable", 0)
if (flag == 1) {
isGetInstalledListPermissionSupported = 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) {
isGetInstalledListPermissionSupported = SUPPORTED
return true
} else {
isGetInstalledListPermissionSupported = UNSUPPORTED
return false
}
} else {
isGetInstalledListPermissionSupported = UNSUPPORTED
return false
}
} catch (e: PackageManager.NameNotFoundException) {
isGetInstalledListPermissionSupported = UNSUPPORTED
return false
}
}
/**
* 在5.1系统手机使用PackageManager获取已安装应用容易发生Package manager has died异常
* https://stackoverflow.com/questions/13235793/transactiontoolargeeception-when-trying-tÏo-get-a-list-of-applications-installed/30062632#30062632
*/
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
}
} }

View File

@ -29,7 +29,6 @@ import com.gh.common.xapk.XapkInstaller;
import com.gh.gamecenter.BuildConfig; import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.common.constant.Constants; import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.utils.ExtensionsKt; 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.common.utils.PermissionHelper;
import com.gh.gamecenter.core.utils.MD5Utils; import com.gh.gamecenter.core.utils.MD5Utils;
import com.gh.gamecenter.core.utils.SentryHelper; import com.gh.gamecenter.core.utils.SentryHelper;
@ -68,14 +67,8 @@ import java.util.zip.ZipFile;
public class PackageUtils { public class PackageUtils {
private static long mLastInstalledPackageListTime = 0L;
private static List<PackageInfo> mInstalledPackageList = null;
private static final String TAG = "PackageUtils"; private static final String TAG = "PackageUtils";
// 设备是否支持禁用获取已安装应用列表。-1 代表支持情况未知0 代表不支持, 1 代表支持
private static int mIsSupportGetInstalledListPermission = -1;
public static String getInstallPackageInfoSourceDir(String packageName) { public static String getInstallPackageInfoSourceDir(String packageName) {
try { try {
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName, return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
@ -677,7 +670,7 @@ public class PackageUtils {
*/ */
public static ArrayList<String> getAllPackageName(Context context) { public static ArrayList<String> getAllPackageName(Context context) {
ArrayList<String> list = new ArrayList<>(); ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = getInstalledPackages(context, 0); List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
for (PackageInfo packageInfo : packageInfos) { for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
if (!context.getPackageName().equals(packageInfo.packageName)) { if (!context.getPackageName().equals(packageInfo.packageName)) {
@ -690,7 +683,7 @@ public class PackageUtils {
public static ArrayList<String> getAllPackageNameIncludeGh(Context context) { public static ArrayList<String> getAllPackageNameIncludeGh(Context context) {
ArrayList<String> list = new ArrayList<>(); ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = getInstalledPackages(context, 0); List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
for (PackageInfo packageInfo : packageInfos) { for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
list.add(packageInfo.packageName); list.add(packageInfo.packageName);
@ -704,11 +697,9 @@ public class PackageUtils {
*/ */
public static ArrayList<String> getAllPackageNameIncludeSystemApps(Context context) { public static ArrayList<String> getAllPackageNameIncludeSystemApps(Context context) {
ArrayList<String> list = new ArrayList<>(); ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = getInstalledPackages(context, 0); List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
for (PackageInfo packageInfo : packageInfos) { for (PackageInfo packageInfo : packageInfos) {
if (!context.getPackageName().equals(packageInfo.packageName)) { list.add(packageInfo.packageName);
list.add(packageInfo.packageName);
}
} }
return list; return list;
} }
@ -717,7 +708,7 @@ public class PackageUtils {
JSONArray jsonArray = new JSONArray(); JSONArray jsonArray = new JSONArray();
try { try {
PackageManager pm = context.getPackageManager(); PackageManager pm = context.getPackageManager();
List<PackageInfo> packageInfos = getInstalledPackages(context, 0); List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
for (PackageInfo packageInfo : packageInfos) { for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
@ -758,7 +749,6 @@ public class PackageUtils {
} }
} }
/** /**
* 启动应用 * 启动应用
* 请使用 PackageLauncher.launchApp() * 请使用 PackageLauncher.launchApp()
@ -778,22 +768,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 统一判断 * todo 统一判断
* <p> * <p>
@ -912,8 +886,8 @@ public class PackageUtils {
String packageName = context.getApplicationContext().getPackageName(); String packageName = context.getApplicationContext().getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
// The name of the process that this object is associated with. // The name of the process that this object is associated with.
if (appProcess.processName.equals(packageName) && appProcess.importance if (appProcess.processName.equals(packageName)
== ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return true; return true;
} }
} }
@ -924,132 +898,6 @@ public class PackageUtils {
return false; 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) { public static String getWebviewPath(Context context) {
final PackageInfo webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(context); final PackageInfo webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(context);
return webViewPackageInfo != null ? webViewPackageInfo.applicationInfo.sourceDir : null; return webViewPackageInfo != null ? webViewPackageInfo.applicationInfo.sourceDir : null;

View File

@ -28,10 +28,10 @@ import org.json.JSONObject
import java.io.File import java.io.File
import java.net.URLEncoder import java.net.URLEncoder
import java.util.* import java.util.*
import kotlin.collections.ArrayList
object BrowserInstallHelper { object BrowserInstallHelper {
// 随便选的 32321 居然在部分 vivo 手机上被占用,喷了
private const val PORT = 40705 private const val PORT = 40705
private const val RESERVE_PORT = 40706 private const val RESERVE_PORT = 40706
@ -40,15 +40,12 @@ object BrowserInstallHelper {
private val mContext by lazy { HaloApp.getInstance().application } private val mContext by lazy { HaloApp.getInstance().application }
private var mUseReservePort = false private var mUseReservePort = false
private val mAllInstalledPackageList: ArrayList<String> by lazy { private var mValidInstalledPackageList: ArrayList<String> = arrayListOf()
PackageUtils.getAllPackageNameIncludeSystemApps(HaloApp.getInstance().applicationContext).apply { private var mValidConditionMatchedCache: Boolean? = null
add(HaloApp.getInstance().applicationContext.packageName)
}
}
private fun getServer(port: Int): DownloadServer { private fun getServer(port: Int): DownloadServer {
val server = DownloadServer(port) val server = DownloadServer(port)
for (packageName in mAllInstalledPackageList) { for (packageName in getAllInstalledPackageList()) {
if (packageName.contains("com.freeme") || packageName.contains("com.zhuoyi")) { if (packageName.contains("com.freeme") || packageName.contains("com.zhuoyi")) {
server.isBuggyDevice = true server.isBuggyDevice = true
break break
@ -57,6 +54,23 @@ object BrowserInstallHelper {
return server 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) { fun downloadFile(filePath: String) {
if (!::mServer.isInitialized) mServer = if (mUseReservePort) getServer(RESERVE_PORT) else getServer(PORT) if (!::mServer.isInitialized) mServer = if (mUseReservePort) getServer(RESERVE_PORT) else getServer(PORT)
if (!mServer.isAlive && !startServer()) { if (!mServer.isAlive && !startServer()) {
@ -237,32 +251,43 @@ object BrowserInstallHelper {
* 是否满足开启浏览器安装的条件 * 是否满足开启浏览器安装的条件
*/ */
private fun isConditionMatched(settingsEntity: NewSettingsEntity): Boolean { private fun isConditionMatched(settingsEntity: NewSettingsEntity): Boolean {
if (mValidConditionMatchedCache != null) {
return mValidConditionMatchedCache!!
}
val packageList = getAllInstalledPackageList()
if (packageList.isEmpty()) return false
settingsEntity.installModel?.whiteList?.let { settingsEntity.installModel?.whiteList?.let {
for (packageName in it) { for (packageName in it) {
if (mAllInstalledPackageList.contains(packageName)) { if (packageList.contains(packageName)) {
return false mValidConditionMatchedCache = false
break
} }
} }
} }
settingsEntity.installModel?.packages?.let { settingsEntity.installModel?.packages?.let {
for (packageName in it) { for (packageName in it) {
if (mAllInstalledPackageList.contains(packageName)) { if (packageList.contains(packageName)) {
return true mValidConditionMatchedCache = true
break
} }
} }
} }
// 匹配部分字符串即可 // 匹配部分字符串即可
settingsEntity.installModel?.regexPackages?.let { settingsEntity.installModel?.regexPackages?.let {
for (packageNamePieces in it) { for (packageNamePieces in it) {
for (installedPackageName in mAllInstalledPackageList) { for (installedPackageName in packageList) {
if (installedPackageName.contains(packageNamePieces)) { if (installedPackageName.contains(packageNamePieces)) {
return true mValidConditionMatchedCache = true
break
} }
} }
} }
} }
return false return mValidConditionMatchedCache ?: false
} }
fun onApkInstalled(path: String?) { fun onApkInstalled(path: String?) {

View File

@ -197,15 +197,7 @@ class SplashScreenActivity : BaseActivity() {
// 尝试获取安装应用列表权限并启动首页(不在乎结果) // 尝试获取安装应用列表权限并启动首页(不在乎结果)
private fun requestGetInstallListPermissionAndLaunchMainActivity() { private fun requestGetInstallListPermissionAndLaunchMainActivity() {
if (PackageUtils.isSupportGetInstalledAppsPermission(this) launchMainActivity()
&& PermissionHelper.isGetInstalledListPermissionDisabled(this)
) {
PermissionHelper.requestGetInstalledAppsListPermission(this, true) {
launchMainActivity()
}
} else {
launchMainActivity()
}
} }
// 删除更新后的光环助手包 // 删除更新后的光环助手包

View File

@ -18,6 +18,7 @@ import android.widget.TextView;
import androidx.collection.ArrayMap; import androidx.collection.ArrayMap;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.gh.common.util.PackageHelper;
import com.gh.common.util.PackageInstaller; import com.gh.common.util.PackageInstaller;
import com.gh.common.util.PackageUtils; import com.gh.common.util.PackageUtils;
import com.gh.gamecenter.R; import com.gh.gamecenter.R;
@ -188,7 +189,7 @@ public class CleanApkAdapter extends BaseRecyclerAdapter<KcSelectGameViewHolder>
} }
private int doType(String packageName) { private int doType(String packageName) {
List<PackageInfo> pakageinfos = PackageUtils.getInstalledPackages(mContext, 0); List<PackageInfo> pakageinfos = PackageHelper.INSTANCE.getInstalledPackages(mContext, 0);
for (PackageInfo pi : pakageinfos) { for (PackageInfo pi : pakageinfos) {
if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
String pi_packageName = pi.packageName; String pi_packageName = pi.packageName;

View File

@ -153,7 +153,7 @@ class NewInstalledGameFragment : ToolbarFragment() {
reuseNoneData.reuseNoneDataDescTv.text = " 及时获悉游戏最新的更新消息" reuseNoneData.reuseNoneDataDescTv.text = " 及时获悉游戏最新的更新消息"
reuseNoneData.reuseResetLoadTv.text = "去开启" reuseNoneData.reuseResetLoadTv.text = "去开启"
reuseNoneData.reuseResetLoadTv.setOnClickListener { reuseNoneData.reuseResetLoadTv.setOnClickListener {
PermissionHelper.requestGetInstalledAppsListPermission(requireActivity()) { PermissionHelper.showGetInstalledAppsListPermissionDialogAndRequestPermission(requireActivity()) {
updateNoDataView() updateNoDataView()
PackageRepository.initData() PackageRepository.initData()
} }

View File

@ -4,7 +4,6 @@ import android.view.View
import com.gh.common.exposure.ExposureListener import com.gh.common.exposure.ExposureListener
import com.gh.common.util.DirectUtils import com.gh.common.util.DirectUtils
import com.gh.download.DownloadManager import com.gh.download.DownloadManager
import com.gh.gamecenter.MainActivity
import com.gh.gamecenter.R import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.LazyFragment import com.gh.gamecenter.common.base.fragment.LazyFragment
import com.gh.gamecenter.common.constant.EntranceConsts import com.gh.gamecenter.common.constant.EntranceConsts
@ -12,12 +11,10 @@ import com.gh.gamecenter.common.eventbus.EBReuse
import com.gh.gamecenter.common.utils.* import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.FixLinearLayoutManager import com.gh.gamecenter.common.view.FixLinearLayoutManager
import com.gh.gamecenter.core.utils.DisplayUtils import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.EmptyCallback
import com.gh.gamecenter.databinding.FragmentGameUpdatableBinding import com.gh.gamecenter.databinding.FragmentGameUpdatableBinding
import com.gh.gamecenter.eventbus.EBDownloadStatus import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.packagehelper.PackageRepository import com.gh.gamecenter.packagehelper.PackageRepository
import com.gh.gamecenter.packagehelper.PackageViewModel import com.gh.gamecenter.packagehelper.PackageViewModel
import com.gh.gamecenter.wrapper.MainWrapperFragment
import com.lightgame.download.DataWatcher import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity import com.lightgame.download.DownloadEntity
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
@ -40,7 +37,6 @@ class UpdatableGameFragment : LazyFragment() {
} }
} }
override fun getRealLayoutId() = R.layout.fragment_game_updatable override fun getRealLayoutId() = R.layout.fragment_game_updatable
override fun onRealLayoutInflated(inflatedView: View) { override fun onRealLayoutInflated(inflatedView: View) {
mBinding = FragmentGameUpdatableBinding.bind(inflatedView) mBinding = FragmentGameUpdatableBinding.bind(inflatedView)
@ -104,15 +100,14 @@ class UpdatableGameFragment : LazyFragment() {
noDataContainer.reuseNoneDataDescTv.text = "及时获悉游戏最新的更新消息" noDataContainer.reuseNoneDataDescTv.text = "及时获悉游戏最新的更新消息"
noDataContainer.reuseResetLoadTv.text = "去开启" noDataContainer.reuseResetLoadTv.text = "去开启"
noDataContainer.reuseResetLoadTv.setOnClickListener { noDataContainer.reuseResetLoadTv.setOnClickListener {
PermissionHelper.requestGetInstalledAppsListPermission( PermissionHelper.showGetInstalledAppsListPermissionDialogAndRequestPermission(
requireActivity(), requireActivity()
false, ) { isGranted ->
object : EmptyCallback { if (isGranted) {
override fun onCallback() { updateNoDataView()
updateNoDataView() PackageRepository.initData()
PackageRepository.initData() }
} }
})
} }
} else { } else {
noDataContainer.reuseNoneDataIv.visibility = View.VISIBLE noDataContainer.reuseNoneDataIv.visibility = View.VISIBLE

View File

@ -41,7 +41,7 @@ public class InstallAndUninstallReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
PackageUtils.dumpInstalledListCache(); PackageHelper.INSTANCE.dumpInstalledListCache();
ExtensionsKt.doOnMainProcessOnly(() -> { ExtensionsKt.doOnMainProcessOnly(() -> {
Utils.log("InstallAndUninstallReceiver:: onReceive->" + intent.getAction() + "==" + intent.getDataString()); Utils.log("InstallAndUninstallReceiver:: onReceive->" + intent.getAction() + "==" + intent.getDataString());

View File

@ -5,8 +5,8 @@ import android.app.Application
import android.content.pm.PackageManager import android.content.pm.PackageManager
import com.gh.common.constant.Config import com.gh.common.constant.Config
import com.gh.common.simulator.SimulatorGameManager import com.gh.common.simulator.SimulatorGameManager
import com.gh.common.util.PackageHelper
import com.gh.gamecenter.common.utils.NetworkUtils import com.gh.gamecenter.common.utils.NetworkUtils
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.common.baselist.ListViewModel import com.gh.gamecenter.common.baselist.ListViewModel
import com.gh.gamecenter.feature.entity.ApkEntity import com.gh.gamecenter.feature.entity.ApkEntity
import com.gh.gamecenter.feature.entity.SimulatorEntity import com.gh.gamecenter.feature.entity.SimulatorEntity
@ -56,7 +56,7 @@ class SimulatorManagementViewModel(application: Application) :
return Single.create<List<SimulatorEntity>> { emitter -> return Single.create<List<SimulatorEntity>> { emitter ->
val simulatorEntityList = ArrayList<SimulatorEntity>() val simulatorEntityList = ArrayList<SimulatorEntity>()
val allInstalledPackages = val allInstalledPackages =
PackageUtils.getInstalledPackages(HaloApp.getInstance().application, PackageManager.GET_ACTIVITIES) PackageHelper.getInstalledPackages(HaloApp.getInstance().application, PackageManager.GET_ACTIVITIES)
allInstalledPackages.forEach { allInstalledPackages.forEach {
if (it.packageName.contains("com.gh")) { if (it.packageName.contains("com.gh")) {
val activityInfo = val activityInfo =

View File

@ -3,12 +3,16 @@ package com.gh.gamecenter.wrapper
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.TextUtils import android.text.TextUtils
import android.view.View import android.view.View
import androidx.annotation.ColorRes import androidx.annotation.ColorRes
import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.text.color
import androidx.core.view.doOnNextLayout import androidx.core.view.doOnNextLayout
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import com.gh.common.util.PackageHelper
import com.gh.gamecenter.R import com.gh.gamecenter.R
import com.gh.gamecenter.ShellActivity import com.gh.gamecenter.ShellActivity
import com.gh.gamecenter.common.base.fragment.ToolbarFragment import com.gh.gamecenter.common.base.fragment.ToolbarFragment
@ -24,6 +28,7 @@ import com.gh.gamecenter.databinding.FragmentMainBinding
import com.gh.gamecenter.databinding.PieceBottomTabBinding import com.gh.gamecenter.databinding.PieceBottomTabBinding
import com.gh.gamecenter.entity.BottomTab import com.gh.gamecenter.entity.BottomTab
import com.gh.gamecenter.login.entity.UserInfoEntity import com.gh.gamecenter.login.entity.UserInfoEntity
import com.gh.gamecenter.packagehelper.PackageRepository
import com.halo.assistant.HaloApp import com.halo.assistant.HaloApp
import com.lightgame.listeners.OnBackPressedListener import com.lightgame.listeners.OnBackPressedListener
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
@ -62,6 +67,8 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
setCurrentItem(mViewModel!!.defaultBottomTabIndex) setCurrentItem(mViewModel!!.defaultBottomTabIndex)
} }
} }
PackageRepository.addInstalledGame("com.woobest.sgwg.aligames")
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -77,6 +84,10 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
mViewModel?.realNameInfoUpdateLiveData?.observe(viewLifecycleOwner) { mViewModel?.realNameInfoUpdateLiveData?.observe(viewLifecycleOwner) {
updateRealNameErrorContainer() updateRealNameErrorContainer()
} }
if (!PackageHelper.isGetInstalledPackagesApiAgreed()) {
showInstallApiHintView(mBinding)
}
} }
fun setCurrentItem(page: Int) { fun setCurrentItem(page: Int) {
@ -255,6 +266,70 @@ 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
}
binding.installApiBtn.setOnClickListener {
val grantedClosure = {
binding.installApiContainer.visibility = View.GONE
PackageHelper.agreeOnGetInstalledPackagesApi()
// 进行包名初始化相关的操作
PackageRepository.initData()
PackageHelper.refreshLocalPackageList()
PackageHelper.refreshList()
}
if (PackageHelper.isSupportGetInstalledAppsPermission(requireContext())) {
// 若系统已经授予了获取应用列表的权限,直接进行授权成功回调
if (!PermissionHelper.isGetInstalledListPermissionDisabled(requireContext())) {
grantedClosure.invoke()
return@setOnClickListener
}
PermissionHelper.showGetInstalledAppsListPermissionDialogAndRequestPermission(requireContext() as FragmentActivity) { isGranted ->
// TODO 处理回调,上报日志等
if (isGranted) {
grantedClosure.invoke()
} else {
// TODO 处理拒绝权限的情况
}
}
} else {
val hintDialog = PermissionHelper.showGetInstalledAppsListPermissionDialogAndRequestPermission(requireContext() as FragmentActivity) {
// do nothing
}
val noticeDialog = DialogHelper.showDialog(
context = requireContext(),
title = "权限申请",
content = "是否允许“光环助手”获取已安装的应用信息",
confirmText = "开启",
cancelText = "拒绝",
confirmClickCallback = {
grantedClosure.invoke()
}
)
noticeDialog?.setOnDismissListener {
hintDialog?.dismiss()
}
}
}
}
override fun onDarkModeChanged() { override fun onDarkModeChanged() {
super.onDarkModeChanged() super.onDarkModeChanged()
changeBottomTabStyle(mBinding.viewPager.currentItem) changeBottomTabStyle(mBinding.viewPager.currentItem)

View File

@ -46,7 +46,6 @@ import com.gh.common.videolog.VideoRecordUtils;
import com.gh.download.simple.DownloadMessageHandler; import com.gh.download.simple.DownloadMessageHandler;
import com.gh.download.simple.SimpleDownloadDatabase; import com.gh.download.simple.SimpleDownloadDatabase;
import com.gh.gamecenter.BuildConfig; import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.Injection;
import com.gh.gamecenter.common.constant.Config; import com.gh.gamecenter.common.constant.Config;
import com.gh.gamecenter.common.constant.Constants; import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.constant.RouteConsts; import com.gh.gamecenter.common.constant.RouteConsts;
@ -351,7 +350,7 @@ public class HaloApp extends MultiDexApplication {
PackageRepository.initData(); PackageRepository.initData();
PackageHelper.refreshLocalPackageList(); PackageHelper.refreshLocalPackageList();
PackageHelper.initList(); PackageHelper.refreshList();
initReceiver(); initReceiver();
initPackageChangesReceiver(); initPackageChangesReceiver();

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

View File

@ -1,5 +1,6 @@
<com.gh.gamecenter.common.view.MaterializedConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <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:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
@ -29,7 +30,7 @@
android:layout_height="40dp" android:layout_height="40dp"
android:background="@color/home_realname_error" android:background="@color/home_realname_error"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/bottomTabContainer" app:layout_constraintBottom_toTopOf="@+id/installApiContainer"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"> app:layout_constraintStart_toStartOf="parent">
@ -41,7 +42,8 @@
android:src="@drawable/ic_realname_error_hint" android:src="@drawable/ic_realname_error_hint"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<TextView <TextView
android:id="@+id/realNameErrorHintTv" android:id="@+id/realNameErrorHintTv"
@ -77,6 +79,60 @@
</androidx.constraintlayout.widget.ConstraintLayout> </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 <LinearLayout
android:id="@+id/bottomTabContainer" android:id="@+id/bottomTabContainer"
android:layout_width="0dp" android:layout_width="0dp"

View File

@ -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_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"; public static final String SP_HAS_COMPLETE_INVITE_CODE = "has_complete_invite_code";

View File

@ -18,10 +18,7 @@ import android.text.Spanned
import android.view.Gravity import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Window import android.view.Window
import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import com.alibaba.android.arouter.launcher.ARouter import com.alibaba.android.arouter.launcher.ARouter
@ -51,41 +48,43 @@ object PermissionHelper {
*/ */
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
fun requestGetInstalledAppsListPermission( fun requestGetInstalledAppsListPermission(
context: FragmentActivity, activity: FragmentActivity,
ignoreResult: Boolean = false, resultCallback: (Boolean) -> Unit
emptyCallback: EmptyCallback
) { ) {
try { try {
val rxPermission = RxPermissions(context) val rxPermission = RxPermissions(activity)
rxPermission rxPermission
.requestEachCombined(PERMISSION_GET_INSTALLED_LIST) .requestEachCombined(PERMISSION_GET_INSTALLED_LIST)
.subscribe { permission -> .subscribe { permission ->
when { when {
permission.granted -> { permission.granted -> {
emptyCallback.onCallback() resultCallback.invoke(true)
} }
permission.shouldShowRequestPermissionRationale -> { permission.shouldShowRequestPermissionRationale -> {
if (ignoreResult) { resultCallback.invoke(false)
emptyCallback.onCallback()
}
} }
else -> { else -> {
if (ignoreResult) { if (SPUtils.getBoolean(Constants.SP_USER_HAS_PERMANENTLY_DENIED_GET_INSTALL_LIST_PERMISSION)) {
emptyCallback.onCallback() showPermissionPermanentlyDeniedDialog(
activity = activity,
permissionName = "获取已安装应用列表权限"
) {
resultCallback.invoke(false)
}
} else { } else {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) SPUtils.setBoolean(
intent.data = Uri.parse("package:" + context.packageName) Constants.SP_USER_HAS_PERMANENTLY_DENIED_GET_INSTALL_LIST_PERMISSION,
context.startActivity(intent) true
)
resultCallback.invoke(false)
} }
} }
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
if (ignoreResult) { resultCallback.invoke(false)
emptyCallback.onCallback()
}
} }
} }
@ -155,7 +154,10 @@ object PermissionHelper {
else -> { else -> {
if (SPUtils.getBoolean(Constants.SP_USER_HAS_PERMANENTLY_DENIED_STORAGE_PERMISSION)) { if (SPUtils.getBoolean(Constants.SP_USER_HAS_PERMANENTLY_DENIED_STORAGE_PERMISSION)) {
showStoragePermissionPermanentlyDeniedDialog(activity = activity) { showPermissionPermanentlyDeniedDialog(
activity = activity,
permissionName = "存储权限"
) {
resultCallback.invoke(false) resultCallback.invoke(false)
} }
} else { } else {
@ -168,11 +170,15 @@ object PermissionHelper {
} }
} }
private fun showStoragePermissionPermanentlyDeniedDialog(activity: Activity, callback: () -> Unit) { private fun showPermissionPermanentlyDeniedDialog(
activity: Activity,
permissionName: String,
callback: () -> Unit
) {
DialogHelper.showDialog( DialogHelper.showDialog(
context = activity, context = activity,
title = "权限申请", title = "权限申请",
content = "在设置-应用-光环助手-权限中开启存储权限,以保证能正常使用相关功能", content = "在设置-应用-光环助手-权限中开启${permissionName},以保证能正常使用相关功能",
confirmText = "去设置", confirmText = "去设置",
cancelText = "放弃", cancelText = "放弃",
confirmClickCallback = { confirmClickCallback = {
@ -239,9 +245,59 @@ object PermissionHelper {
} }
/** /**
* 展示获取存储权限提示弹窗并请求存储权限 * 展示获取已安装列表权限提示弹窗并请求权限
*/ */
private fun showStoragePermissionDialogAndRequestPermission(activity: FragmentActivity, emptyCallback: EmptyCallback) { fun showGetInstalledAppsListPermissionDialogAndRequestPermission(
activity: FragmentActivity,
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))
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))
requestGetInstalledAppsListPermission(activity) { granted ->
resultCallback.invoke(granted)
dialog.dismiss()
}
dialog.show()
return dialog
}
/**
* 展示获取提示弹窗并请求存储权限
*/
private fun showStoragePermissionDialogAndRequestPermission(
activity: FragmentActivity,
emptyCallback: EmptyCallback
) {
val solidContext = activity as? Activity ?: AppManager.getInstance().currentActivity() ?: return val solidContext = activity as? Activity ?: AppManager.getInstance().currentActivity() ?: return
val dialog = Dialog(solidContext, R.style.GhAlertDialog) val dialog = Dialog(solidContext, R.style.GhAlertDialog)
@ -336,18 +392,18 @@ object PermissionHelper {
@JvmStatic @JvmStatic
fun checkGetInstalledAppsListBeforeAction( fun checkGetInstalledAppsListBeforeAction(
context: Context, context: Context,
emptyCallback: EmptyCallback resultCallback: (Boolean) -> Unit
) { ) {
if (context is AppCompatActivity && isGetInstalledListPermissionDisabled(context)) { if (context is AppCompatActivity && isGetInstalledListPermissionDisabled(context)) {
showDialogBeforeRequestingGetInstalledListDialog(context, emptyCallback) showDialogBeforeRequestingGetInstalledListDialog(context, resultCallback)
} else { } else {
emptyCallback.onCallback() resultCallback.invoke(true)
} }
} }
private fun showDialogBeforeRequestingGetInstalledListDialog( private fun showDialogBeforeRequestingGetInstalledListDialog(
context: FragmentActivity, context: FragmentActivity,
emptyCallback: EmptyCallback resultCallback: (Boolean) -> Unit
) { ) {
DialogHelper.showDialog( DialogHelper.showDialog(
context, context,
@ -356,7 +412,7 @@ object PermissionHelper {
cancelText = "放弃", cancelText = "放弃",
confirmText = "去授权", confirmText = "去授权",
cancelClickCallback = null, cancelClickCallback = null,
confirmClickCallback = { requestGetInstalledAppsListPermission(context, false, emptyCallback) }, confirmClickCallback = { requestGetInstalledAppsListPermission(context, resultCallback) },
extraConfig = DialogHelper.Config(hint = HINT_CHECK_USAGE), extraConfig = DialogHelper.Config(hint = HINT_CHECK_USAGE),
uiModificationCallback = { uiModificationCallback = {
it.hintTv.setTextColor(ContextCompat.getColor(context, R.color.text_theme)) it.hintTv.setTextColor(ContextCompat.getColor(context, R.color.text_theme))

View File

@ -26,6 +26,7 @@ import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.alibaba.android.arouter.launcher.ARouter; 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.R;
import com.gh.gamecenter.common.callback.BiCallback; import com.gh.gamecenter.common.callback.BiCallback;
import com.gh.gamecenter.common.constant.EntranceConsts; import com.gh.gamecenter.common.constant.EntranceConsts;
@ -264,17 +265,10 @@ public class ShareUtils {
//检查是否安装手机QQ //检查是否安装手机QQ
public static boolean isQQClientAvailable(Context context) { public static boolean isQQClientAvailable(Context context) {
IPackageUtilsProvider packageUtilsConfig = (IPackageUtilsProvider) ARouter.getInstance().build(RouteConsts.provider.packageUtils).navigation(); IPackageUtilsProvider packageUtilsImpl = (IPackageUtilsProvider) ARouter.getInstance().build(RouteConsts.provider.packageUtils).navigation();
List<PackageInfo> pinfo = packageUtilsConfig.getInstalledPackages(context, 0);
if (pinfo != null) { return packageUtilsImpl.isInstalledWithLauncherIcon(context, "com.tencent.mobileqq")
for (int i = 0; i < pinfo.size(); i++) { || packageUtilsImpl.isInstalledWithLauncherIcon(context, "com.tencent.tim");
String pn = pinfo.get(i).packageName;
if ("com.tencent.mobileqq".equals(pn) || "com.tencent.tim".equals(pn)) {
return true;
}
}
}
return false;
} }
// 邀请好友(专属链接) // 邀请好友(专属链接)

View File

@ -12,6 +12,8 @@ interface IPackageUtilsProvider : IProvider {
fun getGhVersionCode(): Int fun getGhVersionCode(): Int
fun isInstalledWithLauncherIcon(context: Context, packageName: String): Boolean
fun getInstalledPackages(context: Context, flag: Int): List<PackageInfo> fun getInstalledPackages(context: Context, flag: Int): List<PackageInfo>
fun getApkSignatureByPackageName(context: Context, packageName: String): Array<String> fun getApkSignatureByPackageName(context: Context, packageName: String): Array<String>