我想通過Proguard混淆Android應用程序代碼。使用proguard進行處理後,該應用程序自行運行,但從c到java的本機調用失敗,出現java.lang.NoSuchMethodError
。保持從Android調用的Java方法JNI
這段代碼是從本地部分,其中調用Java類實例所做的,名爲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);
}
}
Java有此方法。它只從本地部分調用,而不是其他任何地方。因此,proguard正在刪除該方法。
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);
}
我試過把它添加到proguard-project.txt中,但沒有解決問題。
-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 (***);
}
編譯後,mapping.txt不包括方法,我懷疑proguard刪除它們。 如何讓這些方法被刪除和/或重命名?
編輯/解決方案:
我能夠通過改變全位置使用通配符來解決這個問題。這節省了一些方法,但還不夠。不知道爲什麼,但被傾銷者調用的另一種方法(void InitializePlayer(int)
)也被拋棄,這種方法以某種方式產生了連鎖反應。添加此方法解決了剩餘的缺失方法。最終的解決方案成爲
-keepclassmembers class **.PDecoderNative {
native <methods>;
void InitializePlayer(int);
void EngineStarted(int);
void PositionChanged(int);
void SetDuration(int);
void Completed();
void CompletedWithFade();
void Spectrum(float[]);
}
編輯:問題是不與ProGuard的,但使用ProGuard不能夠從時間project.txt文件讀取時間。將整個項目移至磁盤上的新位置並重新創建文件。它工作完美。
這可能是由於proguard更改方法名稱。有一個選項可以省略1個或多個方法的優化,請參見使用手冊> keep下的[Keep](http://proguard.sourceforge.net/index.html#manual/usage.html)選項。 –
您可以將更改的名稱記錄到mapping.txt,這是一種默認行爲。有類似的項目,如'PDecoderNative getPrevious() - > e',但我提到的方法不會出現在日誌中。 – emrahgunduz