【发布时间】:2014-07-23 12:10:50
【问题描述】:
我正在尝试通过 Proguard 混淆 Android 应用代码。使用 proguard 处理后,应用程序可以自行运行,但是从 c 到 java 的本机调用失败并显示 java.lang.NoSuchMethodError。
此代码来自本机部分,其中调用了名为 EngineStarted 的 java 类实例:
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 选项在使用 > 保留下。
-
您可以将更改的名称记录到 mapping.txt,这是默认行为。有类似
PDecoderNative getPrevious() -> e的项目,但我提到的方法并没有出现在日志中。
标签: java android android-ndk java-native-interface proguard