I am building an app that can trim a video into multiple segments , for that purpose i have used ffmpeg library
This command does all the work
ffmpeg -i testfile.mp4 -c copy -f segment -segment_time 1200 testfile_piece_%02d.mp4
But including this library increased my app size upto ~45 mb
I want to reduce my apk size
I want help in
Deleting non required libs like x86 , x86_64
or Building ffmpeg with required libs only but i dont know which lib is required for segment purpose
and also I dont know how to build ffmpeg from source code
I am using this library 'com.arthenica:mobile-ffmpeg-min-gpl:4.4.LTS'
I found few ways to reduce app size when i was using ffmpeg.
You could use app bundle. so, the unused arms will be ignored. when download from the playstore
I would suggest not deleting x86 cause some low-end devices won't work without it. x86_64 can be deleted though. I have already done it once for min-4.4-lts not for min-gpl-4.4-lts. you can download it and directly use in your project and test it in the low-end devices .aar
I've attempted the solution outlined in building-combined-armv7-x86-apk-after-crosswalk-integration-in-an-ionic-project.
The great thing is that it creates a single apk file. But when I run my cordova application, I get the following alert:
Mismatch of CPU Architecture
The Crosswalk Project Service must be updated to match the CPU architecture of the device. Please install it from the app store, then restart app.
Looks like Crosswalk is not embedded in the combined apk.
Does anyone know how to embed Crosswalk in a combined apk?
After I had spent a lot time looking for I solved it:
If you open the ".apk" file generated with a compressor (like WinRar), inside folder "lib" you are going to see folders for different architectures (x86_64, x86, mips64, mips, armeabi-v7a, armeabi and arm64-v8a in my case). After inspect all them only x86 and armeabi-v7a have "libxwalkdummy.so" and "libxwalkcore.so" files, so I deleted which ones do not have it. So "lib" folder will only contain x86 and armeabi-v7a folders.
After that it seems that app works with crosswalk embedded.
I would like to know if there is any way to extract from an APK file the Application.mk information.
I particularly interested getting from the APK the supported CPU ABI's
if it's not possible reading the Application.mk file, then what is the right way knowing for sure what ABI's the apk is built for?
The tool that you can use server side to analyse an apk are unzip or, if you want to go deeper, apktool. When you unzip the apk you'll find a folder for each supported abi inside the lib folder of the uncompressed apk (x86, armeabi-v7a, etc.). The list of folder is the list of supported ABI, so you can get the information there. By code you can get the list of supported ABI of a device using the CPU_ABI for device running pre Lollipop and SUPPORTED_ABIS for devices running Android 21+.
About your question: the Application.mk is used to build the native library, so it's not zipped within the apk.
I have a few native libraries that are fairly big and bloating the application binary size. I looked into APK splitting but maintaining and QAing multiple APKs is not something I want to do.
So I'd like to exclude unused architectures in my release build flavour using the ndk.abiFilters Gradle property. (The debug builds I want to leave alone so that I can run the HAXM-accelerated emulator on x86).
I was thinking of just having armeabi-v7a and arm64-v8a in my release flavour, but I'm not sure whether it is worth worrying about the market share of the other architectures I'm dropping. After a lot of looking around I cannot find any reference to market share of ARMv6 (armeabi), MIPS, x86 or x86_64. My intuition tells me that the latter three are almost non-existent, but I'm not sure about ARMv6.
I found this link on a forum that has a list of phones that use various architectures. Is there something more reliable somewhere? Maybe with % of users similar to the Android version dashboard?
Anything else I may miss if I just build my native libs for armeabi-v7a and arm64-v8a (or armeabi, armeabi-v7a and arm64-v8a)?
First off, if you're worring about binary size, you don't really need arm64-v8a, all those devices can run the armeabi-v7a binaries just fine. Only if you really need to cram the last extra performance out of it, it might be worthwhile.
As for armeabi and ARMv6; Android itself doesn't officially support it any longer, since Android 4.4 (October 2013) - and since Android 4.0 it should be much less common (from that version, AOSP source requires modifications to still build for ARMv6). So in practice, if you aren't supporting versions below 4.4, you can drop that one without any significant loss.
Also, for x86; many of those devices ship with surprisingly decent emulation of arm binaries, so those can manage with the armeabi-v7a version just fine as well.
EDIT: The above was written in 2015; these days Play Store requires that apps include support for arm64-v8a. But these days the next question is more about whether you need to include armeabi-v7a at all, or if the market share of 32 bit devices is small enough to drop support for.
Including additional architectures will no longer have any impact on the binary size when using app bundles, as in that case Google Play will serve each device only the binaries that apply to that particular device. Not only that, but also application updates will be way smaller and faster.
Leaving the previous information for projects still not using app bundles:
Unfortunately, the Android Dashboard, as useful as it is, does not provide architecture information, nor does Google Analytics.
The Unity statistics used to provide statistics per architecture and CPU features. Note, however, that these are not general statistics, but only cover users of Unity applications/games. The information doesn't seem to be available in a public link anymore, so I have replaced the direct links with the latest snapshots in archive.org.
I was stuck with this problem when using Mapbox, then later found this article which was very useful.
Based on the below picture you just need armeabi-v7a and x86. Then based on Jose Gómez answer, I only added armeabi-v7a and didn't have any problem at all.
So add this line to your app.gradle
android {
defaultConfig {
//other configs
ndk {
abiFilters "armeabi-v7a"
}
}
}
If you're still worried about 2% - 3% of those who use x86 architecture, like ASUS ZenFone and lenovo phones then use this config instead in app.gradle
ndk {
abiFilters "armeabi-v7a", "x86"
}
Also for genymotion emulators you should use x86 architecture
UPDATE
If you get this error while publishing the apk in play store
Then use this
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
And finally, I suggest you use app bundle for releasing the APK
When I read #mstorsjo answer I was a little bit confused how to really use only one (or two) native libs, even though it's quite simple and straightforward. Therefore, I will give here an example and some more explanation (based on my further research).
For each supported architecture we have to create a specific folder in the jniLibs folder and drop the .so file there. As an example, for supporting armeabi-v7a (32bit) and arm64-v8a (64bit):
|--app
|--|--src
|--|--|--main
|--|--|--|--jniLibs
|--|--|--|--|--armeabi-v7a
|--|--|--|--|--|--.so Files
|--|--|--|--|--arm64-v8a
|--|--|--|--|--|--.so Files
With armeabi-v7a you support more than 90% of the available devices, but since it is 32bit architecture, running it on 64bit devices will result in an loss of performance (20-30%) {1}. For each specific case it can be quite handy to check the actual amount of supported devices, which can be done within the Google Play Console in the Release management > Device catalog section, by specifying ABI as filter.
Attention
When you don't add binaries for all architectures you have to be aware of the following:
If your app contains any other native libraries, you'll have to make sure you only have the same versions of them as well. That is due to Android demanding that all loaded native libraries be built for the same architecture. For example, if the first native library loaded is armeabi-v7a, Android will look ONLY for armeabi-v7a libraries on all System.loadLibrary() calls after that. If it doesn't find that exact architecture, it'll throw the java.lang.UnsatisfiedLinkError exception. {1}
I ran into this problem because some of my dependencies used native libraries, whereby armeabi-v7a couldn't be loaded anymore.
I am using Crosswalk browser for my current application, and after the building process it creates 2 libraries (Which are around 17 mb in size each).
And since that adds a big amount of overhead to the application, i was trying to separate the build into 2 different apk's one for arm and one for x86 architecture.
According to android documentation it is possible, but I was not able to found enough information.
Is it possible to build two times with each time only one version of crosswalk lib getting added ?
looking at crosswalk's make_apk.py, it seems that by default, different APKs are already generated for each platform.
You can specify which architectures you want to generate an APK for using the --arch option that can be set to either x86, x86_64 or arm.
The solution for me was to manually delete libxwalkcore.so under crosswalk project -> libs -> armeabi-v7a or x86.
Depending on for which architecture you wish to built delete the other .so file.