我正在尝试通过Proguard使Android应用程序代码混淆。在经过Proguard处理后,应用程序本身可以正常运行,但是从C到Java的本地调用失败,并显示“java.lang.NoSuchMethodError”错误。
以下代码来自本地部分,其中对Java类实例EngineStarted进行了调用:
Java有这个方法。它只能从本地部分调用,而不能在其他任何地方调用。因此,Proguard正在删除该方法。
我尝试将此添加到proguard-project.txt中,但并没有解决问题。
以下代码来自本地部分,其中对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文件。将整个项目移动到磁盘上的新位置并重新创建该文件。现在它完美地工作了。
PDecoderNative getPrevious() -> e
的项目还有很多,但我提到的方法没有出现在日志中。 - emrahgunduz