24

我正在尝试将我的应用程序与 Box、Dropbox 和 Google Drive 集成。所有这 3 项服务都需要许多 3rd 方 jar。此外,我的应用程序已经需要一些 3rd 方 jar。现在,当我尝试从 eclipse 运行我的应用程序时,出现以下错误:

无法执行 dex:方法 ID 不在 [0, 0xffff] 中:65536 转换为 Dalvik 格式失败:无法执行 dex:方法 ID 不在 [0, 0xffff] 中:65536

似乎发生此错误是因为我的应用程序有太多方法。我相当肯定这些方法中的大部分来自第 3 方 jar,因此尝试通过简化我的代码来解决这个问题是不现实的。我在网上找到了这两个建议。

  1. 添加dex.force.jumbo=true到 project.properties(并使用 adt 版本 21)。我这样做了,但仍然得到错误。

  2. 使用多个 dex 文件,如下所述:http ://android-developers.blogspot.co.il/2011/07/custom-class-loading-in-dalvik.html 。这似乎可能是唯一的选择,但我不明白它如何适用于我的情况。问题是像 Drive 这样的服务有太多的依赖关系。在引用其依赖项时,此解决方案是否不需要我修改 Drive 源以使用变形?(这显然不是一种选择)。

  3. 使用 proguard 缩小删除未使用的代码/方法。使用 proguard 导出我的应用程序确实有效,并且文档服务集成在 >4.0 设备上按预期工作。但是,在 2.3 设备上进行测试时会引发 classnotfound 错误。

所以,我希望对这个问题有一些建议。选项 2 是我的情况的解决方案吗?我应该考虑另一种解决方案吗?

4

8 回答 8

14

您还可以将其中的一个或多个开发为您的主应用程序的插件,以可供下载的单独 APK 的形式。该 APK 会暴露一些主应用程序将使用的组件——因为我不知道您与这些服务集成的性质,所以我无法对此提出更具体的建议。您将使用自己的signature自定义级别<permission>来保护两个应用程序之间的通信。而且,作为奖励,如果使用第三方库增加了对额外权限的要求,您只需要插件 APK 中的这些权限,从而使您的主 APK 更小。

于 2013-03-19T20:09:16.193 回答
7

***新****所有其他答案现在都已过时。这是新的修复

Android 5.0 及更高版本

自动包含多 dex 支持。从文档:

Android 5.0 及更高版本使用名为 ART 的运行时,它本机支持从应用程序 APK 文件加载多个 dex 文件。ART 在应用程序安装时执行预编译,扫描 classes(..N).dex 文件并将它们编译为单个 .oat 文件以供 Android 设备执行。有关 Android 5.0 运行时的更多信息,请参阅 ART 简介。

安卓5.0以下

只需将 Android 多 dex 支持工具添加到您的 gradle 构建中:

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.0'
}
于 2015-01-10T05:02:48.100 回答
6

Dalvik VM 每个 dex 文件最多可以有 65536 个方法,因为字节码指令集无法引用需要超过 16 位的方法号(正如 @danfuzz 在评论中指出的那样)。

虽然可以使用多个 dex 文件来解决这个问题,但 Facebook发现了另一个可以部署在他们的应用程序中的修复程序来解决这个问题。

于 2013-03-19T19:18:07.970 回答
5

请参阅 vm/LinearAlloc.c ,您可以找到以下代码:(Android 2.3.3 下为 5MiB,Android 4.0 后为 8MiB 作为我的调查)

#define DEFAULT_MAX_LENGTH (5*1024*1024)

...

线性AllocHdr* pHdr;

...

pHdr->mapLength = DEFAULT_MAX_LENGTH;

我想“Facebook 修复”正在使用本机 C 指针编辑此内存。恕我直言,LinearAlloc 问题和这个方法 ID 问题是不同的。

于 2013-07-10T02:50:13.533 回答
3

我最近遇到了这个问题。在网上搜索了一些更详细的实现之后,我意识到除了:

我意识到问题不一定是我的代码中有太多方法,而是dex我的代码和其他库的完整问题。因此,如果我可以针对库编译我的代码但不将它们包含在classes.dex, 然后dex将库单独包含在内,然后在运行时将它们全部放在一起,它应该可以工作。唯一需要解决的问题是类加载器,Facebook 顺便提到了这个问题。

所以通过一点反思和一些 Groovy 代码,我想我想出了一个相对稳定的方法来将库和应用程序代码打包到单独的dex文件中。

https://gist.github.com/nickcaballero/7045993

于 2013-10-18T18:33:06.727 回答
1

达到 65k 方法限制的大多数问题与在您的应用程序中使用乳牙 Google Play 服务有关。最近,你在使用它时可以获得更多的粒度。

按照本指南,您可以只使用您想要的部分。可能这会解决问题,避免一些黑魔法,或者使用 multiDex。例如,如果您只希望在您的应用程序中使用 Google 地图(并且您没有使用广告、钱包、Google Wear、分析等),那么使用整个依赖项就是浪费时间/空间。你可以这样使用它:

compile com.google.android.gms:play-services-base:6.5.87
compile com.google.android.gms:play-services-maps:6.5.87

您可以在此链接中阅读“部件”的完整列表

于 2015-02-10T14:54:48.443 回答
0

是我编写的一个脚本,用于计算特定文件夹的每个 jar(以及总数)中的方法数。

一旦计算了方法,您就可以专注于重构和删除繁重的库。

于 2014-07-28T09:13:45.490 回答
0

您需要为此启用 Dex 支持。因此,您需要执行以下步骤:

  1. 适用于 Android 的 Gradle 插件 v0.14.0 增加了对 multi-dex 的支持。要启用,您只需在 build.gradle 中声明它:
android {
   defaultConfig {
      ...
      multiDexEnabled = true
   }
}
  1. 如果应用支持 > 5.0(也就是说,如果您的 minSdkVersion 为 20 或更低),您还必须动态修补应用程序 ClassLoader,以便它能够从辅助 dex 加载类。为此,您可以添加此库。
 dependencies {
      ...
      compile 'com.android.support:multidex:1.0.0'
    }
  1. 在代码中启用您有这些选项。选择最适合您的

A. 在 manifest manifest 中添加 MultiDexApplication

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.multidex.App"> <application
android:name="android.support.multidex.MultiDexApplication">
</application>
</manifest>

B. 通过 MultiDexApplication 扩展应用程序

public class App extends MultiDexApplication { .. }

C. 在附加基础上下文的应用程序中安装它。

public class App {
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
        ..
    }

}

有关更多信息,请通过此链接MultiDex

于 2016-05-04T18:44:18.407 回答