Sto spostando un progetto da Ant a Gradle, ma c'è qualcosa che non riesco proprio a capire.Passaggio a Gradle: perché è necessario mantenere nascoste le visualizzazioni personalizzate?
FATTI
Dopo la costruzione di un APK rilascio (cioè offuscato), ho notato che l'applicazione è stata arrestando male. L'errore può essere riassunta da questo:
java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
un debug (vale a dire, non offuscato) APK funziona bene, così ho indovinato aveva a che fare con la mia ProGuard/DexGuard configurazione.
ho cercato di mantenere il riferimento di classe aggiungendo la seguente dichiarazione:
-keep class com.mypackage.MyCustomView
e, di conseguenza, il rilascio APK funziona bene. Poi ho fatto qualche ricerca e ho provato questo in modo più preciso la configurazione ProGuard/DexGuard:
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
che funziona anche, ed è classe indipendente.
DOMANDA
mi chiedo:
- Perché non hanno a che fare con è durante l'utilizzo di Ant?
- Qual è il motivo esatto per cui viene visualizzato l'errore? (Segue rispondere alla prima domanda)
RISPOSTA
La risposta di @Blundell era sostanzialmente corretta. Mi risulta mancava una linea dalla configurazione build.gradle
:
android {
...
buildTypes {
debug {
...
}
release {
proguardFile getDefaultDexGuardFile('dexguard-release.pro') # <----- this line
proguardFile 'dexguard-project.txt'
}
}
}
Risulta che la linea sia effettivamente obbligatoria, dal momento che serve come un insieme base regole per ProGuard/DexGuard. In realtà, questo è parte del file dexguard-release.pro
:
-keepclassmembers !abstract class !com.google.ads.** extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keepclassmembers !abstract class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.content.Context {
public void *(android.view.View);
}
ho trovato la documentazione un po 'troppo vago su questo, spero che possa essere redatto per eliminare qualsiasi ambiguità che potrebbe avere. Tutto sommato, colpa mia.
come/dove si crea la visualizzazione personalizzata? – pskink
I costruttori devono essere mantenuti perché il 'LayoutInflater' li sta usando, ma questo non può essere dedotto dall'analisi statica della sola fonte. Immagino che la tua vera domanda sia: perché la configurazione predefinita di ProGuard/DexGuard che prima era parte dell'SDK non è stata utilizzata? La mia ipotesi è che questo è dovuto ai recenti cambiamenti nel plugin Gradle, insieme a 'runProguard' che viene rinominato e ad altre cose del genere. Se stai utilizzando ProGuard dall'SDK, controlla con il gruppo Google adt-dev. Se stai usando DexGuard, controlla il portale di download, ci sono stati alcuni aggiornamenti recenti in rapida successione. – Barend
@Barend Non sono sicuro di cosa 'perché la configurazione predefinita di ProGuard/DexGuard che prima era parte dell'SDK non utilizzata 'dovrebbe significare. Mi chiedo perché ci sia un comportamento diverso in Ant e Gradle, poiché entrambi utilizzano la stessa versione di DexGuard e stanno entrambi utilizzando lo stesso file di configurazione. – Sebastiano