Android Studio:getAppName函数仅部分返回应用真实名称问题求助
问题分析与解决方案
你的getAppName函数本身实现无问题,无法获取多数应用名称的核心原因是Android的包可见性限制和应用状态异常,具体如下:
核心原因
- Android 11+包可见性限制:从Android 11(API 30)开始,系统默认限制应用访问其他应用的包信息,仅明确声明的应用或系统核心应用(如Gallery、Settings)允许被查询,这是你只能获取少数应用名称的主要原因。
- 应用状态异常:
UsageStats可能包含已卸载应用的残留数据、被禁用的应用,这类应用的ApplicationInfo无法正常获取,会触发NameNotFoundException,从而返回包名。 - 统计逻辑隐患:用应用名称作为
appTimeMap的key,可能出现不同包名对应同一应用名称的情况,导致统计数据被错误合并。
解决方案
1. 配置包可见性(Android 11+)
在AndroidManifest.xml中添加对应配置:
如果你的应用属于屏幕时间工具这类合规场景,可直接申请全包查询权限:
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
若只需访问特定类别应用,可通过queries标签声明:
<queries> <intent> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent> </queries>
2. 优化getAppName函数,处理应用状态
修改函数以规避空指针、权限异常,并检查应用启用状态:
private fun getAppName(packageName: String): String { val context = context ?: return packageName return try { val pm = context.packageManager val applicationInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA) // 仅对启用的应用返回名称,禁用应用返回包名 if (applicationInfo.enabled) { pm.getApplicationLabel(applicationInfo).toString() } else { packageName } } catch (e: PackageManager.NameNotFoundException) { packageName } catch (e: SecurityException) { // 权限不足时返回包名 packageName } }
3. 修正统计逻辑的key冲突问题
不要用应用名称作为Map的key,改用包名作为唯一标识,展示时再转换为应用名称:
private fun getUsageStats(): Map<String, Long> { val endTime = System.currentTimeMillis() val beginTime = endTime - 1000 * 60 * 60 * 24 // 1 day val usageStatsList = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, beginTime, endTime) val appTimeMap = mutableMapOf<String, Long>() for (usageStat in usageStatsList) { val totalTimeInForeground = usageStat.totalTimeInForeground if (totalTimeInForeground > 0) { // 用包名作为key,避免名称重复导致的数据合并错误 appTimeMap[usageStat.packageName] = appTimeMap.getOrDefault(usageStat.packageName, 0) + totalTimeInForeground } } return appTimeMap }
4. 额外注意事项
- 确保应用已获取
PACKAGE_USAGE_STATS权限,该权限需引导用户前往系统设置手动授予(通过Settings.ACTION_USAGE_ACCESS_SETTINGS跳转)。 - 对于系统预装的禁用应用,即使拥有包可见性权限,也可能无法获取应用名称,属于系统限制,只能返回包名。
内容的提问来源于stack exchange,提问作者Chua Jun Yu
相关产品推荐
相关产品推荐

