You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 01:37:02