What is correct and present method of packaging a prebuilt shared library (.so) for Android

While there are replies on this topic historically, they tend to be several years old and definitely not in keeping with the modern way (4.11 at the time of this post) UE deploys custom libraries on Android.

So I would like to know: what is the correct, modern (per our present version of UE) method of packaging prebuilt shared libraries for android such that we can call into them from our GameActivity.Java?

I know that the answer is not modifying private engine source and creating a custom build (that is what a lot of posts outline). I doubt that I need to modify the .MK files for unreal (the present architecture uses things like GameActiivityInsert.XML and such to create changes in the manifest and elsewhere). And I see all kinds of methods all over the place in terms of where to put one’s .so binaries ranging from a plugin to a number of other places.

Here is a simple scenario to answer:

I have a library for android, compiled as arm7 called libsimplelibrary.so. It has a function called AddTwo that adds two floats.

Specific Question:

  1. Where exactly should this binary sit in the file/directory structure a newly generated Unreal project?
  2. what files, specifically, do I need to modify to inform UE4 that this file exists and needs to part of my APK? GameActivityInsert.XML I would think, and our build.cs. But would like to see and understand the bare minimum necessary here.
  3. What UE files need to be modified to load this library. I see a section in gameActivityInsert.XML. Do I add it there? And if so, what is the syntax?

Bonus:
4) how do I call into the library and call the Add function. GameActicityInsert.XML again I would think, but can I simply declare the C function in the shared library as a"native" in the java and call into it? or do I need to craft a JNI call by hand?

(I know there are many posts on this, but they are several years old and either 1) involve modifying a custom build of the ue4 engine or 2) suggest "look at what ", but we are not developing a plugin. I am really hoping for the “hello world”/simplest demonstration of this.)

I would really like to know the answer to this too :slight_smile:

Hi gbrill,

The proper way to do this since 4.10 is to use AndroidPluginLanguage. During packaging, all the APL XML files registered with the build system (in the module Build.cs files) are run to allow copying of resources, modify the AndroidManfest.xml and proguard files, and insert code into GameActivity.java. While APL was intended for plugins, any module may register a XML file to process, so you can just have a code based project and add to its Build.cs, for example.

string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, BuildConfiguration.RelativeEnginePath);
AdditionalPropertiesForReceipt.Add(new ReceiptProperty("AndroidPlugin", Path.Combine(PluginPath, "My_APL.xml")));

The above is an example. The My_APL.xml is expected to be placed in the same directory as the Build.cs (PluginPath).

You can find an example in GearVR_APL.xml. It does some conditional staging of libraries and modifications to the manifest, proguard, and GameActivity.java. is the section you would want to copy your .so into place for packaging. is where your .so would be loaded. Since this is just native code, you can just call it from your C++ code. You only need to use JNI to call back and forth between native C++ and Java code.

I have used the XML archutecture, and I do see my shared libraries packaged. I can also call these libraries on the android device BUT only through dlopen()/dlsym() dynamic calls. You can not, as one would expect, simply link and call the native code function within a shared library from ue4…i get “undefined reference” to any function I try to do this with. It seems as though clang c++ that ue4 is using to compile itself and the gcc that is uses from the NDK are either

  1. not binary compatible or
  2. are not linking in the correct order.

note that I am adding the prebuilt .so library in build.cs, and that normally allows me to call a C++ shared library from ue4 C++, but not in the case of android.

So yes, the XML plugin architecture will work mostly (with a lot of reading, studying and work) but I can not call native-to-native as I would expect.

I know this is old but just want to add that I’ve had no problems doing this. I add PublicAdditionalLibraries.Add("path/to/mylib.so");
to an Android-only section of my .build.cs and am able to call into the library without issue.

If you did not sort this out, I would guess there is something wrong with your compilation settings when building your .so.

wrt. linking error, I think I can close this off also and provide some troublehooting advice for others…This was some time ago, but I did ultimately succeed with linking, and I am trying to remember the issue…but it may have had to do with one of two related things:

  1. an extern “C” declaration (important to stave off name mangling)
  2. it was a C++ dll, not a straight C, so we have name mangling even for standalone, global functions. I think I rectified that with #1.

All in all, I do believe there was a distinction between a C++ and C .so, and my linking issues were do to this.

Doesn’t work for me at v4.16.2 ! I got over all linking and include errors (thanks to this post also), but got dead stuck on error:

error: inline function ‘ExternalFunctionName’ is not defined [-Werror,-Wundefined-inline]

Where ExternalFunctionName is the name of the function from .so file.
Please help!

What do i do: Include .h file with all function signatures in the code and perform PublicAdditionalLibraries.Add(“path/to/mylib.so”); at the Build.cs file. Do i miss something?