Подтвердить что ты не робот

Android: мое приложение слишком велико и дает "Невозможно выполнить dex: идентификатор метода не в [0, 0xffff]: 65536"?

Я пытаюсь интегрировать свое приложение с Box, Dropbox и Google Диском. Все 3 из этих услуг требуют нескольких сторонних банках. Кроме того, в моем приложении уже требуются несколько сторонних баннеров. Теперь, когда я пытаюсь запустить приложение из eclipse, я получаю следующую ошибку:

Невозможно выполнить идентификатор метода dex: не в [0, 0xffff]: 65536 Преобразование в формат Dalvik не удалось: невозможно выполнить идентификатор метода dex: не в [0, 0xffff]: 65536

Кажется, что эта ошибка возникает из-за того, что в моем приложении слишком много методов. Я довольно уверен, что основная часть этих методов принадлежит сторонним банкам, поэтому нереально попытаться решить эту проблему, упростив мой код. Я нашел эти два предложения в Интернете.

  • добавить dex.force.jumbo=true в project.properties(и использовать adt-версию 21). Я сделал это, но все еще получаю ошибку.

  • Используйте несколько файлов dex, как описано здесь: http://android-developers.blogspot.co.il/2011/07/custom-class-loading-in-dalvik.html. Вероятно, это единственный вариант, но я не понимаю, как это применимо в моем случае. Проблема в том, что такие сервисы, как Drive, имеют слишком много зависимостей. Не будет ли это решение требовать, чтобы я изменил источник Drive, чтобы использовать перегиб при обращении к его зависимостям? (это явно не вариант).

  • Использовать proguard для сжатия удалить неиспользуемый код/​​методы. Экспорт моего приложения с помощью proguard действительно работает, и интеграция служб документов работает как ожидается на устройстве > 4.0. Однако при тестировании на устройстве 2.3 бросаются вызовы classnotfound.

Итак, я надеюсь на некоторые советы по этому вопросу. Является ли вариант 2 решением для моего дела? Есть ли другое решение, которое я должен рассмотреть?

4b9b3361

Ответ 1

Вы также можете разработать один или несколько из них в качестве плагина для вашего основного приложения в виде отдельного APK, доступного для загрузки. То, что APK предоставит какой-то компонент, который будет использовать основное приложение, - поскольку я не знаю характера вашей интеграции с этими службами, я не могу сделать более конкретные рекомендации по этому поводу. Вы должны использовать собственный signature -уровень <permission> для защиты сообщений между двумя приложениями. И в качестве бонуса, если использование сторонней библиотеки добавляет требования к дополнительным разрешениям, вам понадобятся только эти разрешения в APK плагина, чтобы ваш основной APK был меньше.

Ответ 2

У Dalvik VM может быть максимум 65536 методов на файл dex из-за того, что набор команд байт-кода не имеет способа ссылаться на номера методов, требующие более 16 бит (как указано в комментариях @danfuzz).

Хотя это можно исправить, используя несколько файлов dex, Facebook нашел другое исправление, которое они могли бы развернуть в своем приложении, чтобы обойти проблему.

Ответ 3

*** NEW **** Все остальные ответы устарели. Здесь новое исправление

Android 5.0 и выше

Поддержка Multi-Dex включена автоматически. Из документов:

Android 5.0 и выше использует время выполнения, называемое ART, которое изначально поддерживает загрузку нескольких файлов dex из файлов APK приложения. ИЗОБРАЗИТЕЛЬНОЕ ИСКУССТВО выполняет предварительную компиляцию во время установки приложения, которая сканирует классов (..N).dex и скомпилирует их в один файл .oat для исполнение на устройстве Android. Для получения дополнительной информации об Android 5.0, см. Знакомство с ART.

Ниже Android 5.0

Просто добавьте инструмент поддержки многопользовательских файлов Android в свою конструкцию 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'
}

Ответ 4

Смотрите vm/LinearAlloc.c, и вы можете найти этот код: (5MiB под Android 2.3.3, 8MiB после Android 4.0 в качестве моего расследования)

#define DEFAULT_MAX_LENGTH (5 * 1024 * 1024)

...

LinearAllocHdr * pHdr;

...

pHdr- > mapLength = DEFAULT_MAX_LENGTH;

Я полагаю, что "исправление в Facebook" редактирует эту память с помощью встроенного указателя языка C. Проблема IMHO LinearAlloc и эта проблема с идентификатором метода - это другое дело.

Ответ 5

Недавно я столкнулся с этой проблемой. После прочесывания сети для более детальной реализации, я понял, что там было не так много, кроме:

Я понял, что проблема не в том, что в моем коде было слишком много методов, но проблема в том, что полный код dex моего кода и других библиотек был проблемой. Итак, если бы я мог скомпилировать свой код с библиотеками, но не включать их в classes.dex, а затем dex библиотеки отдельно, а затем собрать все вместе во время выполнения, он должен работать. Единственной проблемой, которую нужно решить, является загрузчик классов, о котором Facebook упоминал попутно.

Итак, с небольшим отражением и некоторым кодом Groovy, я думаю, что придумал относительно стабильный способ упаковки библиотек и кода приложения в отдельные файлы dex.

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

Ответ 6

Большинство проблем с ограничением метода 65k связаны с использованием мастодонтических сервисов Google Play в ваших приложениях. В последнее время вы можете получить больше детализации при использовании.

Следуя этому руководству, вы можете использовать только те части, которые вы хотите. Вероятно, это устранит проблему, избегая некоторых трюков с черной магией или используя multiDex. Например, если вы только хотите использовать Карты Google в своем приложении (и вы не используете рекламу, кошелек, одежду, аналитику и т.д.), Использование всей зависимости - пустая трата времени/пространства. Вы можете использовать его таким образом:

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

Вы можете прочитать весь список "частей" в эту ссылку

Ответ 7

Здесь - это script, который я написал для подсчета количества методов в каждом банке (и в целом) для конкретной папки.

Как только вы посчитаете методы, вы можете сосредоточиться на рефакторинге и удалении тяжелых библиотек.

Ответ 8

Вам нужно включить поддержку Dex. Поэтому вам необходимо выполнить следующие действия:

  • Gradle plugin v0.14.0 для Android добавляет поддержку multi-dex. Чтобы включить, просто нужно объявить его в файле build.gradle:
android {
   defaultConfig {
      ...
      multiDexEnabled = true
   }
}
  1. если приложение поддерживает > 5.0 (т.е. если ваш minSdkVersion равен 20 или ниже), вам также необходимо динамически исправлять приложение ClassLoader, чтобы он мог загружать классы из вторичных дексов. для этого вы можете добавить эту lib.
 dependencies {
      ...
      compile 'com.android.support:multidex:1.0.0'
    }
  1. включить в коде для этого параметра. выберите тот, который вам подходит лучше всего

а. Добавить 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>

В. Расширьте приложение MultiDexApplication

public class App extends MultiDexApplication { .. }

С. установите его в приложении в привязке базового контекста.

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

}

Подробнее пройдите по этой ссылке MultiDex.