2014-07-23 5 views
5

Sto tentando di offuscare un codice di app Android tramite Proguard. Dopo l'elaborazione con proguard, l'app funziona da sola, tuttavia le chiamate native eseguite da c a java non riescono con java.lang.NoSuchMethodError.Mantenimento dei metodi java richiamati da Android JNI

Questo codice è dalla parte nativa, in cui viene effettuata una chiamata per l'istanza della classe Java, denominata EngineStarted:

void callEngineStarted(JNIEnv* env, bool isStreamOne) 
{ 
    jclass cls; 
    if(isStreamOne == true) { 
     cls = (*env)->GetObjectClass(env, currentObjectOne); 
    } else { 
     cls = (*env)->GetObjectClass(env, currentObjectTwo); 
    } 

    jmethodID midCallBack = (*env)->GetMethodID(env, cls, "EngineStarted", "(I)V"); 
    if (0 == midCallBack) { 
     LOGW("Could not find EngineStarted method in class"); 
     return; 
    } 

    if(isStreamOne == true) { 
     (*env)->CallVoidMethod(env, currentObjectOne, midCallBack, 1); 
    } else { 
     (*env)->CallVoidMethod(env, currentObjectTwo, midCallBack, 0); 
    } 
} 

Il Java è questo metodo. Viene chiamato solo dalla parte nativa e non da nessun'altra parte. Per questo motivo, proguard sta rimuovendo il metodo.

public void EngineStarted (int isStreamOne) 
    { 
    Log.v("decoderService", "PDecoder - Engine started, using stream " + (isStreamOne == 1 ? "one" : "two")); 
    this.isStreamOne = isStreamOne == 1; 

    // Initialize the player 
    InitializePlayer(isStreamOne); 
    } 

Ho provato ad aggiungere questo a proguard-project.txt, ma non ha risolto il problema.

-keep class com.emrahgunduz.AppBase.Services.PlayService.players.pDecoders.PDecoderNative { 
    void EngineStarted(int); 
    void PositionChanged(int); 
    void SetDuration(int); 
    void Completed(); 
    void CompletedWithFade(); 
    void Spectrum (***); 
} 

Dopo la compilazione, mapping.txt non include i metodi, ho il sospetto che proguard li rimuova. Come posso mantenere questi metodi rimossi e/o rinominati?

EDIT/SOLUZIONE:

sono stato in grado di risolvere il problema modificando piena posizione con un carattere jolly. Ciò ha salvato alcuni dei metodi ma non è stato sufficiente. Non so perché, ma un altro metodo (void InitializePlayer(int)) che è stato chiamato da quelli oggetto di dumping è stato anche scaricato che in qualche modo ha creato una reazione a catena. L'aggiunta di questo metodo ha risolto i restanti metodi mancanti. La soluzione finale è diventato

-keepclassmembers class **.PDecoderNative { 
    native <methods>; 
    void InitializePlayer(int); 
    void EngineStarted(int); 
    void PositionChanged(int); 
    void SetDuration(int); 
    void Completed(); 
    void CompletedWithFade(); 
    void Spectrum(float[]); 
} 

EDIT: Il problema non era con il Proguard, ma con Proguard non essere in grado di leggere il file project.txt di volta in volta. Spostato l'intero progetto in una nuova posizione su disco e ricreato il file. Funziona perfettamente.

+0

Probabilmente è dovuto a proguard che modifica i nomi dei metodi. C'è un'opzione per omettere quell'ottimizzazione per 1 o più metodi, vedere le opzioni [Keep] (http://proguard.sourceforge.net/index.html#manual/usage.html) nel manuale in uso> keep. –

+0

È possibile registrare i nomi modificati in mapping.txt, che è un comportamento predefinito. Ci sono oggetti simili come 'PDecoderNative getPrevious() -> e', ma i metodi che ho citato non appaiono nel log. – emrahgunduz

risposta

3

L'analisi è corretta e anche la configurazione è corretta. Dovresti ricontrollare il nome completo della tua classe (com.emrahgunduz.AppBase.Services.PlayService.players.pDecoders.PDecoderNative). Nota che devi usare "$" invece di "." per separare le classi interne, se applicabile.

Se sono stati specificati i nomi corretti, li vedrai nel file proguard/seeds.txt che ProGuard scrive nel processo di build di Android.

Una volta che funziona, è possibile sostituire -keep per -keepclassmembers. ProGuard manterrà comunque i nomi dei metodi ma nasconderà il nome della classe, che in questo caso va bene.

+0

Grazie per la risposta. Ho controllato il nome della classe, era ok. Lo stesso nome appare anche nel file usage.txt con metodi di callback scaricati. Non so perché, ma l'uso completo del nome della classe risulta nel dump dei metodi keep. Tuttavia, cambiando il nome in **. PDecoderNative ha risolto il problema. Accetterò la tua risposta come quella corretta in quanto sono riuscito a risolvere il problema tramite il tuo suggerimento nome/pacchetto. – emrahgunduz

+0

Non riesco a immaginare un motivo per cui ProGuard analizzerebbe il nome della classe senza caratteri jolly in modo errato.Per ricontrollare, puoi provare a copiarlo/incollarlo da proguard/seeds.txt in dexguard-project.txt. Dovresti anche vedere i nomi dei metodi mantenuti in proguard/seeds.txt. –

+0

Indovina, ho iniziato ad avere lo stesso problema dopo aver cambiato i caratteri jolly. Sposta la cartella del progetto e ricrea il file project.txt da zero. Ora funziona senza i caratteri jolly. Probabilmente il file è stato bloccato o danneggiato, o qualche problema di sicurezza non permette a proguard di leggere il file di volta in volta. Penso che l'ultimo aggiornamento su sdk o macosx sia stato un problema. – emrahgunduz

Problemi correlati