Where to put plugin .so files for Android builds?

Hi,

Where should I put my compiled enterprise plugin .so files in order to get them into a Corona deployment build for Android devices?

Up until now I have only built dylib plugin files for the simulator and put them into “./Library/Application Support/Corona/Simulator/Plugins/” and the simulator finds them happily. In order to build the dylib files I skipped the Xcode build stuff and wrote a 20 row Makefile which generate the dylib file.

I would prefer to build the corresponding .so plugin files (for the Android device) using my own short Makefile as well instead of using Android Studio and gradle build inferno.

So the question is: Where should I put compiled plugin .so files so that the Corona build support adds them into the Android device build?

Kind regards

/Joakim

This is how I build own of my plugins for the simulator:

spock:sodium jocke$ ls -l total 8 drwxr-xr-x  22 jocke  staff   748 22 Nov 20:44 Corona -rw-r--r--   1 jocke  staff  2307 18 Nov 20:22 Readme.markdown drwxr-xr-x  12 jocke  staff   408 18 Nov 20:22 android drwxr-xr-x  13 jocke  staff   442 18 Nov 20:22 ios drwxr-xr-x   5 jocke  staff   170 14 Jan 09:51 mac drwxr-xr-x   3 jocke  staff   102 22 Nov 11:43 shared drwxr-xr-x   8 jocke  staff   272 18 Nov 20:22 tvos drwxr-xr-x   4 jocke  staff   136 18 Nov 20:22 win32 spock:sodium jocke$ cd mac/ spock:mac jocke$ ls -l total 40 lrwxr-xr-x  1 jocke  staff    30 18 Nov 20:22 CoronaEnterprise -\> /Applications/CoronaEnterprise -rw-r--r--  1 jocke  staff   521  1 Dec 10:45 Makefile -rwxr-xr-x  1 jocke  staff  9468 14 Jan 09:51 plugin\_sodium.dylib spock:mac jocke$ make gcc -I../../../../vendor/include -I./CoronaEnterprise/Corona/shared/include/Corona -I./CoronaEnterprise/Corona/shared/include/lua -pedantic -L../../../../vendor/lib -undefined dynamic\_lookup -dynamiclib -lsodium -o plugin\_sodium.dylib ../shared/sodium.c spock:mac jocke$ ls -l plugin\_sodium.dylib -rwxr-xr-x  1 jocke  staff  9468 14 Jan 20:12 plugin\_sodium.dylib spock:mac jocke$ cat Makefile INSTALLDIR="/Users/jocke/Library/Application Support/Corona/Simulator/Plugins" CFLAGS=-I../../../../vendor/include -I./CoronaEnterprise/Corona/shared/include/Corona -I./CoronaEnterprise/Corona/shared/include/lua -pedantic LFLAGS=-L../../../../vendor/lib -undefined dynamic\_lookup -dynamiclib LIBS=-lsodium LIBFILE=plugin\_sodium.dylib all: gcc $(CFLAGS) $(LFLAGS) $(LIBS) -o $(LIBFILE) ../shared/sodium.c install: install $(LIBFILE) $(INSTALLDIR) uninstall: rm -f $(INSTALLDIR)/$(LIBFILE) clean: @rm -f $(LIBFILE)

I sat down and read (again):

https://docs.coronalabs.com/native/index.html
and then
https://docs.coronalabs.com/native/android/index.html
and then
https://docs.coronalabs.com/native/android/androidProject.html

Like Pandora’s box.

In my idealised world I thought it would be enough to manage my own AndroidManifest.xml file to specify which permissions I need for my app. Then to compile my plugins to statically linked .so files into a certain location in order for Corona to find them during its Android APK build phase.

It seems that even though I opted for Corona (Enterprise) I still have to find my way through the Android Java API and its SDK, Android Studio settings, gradle scripts and more. I have a hard time realising what to do and what *not* to do when reading the documentation I referred to above.

I can delve into all the Android Java API/SDK stuff including the workings of Android Studio and gradle scripts and more but I would prefer to be shielded from that as much as (reasonably) possible.

Maybe I misunderstand something central?

Cheers
/Joakim

Corona does not cover the native, as they expect you to cover it yourself. I found it much easier to learn through their examples (in the downloaded Sample folder) and also their online codes here : https://bitbucket.org/coronalabs

