2013-04-17 12 views
17

Zajmuję się tworzeniem aplikacji na Androida, która wymaga wielu bibliotek (między innymi na Facebooku, Mapach Google v2 i Quickblox), co powoduje przekroczenie limitu liczby metod 64K limit:Nie mogę utworzyć wielu plików z Androidem z Anta z zewnętrznych słoików

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 

Ponieważ nie mogę tego zrobić bez żadnego z tych bibliotek, Szukałem rozwiązania do błędu granicznego metoda. Znalazłem popularny wpis na blogu od programistów aplikacji na Androida, w którym zaleca się podział kodu źródłowego. (Wpis blogu, o którym mówię, można znaleźć tutaj: http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html). Próbowałem tego rozwiązania bez powodzenia.

Problem polega na tym, że największej ilości kodu nie ma w mojej aplikacji, ale w wymaganych bibliotekach, więc muszę rozłożyć te biblioteki między różne pliki dex, które muszę załadować w mojej aplikacji. Moja wiedza o Ant jest bardzo ograniczona, a co chciałbym wiedzieć, co mam napisać w moim pliku build.xml, aby dek skopiować każdą bibliotekę, gdzie chcę:

  <!-- 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> 

Każda pomoc będzie naprawdę doceniane . Z góry dzięki, pozdrawiam!

+0

znalazłeś rozwiązanie dla tego? Mam dokładnie ten sam problem. – rupps

Odpowiedz

0

ProGuard to narzędzie do minimalizowania kodu źródłowego, usunie wszelkie nieużywane/zduplikowane klasy podczas pakowania aplikacji. Więc nawet jeśli używasz wszystkich zewnętrznych JAR-ów, nie będziesz używał 100% wszystkich klas wewnątrz tych, a wiele z tych JAR-ów może mieć w sobie te same klasy (np. Log4J, itp.).

Proguard is built into dex. Ale domyślnie nie jest aktywowana, należy uruchomić mrówkę w trybie zwolnienia, a być może trzeba również skomentować wiersz w pliku project.properties.

Najprawdopodobniej ProGuard może skończyć się usunięciem niektórych klas używanych w aplikacji przez usunięcie. Jeśli podczas kompilacji gdy ProGuard, masz błędy jak class X not found, a następnie skonfigurować ProGuard w proguard.cfg że trzeba tę klasę:

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

Sprawdź Android ProGuard dokumentację i sprawdzić, czy umożliwiając ProGuard zmniejsza rozmiar (klas i metod) w Twoim pakiecie APK.

6

Najlepszą odpowiedzią, jaką dotychczas usłyszałem na ten problem, jest użycie ProGuarda w trybie zoptymalizowanym (proguard-android-optimize.txt) z flagą -dontobfuscate w celu usunięcia nieużywanych klas i metod z ostatecznego pliku APK (bez maskowania ich) . Następnie możesz skorzystać z pliku ProGuard mapping.txt, aby pomóc ci usunąć nieużywane klasy z używanych przez ciebie bibliotek JAR (nie mam pojęcia o dobrym narzędziu, aby to zrobić). Niestety nie sądzę, aby w ProGuardzie istniała jakaś funkcja automatycznie.

ProGuard działa tylko podczas eksportowania w środowisku Eclipse, a nie podczas uruchamiania aplikacji Uruchom jako -> Android. Oznacza to, że nie pomoże to uniknąć ograniczenia kompilacji debugowania, chyba że użyjesz niestandardowego procesu kompilacji. Twórca ProGuarda sugeruje użycie komercyjnego rodzeństwa DexGuard, które będzie działać w środowisku Eclipse zarówno w kompilacjach debugujących, jak i wydań.

Korzystanie z ProGuard jest silnie zalecane w przypadku wersji wydań, ponieważ zmniejszy to rozmiar kodu, zwiększy wydajność (na przykład dzięki wprowadzeniu kodu) i zaciemni również Twoje źródło. Upewnij się, że wykonałeś wystarczającą liczbę testów na ostatnim pliku APK, ponieważ będzie on znacznie różnił się od debugowania. Niestety, ProGuard sam w sobie nie był wystarczający do rozwiązania mojego problemu, więc usunąłem jedną z moich zależności JAR jako obejście.

Sprawdziłem wiele metod w moich zależnych JAR poleceniem:

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

Przykłady liczb metod dla naszych największych bibliotek:

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, można sprawdzić liczbę metod w pliku APK za pomocą dexdump (który można znaleźć w folderze SDK build-tools, np. "Android Studio.app/sdk/build-tools/21.0.2/dexdump"):

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

W naszym przypadku używaliśmy tylko Guava do wyszukiwania w YouTube, więc łatwo było usunąć tę zależność i dać nam więcej miejsca do oddychania.

Aktualizacja: znalazłem najprostszy sposób na strip niewykorzystany kod z dużych JAR było wykorzystanie dex2jar na moim PROGUARD kompilacji, a następnie użyć JD-GUI porównać tę ostateczną JAR z wejściem konkretnego JAR chciałem przyciąć. Następnie usuwam pakiety najwyższego poziomu, które, jak wiem, zostaną usunięte przez Proguard. To pozwoliło mi usunąć> 8000 metod z aws-android-sdk-1.5.0-core.jar.

+0

Dzięki za udostępnienie. Czy mogę wiedzieć, jak usunąć niechciane pakiety z pliku JAR? Sam plik jar jest w formie binarnej. Czy dekompilujesz je za pomocą JD-GUI w formie plików Java i ponownie je skompilujesz do Jar? –

+0

Skorzystaj z narzędzia "jar", aby uchwycić i przesłać ponownie. –

Powiązane problemy