I have a project with native libraries that I want to use, files with this format: lib<name>.so do get included into apk. But files with <name>.so format does not.
Is there a way to include the later type into apk in lib directory?
If not, is there a way to include the files into a directory inside apk, where I can load it from my native code?
The short answer is "no". The native binaries will only be packed into APK, and extracted to executable files upon installation, if their names follow the lib….so pattern.
Note that these libraries will be extracted to files according to the ABI of the target system. The installer does not check the actual properties of the file. The decision is based on the name of the folder under lib in the APK structure.
If you add the attribute extractNativeLibs=false to the application tag in AndroidManifest.xml of your APK, the installer (on Android Nougat and higher) will not extract the native libraries.
You can trick the system and have files that don't follow the above rule to the lib folder of APK, but there is very little sense in it, because they will never be extracted by the loader (it may also extract file gdbserver if the file is there).
The common practice is to put the arbitrary files in the assets folder of your APK, and extract them programmatically when the app runs for the first time after install. You cannot extract these files to the secured location where the usual native libraries go. You should not extract the native libraries to sdcard (e.g. getExternalFilesDir()), because the system may not allow execution of the files there, regardless of the execute access flag on the file. Make sure that you use the correct ABI flavour.
You can peek at the source code of Nougat native lib loader that can load native libraries from the APK without extraction, and use it to load your custom libraries directly from the assets folder of your APK.
Related
I want to copy and execute some precompiled binaries on device, the problem is that the relative folder structure needs to be the same as in the original package (I cannot move all binaries to root folder).
What so far I found about this is how to copy binaries without .so extension to lib folder here. It works as expected, once installed I can locate the binary using context.getApplicationInfo().nativeLibraryDir, however when I place the directory with binaries it cannot find it using the command.
Further investigation shows that folder does get coppied to apk. I can confirm that by unziping the apk and finding the binaries coppied at /lib/arm64-v8a/.
Now since the apk is fine, the next step I did is check what actually gets copied to device. This can be found in /data/app/app.name.com+random_hash/lib/ and I confirmed that folder does not get copied over, only binaries from root folder do.
What I want to know is whether the code responsible for copying native libraries is located on device and cannot be changed, or the application can be somehow configured to copy the folder structure?
Example repo: https://github.com/D4no0/copy_native_binaries
The code is on device, part of the OS :
"Subdirectory is not supported by the Android OS.
When the APK is installed, the .so libraries are extracted to a directory in the form of /data/app/your.app/lib/. That directory is added to the library path searched by System.loadLibrary so that it can be found. System.loadLibrary do not support a directory structure, thus, the .so files in a subdirectory under lib/ are not extracted."
The above answer is coming from a Googler working on Android, from the following issue :
https://issuetracker.google.com/issues/63707864#comment4
Cheers,
Jérôme
I have a simple cpp library which returns a string value. This was made similar as in the https://developer.android.com/studio/projects/add-native-code.html
After building the apk, after analyzing it I see a lib folder which contains .so files for different ABIs.
My questions is: since the generated files are included in the apk itself, from where and to where does System.loadLibary(String) take action?
Is the library file within the private app's folder and only accessible to the app, after it's being loaded? Do other apps have access to this library once it has been loadLibrary in my app? Is it copied somewhere in the android system folder?
Loads the dynamic library with the specified library name. A file
containing native code is loaded from the local file system from a
place where library files are conventionally obtained. The details of
this process are implementation-dependent. The mapping from a library
name to a specific filename is done in a system-specific manner.
Source: https://developer.android.com/reference/java/lang/Runtime.html#loadLibrary(java.lang.String)
The library is not copied to a shared location when it is loaded. Loading a library means its symbols are linked to native methods.
I am compiling a ROM from source (say CM12.1)
I have obtained the source code and am ready to build.
However I wish to add an app (say ES file explorer) as a user app and another app(say Titanium) as a system app. Also I need to copy a file to one of the system folders.
How is this done?
I dont have the source code of those apps and hence cant compile from
source.
You will have to add the source code of the app the the packages/apps folder. Remove any precompiled files that exist.
Add the android.mk file. You can copy from it from the already available apps in the packages/apps folder and customize it for your app.
Add the app name to core.mk file in build/target/product
Build the ROM and it should have your file.
I have an NDK library that I am creating that needs to contain and access a binary data file (.dat extension). I am having trouble getting the compiled library to see this file. To make things a little more difficult, I am doing this within a library package.
I think it would work if, during my Android.mk file, I copy this .dat file to my app's resources folder, and then access that from within the app, but I feel like there must be a better way.
Any suggestions?
Instead of resources, put it in the assets folder; NDK provides API to access assets from native code.
Often, we unpack some "files" from the resources or assets to the file system (e.g. /sdcard) on the first run of the app after install. This approach works best when the files must be used by external apps and libs (e.g. to play sounds), or when these files will be changing.
Finally, you can link the data into your .so during ndk-build. This will resolve the question how the .dat file will be copied into the app folder, but reading it may be tricky, and modifying - impossible. You don't need to create a huge library. You can create a mock-up library that contains the data. If I understand correctly, you can ignore the file structure, headers, etc. You only need a file named lib something .so in your libs/armeabi (or other) folder.
I have an enterprise app which I am deploying manually (no Google Play) which uses a number of .so libraries for mapping (ArcGIS). However, the .so files (arm, armv7a, x86) in the libs folder blow the .apk size out from 3mb to 21mb. I dont particularly want to remove one of the .so files (removing support for that architecture), or mess around with one .apk per architecture.
Can anyone think of a way I can update my app without including the .so files in each update .apk?
Yes, you can have the Java portion of your app manually download the appropriate .so files into your app's internal storage folder and mark them executable.
You will then have to load them with System.load() and the full pathname of the .so file, rather than System.loadLibrary() and the trimmed library name.
The biggest issue here is that you are now responsible for matching the ABI's yourself, and more importantly, providing your own protection against being tricked into installing a modified or imposter library which might do something nefarious in the name of your app and using it's permissions.
Of course you have to make sure not to try to call any of the native methods before you have installed them.
You could also consider delivering the .so files as binary assets each in its own skeleton .apk having a shared user id (and matching certificate) as your main .apk
Or you could simply make platform-specific .apk's for each target, containing only one .so, and have your distribution system pick the right ones (though that doesn't help with the upgrade problem).