Как использовать существующий файл .so в приложении для Android

Я искал библиотеку, которая должна конвертировать .doc/.docx в .pdf на платформе Android.

Я получил PdFTron android sdk, в котором они предоставили файл libPDFNetC.so.

Для преобразования существует класс с именем Convert, внутри которого есть метод toPDF(), в этом методе они внутренне вызвали собственный метод FileToPdf(). Я пробовал этот код, но не смог вызвать этот собственный метод и получал ошибки

Я хочу знать, что если у вас есть существующий файл .so и если вы хотите вызвать собственный метод, который присутствует в файле .so, то нужно ли использовать JNI? я не знаю много о JNI. любая помощь.


person AndroUser    schedule 18.01.2013    source источник


Ответы (3)


Вы должны связать свою окончательную общую библиотеку, созданную Android NDK, с помощью ndk-build с общей библиотекой PDF, которую, как вы сказали, уже скомпилировали для архитектуры ARM. (Убедитесь, что это так, иначе библиотека не будет работать на 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)

и содержимое файла Application.mk (для использования стандартной библиотеки C++ и создания окончательной общей библиотеки для двух разных версий архитектуры ARM):

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

Затем, после того как вы скомпилируете свой код из Eclipse или из командной строки с помощью сценария ndk-build, он скомпилирует вашу окончательную общую библиотеку и свяжет ее с вашей предварительно созданной общей библиотекой (т. е. с общей библиотекой PDF, которую вы сказал, что вы пытаетесь использовать).

Для общих библиотек APK-файл, созданный и развернутый на устройстве/эмуляторе, содержит окончательную общую библиотеку, а также все предварительно созданные общие библиотеки, с которыми вы связаны, в отличие от связывания со статическими библиотеками, которые не связаны внутри апк.

В вашем случае у вас должно быть две общие библиотеки в каталоге lib вашего приложения Android после того, как apk будет распакован на устройстве. Вы можете проверить это, выполнив следующую команду из терминала:

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 в качестве конечного имени общей библиотеки.

person Alex Bitek    schedule 29.01.2013

Вам нужно убедиться, что файл .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!

person Dieter Van de Walle    schedule 18.01.2013
comment
Спасибо за ответ, я уже пробовал метод 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: re -throw при отсутствии конструктора класса исключения 01-18 15:34:30.875: E/AndroidRuntime(26106): в pdftron.PDF.Convert.FileToPdf(собственный метод) 01-18 15:34:30.875: E/AndroidRuntime(26106) : в pdftron.PDF.Convert.toPdf(SourceFile:642) 01-18 15:34:30.875: E/AndroidRuntime(26106): в - person AndroUser; 18.01.2013
comment
Эта ошибка обрезана... Можете ли вы опубликовать ошибку между тегами кода, чтобы мы могли увидеть, что происходит не так? - person Dieter Van de Walle; 18.01.2013
comment
E/AndroidRuntime(16963): НЕИСПРАВНОЕ ИСКЛЮЧЕНИЕ: main E/AndroidRuntime(16963): java.lang.RuntimeException: повторная выдача отсутствующего конструктора класса исключения E/AndroidRuntime(16963):at pdftron.PDF.Convert.FileToPdf(собственный метод ) E/AndroidRuntime(16963): at pdftron.PDF.Convert.toPdf(SourceFile:642) E/AndroidRuntime(16963): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime(16963): at java.lang.reflect.Method.invoke(Method.java:511) E/AndroidRuntime(16963):at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790) - person AndroUser; 18.01.2013
comment
E/AndroidRuntime(16963): НЕИСПРАВНОЕ ИСКЛЮЧЕНИЕ: main E/AndroidRuntime(16963): java.lang.RuntimeException: повторная выдача отсутствующего конструктора класса исключения E/AndroidRuntime(16963):at pdftron.PDF.Convert.FileToPdf(собственный метод ) E/AndroidRuntime(16963): at pdftron.PDF.Convert.toPdf(SourceFile:642) E/AndroidRuntime(16963): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime(16963): at java.lang.reflect.Method.invoke(Method.java:511) - person AndroUser; 18.01.2013
comment
E/AndroidRuntime(16963):at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790) E/AndroidRuntime(16963):at com.android.internal.os.ZygoteInit.main(ZygoteInit. java:557) E/AndroidRuntime(16963): в dalvik.system.NativeStart.main(собственный метод) - person AndroUser; 18.01.2013
comment
В коде я назвал метод toPDF() класса Convert, который присутствует в файле PDFNet.jar, из этого класса (метода) они внутренне вызывают собственный метод fileToPDF(), при доступе к этому методу я получаю вышеуказанные ошибки, также я добавил jar в пути сборки, так что с этим проблем нет, только проблема с доступом к файлу .so .. @Dieter Van de Walle ... спасибо - person AndroUser; 18.01.2013
comment
Пожалуйста, поместите журнал исключений на pastebin.com или что-то в этом роде, я действительно не могу это прочитать/понять. - person Dieter Van de Walle; 18.01.2013

Для работы с ndk существует .mk (создать файл), который компилируется под JNI для получения файла .so.

Файл .mk написан в собственном коде с использованием фрагмента c/c++.

Теперь для компиляции с использованием JNI есть два распространенных способа:

1.При работе со старыми версиями ADT + SDK: вам потребуется настроить среду Linux в конфигурации Windows для запуска команд JNI в оболочке. Эта среда может быть достигнута с помощью различного программного обеспечения, доступного в сети, такого как установка cygwin.

2.Если версии ADT + SDK, которые вы используете, обновлены: Тогда в самой ADT доступен подключаемый модуль NDK. Так проще работать с ndk и родной библиотекой. Подробнее о NDK см. здесь

person Arpit Garg    schedule 18.01.2013
comment
Спасибо за ответ, но я уже скомпилировал файл .so, только я хочу использовать этот файл в своем приложении для Android. При этом я получаю ошибки при попытке доступа к собственному коду. Спасибо. - person AndroUser; 18.01.2013