How to use Existing .so file in android application [closed] - android

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I was searching for library which should convert .doc/.docx to .pdf in android platform.
I got PdFTron android sdk,in that they have given libPDFNetC.so file.
For Conversion, there is class called Convert, inside that there is a method toPDF(),
in that method they have internally called native method FileToPdf().I tried that code but unable to call that native method and was getting errors
I want to know that if there is existing .so file present with you and if you want to call native method which is present in .so file then is there need to use JNI?. i dont know much about JNI. any help.

You have to link your final shared library that is generated by the Android NDK using the ndk-build to the PDF shared library you said you already have compiled for the ARM architecture.
(Ensure that this is the case, otherwise the library won't work on Android!)
For that, if for example you have the following directory structure:
jni
└── libs
└────── my_shared_lib.so
└── Android.mk
└── Application.mk
You need to have the following content inside the Android.mk file:
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)
and the contents of the Application.mk file (for using the C++ Standard Library, and build the the final shared library for two different versions of the ARM architecture):
APP_OPTIM := debug
APP_PLATFORM := android-14
APP_STL := gnustl_static
APP_ABI := armeabi armeabi-v7a
Then after you compile your code from within Eclipse or from the command line using the ndk-build script it'll compile you final shared library and link it against your prebuilt shared library (i.e. the PDF shared library you said you are trying to use).
For shared libraries the apk that is generated and deployed to the device/emulator contains the final shared library as well as all the prebuilt shared libraries you linked against, in contrast with linking against static libraries which are not bundled inside the apk.
For your use case you should have two shared libraries in the lib directory of your Android application after the apk is unpacked on the device.
You can check this by running the following command from a terminal:
adb shell ls -l /data/data/com.company.myapp/lib
Replace com.company.myapp with your application's package name.
Also, don't forget to put the following inside a static context of a Java class:
class MyClass
{
static
{
try
{
System.loadLibrary("mynativelib");
}
catch (UnsatisfiedLinkError ule)
{
Log.e(TAG, "WARNING: Could not load native library: "
+ ule.getMessage());
}
}
// other code here...
}
Notice the use of the same name inside the System.loadLibrary method call as the final shared library name.

You need to make sure the .so file that maps to the native interface is available on your system, and can be found by Java.
There should be a call like System.loadLibrary("<libraryname>") or System.load("/path/to/libs/lib<libraryname>.so") somewhere in your Java code.
That will instruct the JVM to search for the library with the given name and load it.
System.load("/path/to/libs/lib<libraryname>.so") will just look for the file specified as argument, and load it.
System.loadLibrary("<libraryname.") will look in the configured library path for a library with the name lib<libraryname>.so . The library path is taken from the system variable java.library.path .
Also make sure that the library version you are loading is compatible with the Java JNI mapping!

To work on ndk , there is a .mk (make file) that is complied under JNI to get the .so file.
.mk file is written in the native code using the c /c++ snippet.
Now to compile using JNI , there are the two common ways:
1.While working old ADT + SDK versions:
You would require a linux environment to be configured on the windows configuration for running the JNI commands on shell. This environment can be achieved via various software available on net such as cygwin setup.
2.If the ADT + SDK versions that you use are updated:
Then there is a NDK pluggin available in ADT itself . So it easier to work on the ndk and native library.
For more details on NDK visit here

Related

Call shared library (.so) methods within Android Studios C files

