Making an Android Studio JNI static lib to be read by JNI - android

Too less memory in HW phones and tablets, but HAXM works fine?
My basic problem is that my app (most likely JNI dynamic library loaded by my Java app) is too large. The Java app crashes without calling the JNI instructions using HW phones and templates. However it works fine with the HAXM emulator that just enlarge the primary memory of itself.
I need to reduce the size of the JNI dynamic library, I assume.
I have a huge number of C-functions, most of them not used?
Covering an topic area of application programming, more than 64000 entries and 995 are used. Making a C-program in Win32 the linker filter the unused stuff away. Real smooth.
However in Android Studio I have as usual a Java app written using a dynamic JNI library, that is the Android JNI standard use. There is no linker determine what functions are used or not. However I have a front-end JNI file that calls the other bunch of C-functions. The Java system do not analyse what JNI functions are called and find the tree of calls being able to sort it out, I assume? (Nor would a DLL in WIn32 do because it don't know what will be called, I assume.)
The static lib approach might work, how do I do it?
One idea is to create a static lib of the huge number of C-functions and when the standard Android JNI uses it by calls from the front end JNI file, I assume that this will only use the functions of the static library needed and drop the rest, like when linking for the Win32 C-program. I might be wrong?
Well, I tried to find out how to do a static lib in the Android Studio, and also how to use a proprietary static lib to be linked into the JNI dynamic lib. However it is very hard to find out by googling or searching by stackoverflow. I assume this approach is rare.
Does anyone know how to make a static JNI lib in Android Studio
Does anyone know how to use a static JNI lib in Android Studio making a Android app with a
JNI front-end calling the static lib functions?
And is able to describe it?
It might not be possible in the JNI and then it is good to know it is
impossible. Is it possible to get this optimisation made this way?

You can use a static library in Android Studio, but you should build it with ndk-build using Android.mk as configuration.
In your build.gradle you can refer to this prebuilt library "c:\android\obj\libmystatic.a":
model {
android.ndk {
moduleName = "hello-jni"
abiFilters += armeabi-v7a
ldFlags += "-LC:/android/obj"
ldLibs += "mystatic"
}
}

The issue is how to disguard unused functions in a JNI file
Well I answer my own question with the help of #Michaels hint.
The basic problem is a too huge APK for the HW Samsung Tab3 so it crashes, while the HAXM works fine. Using a small JNI dummy I initially made works in the Tab3 but not the real JNI code. My assumption is it is too large, well is it?
The idea of making a static lib using it when making the dynamic automatic JNI lib is redundant if the optimisations are available in other ways. The horror is to manually sort out what is used among more than 64K entries. Thanks in anyway #Alex.
Yes there are optimisations possible by setting the following flags in the app gradle:
android.ndk {
moduleName = "XXXX"
cppFlags.add("-ffunction-sections")
cppFlags.add("-fdata-sections")
cppFlags.add("-fvisibility=hidden")
CFlags.add("-ffunction-sections")
CFlags.add("-fdata-sections")
CFlags.add("-fvisibility=hidden")
ldFlags.add("-Wl,--gc-sections")
/*
* Other ndk flags configurable here are
* cppFlags += "-fno-rtti"
* cppFlags += "-fno-exceptions"
* ldLibs = ["android", "log"]
* stl = "system"
*/
}
This reduces my APK from 11Mb to 7Mb (removing the unused functions in the JNI part). And some changes in the app, reducing the Win64 app from 0,9Mb to 0,6Mb, reducing the APK to 6Mb. Setting the Build variant to arm7 debug (Tab3) the APK is 2,7MB but still crashes (on the load jni library command in the Main java).
How do I know the release size? - Is it possible to test?
The issue is how large the APK will be in release mode (I have the assumption it is smaller than debug mode) but release versions must be signed etc and my intension is not releasing the app for market but testing the size of it, see if the planned app possibly can fit in a commercial Android HW unit. If not I have to make a general redesign of my planned app, however being much wiser. But redesigning is a huge work and I rather like to be certain the original plan was impossible? Seeing apps like MS Office copies I assumed it must be possible.
Being trying to fiddle with the Build/Edit flavours the Gradle just complains putting away the debugging capabilities, so that was a dead end.
So the present question is:
Is there any possibility to find out and try the app in release shape without commercially releasing it?

Related

How to reduce the size of a C++ static library

I'm developing a cross-platform static C++ library and am wondering if there are any build flags for reducing the size of the final MyLib.lib and libMyLib.a files on each platform (iOS, Android, Windows)?
I understand that every single dependency gets pulled into the build process and this is where my file size is coming from.
Why is my static library so huge?
But shouldn't there be some way to have the Linker/Librarian remove code from MyLib based on dependency calls actually made rather than theoretically possible?
The Linker does this when building the final .EXEcutable, but it seems the same rules could apply at the library linking level.
Overall this is a big problem for me because my cross-platform library is around 500MB for Windows and around 200MB on iOS. Oddly, Android is a reasonable 3.5MB.

Deploying ARMv7 compiled code gets INSTALL_FAILED_CPU_ABI_INCOMPATIBLE

My project includes native libraries compiled only for ARMv7. When I try to install it on Samsung Galaxy Y (which has ARMv6), I get INSTALL_FAILED_CPU_ABI_INCOMPATIBLE error.
However, I want to make my application deployable for every devices, no matter they have ARMv7 or not. If target device is an ARMv7, using native library will be a plus. That's it. For the rest of devices, application will do its job without calling native methods. (Because of libary has a large .so file, I don't want to include compilations for other architectures).
Any ideas to overcome this error ? How can I tell Android to ignore native libraries compiled for different architectures and make my APK deployable ?
PS. I'm seeking soultions rather than "creating mutiple APKs"
Thanks
So, by looking trough the NDK documentation I found this interesting hint (look inside the NDK folder in docs/Programmers_Guide/html/md_3__key__topics__c_p_u__support__chapter_1-section_8__a_b_is.html):
put your library inside assets folder
at runtime detect the cpu architecture using this java call: String arch = System.getProperty("os.arch");
If the result is something like "armv71" copy the lib from your assets to your data directory in the lib subdir: /data/data/<package_name>/lib/
Now you can safely call System.loadLibrary(...)