When you package your plugin for distribution the ‘.so’ files should be put in an armeabi-v7a directory under android.

plugins/2016.2830/android/armeabi-v7a   

                 /iphone

                 /iphone-sim

                 /mac-sim

                 /win32-sim

Thanks. Had a bad day. I will heed your advice. Nothing is so simple as believed by the fool.

Cheers
Joakim

I looked at the https://bitbucket.org/coronalabs/store-hosted-luaproc plugin and it has the following:

$ pwd /Users/jocke/Downloads/coronalabs-store-hosted-luaproc-af6c895766b4 $ ls -l plugins/2016.2872/android/ total 1768 -rwxr-xr-x@ 1 jocke  staff  893452 27 Dec 00:23 libplugin.luaproc.so -rwxr-xr-x  1 jocke  staff     178 16 Jan 09:28 metadata.lua -rwxr-xr-x@ 1 jocke  staff     179 27 Dec 00:23 metadata.lua~ spock:coronalabs-store-hosted-luaproc-af6c895766b4 jocke$ cat metadata.json  {     "contact": "steve@xibalbastudios.com",     "url": "http://www.xibalbastudios.com",     "pluginName": "plugin.luaproc",     "publisherId": "com.xibalbastudios" }

I tried to use the same naming convention in my app:

$ ls -l android/ total 256 -rwxr-xr-x  1 jocke  staff  124812 14 Jan 22:57 libplugin.sodium.so -rw-r--r--  1 jocke  staff     167 16 Jan 09:27 metadata.lua

I built the APK and tried but the device can still not find the plugin. I then tried to put the .so file under android/armeabi-v7a instead. Then under libs. Nothing worked on the device.

Any hints?

I must be reading the wrong documentation. Or too many of them. :slight_smile:

Cheers

/Joakim

You are planning to submit the plugin to the Corona Marketplace, right?

I just plan to use my plugin in my app. I will be using the luaproc store plugin as well but both of them (their .so files and metadata.lua files) have to be put in the correct position in order for the APK to work in the end.

Aha. I thought you were trying to submit a plugin to the Corona Marketplace. Disregard everything I’ve said so far as it only applies to Marketplace plugin submissions  :slight_smile:
 