I'm struggling with this for several days now. At the moment i'm just testing it with a simple C++ project (1 .h & 1 .cpp file) and a minimalistic App including the ndk helloJNI sample code (which worked perfect easily):
Target
Import existing C/C++ files (project) to Android Studio
Approach
After trying out some of the (dozens) of different possibilities, i think/thought the following steps would be the best solution for my purpose:
Create the shared library (Calculator.so) from Visual Studios 2015 "Create shared library for Android" (or something) [successful]
Create jniLibs folder in src/main/ with its subfolders (x86 the relevant one in my case)
Add the Android.mk file in src/main/jniLibs which has to be placed there (?)
Include statement: System.loadLibrary("Calculator") without "lib" and ".so" in MainActivity
The library is listed in Android Studio in its folder jniLibs as like the Android.mk. Moreover if i build the apk, the library is successfully packed (verified by unzipping) and i dont get any errors.
BUT: how can i call the methods in the library? I tried the different solutions offered in other threads, but i think i missed something in my .mk or my steps described above.
Tried
Different #include <myLib> statements in native-lib.cpp, like s
Different Android.mk settings (but i'm new to make files so not even tutorials helped me much with my specific problem ::) )
Other locations for the libCalculator.so like in the subfolder x86
and many others - simply not reminding atm (wasntme)
Your help is highly appreciated!
Android.mk
LOCAL_PATH := $(call my-dir)
APP_ABI := x86
# library info
include $(CLEAR_VARS)
LOCAL_MODULE := Calculator
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/Calculator.so
LOCAL_EXPORT_C_INCLUDES := ..../Visual Studio 2015/Projects/SO_Library/SO_Library
include $(BUILD_SHARED_LIBRARY)
There are lots of things, you can do in Android NDK. For example, Camera hardware is one of the heaviest hardware in Android OS. Detecting faces, things, giving effects and for thousands of features NDK is the best.
Some helps for your steps:
You can built and prebuilt shared(.so) and static(.a) libraries in Android Studio also. Not need Visual Studio.
Don't create jniLibs folder in main folder. When you build your project via gradle, it already creates this folder and put your target libraries. If you want prebuilt any libraries, put these libraries in main/jni/libs folder and prebuilt then with Android.mk.
Don't add the Android.mk file in jnilibs folder. Create this file in main/jni folder. Also Application.mk file.
Call your libraries, in any activity, where you need, in static method. Like this:
static { System.loadLibrary("my_library") }
Without "lib" and ".so" extensions.
When you want to call your native methods, just use "native" keyword. For example:
private native int nGetNumberFromNativeSide();
Just call this method, where you want, and get result. But for ndk building in gradle side, look at this answer. For building library in Android.mk, these sample lines maybe help you:
include $(CLEAR_VARS)
ifneq (,$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86 arm64-v8a x86_64))
LOCAL_MODULE := my_library
LOCAL_SRC_FILES := $(LOCAL_SRC_LOCATION)/native1.cpp native2.cpp
include $(BUILD_SHARED_LIBRARY)
You can put name anything you want, but dont add lib and .so extensions. Ndk is already doing it.
I have already gave Android.mk example.
When you build Android.mk file, it locates your libraries appropriate folder. Like main/libs/x86/libmy_library.so.
I guess this answer will help you. If you have more questions, add to comment, i'll edit my answer and add answers.

Dalvik is looking for .so file with '.0' extension - why?

I have started developing a very simple Android application that consists of three parts:
the Java application itself
a pre-built shared library (we'll call it libfoo)
another shared library that uses the pre-built library (we'll call it libfoowrapper)
The file system looks something like this:
jni
Android.mk
libfoo.so
foowrapper.c
The Android.mk file contains the following contents:
LOCAL_PATH := $(call my-dir)
#==============================
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILT_SHARED_LIBRARY)
#=========================
include $(CLEAR_VARS)
LOCAL_MODULE := foowrapper
LOCAL_SRC_FILES := foowrapper.c
LOCAL_SHARED_LIBRARIES := foo-prebuilt
include $(BUILD_SHARED_LIBRARY)
When I build the application in Eclipse, things seem to work fine - no errors are reported. However, when I upload the application to my Samsung Discover (running Android 4.0.4), I get the following error in the log:
03-05 21:20:27.859: E/AndroidRuntime(20324): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1936]: 102 could not load needed library 'libfoo.so.0' for 'libfoowrapper.so' (load_library[1091]: Library 'libfoo.so.0' not found)
Why is the Dalvik looking for a .so.0 file instead of a .so file? What changes do I need to make to my app to get rid of this error?
At least in the Linux world, every shared library has a special name called the soname. The soname has the prefix lib, the name of the library, the phrase .so, followed by a period and a version number that is incremented whenever the interface changes (as a special exception, the lowest-level C libraries don't start with lib). A fully-qualified soname includes as a prefix the directory it's in; on a working system a fully-qualified soname is simply a symbolic link to the shared library's real name.
Every shared library also has a real name, which is the filename containing the actual library code. The real name adds to the soname a period, a minor number, another period, and the release number. The last period and release number are optional. The minor number and release number support configuration control by letting you know exactly what version(s) of the library are installed. Note that these numbers might not be the same as the numbers used to describe the library in documentation, although that does make things easier.
Reference: Linux Standard Base
Edit:
It seems this is not an uncommon problem, haven't seen any real solutions to it, but perhaps this will get you started to finding something that works for you.
Problem with LOCAL_SRC_FILES when using PREBUILT_SHARED_LIBRARY
https://groups.google.com/forum/#!topic/android-ndk/_UhNpRJlA1k
Creating non-versioned shared libraries for android
http://www.opengis.ch/2011/11/23/creating-non-versioned-shared-libraries-for-android/
Library 'libproj.so.0' not found
https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/ai3tu0XXs88

How to link to the libmedia.so system library in an Android NDK app using android.mk?

I want to create a Player which uses Android system/lib/libmedia.so.
Directly use JNI to play a video.
In Android.mk, i add "-lmedia" for including the library, but i can't link this directly.
This is my process.
write a Cpp file which includes some header file in libmedia.so
add "-lmedia" in Android.mk of LOCAL_LDLIBS
such as..
LOCAL_LDLIBS -lmedia -lstagefright
use ndk-build to build .so
error occured!!
Does anybody have some answer to help???
libmedia.so and libsinstructionght.so are not part of the public API. This means that in theory, you should not rely on them. In practice, though, these libraries are present on all devices, but they are different.
You can extract this binary file from your device, or even from an emulator using command
adb pull /system/lib/libmedia.so C:/android-ndk/platforms/android-14/arch-arm/usr/lib
This will put ths file together with the public API so that using it with ndk-build is easier. On the other hand, you should be aware of fragmentation not lnly between different levels of Android, but also chipsets, manufacturers, and even models.
To handle this, I pull .so files from different devices into separate directories, and add one of them to the linker path, e.g.
LOCAL_LDLIBS += -Lc:/android/galaxys.4.1.2.system.lib
This instruction above can not resolve the big problem you are facing with your approach. libmedia.so is not intended to be linked to user apps. It assumes the context of a privileged user with access to protected devices, such as camera, codecs, and screen.
You can make full use of this library if you target a rooted device, or prepare a custom ROM. And know what you are doing, and how to avoid stealing essential resources from the system.
Otherwise there is very little gain in linking the media lib.
PREBUILT_SHARED_LIBRARY
Points to a build script used to specify a prebuilt shared library.
Unlike BUILD_SHARED_LIBRARY and BUILD_STATIC_LIBRARY, the value
of LOCAL_SRC_FILES must be a single path to a prebuilt shared
library (e.g. foo/libfoo.so), instead of a source file.
You can reference the prebuilt library in another module using
the LOCAL_PREBUILTS variable (see docs/PREBUILTS.html for more
information).
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILT_SHARED_LIBRARY)
Refrenced from NDK documentation.
PREBUILT_STATIC_LIBRARY
This is the same as PREBUILT_SHARED_LIBRARY, but for a static library
file instead. See docs/PREBUILTS.html for more.
Please read the NDK documentation for more details.

android using external shared library

I am facing issues in using an external shared library in my Android application. I created an Android.mk file as given below:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyApp
LOCAL_SRC_FILES := myexternallib.so
include $(PREBUILT_SHARED_LIBRARY)
Using ndk-build I am able to generate a local native library and I use this native library in my System.loadLibrary method.
When I run the application I get an error java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1486]: 2659 unknown reloc type 19 # ( 4220)
On further search I found a link which recommends to build the shared library using the android toolchain. So I used one of the toolchain arm-eabi-gcc, which is available in the prebuilt/linux_x86/toolchain/arm-eabi-4.4.3/bin directory of the android source code, to build my source files. I get an error arm-eabi-gcc: error trying to exec 'cc1': execvp: No such file or directory. I also noticed that the toolchain folder does not have a file named cc1.
Am I following the right procedure? Is there some other way to reference external shared library in Android code?
It is true that you should use Android toolchain.
Android NDK comes with detailed instructions on using its toolcahin: http://source-android.frandroid.com/ndk/docs/STANDALONE-TOOLCHAIN.html. If you have specific questions about this document, feel free to ask.

Eclipse does not create shared library file in the mixed project (NDK and Java)

I have a project in Eclipse which mixes native and Java code using CDT and ADT. It is really simple - demo project, just as in the android-ndk-r7/ samples/hello-jni
My Android.mk (in the /jni folder) is:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := hlsdrm
LOCAL_SRC_FILES := hlsdrm.cpp
include $(BUILD_SHARED_LIBRARY)
Everything compiles fine, I can load hlsdrm library by
System.loadLibrary("hlsdrm");
and call the native functions. But where is the library file placed? There is no libhlsdrm.so shared library in any of the project folders. As I could read, it should create a folder "libs" and place the resulting library in it.
Also, when I try to list libraries which is used by the application process by calling:
PackageManager pm = getPackageManager();
String applicationPackage = this.getApplicationInfo().packageName;
ApplicationInfo ai = pm.getApplicationInfo(applicationPackage, PackageManager.GET_SHARED_LIBRARY_FILES);
String[] soFiles = ai.sharedLibraryFiles;
then the soFiles variable is empty...
I have tried to specify the library by uses-library value in the application section of the manifest, but after then Android OS refuses to install that application and shows INSTALL_FAILED_MISSING_SHARED_LIBRARY error.
Can anybody explain me how can I get my shared library - the physical .so file?
Why the sharedLibraryFiles is empty even though the library loads and the native method can be called?
How can I install the application that requires custom shared library?
First of all, you should create libs folder and set up your project.
Refer to following article to do that:
http://maxters.net/2011/02/android-ndk-builder-for-eclipse-in-windows/
Regarding the library: it should be installed in /data/data/com.company.yourApp/lib/libhlsdrm.so
Btw: soFiles is not supposed to contain native libraries (.so files), but .jar files. For example if you specify in you manifest <uses-library android:name="com.google.android.maps" /> your soFiles variable will contain /system/framework/com.google.android.maps.jar

Categories

Resources