如何在安卓应用中使用已有的.so文件

7
我在寻找适用于Android平台的将.doc/.docx转换成.pdf的库。
我得到了PdFTron Android SDK,其中包含libPDFNetC.so文件。
对于转换,有一个名为Convert的类,在其中有一个方法toPDF()。在该方法中,他们内部调用了本机方法FileToPdf()。我尝试过这段代码,但无法调用该本机方法并且一直出错。
我想知道如果您手头上有现有的.so文件,并且您想要调用其中存在的本机方法,那么是否需要使用JNI?我对JNI不太了解,请帮忙。
3个回答

4
您需要将使用ndk-build生成的最终共享库与您已经编译为ARM架构的PDF共享库链接起来。(请确保是这种情况,否则该库将无法在Android上运行!)
为此,例如,如果您有以下目录结构:
jni
└── libs
└────── my_shared_lib.so
└── Android.mk
└── Application.mk

你需要在Android.mk文件中添加以下内容:

LOCAL_PATH := $(call my-dir)

# define our prebuilt shared library as a module to the build system
include $(CLEAR_VARS)
LOCAL_MODULE := mysharedlib
LOCAL_SRC_FILES := libs/my_shared_lib.so
include $(PREBUILT_SHARED_LIBRARY)

# The final shared library that will be bundled inside the .apk
include $(CLEAR_VARS)
LOCAL_MODULE := mynativelib
LOCAL_LDLIBS := -landroid -llog
LOCAL_CPPFLAGS := -O0 -g3 -std=c++11 -Wall -Wextra 
LOCAL_SHARED_LIBRARIES := mysharedlib
LOCAL_C_INCLUDES := myheader1.h myheader2.h
LOCAL_SRC_FILES := src_file1.cpp src_file2.cpp
include $(BUILD_SHARED_LIBRARY)

以下是使用C++标准库并为两种不同版本的ARM架构构建最终共享库所需的Application.mk文件内容:

APP_OPTIM := debug
APP_PLATFORM := android-14
APP_STL := gnustl_static
APP_ABI := armeabi armeabi-v7a

在Eclipse中编译代码或使用ndk-build脚本从命令行编译代码后,会生成最终共享库并将其链接到预构建的共享库(即您要使用的PDF共享库)。对于共享库而言,生成和部署到设备/模拟器的apk包含最终共享库以及所有链接到的预构建共享库,与链接静态库不同,静态库没有打包在apk包内。在您的用例中,apk解压后应该在Android应用程序的lib目录中有两个共享库。您可以通过从终端运行以下命令来检查这一点:
adb shell ls -l /data/data/com.company.myapp/lib

将com.company.myapp替换为您的应用程序包名。

此外,不要忘记将以下内容放置在Java类的静态上下文中:

class MyClass
{
      static
      {
            try
            {
                System.loadLibrary("mynativelib");
            }
            catch (UnsatisfiedLinkError ule)
            {
               Log.e(TAG, "WARNING: Could not load native library: " 
                      + ule.getMessage());
            }
      }

       // other code here...
}

注意在System.loadLibrary方法调用中使用与最终共享库名称相同的名称。


2
你需要确保与本地接口相对应的 .so 文件在你的系统上可用,并且可以被 Java 找到。
在你的 Java 代码中应该有一个类似于 System.loadLibrary("<libraryname>") 或者 System.load("/path/to/libs/lib<libraryname>.so") 的调用。这将指示 JVM 搜索给定名称的库并加载它。
  • System.load("/path/to/libs/lib<libraryname>.so") 只会查找指定参数的文件并加载它。
  • System.loadLibrary("<libraryname.") 将在配置的库路径中查找名为 lib<libraryname>.so 的库。库路径来自系统变量 java.library.path
此外,请确保加载的库版本与 Java JNI 映射兼容!

谢谢回复,我已经尝试了system.load("data/data/package-name/libfile.so")方法,但是我仍然得到相同的错误。01-18 15:34:30.875: E/AndroidRuntime(26106): FATAL EXCEPTION: main 01-18 15:34:30.875: E/AndroidRuntime(26106): java.lang.RuntimeException: 重新抛出异常类缺少构造函数 01-18 15:34:30.875: E/AndroidRuntime(26106): at pdftron.PDF.Convert.FileToPdf(Native Method) 01-18 15:34:30.875: E/AndroidRuntime(26106): at pdftron.PDF.Convert.toPdf(SourceFile:642) - AndroUser
1
那个错误被截断了... 你能把错误放在代码标签之间发一下吗,这样我们就能看到出了什么问题? - Dieter Van de Walle
E/AndroidRuntime(16963): 致命的异常:主要 E/AndroidRuntime(16963): java.lang.RuntimeException:重新抛出异常类缺少构造函数 E/AndroidRuntime(16963):在pdftron.PDF.Convert.FileToPdf(Native Method)中 E/AndroidRuntime(16963):在pdftron.PDF.Convert.toPdf(SourceFile:642) 中 E/AndroidRuntime(16963):在java.lang.reflect.Method.invokeNative(Native Method)中 E/AndroidRuntime(16963):在java.lang.reflect.Method.invoke(Method.java:511) 中 E/AndroidRuntime(16963):运行于com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790) - AndroUser
E/AndroidRuntime(16963): 致命异常: 主要 E/AndroidRuntime(16963): java.lang.RuntimeException: 重新抛出异常类缺少构造函数 E/AndroidRuntime(16963): 在pdftron.PDF.Convert.FileToPdf(Native Method) E/AndroidRuntime(16963): 在pdftron.PDF.Convert.toPdf(SourceFile:642) E/AndroidRuntime(16963): 在java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime(16963): 在java.lang.reflect.Method.invoke(Method.java:511) - AndroUser
E/AndroidRuntime(16963): 在com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)处 E/AndroidRuntime(16963): 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)处 E/AndroidRuntime(16963): 在dalvik.system.NativeStart.main(Native Method)处 - AndroUser
显示剩余2条评论

0

要在ndk上工作,需要编译JNI下的.mk(make file)以获取.so文件。

.mk文件是使用c / c ++片段编写的本地代码。

现在,使用JNI进行编译有两种常见方法:

1.在使用旧ADT + SDK版本时: 您需要在Windows配置中配置Linux环境,以便在shell上运行JNI命令。可以通过各种可用于网络的软件(如cygwin setup)来实现此环境。

2.如果您使用的ADT + SDK版本已更新: 那么ADT本身就有一个NDK插件。因此,更容易在ndk和本地库上工作。 有关NDK的更多详细信息,请访问此处


感谢回复,但我已经编译了.so文件,我只想在我的Android应用程序中使用该文件。在这样做时,尝试访问本地代码时出现错误。谢谢。 - AndroUser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接