2012-01-13 13 views
21

ho notato che il "modello" proguard.cfg contiene sempre la seguente:Che cosa rende certe classi di android "must -keep"?

-keep public class * extends android.app.Activity 
-keep public class * extends android.app.Application 
-keep public class * extends android.app.Service 
-keep public class * extends android.content.BroadcastReceiver 
-keep public class * extends android.content.ContentProvider 
-keep public class * extends android.app.backup.BackupAgentHelper 
-keep public class * extends android.preference.Preference 
-keep public class com.android.vending.licensing.ILicensingService 

Perché questi particolari classi e non altre?

È questa l'elenco completo di classi che non devono essere "ottimizzate" da ProGuard?

risposta

24

In breve, tali classi si trovano nel modello proguard.cfg poiché tali classi possono essere dichiarate in AndrodiManifest.xml.

Considerate questa applicazione minima:

CustomTextView.java:

package com.example.android; 

import android.content.Context; 
import android.widget.TextView; 

public class CustomTextView extends TextView { 
    public CustomTextView(Context context) { 
     super(context); 
     setText("The class name of this class is not important"); 
    } 
} 

ExampleActivity.java:

package com.example.android; 

import android.app.Activity; 
import android.os.Bundle; 
import android.util.Log; 

public class ExampleActivity extends Activity { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(new CustomTextView(this)); 
     Log.i("ExampleActivity", "The class name of this class is important"); 
    } 
} 

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
     package="com.example.android" 
     android:versionCode="1" 
     android:versionName="1.0"> 
    <application> 
     <activity android:name=".ExampleActivity"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
      </intent-filter> 
     </activity> 
    </application> 
</manifest> 

Ora, senza la linea

-keep public class * extends android.app.Activity 

nel Proguard.file cfg, proguard potrebbe essere tentato di rinominare ExampleActivity in A. Tuttavia, non sa nulla di AndroidManifest.xml, quindi non toccherà il file manifest. Poiché il sistema operativo Android utilizza i nomi di classe dichiarati nel manifest dell'applicazione per avviare un'applicazione, il sistema operativo Android tenterà di creare un'istanza ExampleActivity, ma tale classe non esisterà da quando proguard lo ha rinominato!

Nel caso di CustomTextView, va bene per Proguard per rinominarlo dire B, perché il nome della classe non è importante in quanto non è dichiarato nel manifesto, unico riferimento da codice che Proguard aggiornerà quando cambia il nome della classe CustomTextView.

In un modo o nell'altro, tutte le classi a cui fa riferimento il file proguard.cfg del modello possono essere dichiarate nel manifest, quindi proguard non deve toccarle.

+0

Grazie per aver compreso la mia domanda e per aver fornito una così grande risposta. +1 già e ho intenzione di accettare +50 la tua risposta a meno che non arrivi qualcosa di sorprendente. Ora le domande di follow-up: ** '# 1.' ** Ho capito correttamente dalla tua risposta che' -keep' influisce anche sulla mappatura, non solo sull'ottimizzazione? ** '# 2.' ** Se versioni future di Proguard supportano AndroidManifest.xml,' -keep' non sarà più richiesto per le classi sopra menzionate? –

+0

** '# 1.' **: Non sono del tutto sicuro di cosa intendi per" mappatura ". Se intendete "rinominare le classi", allora sì, '-keep' impedisce a proguard non solo di rimuovere la classe ma anche di rinominare la classe. Se per "mappatura" si intende qualcosa relativo ad AndroidManifest.xml, quindi no, '-keep' non ha alcuna relazione con' AndroidManifest.xml', che è esattamente il motivo per cui '-keep' è necessario in primo luogo (vedi risposta a # 2). ** '# 2.' ** Sì, se proguard conoscesse la semantica di AndroidManifest.xml (e come modificarlo), quindi' -keep' non sarebbe necessario. –

2

Vedere ProGuard Manual. Essa afferma che -keep:

Specifica classi e membri della classe (campi e metodi) di essere conservato come punti di ingresso al codice. Ad esempio, per mantenere un'applicazione, è possibile specificare la classe principale insieme al suo metodo principale . Per elaborare una libreria, è necessario specificare tutti gli elementi accessibili accessibili.

E 'questa la lista completa delle classi che non deve essere offuscato da ProGuard?

Se si specifica -keep Ciò non significa una mancanza di offuscamento. Significa che mantiene quelle classi nel tuo codice. Poiché ProGuard sta tentando di ottimizzare e ridurre la tua app, potrebbe rimuovere alcune classi se non sembrano essere utilizzate. Non fidarti del 100%, ma è quello che ho letto su qualche altro post di SO una volta.

Perché queste classi particolari e non altre?

Suppongo che quelle classi siano piuttosto importanti. E come puoi vedere la maggior parte di loro sono classi che extend quelle elencate. Se si specifica, Service o qualsiasi altra cosa elencata, non si vorrebbe che fosse rimosso durante l'ottimizzazione.

+0

Grazie, ma sto cercando una risposta specifica per le particolari classi ** di Android ** che ho elencato. Ad esempio, ** cosa ** rende 'BroadcastReceiver' deve' -keep'? Dichiarare "abbastanza importante" non mi dice nulla ... –

+0

Beh, direi che il motivo per "BroadcastReceiver" potrebbe essere che spesso una classe 'BroadcastReceiver' non sembra essere usata (tramite altro codice Java), ma è referenziato nel tuo manifest. Il significato è usato, ma 'Proguard' non lo riconosce, quindi devi' -keep' così 'Proguard' non lo rimuove. Non ne so nulla di questo, è solo una mia comprensione dalla lettura del [Proguard Manual'] (http://proguard.sourceforge.net/index.html#). – Jakar

+0

Grazie. Ho letto il manuale ma ancora non capisco perché ** ADT ** abbia scelto queste classi per essere lì nel template 'proguard.cfg'. La descrizione per '-keep' si legge:" Specifica classi e membri della classe (campi e metodi) da conservare come ** punti di ingresso ** nel codice. " A proposito, le classi derivate da quelle sopra elencate non solo sono mantenute ma sono ** anche non offuscate **. –

Problemi correlati