【Android】Apk图标的提取、相同目录下相同包名提取的不同图标apk但是提取结果相同的bug解决

一般安卓提取apk图标我们有两种常用方法:

1、如果已经获取到 ApplicationInfo 对象(假设名为 appInfo),那么我们获取方法为:

appInfo.loadIcon(packageManager)// 返回一个 Drawable 对象

2、 如果还没获取到 ApplicationInfo 对象,我们一般会先获取 packageInfo 对象,然后通过它来获取 ApplicationInfo 对象,

但是这个方法会存在一个 bug ,就是需要设置 sourceDir 、publicSourceDir 两个源路径属性之后才能正常获取到图标。

然后设置上面两个属性之后,如果设置图标之后,相同包名,但是图标不相同的,就会导致后续获取的图标都相同,也就是说,包名相同图标不同,但是获取到的图标竟然都相同!

初步分析,原因应该出现在包名、两个源路径身上。
这应该是 Android SDK 自己写 loadIcon 代码的时候也没考虑过的使用情况。
可能是包名作为类似 Key 之类的,然后通过包名找到源路径,然后通过源路径获取图标。
所以如果获取一次之后,只设置源路径而不修改包名,那么获取的将是旧的源路径对应的图标。

在这里插入图片描述

为了解决这个问题,以下是我改良之后的 Kotlin 代码

fun getAppIconFromApkPath(context: Context, apkFilePath: String): Drawable? {
	// 1. 获取 包管理器,并通过包管理器、apk 路径获取 packageInfo 
    val packageManager: PackageManager = context.packageManager
    val packageInfo = packageManager.getPackageArchiveInfo(
        apkFilePath,
        0//PackageManager.GET_ACTIVITIES//GET_META_DATA
    )
    // 2. 访问、修改 packageInfo 对象的 applicationInfo 对象里面一些属性,比如packageName、sourceDir、publicSourceDir、loadIcon
    packageInfo?.applicationInfo?.apply {
        // 2.1. 【关键步骤】设置 包名
        val oldPackageName = packageName// 保存旧的包名,因为下面获取 apk 图标之后要恢复
        packageName = apkFilePath// 将其包名改成一个任意的、唯一的其他字符串,这样获取到的图标才不会冲突
        // 2.2. 【必须步骤】设置源路径:设置sourceDir和publicSourceDir属性为APK文件的路径。这样可以确保加载的是APK文件中的资源,而不是系统资源。
        sourceDir = apkFilePath
        publicSourceDir = apkFilePath// 设置这两个路径之后,同时也会把相关包名的文件设置。所以会导致已安装的和其他文件图标不一样!!!

        // 2.3. 通过 loadIcon 来获取 apk 图标
        val icon = loadIcon(packageManager)

        // 2.4. 【关键步骤】获取到图标之后,先恢复前面修改的包名、源路径,最后才能返回图标
        packageName = oldPackageName// 恢复成原来的包名(修改之前的)
        sourceDir = null// 并且把其他的数据还原为null
        publicSourceDir = null

        // 2.5. 最后返回获取到的图标
        return icon
    }
    return null
}

注意:以上只是个人测试代码,不保证没有其他结果。其他情况请自行测试!

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-12 07:48:06       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-12 07:48:06       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-12 07:48:06       82 阅读
  4. Python语言-面向对象

    2024-05-12 07:48:06       91 阅读

热门阅读

  1. C++Primer Plus第三章编程练习4

    2024-05-12 07:48:06       28 阅读
  2. Node.js -- 会话控制

    2024-05-12 07:48:06       32 阅读
  3. iOS 如何让超出父视图的部分响应事件

    2024-05-12 07:48:06       34 阅读
  4. 电商平台遭遇DDOS、CC攻击有什么防护方案

    2024-05-12 07:48:06       29 阅读
  5. Lucene 英文词根处理

    2024-05-12 07:48:06       32 阅读
  6. 十分钟“手撕”内部类+static在内部类的使用

    2024-05-12 07:48:06       35 阅读
  7. react经验15:拖拽排序组件dnd-kit的使用经验

    2024-05-12 07:48:06       34 阅读
  8. vue.js 介绍

    2024-05-12 07:48:06       31 阅读
  9. React Router DOM BrowserRouter

    2024-05-12 07:48:06       36 阅读
  10. Pycharm所有快捷键的使用

    2024-05-12 07:48:06       25 阅读
  11. 【DevOps】Linux 网络命令netstat详解

    2024-05-12 07:48:06       30 阅读
  12. ensp简单ac+ap+sta无线配置和脚本

    2024-05-12 07:48:06       25 阅读
  13. ubuntu删除opencv

    2024-05-12 07:48:06       29 阅读
  14. 华为OD介绍

    2024-05-12 07:48:06       30 阅读