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.


  • Lifetime Qt Champion

    Hi,

    What build system is used for Mediainfo ?



  • By default it uses automake. After some trials I think I just need to comment out this line:

    CONFIG += staticlib
    

    Is this correct? Further I run into many dependencies problems but I do believe that QtCreator now tries to compile a dynamic library.


  • Moderators

    @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 more

    I 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.


  • Moderators

    @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.


  • Moderators

    @vlada
    i don't know this library.
    But it seems you also have to deploy a org.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.


  • Moderators

    @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 init

    It 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?


  • Moderators

    @vlada
    seems like Android has issues loading versioned libs.



  • 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.


  • Moderators

    @vlada You can use nm tool to list all symbols:

    nm MY_LIB.so
    


  • 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.


  • Moderators

    @vlada Are you sure you called objdump on that library? That list looks like a dump from a C standard library.



  • Yes, I'm pretty sure I called it on the correct library. Or at least I thought it is the correct library. I found it here.

    I hope I will have some time over the weekend to try to compile it myself.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.