繁体   English   中英

保持从Android JNI调用java方法

[英]Keeping java methods called from Android JNI

我正试图通过Proguard混淆Android应用程序代码。 在使用proguard处理后,应用程序自行工作,但是从c到java的本机调用失败了java.lang.NoSuchMethodError

此代码来自本机部分,其中调用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文件。 将整个项目移动到磁盘上的新位置并重新创建该文件。 它工作得很好。

您的分析是正确的,您的配置也是正确的。 您应该仔细检查类的完全限定名称(com.emrahgunduz.AppBase.Services.PlayService.players.pDecoders.PDecoderNative)。 请注意,您必须使用'$'而不是'。' 如果适用,将内部类别分开。

如果您指定了正确的名称,您将在ProGuard在Android构建过程中写出的文件proguard / seeds.txt中看到它们。

一旦这个工程,你可以替换-keep通过-keepclassmembers 然后ProGuard仍会保留方法名称,但会混淆类名,在这种情况下这很好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM