Compiling a library for Android
-
Hi,
I would like to use MediaInfo library in my application on Android.
There is no official Android support for this library but some people successfully compiled it. I downloaded the source-code and tried to compile it. I was able to create a libmediainfo.a static library. But I would like to build a shared (.so) library instead. How can I instruct QtCreator to do it?
Thank you.
-
Hi,
What build system is used for Mediainfo ?
-
-
@vlada said in Compiling a library for Android:
Is this correct?
yes.
Further I run into many dependencies problems but I do believe that QtCreator now tries to compile a dynamic library.
When compiling a static library the application/library including the static library has to make sure the dependencies are also linked.
Since you now compile a dynamic library you now already have to provide and link the dependencies (static or also dynamic). -
OK, now it is much more clear to me. So I have to compile also the other dependencies first and then create the shared library.
Now I found that someone already managed to compile the library for Android. I found it here.
So I tried to use it but I got this error:
D/dalvikvm( 1347): Trying to load lib /data/app-lib/org.qtproject.muzika-2/libmediainfo.so 0xb3d2cbf0
D/dalvikvm( 1347): Added shared lib /data/app-lib/org.qtproject.muzika-2/libmediainfo.so 0xb3d2cbf0
E/libmediainfo-jni( 1347): Native registration unable to find class 'org/mediainfo/android/MediaInfo'!
W/System.err( 1347): java.lang.reflect.InvocationTargetException
W/System.err( 1347): at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err( 1347): at java.lang.reflect.Method.invoke(Method.java:515)
W/System.err( 1347): at org.qtproject.qt5.android.bindings.QtLoader.loadApplication(QtLoader.java:237)
W/System.err( 1347): at org.qtproject.qt5.android.bindings.QtLoader.startApp(QtLoader.java:647)
W/System.err( 1347): at org.qtproject.qt5.android.bindings.QtActivityLoader.onCreate(QtActivityLoader.java:181)
W/System.err( 1347): at org.qtproject.qt5.android.bindings.QtActivity.onCreate(QtActivity.java:269)
W/System.err( 1347): at android.app.Activity.performCreate(Activity.java:5231)
W/System.err( 1347): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
W/System.err( 1347): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
W/System.err( 1347): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
W/System.err( 1347): at android.app.ActivityThread.access$800(ActivityThread.java:135)
W/System.err( 1347): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
W/System.err( 1347): at android.os.Handler.dispatchMessage(Handler.java:102)
W/System.err( 1347): at android.os.Looper.loop(Looper.java:136)
W/System.err( 1347): at android.app.ActivityThread.main(ActivityThread.java:5017)
W/System.err( 1347): at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err( 1347): at java.lang.reflect.Method.invoke(Method.java:515)
W/System.err( 1347): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
W/System.err( 1347): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
W/System.err( 1347): at dalvik.system.NativeStart.main(Native Method)
W/System.err( 1347): Caused by: java.lang.NoClassDefFoundError: org/mediainfo/android/MediaInfo
W/System.err( 1347): at java.lang.Runtime.nativeLoad(Native Method)
W/System.err( 1347): at java.lang.Runtime.doLoad(Runtime.java:421)
W/System.err( 1347): at java.lang.Runtime.load(Runtime.java:331)
W/System.err( 1347): at java.lang.System.load(System.java:512)
W/System.err( 1347): at org.qtproject.qt5.android.QtNative.loadBundledLibraries(QtNative.java:190)
W/System.err( 1347): at org.qtproject.qt5.android.QtActivityDelegate.loadApplication(QtActivityDelegate.java:504)
W/System.err( 1347): ... 20 more
W/System.err( 1347): Caused by: java.lang.ClassNotFoundException: Didn't find class "org.mediainfo.android.MediaInfo" on path: DexPathList[[zip file "/data/app/org.qtproject.muzika-2.apk"],nativeLibraryDirectories=[/data/app-lib/org.qtproject.muzika-2, /vendor/lib, /system/lib]]
W/System.err( 1347): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
W/System.err( 1347): at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
W/System.err( 1347): at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
W/System.err( 1347): ... 26 moreI don't understand very well what's going on here. It looks like the main application can not find the library. I checked the APK and the libmediainfo.so in in the directory lib/armeabi-v7a like all other shared libraries.
-
@vlada
This is a Java related error.
Caused by: java.lang.NoClassDefFoundError: org/mediainfo/android/MediaInfo
I don't know what happens in the code, but just from the error message your apk misses the java class
org.mediainfo.android.MediaInfo
-
@raven-worx Yes, that is about all I understood too. The error message comes form the Java wrapper in QtCreator. But the library (libmediainfo.so) is there. Where does the library name org.mediainfo.android.MediaInfo comes from?
I use TagLib the same way without any problems.
-
@vlada
i don't know this library.
But it seems you also have to deploy aorg.mediainfo.android.MediaInfo
Java class in your apk -
OK, now I see it. The source also contains a Java wrapper for the library. That is probably needed. But I found another library version from the same author.
This seems to work directly. Well at least the application now starts. But when I try to use the library, I get this error: "Unable to load libmediainfo.so.0"
Oh no again! I was fighting for many days to fix this error with TagLib. It is caused by the fact that Android doesn't know library versions but Linux on the other hand always creates hard links for these libraries and the programs link against them.
Where does the name (with .0 extension) come from? Isn't there any other way to solve it then to compile the library without any version? The project where I took the compiled library from is apparently able to use this library on Android.
-
@vlada said in Compiling a library for Android:
But when I try to use the library, I get this error: "Unable to load libmediainfo.so.0"
did you deploy this lib in the apk?
-
@raven-worx Yes, the library is included. But it's name is libmediainfo.so. I found it is referenced in the header file so I modified it to include Android specific library name:
#if defined(_WIN32) || defined(WIN32) #ifdef _UNICODE #define MEDIAINFODLL_NAME L"MediaInfo.dll" #else //_UNICODE #define MEDIAINFODLL_NAME "MediaInfo.dll" #endif //_UNICODE #elif defined(__APPLE__) && defined(__MACH__) #define MEDIAINFODLL_NAME "libmediainfo.0.dylib" #define __stdcall #ifdef __cplusplus #include <new> //for size_t #else /* __cplusplus */ #include <stddef.h> //for size_t #endif /* __cplusplus */ #elif defined(ANDROID) || defined(__ANDROID__) #define MEDIAINFODLL_NAME "libmediainfo.so" #define __stdcall #else #define MEDIAINFODLL_NAME "libmediainfo.so.0" #define __stdcall #endif //!defined(_WIN32) || defined(WIN32)
Here I added the lines regarding Android. Unfortunately it didn't help. During program execution I get this error:
D/dalvikvm( 3296): Trying to load lib /data/app-lib/org.qtproject.muzika-2/libmediainfo.so 0xb3d087b0
E/linker ( 3296): "libmediainfo.so": ignoring 2-entry DT_PREINIT_ARRAY in shared library!
D/dalvikvm( 3296): Added shared lib /data/app-lib/org.qtproject.muzika-2/libmediainfo.so 0xb3d087b0
D/dalvikvm( 3296): No JNI_OnLoad found in /data/app-lib/org.qtproject.muzika-2/libmediainfo.so 0xb3d087b0, skipping initIt seems the program can find the library. But when I actually try to use it, I get this error:
D/libMuzika.so( 3296): (null):0 ((null)): "Unable to load libmediainfo.so"In the header file (MediaInfoDLL.h) the library is then loaded with this command(s):
if (!MediaInfo_Module) MediaInfo_Module = dlopen(MEDIAINFODLL_NAME, RTLD_LAZY); if (!MediaInfo_Module) MediaInfo_Module = dlopen("./" MEDIAINFODLL_NAME, RTLD_LAZY);
Do you have any idea what the problem could be now?
-
-
Yes, I know about the problem with versioned libraries in Android. I spend many days before I made TagLib working in my application because of this. But in this case the problem is elsewhere.
I did some more tests and debugging with my limited skills and found out that the library is in fact loaded. The command
MediaInfo_Module = dlopen(MEDIAINFODLL_NAME, RTLD_LAZY);
returns a valid handle. But next in the header file are assigned functions of the library and this is where it fails. The code looks like this:
MediaInfo_Inform=(MEDIAINFO_Inform)dlsym(MediaInfo_Module, "MediaInfoA_Inform");
If I call
qDebug() << dlerror();
I get following error: "undefined symbol: MediaInfo_Inform". What should I try to find out what is the problem? Is it possible to find out what functions does the library provide? Thank you.
-
Thank you for the tip. So it seems it is not the correct library. This is the output I got from objdump (I found it when trying to find how to use nm):
DYNAMIC SYMBOL TABLE: 00000000 DF *UND* 00000000 __libc_init 00000000 DF *UND* 00000000 __cxa_atexit 00000000 DF *UND* 00000000 strcmp 00000000 DF *UND* 00000000 __errno 00000000 DF *UND* 00000000 lstat 00000000 DF *UND* 00000000 __stack_chk_fail 00000000 DO *UND* 00000000 __stack_chk_guard 00000000 DF *UND* 00000000 stat 00000000 DF *UND* 00000000 realloc 00000000 DF *UND* 00000000 malloc 00000000 DF *UND* 00000000 free 00000000 DF *UND* 00000000 strcpy 00000000 DF *UND* 00000000 opendir 00000000 DF *UND* 00000000 mbrtowc 00000000 DF *UND* 00000000 closedir 00000000 DF *UND* 00000000 readdir 00000000 DF *UND* 00000000 issetugid 00000000 DF *UND* 00000000 getlogin 00000000 DF *UND* 00000000 getenv 00000000 DF *UND* 00000000 getpwnam 00000000 DF *UND* 00000000 getuid 00000000 DF *UND* 00000000 getpwuid 00000000 DF *UND* 00000000 qsort 001deba9 g DF .text 00000068 operator new(unsigned int) 00000000 DF *UND* 00000000 pthread_mutex_init 00000000 DF *UND* 00000000 pthread_mutex_destroy 001deffd g DF .text 00000008 operator delete(void*) 00000000 DF *UND* 00000000 pthread_mutex_lock 00000000 DF *UND* 00000000 pthread_mutex_unlock 00000000 DF *UND* 00000000 mkdir 00000000 DF *UND* 00000000 truncate 00000000 DF *UND* 00000000 unlink 00000000 DF *UND* 00000000 rename 00000000 DF *UND* 00000000 wmemcmp 00000000 DF *UND* 00000000 memset 00000000 DF *UND* 00000000 fmodf 00000000 DF *UND* 00000000 fmod 00000000 DF *UND* 00000000 strlen 00000000 DF *UND* 00000000 pthread_attr_init 00000000 DF *UND* 00000000 pthread_attr_setdetachstate 00000000 DF *UND* 00000000 pthread_create 00000000 DF *UND* 00000000 sched_yield 000162a5 w DF .text 00000018 tolower 00000000 DO *UND* 00000000 _tolower_tab_ 000162bd w DF .text 00000018 toupper 00000000 DO *UND* 00000000 _toupper_tab_ 001df1f5 g DF .text 00000014 operator new[](unsigned int) 001dee45 g DF .text 00000004 operator delete[](void*) 00000000 DF *UND* 00000000 wcslen 00000000 DF *UND* 00000000 wcsncpy 00000000 DF *UND* 00000000 strncpy 00000000 DF *UND* 00000000 memcpy 00000000 DF *UND* 00000000 gmtime 00000000 DF *UND* 00000000 localtime 001de4a9 g DF .text 00000004 operator delete(void*, std::nothrow_t const&) 002f3fc0 g DO .rodata 00000001 std::nothrow 001df449 g DF .text 00000050 operator new(unsigned int, std::nothrow_t const &) 00000000 DF *UND* 00000000 strftime 00000000 DF *UND* 00000000 time 00000000 DF *UND* 00000000 memmove 00000000 DF *UND* 00000000 pow 00000000 DF *UND* 00000000 powf 00000000 DF *UND* 00000000 ceil 001df3f5 g DF .text 00000018 __cxa_pure_virtual 001de38d g DF .text 0000009a __cxa_guard_acquire 001de469 g DF .text 0000003e __cxa_guard_release 001de429 g DF .text 00000040 __cxa_guard_abort 00000000 DF *UND* 00000000 logf 00000000 DF *UND* 00000000 log 00000000 DF *UND* 00000000 log10 00000000 DF *UND* 00000000 log10f 00000000 DF *UND* 00000000 floorf 00000000 DF *UND* 00000000 memcmp 00000000 DF *UND* 00000000 strtod 00000000 DF *UND* 00000000 strchr 00000000 DF *UND* 00000000 atoi 00000000 DF *UND* 00000000 uncompress 00000000 DF *UND* 00000000 compress2 00000000 DF *UND* 00000000 atan2f 00000000 DF *UND* 00000000 ceilf 00000000 DF *UND* 00000000 setlocale 001d5d0d w DF .text 00000024 isspace 00000000 DO *UND* 00000000 _ctype_ 00000000 DF *UND* 00000000 strncmp 00000000 DF *UND* 00000000 snprintf 00000000 DF *UND* 00000000 sscanf 00000000 DF *UND* 00000000 fseek 00000000 DF *UND* 00000000 fgetc 00000000 DF *UND* 00000000 ferror 00000000 DF *UND* 00000000 ftell 00000000 DF *UND* 00000000 fread 00000000 DF *UND* 00000000 fopen 00000000 DF *UND* 00000000 fclose 00000000 DF *UND* 00000000 printf 00000000 DO *UND* 00000000 __sF 00000000 DF *UND* 00000000 vfprintf 00000000 DF *UND* 00000000 vsnprintf 00000000 DF *UND* 00000000 __android_log_print 00000000 DF *UND* 00000000 syscall 00000000 DF *UND* 00000000 abort 00000000 DF *UND* 00000000 pthread_key_delete 00000000 DF *UND* 00000000 pthread_getspecific 00000000 DF *UND* 00000000 pthread_setspecific 00000000 DF *UND* 00000000 pthread_key_create 00000000 DF *UND* 00000000 write 00000000 DF *UND* 00000000 acos 00000000 DF *UND* 00000000 asin 00000000 DF *UND* 00000000 atan 00000000 DF *UND* 00000000 atan2 00000000 DF *UND* 00000000 cos 00000000 DF *UND* 00000000 cosh 00000000 DF *UND* 00000000 exp 00000000 DF *UND* 00000000 frexp 00000000 DF *UND* 00000000 sqrt 00000000 DF *UND* 00000000 modf 00000000 DF *UND* 00000000 sin 00000000 DF *UND* 00000000 sinh 00000000 DF *UND* 00000000 tan 00000000 DF *UND* 00000000 tanh 00000000 DF *UND* 00000000 wmemcpy 00000000 DF *UND* 00000000 vsprintf 00000000 DF *UND* 00000000 memchr 00000000 DF *UND* 00000000 wcsftime 00000000 DF *UND* 00000000 pthread_once 00000000 DF *UND* 00000000 fflush 00000000 DF *UND* 00000000 fdopen 00000000 DF *UND* 00000000 setvbuf 00000000 DF *UND* 00000000 read 00000000 DF *UND* 00000000 writev 00000000 DF *UND* 00000000 lseek 00000000 DF *UND* 00000000 ioctl 00000000 DF *UND* 00000000 poll 00000000 DF *UND* 00000000 fstat 00000000 DF *UND* 00000000 wmemchr 00000000 DF *UND* 00000000 strcoll 00000000 DF *UND* 00000000 strxfrm 00000000 DF *UND* 00000000 wcscoll 00000000 DF *UND* 00000000 wcsxfrm 00000000 DF *UND* 00000000 fwrite 00000000 DF *UND* 00000000 getwc 00000000 DF *UND* 00000000 putwc 00000000 DF *UND* 00000000 getc 00000000 DF *UND* 00000000 ungetc 00000000 DF *UND* 00000000 ungetwc 00000000 DF *UND* 00000000 putc 00000000 DF *UND* 00000000 wmemset 00000000 DF *UND* 00000000 wmemmove 00000000 DF *UND* 00000000 wctype 00000000 DF *UND* 00000000 towupper 00000000 DF *UND* 00000000 towlower 00000000 DF *UND* 00000000 iswctype 00000000 DF *UND* 00000000 wctob 00000000 DF *UND* 00000000 btowc 00000000 DF *UND* 00000000 pthread_cond_destroy 00000000 DF *UND* 00000000 pthread_cond_wait 00000000 DF *UND* 00000000 pthread_cond_signal 00000000 DF *UND* 00000000 pthread_cond_broadcast 00000000 DF *UND* 00000000 strerror 00000000 DF *UND* 00000000 fputs 00000000 DF *UND* 00000000 fputc 00000000 DF *UND* 00000000 sprintf 00304458 g D *ABS* 00000000 _edata 00304458 g D *ABS* 00000000 __bss_start 0030a329 g D *ABS* 00000000 _end 00000000 w DF *UND* 00000000 __gnu_Unwind_Find_exidx 00000000 DF *UND* 00000000 raise
It is clear the functions I'm trying to use are simply not there. So I have probably no other option then to compile the library myself.