首页 > 解决方案 > 在 Release 中未找到 void com.organization.app.Activity.a() 的实现

问题描述

我想要做的只是从我的 Java android 活动中调用一个本机函数,该活动在我的 C++ 代码库中实现。签名可以是任何东西,但让我们将其定义为void fooBar().

我的工作区以 gradle 项目的树形结构组织,所有项目都是“com.android.library”项目,但应用程序是“com.android.application”。所有项目都包含某种形式的 C++ 代码,其中一些包含 Java 类。活动类位于根项目(“核心”)中。该函数的本机实现位于同一项目的 .cpp 文件中。

这是 logcat 的错误输出:

E/com.organization.app: No implementation found for void com.organization.app.Activity.a() (tried Java_com_organization_app_Activity_a and Java_com_organization_app_Activity_a__)
E/AndroidRuntime: FATAL EXCEPTION: Thread-9
    Process: com.organization.app, PID: 3607
    java.lang.UnsatisfiedLinkError: No implementation found for void com.organization.app.Activity.a() (tried Java_com_organization_app_Activity_a and Java_com_organization_app_Activity_a__)
        at com.organization.app.Activity.a(Native Method)
        at com.organization.app.Activity.onStart(Unknown Source:0)

在为 Debug 构建时,我可以fooBar()完美地调用此函数,但在 Release 中,它会尝试使用不同的名称加载该函数。即,a()。native端的函数签名没有什么问题,因为我只要把函数名改成Java_com_organization_app_Activity_a就调用成功了。我还尝试添加更多函数,这些函数的新名称分别变为b()和。c()

我在哪里调用该函数似乎也无关紧要,所以它onStart在这里说的事实是无趣的。

我尝试寻找有类似问题的人,但他们都是 C/C++ 中的函数签名问题。

标签: javaandroidc++java-native-interface

解决方案


我找到了解决方案。

我在 Debug 和 Release 之间做了一些交叉引用,发现关闭minifyEnabled或删除 proguard 文件声明会使异常消失。之后,我查看了我正在使用的 proguard 文件(它恰好是用于优化的默认文件)并看到了两个有趣的部分。

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
    native <methods>;
}

^ 本节应该确保我的本机函数没有从二进制文件中丢弃。为什么会发生这种情况,我仍然不知道。

# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep

^ 本节给了我一个想法,@Keep用来强制它不丢弃该功能。经过一些测试和确认,事实证明这是一个有效的解决方案。

我会做一些进一步的测试来找出收缩器没有保留我的原生功能的根本原因,但是因为我找到了解决方案,所以我会将它标记为已解决。希望这对将来遇到此问题的任何人有所帮助。


推荐阅读