diff --git a/app/src/main/java/com/gh/gamecenter/download/DownloadFragment.kt b/app/src/main/java/com/gh/gamecenter/download/DownloadFragment.kt index 19696baf85..d9db415103 100644 --- a/app/src/main/java/com/gh/gamecenter/download/DownloadFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/download/DownloadFragment.kt @@ -161,6 +161,7 @@ class DownloadFragment : BaseFragment_TabLayout() { val showOnFailed = downloadManagerAd?.displayRule?.onFailedAction == "show" if ((showThirdPartyAd && thirdPartyAd != null) || (!showThirdPartyAd && thirdPartyAd != null && ownerAd == null)) { initThirdPartyAd(downloadManagerAd, thirdPartyAd) { isSuccess -> + if (!isAdded) return@initThirdPartyAd mBinding.maskView.goneIf(!isSuccess) if (!isSuccess && ownerAd != null && showOnFailed) { mSlideInterval = ownerAd.adSource?.sliderInterval ?: -1 @@ -215,7 +216,7 @@ class DownloadFragment : BaseFragment_TabLayout() { } private fun initOwnerAd(adConfig: AdConfig) { - if (adConfig.id.isEmpty()) return + if (!isAdded || adConfig.id.isEmpty()) return mAdGameViewModel = viewModelProvider(AdGameViewModel.Factory(adConfig)) initAdGameBanner(adConfig) mBinding.closeAdIv.setOnClickListener { @@ -249,6 +250,7 @@ class DownloadFragment : BaseFragment_TabLayout() { adConfig.displayRule.onFailedAction == "show" && adConfig.thirdPartyAd != null) { // 自有广告游戏为空时,显示第三方广告 initThirdPartyAd(adConfig, adConfig.thirdPartyAd) { isSuccess -> + if (!isAdded) return@initThirdPartyAd mBinding.maskView.goneIf(!isSuccess) if (isSuccess) { SPUtils.setLong(Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME, System.currentTimeMillis()) diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/SpecialDownloadDialogFragment.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/SpecialDownloadDialogFragment.kt index 1899069c6f..5d0397e049 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/SpecialDownloadDialogFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/SpecialDownloadDialogFragment.kt @@ -394,7 +394,7 @@ class SpecialDownloadDialogFragment : BaseDraggableDialogFragment() { SensorsBridge.trackDownloadComponentsContentClick( gameId = gameEntity.id, gameName = gameEntity.name ?: "unknown", - gameSchemeType = gameEntity.gameBitChinese, + gameSchemaType = gameEntity.gameBitChinese, downloadStatus = gameEntity.downloadStatusChinese, gameType = gameEntity.categoryChinese, downloadType = if (asVGame) "畅玩下载" else "本地下载", @@ -405,7 +405,7 @@ class SpecialDownloadDialogFragment : BaseDraggableDialogFragment() { SensorsBridge.trackDownloadComponentsShow( gameId = gameEntity.id, gameName = gameEntity.name ?: "unknown", - gameSchemeType = gameEntity.gameBitChinese, + gameSchemaType = gameEntity.gameBitChinese, downloadStatus = gameEntity.downloadStatusChinese, gameType = gameEntity.categoryChinese, downloadType = if (asVGame) "畅玩下载" else "本地下载", diff --git a/app/src/main/java/com/gh/gamecenter/hud/HeadUpDisplayLogHelper.kt b/app/src/main/java/com/gh/gamecenter/hud/HeadUpDisplayLogHelper.kt index 0a56e82d4c..ccf25e74ba 100644 --- a/app/src/main/java/com/gh/gamecenter/hud/HeadUpDisplayLogHelper.kt +++ b/app/src/main/java/com/gh/gamecenter/hud/HeadUpDisplayLogHelper.kt @@ -13,7 +13,7 @@ object HeadUpDisplayLogHelper { source = source, downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载", downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE), - gameSchemeType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位", + gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位", gameType = downloadEntity.getMetaExtra(Constants.GAME_CATEGORY_IN_CHINESE), gameId = downloadEntity.gameId, gameName = downloadEntity.name @@ -25,7 +25,7 @@ object HeadUpDisplayLogHelper { source = source, downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载", downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE), - gameSchemeType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位", + gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位", gameType = downloadEntity.getMetaExtra(Constants.GAME_CATEGORY_IN_CHINESE), gameId = downloadEntity.gameId, gameName = downloadEntity.name @@ -36,7 +36,7 @@ object HeadUpDisplayLogHelper { SensorsBridge.trackAutomaticInstallationPromptBarShow( downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载", downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE), - gameSchemeType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位", + gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位", gameType = downloadEntity.getMetaExtra(Constants.GAME_CATEGORY_IN_CHINESE), gameId = downloadEntity.gameId, gameName = downloadEntity.name @@ -47,7 +47,7 @@ object HeadUpDisplayLogHelper { SensorsBridge.trackAutomaticInstallationPromptBarClick( downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载", downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE), - gameSchemeType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位", + gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位", gameType = downloadEntity.getMetaExtra(Constants.GAME_CATEGORY_IN_CHINESE), gameId = downloadEntity.gameId, gameName = downloadEntity.name diff --git a/app/src/main/java/com/gh/ndownload/suspendwindow/NDownloadDrawOverlayPermissionWindowController.kt b/app/src/main/java/com/gh/ndownload/suspendwindow/NDownloadDrawOverlayPermissionWindowController.kt index f854d8a263..b9a78fca0d 100644 --- a/app/src/main/java/com/gh/ndownload/suspendwindow/NDownloadDrawOverlayPermissionWindowController.kt +++ b/app/src/main/java/com/gh/ndownload/suspendwindow/NDownloadDrawOverlayPermissionWindowController.kt @@ -3,7 +3,6 @@ package com.gh.ndownload.suspendwindow import android.app.Activity import android.app.Application import android.app.Application.ActivityLifecycleCallbacks -import android.os.Build import android.os.Bundle import androidx.core.view.ViewCompat import com.gh.gamecenter.common.constant.Constants @@ -128,7 +127,7 @@ class NDownloadDrawOverlayPermissionWindowController(val application: Applicatio SensorsBridge.trackDownloadSuspendedWindowGuideShow( gameId = downloadEntity.gameId, gameName = downloadEntity.name, - gameSchemeType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位", + gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位", gameType = downloadEntity.categoryChinese, downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE), downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载" diff --git a/app/src/main/java/com/gh/ndownload/suspendwindow/window/NDownloadSuspendWindow.kt b/app/src/main/java/com/gh/ndownload/suspendwindow/window/NDownloadSuspendWindow.kt index 7bd8fe77f7..09c08457ba 100644 --- a/app/src/main/java/com/gh/ndownload/suspendwindow/window/NDownloadSuspendWindow.kt +++ b/app/src/main/java/com/gh/ndownload/suspendwindow/window/NDownloadSuspendWindow.kt @@ -48,10 +48,17 @@ abstract class NDownloadSuspendWindow( fun attach() { if (!isAttached) { - _isAttached = true - windowManager.addView(root, layoutParams) - context.registerComponentCallbacks(this) - onAttach() + try { + _isAttached = true + windowManager.addView(root, layoutParams) + context.registerComponentCallbacks(this) + onAttach() + } catch (e: Throwable) { + // 处理“Unable to add window android.view.ViewRootImpl$W@7bc9502 -- permission denied for window type 2038”的异常 + // 目前Sentry上仅Z10型号的手机报这个错误(Android 8.1.0),这里明明已经授予了SYSTEM_ALERT_WINDOW权限,但是就是会抛异常= =,只能暴力捕获处理了。。。 + // 相关异常的链接:https://sentry.shanqu.cc/organizations/lightgame/issues/407275/?project=22 + _isAttached = false + } } } diff --git a/build.gradle b/build.gradle index 8a74f34674..ab8efc0edc 100644 --- a/build.gradle +++ b/build.gradle @@ -17,8 +17,8 @@ buildscript { password("u9gZYH4MQEwLLQZK") } } - maven { url 'https://jitpack.io' } maven { url "https://maven.google.com" } + maven { url 'https://jitpack.io' } } dependencies { @@ -41,7 +41,6 @@ allprojects { google() jcenter() mavenCentral() - maven { url 'https://jitpack.io' } maven { url 'https://maven.aliyun.com/repository/public' } maven { url 'https://maven.aliyun.com/repository/central'} maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases/' } @@ -55,6 +54,7 @@ allprojects { // 配置HMS Core SDK的Maven仓地址。 maven { url 'https://developer.huawei.com/repo/' } maven { url 'https://developer.hihonor.com/repo' } + maven { url 'https://jitpack.io' } } } task clean(type: Delete) { diff --git a/module_common/src/main/java/com/gh/gamecenter/common/utils/SensorsBridge.kt b/module_common/src/main/java/com/gh/gamecenter/common/utils/SensorsBridge.kt index 73f07e3bf5..3f6fd9e799 100644 --- a/module_common/src/main/java/com/gh/gamecenter/common/utils/SensorsBridge.kt +++ b/module_common/src/main/java/com/gh/gamecenter/common/utils/SensorsBridge.kt @@ -26,7 +26,7 @@ object SensorsBridge { private const val KEY_LAST_PAGE_BUSINESS_ID = "last_page_business_id" private const val KEY_DOWNLOAD_STATUS = "download_status" private const val KEY_DOWNLOAD_TYPE = "download_type" - private const val KEY_GAME_SCHEME_TYPE = "game_scheme_type" + private const val KEY_GAME_SCHEMA_TYPE = "game_schema_type" private const val KEY_GAME_TYPE = "game_type" const val KEY_POSITION = "position" const val KEY_TAB_CONTENT = "tab_content" @@ -4013,7 +4013,7 @@ object SensorsBridge { * 触发时机:当下载悬浮窗引导图展示时触发上报 * @param gameId 游戏ID * @param gameName 游戏名称 - * @param gameSchemeType 游戏架构类型:64位/32位 + * @param gameSchemaType 游戏架构类型:64位/32位 * @param downloadStatus 游戏下载状态 * @param gameType 游戏的类型:单机、网游等 * @param downloadType 实际下载方式:本地下载/畅玩下载 @@ -4022,7 +4022,7 @@ object SensorsBridge { fun trackDownloadSuspendedWindowGuideShow( gameId: String, gameName: String, - gameSchemeType: String, + gameSchemaType: String, downloadStatus: String, gameType: String, downloadType: String @@ -4030,7 +4030,7 @@ object SensorsBridge { val json = json { KEY_GAME_ID to gameId KEY_GAME_NAME to gameName - KEY_GAME_SCHEME_TYPE to gameSchemeType + KEY_GAME_SCHEMA_TYPE to gameSchemaType KEY_DOWNLOAD_STATUS to downloadStatus KEY_GAME_TYPE to gameType KEY_DOWNLOAD_TYPE to downloadType @@ -4070,7 +4070,7 @@ object SensorsBridge { * @param source 来源:游戏下载\重启APP * @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载 * @param downloadStatus 所上报游戏下载状态 - * @param gameSchemeType 所上报游戏架构类型:64位/32位 + * @param gameSchemaType 所上报游戏架构类型:64位/32位 * @param gameType 游戏的类型:单机、网游等 * @param gameId 游戏ID * @param gameName 游戏名称 @@ -4079,7 +4079,7 @@ object SensorsBridge { source: String, downloadType: String, downloadStatus: String, - gameSchemeType: String, + gameSchemaType: String, gameType: String, gameId: String, gameName: String @@ -4088,7 +4088,7 @@ object SensorsBridge { KEY_SOURCE to source KEY_DOWNLOAD_TYPE to downloadType KEY_DOWNLOAD_STATUS to downloadStatus - KEY_GAME_SCHEME_TYPE to gameSchemeType + KEY_GAME_SCHEMA_TYPE to gameSchemaType KEY_GAME_TYPE to gameType KEY_GAME_ID to gameId KEY_GAME_NAME to gameName @@ -4103,7 +4103,7 @@ object SensorsBridge { * @param source 来源:游戏下载\重启APP * @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载 * @param downloadStatus 所上报游戏下载状态 - * @param gameSchemeType 所上报游戏架构类型:64位/32位 + * @param gameSchemaType 所上报游戏架构类型:64位/32位 * @param gameType 游戏的类型:单机、网游等 * @param gameId 游戏ID * @param gameName 游戏名称 @@ -4112,7 +4112,7 @@ object SensorsBridge { source: String, downloadType: String, downloadStatus: String, - gameSchemeType: String, + gameSchemaType: String, gameType: String, gameId: String, gameName: String @@ -4121,7 +4121,7 @@ object SensorsBridge { KEY_SOURCE to source KEY_DOWNLOAD_TYPE to downloadType KEY_DOWNLOAD_STATUS to downloadStatus - KEY_GAME_SCHEME_TYPE to gameSchemeType + KEY_GAME_SCHEMA_TYPE to gameSchemaType KEY_GAME_TYPE to gameType KEY_GAME_ID to gameId KEY_GAME_NAME to gameName @@ -4135,7 +4135,7 @@ object SensorsBridge { * 触发时机:触发自动下载提示条展示时上报 * @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载 * @param downloadStatus 所上报游戏下载状态 - * @param gameSchemeType 所上报游戏架构类型:64位/32位 + * @param gameSchemaType 所上报游戏架构类型:64位/32位 * @param gameType 游戏的类型:单机、网游等 * @param gameId 游戏ID * @param gameName 游戏名称 @@ -4143,7 +4143,7 @@ object SensorsBridge { fun trackAutomaticInstallationPromptBarShow( downloadType: String, downloadStatus: String, - gameSchemeType: String, + gameSchemaType: String, gameType: String, gameId: String, gameName: String @@ -4151,7 +4151,7 @@ object SensorsBridge { val json = json { KEY_DOWNLOAD_TYPE to downloadType KEY_DOWNLOAD_STATUS to downloadStatus - KEY_GAME_SCHEME_TYPE to gameSchemeType + KEY_GAME_SCHEMA_TYPE to gameSchemaType KEY_GAME_TYPE to gameType KEY_GAME_ID to gameId KEY_GAME_NAME to gameName @@ -4165,7 +4165,7 @@ object SensorsBridge { * 触发时机:触发自动下载提示条点击时上报 * @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载 * @param downloadStatus 所上报游戏下载状态 - * @param gameSchemeType 所上报游戏架构类型:64位/32位 + * @param gameSchemaType 所上报游戏架构类型:64位/32位 * @param gameType 游戏的类型:单机、网游等 * @param gameId 游戏ID * @param gameName 游戏名称 @@ -4173,7 +4173,7 @@ object SensorsBridge { fun trackAutomaticInstallationPromptBarClick( downloadType: String, downloadStatus: String, - gameSchemeType: String, + gameSchemaType: String, gameType: String, gameId: String, gameName: String @@ -4181,7 +4181,7 @@ object SensorsBridge { val json = json { KEY_DOWNLOAD_TYPE to downloadType KEY_DOWNLOAD_STATUS to downloadStatus - KEY_GAME_SCHEME_TYPE to gameSchemeType + KEY_GAME_SCHEMA_TYPE to gameSchemaType KEY_GAME_TYPE to gameType KEY_GAME_ID to gameId KEY_GAME_NAME to gameName @@ -4195,7 +4195,7 @@ object SensorsBridge { * 触发时机:下载组件展示时上报 * @param gameId 游戏ID * @param gameName 游戏名称 - * @param gameSchemeType 游戏架构类型:64位/32位 + * @param gameSchemaType 游戏架构类型:64位/32位 * @param downloadStatus 所上报游戏下载状态 * @param gameType 游戏的类型:单机、网游等 * @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载 @@ -4203,7 +4203,7 @@ object SensorsBridge { fun trackDownloadComponentsShow( gameId: String, gameName: String, - gameSchemeType: String, + gameSchemaType: String, downloadStatus: String, gameType: String, downloadType: String, @@ -4211,7 +4211,7 @@ object SensorsBridge { val json = json { KEY_GAME_ID to gameId KEY_GAME_NAME to gameName - KEY_GAME_SCHEME_TYPE to gameSchemeType + KEY_GAME_SCHEMA_TYPE to gameSchemaType KEY_DOWNLOAD_STATUS to downloadStatus KEY_GAME_TYPE to gameType KEY_DOWNLOAD_TYPE to downloadType @@ -4225,7 +4225,7 @@ object SensorsBridge { * 触发时机:下载组件点击时上报 * @param gameId 游戏ID * @param gameName 游戏名称 - * @param gameSchemeType 游戏架构类型:64位/32位 + * @param gameSchemaType 游戏架构类型:64位/32位 * @param downloadStatus 所上报游戏下载状态 * @param gameType 游戏的类型:单机、网游等 * @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载 @@ -4235,7 +4235,7 @@ object SensorsBridge { fun trackDownloadComponentsContentClick( gameId: String, gameName: String, - gameSchemeType: String, + gameSchemaType: String, downloadStatus: String, gameType: String, downloadType: String, @@ -4245,7 +4245,7 @@ object SensorsBridge { val json = json { KEY_GAME_ID to gameId KEY_GAME_NAME to gameName - KEY_GAME_SCHEME_TYPE to gameSchemeType + KEY_GAME_SCHEMA_TYPE to gameSchemaType KEY_DOWNLOAD_STATUS to downloadStatus KEY_GAME_TYPE to gameType KEY_DOWNLOAD_TYPE to downloadType diff --git a/module_core/src/main/java/com/gh/gamecenter/core/utils/ProcessUtil.java b/module_core/src/main/java/com/gh/gamecenter/core/utils/ProcessUtil.java index 7bff86d457..6562c4762d 100644 --- a/module_core/src/main/java/com/gh/gamecenter/core/utils/ProcessUtil.java +++ b/module_core/src/main/java/com/gh/gamecenter/core/utils/ProcessUtil.java @@ -6,6 +6,8 @@ import android.text.TextUtils; import androidx.annotation.Nullable; +import java.io.BufferedReader; +import java.io.FileReader; import java.lang.reflect.Method; public class ProcessUtil { @@ -20,13 +22,25 @@ public class ProcessUtil { return currentProcessName; } - //1)通过Application的API获取当前进程名 + //0)通过反射 ActivityThread 获取实例再获取当前进程名 + currentProcessName = getCurrentProcessNameByActivityThreadInstance(); + if (!TextUtils.isEmpty(currentProcessName)) { + return currentProcessName; + } + + //1)通过 CMD 获取当前进程名 + currentProcessName = getCurrentProcessNameByCMD(android.os.Process.myPid()); + if (!TextUtils.isEmpty(currentProcessName)) { + return currentProcessName; + } + + //2)通过 Application 的 API 获取当前进程名 currentProcessName = getCurrentProcessNameByApplication(); if (!TextUtils.isEmpty(currentProcessName)) { return currentProcessName; } - //2)通过反射ActivityThread获取当前进程名 + //3)通过反射 ActivityThread 获取当前进程名 currentProcessName = getCurrentProcessNameByActivityThread(); if (!TextUtils.isEmpty(currentProcessName)) { return currentProcessName; @@ -38,7 +52,7 @@ public class ProcessUtil { /** * 通过Application新的API获取进程名,无需反射,无需IPC,效率最高。 */ - public static String getCurrentProcessNameByApplication() { + private static String getCurrentProcessNameByApplication() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { return Application.getProcessName(); } @@ -48,7 +62,7 @@ public class ProcessUtil { /** * 通过反射ActivityThread获取进程名,避免了ipc */ - public static String getCurrentProcessNameByActivityThread() { + private static String getCurrentProcessNameByActivityThread() { String processName = null; try { final Method declaredMethod = Class.forName("android.app.ActivityThread", false, Application.class.getClassLoader()) @@ -64,4 +78,52 @@ public class ProcessUtil { return processName; } + private static String getCurrentProcessNameByActivityThreadInstance() { + try { + // Get ActivityThread class + Class activityThreadClass = Class.forName("android.app.ActivityThread",false, Application.class.getClassLoader()); + + // Get the current ActivityThread instance + Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread"); + currentActivityThreadMethod.setAccessible(true); + Object activityThread = currentActivityThreadMethod.invoke(null); + + // Get the getProcessName method + Method getProcessNameMethod = activityThreadClass.getDeclaredMethod("getProcessName"); + getProcessNameMethod.setAccessible(true); + + // Call the getProcessName method + return (String) getProcessNameMethod.invoke(activityThread); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private static String getCurrentProcessNameByCMD(int pid) { + //get from /proc/PID/cmdline + BufferedReader br = null; + try { + br = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline")); + String processName = br.readLine(); + if (!TextUtils.isEmpty(processName)) { + processName = processName.trim(); + if (!TextUtils.isEmpty(processName)) { + return processName; //OK + } + } + } catch (Exception ignored) { + + } finally { + try { + if (br != null) { + br.close(); + } + } catch (Exception ignored) { + } + } + //failed + return null; + } + } \ No newline at end of file diff --git a/vasdk b/vasdk index f932da435f..ff118306e4 160000 --- a/vasdk +++ b/vasdk @@ -1 +1 @@ -Subproject commit f932da435fa254d1529aff61543ff5a7b8231e1a +Subproject commit ff118306e45c1044683bcded38df6bdf4d9465fa