Adding a 3rd-party sharedlib to the android package

2,320 views
Skip to first unread message

Progman3K

unread,
Jul 25, 2012, 4:29:20 PM7/25/12
to andro...@googlegroups.com
Hi,

I'm using the native-activity sample as a base.

I wish to dynamically load and call into a 3rd-party shared-library.
All I have is the externally-produced file libfoo.so and the knowledge of the name of one of the functions

The project has no links to the shared-library.

for example:

void android_main( struct android_app * state ) {

    void * handle = dlopen( "foo", RTLD_LAZY );
   
    if ( ! handle ) {

        return -1;
       
    }

    typedef int (*FOOPROC)( int );

    FOOPROC fooproc = (FOOPROC)dlsym( handle, "fooproc" );

    if ( NULL != fooproc ) {

        int iRet = fooproc( 0 );


    }

}


So how do I get the binary file included in the android package if there is no link to it in any of the project files or which file must I modify to add the binary?

RichardC

unread,
Jul 25, 2012, 5:18:45 PM7/25/12
to andro...@googlegroups.com
Put it into the correct (for the ABI) sub folder below libs in your project.

Progman3K

unread,
Jul 25, 2012, 5:50:01 PM7/25/12
to andro...@googlegroups.com

I tried that, I put the file in the proper architecture folder, right alongside where the project-compiled shared library winds up:


$ ls -l lib/armeabi
total 404
-rwxr-xr-x 1 jc jc 394887 Jul 25 12:16 libfoo.so
-rwxr-xr-x 1 jc jc  14548 Jul 25 16:17 libnative-activity.so

$ file lib/armeabi/libfoo.so
libfoo.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped

And no even though the libnative-activity.so file gets included into the .apk file, libfoo.so does not.

RichardC

unread,
Jul 25, 2012, 6:05:41 PM7/25/12
to andro...@googlegroups.com
Works for me:
  1. In Eclipse opened an existing project that does not have a libs folder.
  2. Created a lib/armeabi folder
  3. From Windows explorer grabbed a random libfoo.so from a different project and dropped into the above folder
  4. Back in Eclipse made a trivial change to AndroidManifest.xml to force a rebuild (do not clean as it will delete the contents of the libs folder!)
  5. Deployed to my phone from Eclipse "Debug As > Android Application"
  6. Grabbed the project's apk file from the bin folder.
  7. Renamed to to .zip and opened it
  8. lib/armeabi/libfoo.so was in the apk deployed to the phone

Progman3K

unread,
Jul 25, 2012, 6:13:21 PM7/25/12
to andro...@googlegroups.com
I'm working strictly from the command-line, here's my build procedure:

