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

Не удается создать несколько файлов Android dex с помощью Ant из внешних банок

Я разрабатываю приложение для Android, которое требует нескольких библиотек (для Facebook, Google Maps v2 и Quickblox среди других), что приводит к переполнению суммы метода, которая превышает 64-килобайтный лимит:

Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536

Как я не могу обойтись без какой-либо из этих библиотек, я искал решение для ошибки ограничения метода. Я нашел популярную запись в блоге от разработчиков Android, где рекомендуется разделение исходного кода. (Запись в блоге, о которой я говорю, можно найти здесь: http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html). Я пробовал это решение без успеха.

Теперь проблема заключается в том, что самый большой объем кода не в самом моем приложении, а в необходимых библиотеках, поэтому мне приходится распространять эти библиотеки среди разных файлов dex, которые я должен загрузить в своем приложении. Мои знания о Ant очень ограничены, и то, что я хотел бы знать, - это то, что я должен написать в файле build.xml, чтобы сделать dex копией каждой библиотеки, где я хочу:

            <!-- Primary dex to include my source code and some libraries. -->
            <copy todir="${out.classes.absolute.dir}.1" >
                <fileset dir="${out.classes.absolute.dir}" >

                ...

                </fileset>
            </copy>


            <!-- Secondary dex to include some other libraries. -->
            <copy todir="${out.classes.absolute.dir}.2" >
                <fileset dir="${out.classes.absolute.dir}" >

                ...  

                </fileset>
            </copy>

Любая помощь будет по-настоящему оценена. Спасибо заранее, любезно!

4b9b3361

Ответ 1

Лучшим ответом, который я слышал до этой проблемы, является использование ProGuard в оптимизированном режиме (proguard-android-optimize.txt) с флагом -dontobfuscate для удаления неиспользуемых классов и методов из окончательного APK (без обфускации их). Затем вы можете использовать файл ProGuard mapping.txt, чтобы помочь вам удалить неиспользуемые классы из используемых JAR-библиотек библиотеки (я не знаю о хорошем инструменте для этого). К сожалению, я не думаю, что в ProGuard есть функция, чтобы сделать это автоматически.

ProGuard работает только при выполнении экспорта в Eclipse, а не при выполнении приложения "Запуск As → Android". Это означает, что это не поможет избежать ограничения на отладочные сборки, если вы не используете собственный процесс сборки. Создатель ProGuard предлагает использовать свой коммерческий брат DexGuard, который будет запускаться в Eclipse как для отладочных, так и для выпуска сборок.

Использование ProGuard настоятельно рекомендуется для сборки релизов, так как это уменьшит размер вашего кода, улучшит производительность (например, с помощью встраивания кода) и будет запутывать ваш источник. Убедитесь, что вы проверили достаточное количество тестов в последнем APK, поскольку оно будет сильно отличаться от отладочного. К сожалению, ProGuard сам по себе недостаточно для решения моей проблемы, поэтому я удалил одну из своих зависимостей JAR в качестве обходного пути.

Я проверил количество методов в зависимых JAR с помощью этой команды:

dx --dex --output=temp.dex library.jar
cat temp.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 "%d\n"'

Примеры номеров методов для наших самых больших библиотек:

11222 guava-11.0.1.jar    
10452 aws-android-sdk-1.5.0-core.jar    
5761 org.restlet.jar    
5129 protobuf-java-2.4.1.jar    
2499 aws-android-sdk-1.5.0-s3.jar    
2024 ormlite-core-4.41.jar    
1145 gson-2.2.2.jar    
1716 google-http-client-1.11.0-beta.jar    

FYI, вы можете проверить количество методов в APK, используя dexdump (который вы можете найти в своей папке SDK build-tools, например "Android Studio.app/sdk/build-tools/21.0.2/dexdump" )

dexdump -f MyApp.apk | grep method_ids_size
method_ids_size     : 64295

В нашем случае мы использовали Guava только для поиска YouTube, поэтому было легко удалить эту зависимость и дать нам больше передышки.

Обновление:. Я нашел, что самый простой способ избавиться от неиспользуемого кода от больших JAR - использовать dex2jar в моей сборке Proguard, а затем использовать JD-GUI для сравнения этого финального JAR с конкретным входным JAR я хотел обрезать. Затем я удаляю пакеты верхнего уровня, которые, как мне известно, удаляются Proguard. Это позволило мне удалить > 8000 методов из aws-android-sdk-1.5.0-core.jar.

Ответ 2

ProGuard - это инструмент для минимизации исходного кода, он удалит все неиспользуемые/дублированные классы при упаковке приложения. Поэтому, даже если вы используете все эти внешние JAR, вы не будете использовать 100% всех классов внутри них, и многие из этих JAR могут иметь одинаковые классы внутри них (например, Log4J и т.д.).

Proguard встроен в dex. Но по умолчанию он не активируется, вам нужно запустить ant в режиме деблокирования, и вам также может потребоваться прокомментировать строку в project.properties.

Скорее всего, ProGuard может удалить некоторые классы, используемые в вашем приложении. Если при компиляции в ProGuard вы получаете такие ошибки, как class X not found, тогда настройте ProGuard в proguard.cfg, что вам нужен этот класс:

-keep public class <full path to the class that you need>

Ознакомьтесь с документацией на Android ProGuard и посмотрите, позволяет ли включить proguard размер (классов и методов) в вашем APK.