2015-12-21 20 views
27

Esiste un modo ragionevolmente semplice per il file build.gradle di un modulo per indicare che alcuni file da una dipendenza dovrebbero essere esclusi? Sono specificamente interessato ad escludere determinate risorse da una RAA.Come escludere risorse specifiche da una priorità AAR?


LeakCanary è una libreria interessante per aiutare a rintracciare le perdite di memoria. Tuttavia, ha un requisito non documentato di compileSdkVersion di 21 o versione successiva. Mentre la maggior parte dei progetti non dovrebbe avere problemi con questo, è sconveniente che una libreria richieda un certo compileSdkVersion senza una buona ragione. Un team di sviluppo potrebbe aver congelato il proprio compileSdkVersion come parte di una politica generale per modificare solo quei tipi di impostazioni come parte dei principali aggiornamenti di versione della propria app o qualcosa del genere.

In questo caso, per v1.3.1 di LeakCanary almeno, è richiesto l'unica ragione compileSdkVersion, AFAICT, è perché la relazione annuale di attività ha una directory res/values-v21/, che contiene una definizione del tema che eredita da Theme.Material. Questo tema è utilizzato da un'attività diagnostica. Questa attività non è mai vista dagli utenti finali, solo dagli sviluppatori nelle build debug. Francamente, a cosa assomiglia quell'attività, a livello di tema, non importa. Forzare un compileSdkVersion di 21 solo per avere quell'attività diagnostica ha un certo tema, IMHO, stupido.

Sarebbe bello se come parte di una direttiva compile potessimo dire "hey, per favore, salta il res/values-v21/ da questo AAR, m'kay?". Poiché il tema -v21 sta semplicemente fornendo una definizione alternativa di un tema definito altrove, l'eliminazione del tema -v21 non interromperà la generazione o interromperà le cose in fase di runtime, ma semplicemente ci darà un'attività di diagnostica legata a Holo -themed.

Non riesco a vedere come this answer funziona con le dipendenze. Sono anche incerto if it is complete, and it certainly does not appear to be supported. Inoltre non si qualifica come "semplice" — Non mi aspetto che qualcuno provi a rilasciare questo in un file build.gradle solo per bloccare un singolo file da una libreria diagnostica come LeakCanary.

Quindi, c'è qualcosa di più semplice di questo che funziona con le edizioni attuali di Android Plugin per Gradle?

+0

credo, la soluzione per LeakCanary (https://github.com/square/leakcanary) sarebbe quello di forchilo e compila la tua versione con il corretto 'compileSdkVersion'. Non sono sicuro che possa essere contato come risposta alla domanda. –

+0

@ KonstantinLoginov: LeakCanary sembra avere un buon numero di parti mobili interconnesse, motivo per cui sono scettico sul fatto che una forcella sarà così facile. Ho fatto abbastanza spintoni per determinare che l'unica caratteristica di Android 5.0+ era 'Theme.Material', che è quello che mi ha spinto a fare questa domanda. Mentre sto inquadrando la domanda nel contesto di LeakCanary, il problema trascende quella libreria. – CommonsWare

+0

Sarebbe bello se l'attuale sorgente di plugin gradle di google fosse pubblica. I tag per l'origine della DSL [1] sono molto indietro rispetto ai tag di rilascio [2]. [1] https://android.googlesource.com/platform/tools/gradle/+refs [2] https://jcenter.bintray.com/com/android/tools/build/gradle/ – JBirdVegas

risposta

-3

Sì, è possibile utilizzare Proguard

buildTypes { 
    release { 
     proguardFiles getDefaultProguardFile('proguard-android.txt'), 
     'proguard-rules.pro' 
    } 
debug { 
     proguardFiles getDefaultProguardFile('proguard-android.txt'), 
     'proguard-rules.pro' 
    } 
} 
+1

Questo non funzionerà. –

11

EDIT:

Ha scritto compito Gradle avanzate per voi:

final List<String> exclusions = []; 

Dependency.metaClass.exclude = { String[] currentExclusions -> 
    currentExclusions.each { 
     exclusions.add("${getGroup()}/${getName()}/${getVersion()}/${it}") 
    } 
    return thisObject 
} 

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    testCompile 'junit:junit:4.12' 
    compile ('com.android.support:appcompat-v7:20.+') 
    debugCompile ('com.squareup.leakcanary:leakcanary-android:1.3.1') 
      .exclude("res/values-v21/values-v21.xml") 
    releaseCompile ('com.squareup.leakcanary:leakcanary-android-no-op:1.3.1') 
} 

tasks.create("excludeTask") << { 
    exclusions.each { 
     File file = file("${buildDir}/intermediates/exploded-aar/${it}") 
     println("Excluding file " + file) 
     if (file.exists()) { 
      file.delete(); 
     } 
    } 
} 

tasks.whenTaskAdded({ 
    if (it.name.matches(/^process.*Resources$/)) { 
     it.dependsOn excludeTask 
    } 
}) 

Ora è possibile utilizzare il metodo .exclude() su ogni dipendenza, fornendo nella lista dei percorsi, si desidera escludere dalla dipendenza specificata. Inoltre, è possibile impilare le chiamate al metodo .exclude().

+0

Penso che la tua definizione 'LEAKCANARY_ARTIFACT_NOOP' abbia un bug. E mentre questo è interessante, non risponde alla domanda reale: "Esiste un modo ragionevolmente semplice per il file' build.gradle' di un modulo per indicare che alcuni file da una dipendenza dovrebbero essere esclusi? " Affronta il mio esempio di scenario in modo alternativo (modificando le risorse). Grazie comunque! – CommonsWare

+0

Non penso che ci sia un modo per fare ciò che vuoi fuori dalla scatola. Ma puoi scrivere il tuo compito, come questo, che sarà eseguito prima della fusione delle risorse e cancellerà le risorse che non ti servono. Tutte le risorse di ogni modulo di aar sono memorizzate nella directory build/exploded-aar, e puoi tranquillamente rimuoverle da lì e non verrebbero processate affatto. Tuttavia, riguardo alla semplicità: puoi scrivere il tuo wrapper per la chiusura "compile" che può prendere array di file/dir che saranno esclusi nell'attività. Proverò a farlo domani. – IlyaGulya

+0

Modificata la risposta. Ora escludere è molto più semplice, penso. – IlyaGulya

0

Credo che sia possibile risolvere questo problema in modo più elegante utilizzando la funzione PackagingOptions del DSL Android Gradle Plugin.

Sono stato in grado di usarlo io stesso per escludere alcune librerie native che non avevo bisogno di introdurre da un AAR nel mio progetto.

android { 
    ... 
    packagingOptions { 
     exclude '/lib/armeabi-v7a/<file_to_exclude>' 
    } 
} 

Per il caso descritto nella domanda, credo che questo dovrebbe funzionare:

android { 
    ... 
    packagingOptions { 
     exclude '/res/values-v21/<file_to_exclude>' 
    } 
} 
+1

Qualche volta provo, ma sono scettico sul fatto che funzionerà. Innanzitutto, 'pacakgingOptions' è troppo tardi nel processo di compilazione - la build dovrebbe fallire a causa della' compileSdkVersion' prima che arrivi. In secondo luogo, AFAIK, 'packagingOptions' si riferisce all'esclusione delle cose in base a dove si trovano nell'APK e le risorse XML non vanno nell'APK come file ordinari. Grazie comunque! – CommonsWare

+0

c'è qualche possibilità di farlo dinamicamente? https://stackoverflow.com/questions/46543271/how-to-exclude-files-from-aar-with-gradle-dynamically – 4ntoine

Problemi correlati