To include ‘.so’ files into your Android Studio project you’ll need to do a few things:
 

  1. Copy all the extra ‘.so’ files you plan to use into the directory app/libs/armeabi-v7a
    (forget about the metadata.lua files. They’re not needed in Android Studio)
     

  2. Create a new task in the app’s build.gradle file.

    task copyMyNativeLibs(type: Copy) { from fileTree(dir: “$projectDir/libs”, include: “**/*.so”) into “$jniLibsDir” dependsOn “copyCoronaNativeLibs” doFirst { println “== copyMyNativeLibs ==” } }

  3. Modify task certifyBuild and change dependsOn to “copyMyNativeLibs”

Thanks for your time!

I did as you suggested, i.e.

$ grep copyMyNativeLibs android/app/build.gradle  task copyMyNativeLibs(type: Copy) {         println "== copyMyNativeLibs =="     dependsOn 'copyMyNativeLibs' $ ls -l android/app/libs/armeabi-v7a/ total 744 -rwxr-xr-x  1 jocke  staff  124644 16 Jan 12:43 libplugin.sodium.so -rwxr-xr-x  1 jocke  staff  124644 16 Jan 12:33 plugin\_sodium.so -rwxr-xr-x  1 jocke  staff  124644 16 Jan 12:42 sodium.so

and then I wrote a very simple main.lua:

$ cat Corona/main.lua  local Sodium = require "plugin.sodium"; assert(false, tostring(Sodium))

I then built an Android APK but the plugin .so file can still not be found (see attachment). Do you have a pointer into documentation which talks about how to do this. I must have missed it.

Thanks

/Jocke

I forgot the attachment. Here it is.

Summary:

Putting the .so files in app/libs/armeabi-v7a/ works as you describe, if I build the APK with Android Studio.

Thanks!

/Joakim

Hi,

I put my .so files in app/libs/armeabi-v7a/ and it all works on Android 7.x devices but to my surprise not on Android 6.x devices. 

The short story is that I have my plugin libplugin.sodium.so which in turn depend on the third party library libsodium.so. Both of them sits in the armeabi-v7a/ folder and the apps work on my Android 7.x device (Google Nexus 5x).

On my Android 6.x device it fails with ‘dlopen failed: library “libsodium.so” not found’. See runtime-error.jpg attachment.

The surprising thing is that it works on 7.x devices and not on 6.x devices (not vice versa).

Have anyone seen something like this?

The content of my armeabi-v7a/ folder:

spock:armeabi-v7a jocke$ pwd /Users/jocke/src/blackmode/trunk/app/ui3/android/app/libs/armeabi-v7a spock:armeabi-v7a jocke$ ls -l total 7184 -rwxr-xr-x  1 jocke  staff  2315200 17 Mar 10:04 libcrypto.so -rwxr-xr-x  1 jocke  staff    13564 30 Jan 18:48 libplugin.bit.so -rwxr-xr-x  1 jocke  staff   893452  6 Feb 11:21 libplugin.luaproc.so -rwxr-xr-x  1 jocke  staff    29680 17 Mar 10:02 libplugin.scrypt.so -rwxr-xr-x  1 jocke  staff     4452 17 Mar 10:02 libplugin.sodium.so -rwxr-xr-x  1 jocke  staff   401792 17 Mar 10:04 libsodium.so spock:armeabi-v7a jocke$ arm-linux-androideabi-objdump -p libplugin.sodium.so | grep NEEDED   NEEDED               libsodium.so   NEEDED               liblua.so   NEEDED               libcorona.so

I assume you already have added a Gradle task to your build.gradle (Module app) to copy them over to the $jniLibsDir as described above?

It’s important that your new custom task should have: dependsOn “copyCoronaNativeLibs”, and that the dependsOn in task certifyBuild is dependsOn “copyMyNativeLibs”.

Yes, i have added gradle rules so that all the .so files in my last reply are copied. The problem seems to be that the libplugin.sodium.so is loaded ok and in turn its wants to use the libsodium.so library (which resides in the same folder as itself). This fails on Android 6.x devices. The same APK file works on Android 7.x devices though. That is the strange thing.

Have you tried using apktool to look at what’s actually included in your APK?

https://ibotpeaches.github.io/Apktool/

Use: apktool d yourapp.apk

Thanks!

This is what I see:

spock:apk jocke$ apktool d app-debug6.apk I: Using Apktool 2.2.2 on app-debug6.apk I: Loading resource table... I: Decoding AndroidManifest.xml with resources... I: Loading resource table from file: /Users/jocke/Library/apktool/framework/1.apk I: Regular manifest package... I: Decoding file-resources... I: Decoding values \*/\* XMLs... I: Baksmaling classes.dex... I: Copying assets and libs... I: Copying unknown files... I: Copying original files... spock:apk jocke$ find app-debug6 -name '\*.so' -print app-debug6/lib/armeabi-v7a/libads.so app-debug6/lib/armeabi-v7a/libalmixer.so app-debug6/lib/armeabi-v7a/libanalytics.so app-debug6/lib/armeabi-v7a/libcorona.so app-debug6/lib/armeabi-v7a/libcrypto.so app-debug6/lib/armeabi-v7a/libgameNetwork.so app-debug6/lib/armeabi-v7a/libjnlua5.1.so app-debug6/lib/armeabi-v7a/liblicensing.so app-debug6/lib/armeabi-v7a/liblua.so app-debug6/lib/armeabi-v7a/libmpg123.so app-debug6/lib/armeabi-v7a/libopenal.so app-debug6/lib/armeabi-v7a/libplugin.bit.so app-debug6/lib/armeabi-v7a/libplugin.luaproc.so app-debug6/lib/armeabi-v7a/libplugin.scrypt.so app-debug6/lib/armeabi-v7a/libplugin.sodium.so app-debug6/lib/armeabi-v7a/libplugins.so app-debug6/lib/armeabi-v7a/libsodium.so

I’m a bit at a loss as all ‘so’ files are included in your APK.
Since it runs on your Android 7 device I’m grasping at straws here. It may be your Android 7 device supports 64 bit while your Android 6 device doesn’t. Where did you get the libsodium.so file, and are you certain the one you have is not 64-bit? It needs to be 32-bit.

I compiled libsodium.so myself as well and I have read https://developer.android.com/ndk/guides/standalone_toolchain.html several times to get the NDK cross-compile right.

Below I used “readelf -h” to inspect the headers of libplugin.sodium.so and libsodium.so. It looks OK.

I must be missing something even more basic here…

spock:test7 jocke$ apktool d app-debug7.apk I: Using Apktool 2.2.2 on app-debug7.apk I: Loading resource table... I: Decoding AndroidManifest.xml with resources... I: Loading resource table from file: /Users/jocke/Library/apktool/framework/1.apk I: Regular manifest package... I: Decoding file-resources... I: Decoding values \*/\* XMLs... I: Baksmaling classes.dex... I: Copying assets and libs... I: Copying unknown files... I: Copying original files... spock:test7 jocke$ find app-debug7 -name '\*.so' -print app-debug7/lib/armeabi-v7a/libads.so app-debug7/lib/armeabi-v7a/libalmixer.so app-debug7/lib/armeabi-v7a/libanalytics.so app-debug7/lib/armeabi-v7a/libcorona.so app-debug7/lib/armeabi-v7a/libcrypto.so app-debug7/lib/armeabi-v7a/libgameNetwork.so app-debug7/lib/armeabi-v7a/libjnlua5.1.so app-debug7/lib/armeabi-v7a/liblicensing.so app-debug7/lib/armeabi-v7a/liblua.so app-debug7/lib/armeabi-v7a/libmpg123.so app-debug7/lib/armeabi-v7a/libopenal.so app-debug7/lib/armeabi-v7a/libplugin.bit.so app-debug7/lib/armeabi-v7a/libplugin.luaproc.so app-debug7/lib/armeabi-v7a/libplugin.scrypt.so app-debug7/lib/armeabi-v7a/libplugin.sodium.so app-debug7/lib/armeabi-v7a/libplugins.so app-debug7/lib/armeabi-v7a/libsodium.so spock:test7 jocke$ /usr/local/Cellar/android-ndk/r14/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86\_64/bin/arm-linux-androideabi-readelf -h app-debug7/lib/armeabi-v7a/libplugin.sodium.so ELF Header:   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00   Class:                             ELF32   Data:                              2's complement, little endian   Version:                           1 (current)   OS/ABI:                            UNIX - System V   ABI Version:                       0   Type:                              DYN (Shared object file)   Machine:                           ARM   Version:                           0x1   Entry point address:               0x0   Start of program headers:          52 (bytes into file)   Start of section headers:          3652 (bytes into file)   Flags:                             0x5000200, Version5 EABI, soft-float ABI   Size of this header:               52 (bytes)   Size of program headers:           32 (bytes)   Number of program headers:         5   Size of section headers:           40 (bytes)   Number of section headers:         20   Section header string table index: 19 spock:test7 jocke$ /usr/local/Cellar/android-ndk/r14/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86\_64/bin/arm-linux-androideabi-readelf -h app-debug7/lib/armeabi-v7a/libsodium.so ELF Header:   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00   Class:                             ELF32   Data:                              2's complement, little endian   Version:                           1 (current)   OS/ABI:                            UNIX - System V   ABI Version:                       0   Type:                              DYN (Shared object file)   Machine:                           ARM   Version:                           0x1   Entry point address:               0x0   Start of program headers:          52 (bytes into file)   Start of section headers:          400392 (bytes into file)   Flags:                             0x5000200, Version5 EABI, soft-float ABI   Size of this header:               52 (bytes)   Size of program headers:           32 (bytes)   Number of program headers:         8   Size of section headers:           40 (bytes)   Number of section headers:         35   Section header string table index: 34 spock:test7 jocke$

/Joakim

A little bit more info:

spock:test7 jocke$ /usr/local/Cellar/android-ndk/r14/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86\_64/bin/arm-linux-androideabi-readelf -d app-debug7/lib/armeabi-v7a/libplugin.sodium.so | grep NEEDED  0x00000001 (NEEDED)                     Shared library: [libsodium.so]  0x00000001 (NEEDED)                     Shared library: [liblua.so]  0x00000001 (NEEDED)                     Shared library: [libcorona.so] spock:test7 jocke$ /usr/local/Cellar/android-ndk/r14/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86\_64/bin/arm-linux-androideabi-readelf -d app-debug7/lib/armeabi-v7a/libsodium.so | grep NEEDED  0x00000001 (NEEDED)                     Shared library: [libc.so]  0x00000001 (NEEDED)                     Shared library: [libdl.so] spock:test7 jocke$

/Joakim