Android 安卓:我的应用程序太大了,并且给出了;无法执行dex:method ID不在[0,0xffff]:65536“中?”;?

Android 安卓:我的应用程序太大了,并且给出了;无法执行dex:method ID不在[0,0xffff]:65536“中?”;?,android,dalvik,dx,Android,Dalvik,Dx,我正在尝试将我的应用程序与Box、Dropbox和Google Drive集成。所有这三项服务都需要许多第三方JAR。此外,我的应用程序已经需要一些第三方JAR。现在,当我尝试从eclipse运行应用程序时,出现以下错误: 无法执行dex:method ID不在[0,0xffff]:65536转换中 转换Dalvik格式失败:无法执行[0]中的dex:method ID, 0xffff]:65536 似乎发生此错误是因为我的应用程序有太多的方法。我相当确定这些方法大部分来自第三方JAR,因此试图

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

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

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

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

  • 使用多个dex文件,如下所述:。这似乎是唯一的选择,但我不明白它如何适用于我的情况。问题是像Drive这样的服务有太多的依赖项。这个解决方案不要求我修改驱动器源代码,以便在引用其依赖项时使用拐点吗?(这显然不是一种选择)

  • 使用proguard收缩删除未使用的代码/方法。使用proguard导出我的应用程序确实有效,文档服务集成在>4.0设备上也能按预期工作。但是,在2.3设备上测试时会抛出classnotfound错误


  • 所以,我希望在这个问题上能得到一些建议。选项2是我的案例的解决方案吗?是否存在另一个我应该考虑的解决方案?

    < P> Delvik VM每一个DEX文件最多可以有65536种方法,这是因为字节码指令集没有方法引用多于16位的方法数(如注释中的“@丹弗斯指出的”)。
    虽然可以使用多个dex文件修复此问题,但Facebook表示,他们可以在应用程序中部署这些文件来解决此问题。

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

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

    #定义默认的最大长度(5*1024*1024)

    LinearAllocHdr*pHdr

    pHdr->mapleLength=默认最大长度

    我想“Facebook补丁”是通过使用本机C指针来编辑这个内存的。
    IMHO LinearAlloc问题和这个方法ID问题是不同的事情。

    我最近遇到了这个问题。在浏览web以获得更详细的实现后,我意识到除了以下内容之外,没有其他内容:

    • 很好,但现在Gradle已经在了,有点过时了:
    • 没有太多细节,但对如何做到这一点有一个模糊的想法:
    我意识到问题不一定是我的代码中有太多的方法,而是我的代码和其他库的完整
    dex
    。因此,如果我可以针对库编译代码,但不将它们包含在
    classes.dex
    中,然后将
    dex
    库分开,然后在运行时将它们放在一起,那么应该可以工作。唯一需要解决的问题是类加载器,Facebook顺便提到了它

    因此,通过一些反思和一些Groovy代码,我认为我找到了一种相对稳定的方法,将库和应用程序代码打包到单独的
    dex
    文件中

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

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

    ***新****所有其他答案现在都过时了。这是新的解决方案 安卓5.0及更高版本 从文档中:

    Android 5.0及更高版本使用一个名为ART的运行时,该运行时在本地 支持从应用程序APK文件加载多个dex文件。艺术 在应用程序安装时执行预编译,扫描 类(…N).dex文件,并将其编译为单个.oat文件,以便 由Android设备执行。更多关于Android的信息 5.0运行时,请参见介绍艺术

    低于安卓5.0


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

    接下来,您只能使用所需的零件。这可能会解决问题,避免一些黑魔法,或者使用多重索引。例如,如果你只想在你的应用程序中使用谷歌地图(而你没有使用广告、钱包、谷歌服装、分析等等),那么使用整个依赖关系就是浪费时间/空间。您可以这样使用它:

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

    您可以在

    中阅读整个“部件”列表,您需要为此启用Dex支持。因此,您需要执行以下步骤:

  • Android的Gradle插件v0.14.0增加了对多索引的支持。要启用,只需在build.gradle中声明:
  • 如果应用程序支持>5.0(即,如果您的MinSDK版本为20或更低),您还必须动态修补应用程序类加载器,以便它能够从辅助索引加载类。为此,您可以添加此库
  • 在具有这些选项的代码中启用。乔斯
    compile com.google.android.gms:play-services-base:6.5.87
    compile com.google.android.gms:play-services-maps:6.5.87
    
    android {
       defaultConfig {
          ...
          multiDexEnabled = true
       }
    }
    
     dependencies {
          ...
          compile 'com.android.support:multidex:1.0.0'
        }
    
    <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>
    
    public class App extends MultiDexApplication { .. }
    
    public class App {
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(base);
            MultiDex.install(this);
            ..
        }
    
    }