2013-04-17 11 views
17

Sto sviluppando un'applicazione per Android che richiede più librerie (per Facebook, Google Maps v2 e Quickblox tra gli altri), con conseguente superamento della quantità del metodo che supera il limite di 64 KB:Impossibile creare più file dex Android con Ant da contenitori esterni

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 

Come io non posso fare a meno di una qualsiasi di queste librerie, ho cercato una soluzione per il bug limite di metodo. Ho trovato un popolare blog da Android Developers, in cui è raccomandata una divisione del codice sorgente. (Il blog di cui sto parlando può essere trovato qui: http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html). Ho provato questa soluzione senza successo.

Il problema che ho ora è che la maggior quantità di codice non è nella mia app stessa, ma nelle librerie richieste, quindi devo diffondere quelle librerie tra i diversi file dex che devo caricare nella mia app. La mia conoscenza di Ant è molto limitato, e quello che mi piacerebbe sapere è quello che avrei dovuto scrivere nel mio file build.xml per rendere dex copiare ogni libreria dove voglio:

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

qualsiasi aiuto sarebbe veramente apprezzato . Grazie in anticipo, cordiali saluti!

+0

hai trovato una soluzione per questo? Ho lo stesso identico problema. – rupps

risposta

0

ProGuard è uno strumento di minificazione del codice sorgente, rimuoverà tutte le classi inutilizzate/duplicate durante il confezionamento dell'applicazione. Quindi, anche se stai utilizzando tutti questi JAR esterni, non utilizzerai al 100% tutte le classi all'interno di questi e molti di questi JAR potrebbero avere le stesse classi al loro interno (ad esempio Log4J, ecc.).

Proguard is built into dex. Ma non viene attivato per impostazione predefinita, è necessario eseguire ant nella modalità di rilascio e potrebbe essere necessario commentare una riga in project.properties.

Molto probabilmente, ProGuard potrebbe finire con rimuovere alcune classi utilizzate nell'applicazione. Se durante la compilazione quando ProGuard, si ottiene gli errori come class X not found, quindi configurare ProGuard in proguard.cfg che è necessario che la classe:

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

Scopri i ProGuard Android documentazione e vedere se permettendo Proguard riduce le dimensioni (di classi e metodi) nel tuo APK.

6

La migliore risposta che ho sentito finora su questo problema è usare ProGuard in modalità ottimizzata (proguard-android-optimize.txt) con il flag -dontobfuscate per rimuovere classi e metodi non utilizzati dall'APK finale (senza offuscarli) . Quindi puoi utilizzare ProGuard mapping.txt per aiutarti a togliere le classi non utilizzate dai JAR della libreria che usi (non sono a conoscenza di un buon strumento per farlo). Sfortunatamente non penso ci sia una funzionalità in ProGuard per farlo automaticamente.

ProGuard viene eseguito solo quando si esegue un'esportazione in Eclipse, non quando si esegue Esegui come -> Applicazione Android. Ciò significa che non aiuterà a evitare il limite delle build di debug, a meno che non si utilizzi un processo di compilazione personalizzato. Il creatore di ProGuard suggerisce di utilizzare il suo fratello commerciale DexGuard, che verrà eseguito in Eclipse sia su build di debug che di release.

L'uso di ProGuard è fortemente incoraggiato per i build di rilascio in quanto ridurrà la dimensione del codice, migliorerà le prestazioni (ad esempio mediante il codice di allineamento) e offuscerà anche la sorgente. Assicurati di fare abbastanza test sull'APK finale in quanto sarà radicalmente diverso da quello di debug. Sfortunatamente, ProGuard da solo non era abbastanza per risolvere il mio problema, quindi ho rimosso una delle mie dipendenze JAR come soluzione alternativa.

ho controllato il numero di metodi nei miei JAR dipendenti di utilizzare questo comando:

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

Esempi numero di metodi per i nostri più grandi biblioteche:

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, è possibile verificare il numero di metodi nel tuo APK usando dexdump (che puoi trovare nella cartella SDK build-tools, ad esempio "Android Studio.app/sdk/build-tools/21.0.2/dexdump"):

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

Nel nostro caso usavamo Guava solo per effettuare ricerche su YouTube, quindi è stato facile rimuovere tale dipendenza e darci più spazio per respirare.

Aggiornamento: Ho trovato il modo più semplice per togliere codice non utilizzato da grandi vasi è stato quello di utilizzare dex2jar sul mio Proguard costruzione, quindi utilizzare JD-GUI per confrontare quel vaso finale con la specifica JAR di input che volevo tagliare. Quindi rimuovo i pacchetti di livello superiore che so vengano rimossi da Proguard. Questo mi ha permesso di rimuovere> 8000 metodi da aws-android-sdk-1.5.0-core.jar.

+0

Grazie per aver condiviso. Posso sapere come si rimuovono i pacchetti indesiderati dal file jar? Come il file jar stesso è in forma binaria. Li decomponi usando la JD-GUI in forma di file Java e li ricomponi di nuovo in Jar? –

+0

Usa lo strumento "jar" per aprire e riawiare. –

Problemi correlati