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.
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. –
È 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