【问题标题】:How can I make android delete old native libraries?如何让 android 删除旧的原生库?
【发布时间】:2013-05-08 20:55:29
【问题描述】:

我正在尝试从我的应用程序中删除一些本机库,因为我不再使用它们,但是在我的手机中安装了 apk 后,我可以看到本机库仍然存在。 正如我所看到的,android 确实通过替换我的 libs/ 目录中的文件来正确复制/更新本机库,但显然当它们不在 apk 中时它不会删除它们。 我怎么知道图书馆还在那里?首先,应用程序的大小保持不变,我正在删除一些非常大的库,其次,如果我离开 System.load(...) 语句,应用程序仍然能够加载库。

我找到的唯一解决方案是卸载应用程序并重新安装,但这对于从 google play 更新应用程序的用户来说不是一个明显的解决方案,是的,这个问题严重影响了我的应用程序功能.

我已经检查过了,显然我可以自己删除文件,比如在服务创建期间,但我不想这样弄乱安装。

你知道有没有办法告诉 Android 它需要删除所有原生库并重新复制它们?

谢谢, 迈克

[编辑]

我刚刚发现 GB 正确更新了库,它删除了现在缺失的,但 ICS 和 JB 都没有这样做,即使它们不再在 apk 中,这两个也会留下旧的 .so 文件.

我尝试从 /data/data/mypackage/lib 手动删除 .so 文件,但它不会让我这样做。

有什么想法吗?

【问题讨论】:

  • 您也可以在应用程序上清除数据,但这会清除应用程序私有目录中存储的所有数据。但是这些旧库的存在是如何导致问题的——如果它们不被调用,它们就坐在那里。
  • 听起来您在此设备上安装的 Android 版本可能已损坏。你在模拟器上得到同样的行为吗?一方面,应用程序代码不应该有权修改其 lib/ 文件夹的内容,所以如果可以的话,这本身就表明一些非常不标准的东西。我很好奇,如果您创建一个升级 apk 的长度为零的 .so 文件,该文件与您要清除的文件同名,会发生什么。此外,您可能希望在adb shell 中使用run-as your.package.name 命令,然后在ls -l lib 中查看实际安装的内容。
  • 问题是加载这些库的类不是我的,所以我不能阻止它们从java加载。
  • 如果您的应用程序中的代码试图加载它们,删除它们可能会导致运行时异常。您需要删除依赖于它们的代码,或者使用每个本机方法的假版本制作存根库,这些本机方法什么都不做,每个都以适当的方式。或者全局捕获这些异常并以某种方式恢复。
  • 实际上@ChrisStratton,我没有尝试通过代码删除库,我只是读到它是可能的,但我不想使用该选项。我还尝试用同名的空文件替换 .so 文件,应用程序崩溃并出现“致命信号 7”错误,这在 java 中无法捕获,因为它不是异常。

标签: android android-install-apk


【解决方案1】:

好的,所以我放弃了 android 来做这件事,我必须自己做。我从这里得到了一些提示:http://www.moodstocks.com/2012/03/20/ice-cream-sandwich-why-native-code-support-sucks/

这就是我所做的:

  1. 用文件夹 libs/armeabi、libs/armeabi-v7a 和 libs/x86 的内容制作三个 zip 文件,分别命名为 libs_armeabi.zip、libs_armeabi_v7a.zip 和 libs_x86.zip。

  2. 将 zip 文件移动到 res/raw 文件夹。

  3. 删除三个libs文件夹下的文件并用touch重新创建(在-nix系统中),记住ICS和JB不会删除lib文件夹下的旧文件,所以只删除文件会导致应用保留那些非常大的文件。

  4. 使用以下两种方法以编程方式验证处理器架构:

    public static boolean isArmv7() {
        try {
            return Build.VERSION.SDK_INT >= 4 && Build.class.getField("CPU_ABI").get(null).toString().startsWith("armeabi-v7");
        } catch (Throwable e) {}
    
        return false;
    }
    
    public static boolean isX86() {
        try {
            return Build.VERSION.SDK_INT >= 4 && Build.class.getField("CPU_ABI").get(null).toString().startsWith("x86");
        } catch (Throwable e) {}
    
        return false;
    }
    
  5. 根据处理器架构,以编程方式将三个文件之一解压缩到您想要的任何文件夹,我正在使用 /data/data/myPackage/app_libs(使用 context.getDir("libs",Context.MODE_PRIVATE); 返回该路径)。

这里可能会涉及到更多的逻辑,比如提取 libs_armeabi.zip 文件,然后从 libs_armeabi_v7a.zip 或 libs_x86.zip 中提取文件,或者从它们中提取文件,覆盖具有相同名称的文件(我'我只是在这里徘徊,因为我实际上没有尝试过),幸运的是我的三个文件上的库已经重命名并且在每个 zip 文件中都是专有的,所以我只需要提取三个文件中的一个。

  1. 将 System.loadLibrary 方法调用替换为支持使用完整路径加载库的 System.load,并为每个库添加完整路径。

这种方法有额外的好处:

  • 随着库的压缩,apk 大小将减小,从而使 google play 商店中的应用程序更小。

  • 作为存储在原始资源中的库,android不会自动复制它们,允许您将它们复制到任何你想要的地方并使用完整路径加载它们。

  • 如果需要,您可以决定将库复制到 sd 卡,我不建议这样做,但现在您可以这样做,例如当手机空间不足时。

希望这会有所帮助!

【讨论】:

  • 如果我有一个应用程序我必须确定本机库和支持的本机架构,方法有帮助吗?该应用程序已安装并且我正在使用另一个应用程序来检查构建。我说得通吗?
  • 链接不再有效
【解决方案2】:

本机 lib 目录中的所有文件的所有者都是 System.所以在你的应用中,没有root权限是不能删除这些文件的。

将你的 lib 目录移动到 res/raw,然后手动将它们复制到内部数据是一个不错的选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多