Selective renderscript libraries

I've been working with renderscript in my project for a while now. In a recent effort to minimize APK size, I started wondering and researching whether the renderscript native libraries (libRSSupport.so and librsjni.so) - often bundled within the APK, can be omitted for build-targets such as x86 and mips, which are not necessary for release versions of the APK? (note: the libs are added to the APK regardless of the value of APP_ABI set within Application.mk)
I have come across blogs (much like this one - http://ph0b.com/android-studio-gradle-and-ndk-integration) seemingly describing how that can be achieved using gradle. But what about projects not using gradle (as my own)? Does anybody know a way -- for example, perhaps an undocumented variable that can be added to the project.properties?
Any help will be appreciated.
You really cannot remove those libraries, as they are needed for the app to run correctly on other non-ARM devices.

Debug Android Native located in dependent eclipse project

(ADK 21, NDK r8d, Eclipse Juno)
[I've built several Android apps so decent experience using ADK/NDK etc]
Eclipse project setup:
- AppProject (android, java, no jni)
- LibProject (android, java, Yes jni)
Previously, all of it was in one project - builds fine, runs fine, and native debugging worked great.
Then I split off the "reusable" portion to make a library of common code to use with multiple "AppProject" application front ends. (Everything still builds, links, packs, and runs okay)
However, when I run "AppProject", I can no longer debug the native library.
What is the solution?
Possible option #1:
- Modify "LibProject" Android.mk to export a PreBuilt that is used by AppProject?
- (I would have all the debug symbols so I'm thinking that would work okay)
Would I need to cnature the AppProject as well? In other words, so it has an Android.mk to import the output .so from LibProject
Possible option #2
- http://stackoverflow.com/a/14344377/735533
- that workaround uses ndk-gdb
- I'm hoping for a solution where I can debug LibProject in Eclipse directly when running AppProject
Is there a better way to debug the native code located in the dependent project "LibProject" when running the main application "AppProject"?
Tia
For those curious ...
I tried prebuilts ...
And it definitely seems the be the way to go (test project setup worked)
But the structure of my codebase is a bit heavy on the native/non-native crosstalk and didn't want to take the time (yet) to do a proper reorganization at the moment.
However, restructuring as a prebuilt is on my "Important ToDo" list now
Anywhere, here is my solution.
On Linux (unix flavors) ... use links - the sources are linked into each AppProject from LibProject.
Basically the "LibProject" becomes a sort of "template" during development - it is not built or used as a library directly. Rather, each AppProject becomes self-sufficient, standalone, application with the contents of the library project embedded in its own code tree. Best part is native debugging works like a charm again.
Although it sort of defeats the point of making, there are benefits - one common codebase for the "library" portion ... which is really what I desire for the time being.
Also, conversion to use as a true Library dependency by the Application projects for, say, eventual release builds is an easy switch. Once debugged and ready, the Library can be built separately, packed normally with the application "front ends", and upgraded independently of the applications.

Android.mk for LibXtract

Can somebody help me write Android.mk for LibXtract or point me in correct directoin?
Here is source for lib - https://github.com/jamiebullock/LibXtract.git
Or mayby there is a way to use linux generated shared objects in Android?
Especially for bigger established projects, crafting Android.mk files is quite an effort. More so, if you are not familiar with Android NDK build architecture whose understanding requires digging deep into the documentation and Android NDK make files. I would suggest trying to use existing make files by setting CC to point to your NDK tool chain, and CFLAGS += -sysroot $(SYSROOT) where SYSROOT=${NDK_INSTALL_DIR}/platforms/android-<level>/arch-<arch>/ (depending on targeted Android API version and architecture). Even without knowing about your library, I would bet you should have good chance of success this way. Android NDK documentation (${NDK_INSTALL_DIR}/doc/STANDALONE-TOOLCHAIN.html) details the use of independent tool chain and also instructs how to create a standalone tool chain that will not require the use of -sysroot argument to xxx-gcc.
If you decide to use Android.mk instead, you might check existing projects -CSipSimple comes to my mind (PJSIP converted from standard form GNU make files).
Important is to create the shared objects using Android tool chains. It is possible to build them outside of your application source tree, and then just copy the shared objects into the package source libs/<architecture>/ directory.
Integration with your build system depends on details that are not known (including how smooth you desire this whole integration to be e.g. because of other people working with the same project). If you are creating an application from command line, the easiest would be to have GNU make file or shell script in the package root directory ensure libXtract.so and your application package is up-to-date by calling libXtract make file and ant to build and pack your Java application. If you are using ant there should be a way to specify using make to take care of libXtract.so. I am not sure if eclipse is completely relying on ant for building an application to know if this would be enough for enabling complete build by clicking mouse buttons from within eclipse, too.
The answer to this question says you could use cmake script to build Android.mk files - I have not tried this approach.

Categories

Resources