I am currently porting a library from Linux to Android and I am having some trouble.
The lib has an extension system : it will look for all the files with a particular extension in the folder /usr/local/lib/{thelibname}/extensions/, check if they are dynamic libraries, and load them and call a handler if it is the case.
However, I don't think it is possible to tinker with the base filesystem folders in Android.
I looked into assets but they did not convince me, it looks like they are more intended for images, audio, etc...
Is there another way to embed some files in an .apk and load them afterwards by enumerating a DIR* and calling dlopen ?
The other possibility would be to put the extensions with the app data but I don't know if there is a standard path for this that I could hardcode in the lib, is there? And I don't how to put some stuff in the data at the installation of the apk ? (I use QtCreator for the generation of the APK)
Okay, I found another question which helped me to solve my problem :
How to integrate native runtime library with dlopen on NDK?
You can easily load extension libraries from anywhere in the file system, including shared folders like /sdcard/ and her children. Any app (and native libraries therein) can gain full read access to /sdcard/ with READ_EXTERNAL_STORAGE permission.
This way you can establish a folder where the extensions will be updated not necessarily by a single APK (note the changes for WRITE_EXTERNAL_STORAGE in KitKat).
If you want to deploy all extension libraries as part of the APK, it's easiest to put them in the standard folder that is used to pack the APKs (for ADT, it's ${project_root}/libs/armeabi) and then they will be automagically installed in /data/app-lib/${app_package}. This approach allows to prepare an APK for multiple architectures, preparing appropriate files in ${project_root}/libs/x86, etc.
Note that all libraries must have lib prefix and .so suffix, so e.g. mylib.so or libcrypto.so.6 will not work, even though theoretically such libraries can be loaded by dlopen().
Your app has read access to the /data/app-lib/${app_package} directory, so you can scan it either from C code, or from Java. In Java, its easy to resolve the ${app_package} even if you don't want to hardcode this name. Simply call getApplicationContext().getPackageName().
In C, you can use /proc/${pid} to find the full path to your shared library, and this way you will also know the path to the extensions.
Related
I am trying to package /somewhere/lib/python3.x inside APK's lib folder like jniLibs. But it contains *.py, *.pyc and other files. I have asked another question, but there is no answer. So this is a general question: do you ever used or developed any plugins that embed non-standard files in APK instead of using assets?
How would you access those files? I mean you could put them in the apk, an apk is just a zip file. But the system won't unpack them for you, and at runtime you won't be able to access the apk file itself (installation unzips your file and deletes the apk). You might be able to fool it into doing so by putting it with the jni libs and hoping it doesn't look at extention, but it seem like a bad idea.
However its not uncommon for an app to take its assets and write them to the filesystem on first boot. In fact its fairly common to do this with updatable assets (you'd then just download new versions on top of them, but you can use the old versions to not need an immediate network connection). This would probably work for you. Just make your initial activity a splash screen, and have it do the copy from assets to files in the background while the splash is up.
I'm trying to use some executables inside my app. This executable is C++ based (with images and logs as output), there may be other ways to use C++ code, but in this specific context, it might be the best to use it as an executable which only needs arguments. (NDK f.e. will be too much changing of the used library and I'm hoping there may be a way to parallelize this process some days)
My research showed that some other people were looking for similar problems. It seems that the best way was to add these external programs inside the assets folder (app/src/main/assets). That is what I did, but now I'm not quite sure how to get my data inside the assets folder. Some posting said that these files have to be extracted in another folder to get them work.
So I tried this method:
How to copy files from 'assets' folder to sdcard? (result: app shutdown)
I would like to add some code, but there isn't much for now. As I already told my executable should be inside assets and its name is f.e. exec, I also named it libexec.so, because I read somewhere that you have to name these files like lib"...".so to get them extracted. In general, my aim is to use this executable like:
data/exec
Now to my questions:
How can I get access my assets files?
Or should I use another folder instead of assets, will it be easier to use? How could I add an external executable there?
After some time I managed to get it work through:
https://github.com/flipagram/android-assetcopier
I just had to change something:
Example was:
File destDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
I've changed it to: File destDir = (MainActivity.this).getFilesDir(); - so there is no problem with permissions (I guess).
But be aware: Copying is successful, but I did not manage to run the program successfully. Maybe the whole process will get killed through a security manager or something else won't work.
I would like to separate my Android Java application from codec pack (a .so library), to be distributed separately as .apk (the main app doesn't require these codecs to work properly + there's licence clash). How do I do such thing? Is it at all possible?
Yes, many game developers do the following for .so and graphics data.
I am assuming you are familiar with NDK.
your app needs access to the SD
Once User installs your app start downloading your .so files into a location on the sdcard
load your .so dynamically and make call to the functions you require
So, currently there is no way on Android, but to manually preload dependent shared libs. That's fine with me, not a big deal.
There is also some problem with android buildsystem (prebuild libraries feature), and for that reason I had to name differently different builds of my dependent shared library: libsal.so and libsal-slim.so. Depending on build settings one of these two makes it into the final apk. Then, on java side, I try to load libsal.so and if it fails, then I try to load libsal-slim.so.
It worked all fine, until we stumbled upon a phone that ships that libsal.so in default firmware installed into /system/lib. For that reason, my app stopped working on that phone if it's built with libsal-slim.so, since it tries to load libsal.so first and it loads wrong library from /system/lib.
Question: how can I ensure that only library from my install folder gets loaded? Maybe I can somehow retrieve install folder of my app and "calculate" full path of my shared lib? How can I do that java voodoo magic? I'm big time noob in java and android in general, if this questions looks too naive :) and yes, I don't speak English (or how they say), please rely in c++ [end-of-joke]
libsal.so isn't actual name, I used it only for example.
Using System.load(fullpath_of_the_lib)can probably solve your problem.
But your problem is to get the fullpath_of_the_lib. In fact the android API don't allow you to get the path of a resource. You can only get a stream to read it.
To workaround this limitation, what you can do is the following:
put your lib in your app assets folder.
open a InputStream on your lib : getAssets().open("libsal.so")
create a file named "libsal.so" (or whatever) in your sdcard
copy bytes from the inputstream to the file just created
get the absolute filepath of your "libsal.so" on the sdcard
call System.load(fullpath_of_the_lib_on_the_sd_card)
Of course you only need the last step in the lib is already on the sdcard.
An simpler alternative is maybe renaming your lib to something like libMyVeryUncommonLibraryName.so so that it won't conflict with another library name.
I'm programming an application in android which uses OCR. I'm using the tesseract ocr and I want to ask where should I put the language files in my project, so that when I install my app in my phone(Samsung Galaxy S) the files be somewhere for the app to use them for the ocr process. I think that it should be in a place like: /mnt/sdcard/tesseract/tessdata, but how this can be done without putting them myself in my device and let the installation to do this.
You'll have to include the files with your project in the assets folder.
See AssetManager to learn how to access your files from your activity. Also I would suggest that you don't copy them to the SDCard. Unfortunately since your files are going to have to be included with your project, and thus will be present in your apk file you're going to end up with a larger application size. But also unfortunately I don't believe that there is a way to delete the files from your apk at runtime, so even if you copy them over to the SD your app is still going to be the same size. For that reason I see no reason to copy them to the SD card, just access them from the AssetManager when you need to get them. Doing it that way also means that your application will not break if the SD card is removed / unmounted.
Simply put them under Assets in a "tessdata" folder. That is in your project.
You can use Xamarin and the Tesseract for Xamarin nuget package, they're really easy to use, just bear in mind that you probably will have to install older version of the nugget if the latest version doesn't work. (2.10 was the working one as far as i remember)