Using resource files in NDK - android

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.

Related

Accessing assets stored in AAR from application

I have a library project which includes some TFLite models. I want to be able to distribute the library and include the models in the AAR's assets folder. I've put everything in the assets folder and when inspecting the resulting AAR, I see that the models exists.
My question is, how can I access these models? either from the library itself (preferably) or from the application that uses it?
If I look try and access the assets the normal way for an application
AssetManager am = context.getAssets();
am.list(assetFolder)
I get an empty list.
I saw many posts about including assets in an android AAR library but none that referred to how to actually use these assets, so am I missing something very basic here?
EDIT
This is how the AAR is structured
Inside the assets folder I have a resources folder which contains the models
so
- AAR
-- assets
--- resources
---- model
I tried different values for assetFolder in the code, /, resources, all gave empty lists
Try with:
am.list("resources/model")
Just tested with aar and it works. Be careful, list returns directories and files in the specified path, it doesn't show files in subfolders

Include files with different prefixes in apk

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.

Android NDK cpp library where is located and where is loaded?

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.

Pack the app with some files in the data->data->files directory

I have some files that I want to read from my app.Currently, I have to do the following:
Check if the file exists in the files directory.
If it doesnt, then copy the files from assets to the files directory
If it does, then, skip step 2
So, is it possible to not copy the files ? This increases the size of my app (uselessly) as there is an extra copy of all the files.
Note, that I have to access the file using getfiles(). I am using a library that doesnt work if I give the uri of my assets folder.
So, it it somehow possible to compile the app with some files already in the files directory ?
Internal storage for you app is created when application is installed so there is no way to provide files there during compile time, that would be magic.
You could try creating ContentProvider for sharing your files stored inside assets folder.
Besides, you should tell which library you are using. Then I may be able to suggest something more precise.

Separate .so libraries from .apk

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

Categories

Resources