ndk-build clean
ndk-build NDK_DEBUG=0 V=1
android update project -p . --target 1 --subprojects
ant release
jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 bin/*-release-unsigned.apk
zipalign -v 4 bin/*-release-unsigned.apk bin/output.apk

The produced .pkg file never contains libfoo.so

RichardC

unread,
Jul 25, 2012, 6:28:51 PM7/25/12
to andro...@googlegroups.com
Is your library still in the libs folder when the build ends?  The "ndk-build clean" will delete it and you don't show where in your build procedure you copy the file back into libs.

The rest of your build looks normal and the packaging process is not clever enough to workout dependences in the libs folder and just grabs it all.

Progman3K

unread,
Jul 26, 2012, 4:22:28 PM7/26/12
to andro...@googlegroups.com
You're right, what was happenning is the build command would wipe the output folders first.

It also apparently only adds files to the package if they end in .so

What would you do if you wanted to include a datafile?

So the way I've gotten it to work is that any 3rd-party lib you want to link against must be copied anywhere else but the lib folder for the link stage, but it MUST be copied to the lib folder after the build so the project update step will include it in the package...

Is that the correct way to do it?

Dan V.

unread,
Jul 30, 2012, 10:26:04 PM7/30/12
to andro...@googlegroups.com
Here's how I do it, without messing around in the intermediate build stages:

In Android.mk, define your extra library as a prebuilt, e.g.

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := mylibs/libfoo.so
include $(PREBUILT_SHARED_LIBRARY)

In Application.mk, add the module for packaging, e.g.

APP_MODULES := native-activity foo

Now an ant build will include libfoo.so alongside libnative-activity.so (e.g. /data/data/com.example.native_activity/libs/libfoo.so)

If you want to add data files consider using the asset manager class.

Fabien R

unread,
Jul 31, 2012, 3:22:27 AM7/31/12
to andro...@googlegroups.com
On 25/07/2012 23:50, Progman3K wrote:
> I tried that, I put the file in the proper architecture folder, right
> alongside where the project-compiled shared library winds up:
>
>
> $ ls -l lib/armeabi
>
Pay attention. Depending on your ADT version, the directory shall be
"lib" or "libs".
-
Fabien

Progman3K

unread,
Aug 2, 2012, 5:04:28 PM8/2/12
to andro...@googlegroups.com
OK, I've tried every permutation I could think up of what you suggested and couldn't get it to work.

I'm starting from the native-activity sample, so please consider that as a starting point.

The existing jni/Android.mk file contains this:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := native-activity
LOCAL_SRC_FILES := main.c
LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM -ldl
LOCAL_STATIC_LIBRARIES := android_native_app_glue

include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/native_app_glue)


Do I add the lines you said to the beginning of this? At the end? In a different file? If in a different file, where is this file located in the project tree?

I really did try every variation I could think of and can't seem to get it to work.

Please help!

Progman3K

unread,
Aug 2, 2012, 6:17:08 PM8/2/12
to andro...@googlegroups.com
I tried like this:

jni/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := native-activity
LOCAL_SRC_FILES := main.c
LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM -ldl
LOCAL_STATIC_LIBRARIES := android_native_app_glue

include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/native_app_glue)


LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := simplelib
LOCAL_SRC_FILES := libsimplelib.so
include $(PREBUILT_SHARED_LIBRARY)

When I build

ndk-build NDK_DEBUG=0 V=1
Android NDK: ERROR:/opt/android-ndk-r8/sources/android/native_app_glue/Android.mk:simplelib: LOCAL_SRC_FILES points to a missing file   
Android NDK: Check that /opt/android-ndk-r8/build/core/libsimplelib.so exists  or that its path is correct  
/opt/android-ndk-r8/build/core/prebuilt-library.mk:43: *** Android NDK: Aborting    .  Stop.

Why is it looking for simplelib in /opt/whatever when I explicitly added it to LOCAL_SRC_FILES???




On Monday, July 30, 2012 10:26:04 PM UTC-4, Dan V. wrote:
On Monday, July 30, 2012 10:26:04 PM UTC-4, Dan V. wrote:

Dan V.

unread,
Aug 5, 2012, 9:45:35 PM8/5/12
to andro...@googlegroups.com
Try calling my-dir only once, e.g.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := simplelib
LOCAL_SRC_FILES := libsimplelib.so
include $(PREBUILT_SHARED_LIBRARY) 

include $(CLEAR_VARS)
LOCAL_MODULE    := native-activity
LOCAL_SRC_FILES := main.c
LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM -ldl
LOCAL_STATIC_LIBRARIES := android_native_app_glue
include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/native_app_glue)


Progman3K

unread,
Aug 7, 2012, 5:08:14 PM8/7/12
to andro...@googlegroups.com
Thank you, Dan!
That does work!

From what I understand, the path the library gets extracted to (in the sample app) is

/data/data/com.example.native_activity/lib/

Which apparently relies on the value

        package="com.example.native_activity"

from the AndroidManifest.xml file.

Is there a way for a native application to query the manifest?

Thank you very much for the clarifications, you've really lit the way!

Tor Lillqvist

unread,
Aug 8, 2012, 3:25:28 AM8/8/12
to andro...@googlegroups.com

Is there a way for a native application to query the manifest?


Don't fall into the trap of thinking that just because you write your own code of your app as "native" code, that your app would be a "native app". There are no "native apps". There are just apps that use some native libraries (built with the NDK) included with the app (in addition to the system native libraries). They still run with a Java (well, Dalvik) virtual machine in the process, and the "main" of the app is (system-provided) Java code. So you really don't lose any performance or whatever by writing parts of your app in Java, those parts that need to call the Android Java APIs, to find out the application's data directory for instance.

--tml


Progman3K

unread,
Aug 8, 2012, 1:00:01 PM8/8/12
to andro...@googlegroups.com
Thank you, Tor.

Your advice is sage.
It's just that I have an existing c/c++ app to port.

With the NDK it is possible to make normal, native apps; with the possible caveat that they should be text-mode.
Graphical apps, I assume must be done in concert with the Java VM.

So I think my question should be
Is there a concise reference of how to read Dalvik's variables and is there a list of the more interesting variables?

Tor Lillqvist

unread,
Aug 8, 2012, 2:47:19 PM8/8/12
to andro...@googlegroups.com

With the NDK it is possible to make normal, native apps; with the possible caveat that they should be text-mode.

If you mean free-standing Linux executables (for ARM, that link against Android system libraries), that read / write text from stdin /  stdout, those aren't "apps" in the Android ense. You won't be able to install and run such executables on normal non-rooted Android devices. And this group is, to the best of my knowledge, about developing native code using the NDK for normal Android apps, not code to be run on rooted devices.

--tml

Ian Ni-Lewis

unread,
Aug 8, 2012, 2:57:32 PM8/8/12
to andro...@googlegroups.com
More to the point, a free-standing Linux executable wouldn't have a manifest, rendering the OP's question moot.

It is possible, using the NDK and NativeActivity, to make an app without writing any Java code. This should not be confused with writing an app that has no Dalvik bytecode in it. NativeActivity still runs under the Dalvik VM--it just takes care of some of the boilerplate that you'd otherwise have to write to manage your C++ code under the vanilla Activity class.


--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To view this discussion on the web visit https://groups.google.com/d/msg/android-ndk/-/5OE2-QeeZjcJ.

To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.



--
Ian Ni-Lewis
Developer Advocate
Android Developer Relations


Reply all
Reply to author
Forward
0 new messages