3

我构建了一个 android 应用程序,它使用 android NDK 来创建一个共享的本地库 (.so) 来计算 sha1,当它在一个自包含项目中时它工作得很好。最近虽然我将该项目变成了一个Android共享项目并将jni代码保留在那里..然后我创建了一个引用共享项目的新项目并且该项目似乎正常工作,除了在调用本机函数时我得到一个UnsatisfiedLinkError。本机函数从名为 Hash 的 Java 类中调用。在这个类中,有一些本机函数调用计算文件的 sha1 哈希值。

ndk/jni 代码正在编译,它确实进入了应用程序的 APK,但是我继续收到该错误。我已经在我的手机上卸载了该应用程序,完成了 ndk-build clean 以确保它没有得到旧的引用......等等,没有运气。我还确保我的 jni 函数的名称与

所以这是我的代码的要点:

哈希.java

package com.mydomain.sdk.util.Hash

public class Hash {
    static {
      System.loadLibrary("native_sha1")
    }

    public static native String getFileHashNative(String fileName);

}

然后我有(在同一个项目中

jni/Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE    := native_sha1
LOCAL_SRC_FILES := sha1.c sha1_native.c
include $(BUILD_SHARED_LIBRARY)

jni/sha1_native.c

jstring Java_com_mydomain_sdk_util_Hash_getFileHashNative(JNIEnv * env, jclass this, jstring fileName)
{
  //call function from sha1.c to get sha1, return to user
}

无论如何,这一切都很好,直到我改变了我的项目的结构,以便我可以重用公共代码(把它放到 android 库项目中)。如果我编译我的应用程序并打开 .apk 文件,我可以看到一个 lib 目录,其中有 armeabi/libnative_sha1.so 文件。因此,它肯定在那里,只是无法正常工作。

更新 - 一些调试信息

好的,所以我添加了一些调试。我将 loadLibrary 从静态块中取出并将其放入我在尝试调用 Hash.getFileHashNative 之前调用的函数中

12-15 12:34:13.143: D/Hash(31567): Attempting to load native_sha1 lib
12-15 12:34:13.153: D/dalvikvm(31567): Trying to load lib /data/data/com.mydomain/lib/libnative_sha1.so 0x4051e4f8
12-15 12:34:13.163: D/dalvikvm(31567): Added shared lib /data/data/com.mydomain/lib/libnative_sha1.so 0x4051e4f8

12-15 12:34:13.163: D/dalvikvm(31567): No JNI_OnLoad found in /data/data/com.mydomain/lib/libnative_sha1.so 0x4051e4f8, skipping init
12-15 12:34:13.163: W/dalvikvm(31567): No implementation found for native Lcom/mydomain/sdk/util/Hash;.getFileHashNative (Ljava/lang/String;)Ljava/lang/String;

我不确定是什么原因造成的,但它显然无法找到该功能。我唯一要修改的是 mydomain 的名称,其他一切都是准确的。另外请注意,我的库项目有包com.mydomain.sdk 的名称,我的应用程序项目只是 com.mydomain sha1 的源代码位于 com.mydomain.sdk.util.Hash 下的库项目中我不明白这里发生了什么。有任何想法吗?

4

1 回答 1

3

好吧,我讨厌回答我自己的另一个问题,但是经过几个小时的努力,我想我终于弄明白了。在我的应用程序清单中,我需要设置

AndroidManifest.xml

 <uses-library android:name="com.mydomain.sdk" android:required="true" />

这很奇怪,因为在我在线阅读的大多数文档中,他们没有提到使用它,我认为它只是与市场用于解决应用程序之间的依赖关系(而不是库的依赖关系)有关。我也觉得奇怪的是,当我没有那个项目时,项目编译和运行时至少没有发出警告。

-- 2014 年 1 月更新 --

应用程序不再需要编译和运行。如果您使用的是相对较新的(大约 1.5 年内)Android 构建工具,则根本不需要它。我已经一年多没有遇到这个问题了。

于 2011-12-15T23:45:39.357 回答