29

I have a bit unusual problem - my Android app contains native libs and I build native libs for armeabi-v7a and x86. However, now I need to integrate a third party library into my app which also contains native libraries (third party library is Crashlytics which I included via Maven from my build.gradle.). The problem is that third party library's AAR provides all arhitectures (armeabi, arm64-v8a, armeabi-v7a, mips, mips64, x86 and x86_64) and my app only supports armeabi-v7a and x86 (arm64-v8a is planned for near future), so when final apk is built it contains 3rd party library's all ABI's and only x86 and armeabi-v7a ABI's of my native code. This causes my app to crash when launched on arm64 device like Galaxy S6.

My question is: is it possible to include only selected ABI's from 3rd party AAR?

Please note that I am aware of APK splits, but this only solves my problem partially, i.e. it works only if I distribute my app via Play Store. Although Play Store supports beta test distribution, the propagation of updated APK is rather slow, so prior pushing an update to app's PlayStore beta channel, we push an update via Crashlytics' beta distribution system, which is much faster. The problem is that Crashlytics' distibution system does not support APK splits (or am I wrong?). Therefore, I actually need to build an "universal" APK that will contain only selected ABIs. How to achieve that?

Although I would be satisfied even with Crashlytics'-specific answers (like for example, how to distribute APK splits via their beta channel), I would be much more satisfied with solution for building "universal" APK that contains only selected ABIs, because at our company we also provide SDKs to our clients as AAR archives that contain only supported architectures and we would like to instruct them how to handle case when they integrate our SDK with other SDKs that have different ABI's supported.

I am using latest stable Android studio (1.2.1.1), gradle 2.4 and android gradle plugin version 1.2.3.

DoDo
  • 2,248
  • 2
  • 22
  • 34
  • See whether `ndk.abiFilter` in the product flavor/`defaultConfig` DSL will let you specify multiple items. The examples I see only ever list one. If it does accept a comma-delimited list, that probably will address your issue. – CommonsWare Jun 19 '15 at 20:14
  • I tried exactly that priror asking a question here on stackoverflow. There is a gradle error if I specify multiple ABIs in abiFilter saying that DSL method 'abiFilter' does not exist. I even tried putting multiple ABIs inside single string to abiFilter, but that didn't work too - it made APK without native libs at all. – DoDo Jun 20 '15 at 16:21

4 Answers4

27
packagingOptions {
    exclude 'lib/arm64-v8a/libcrashlytics-envelope.so'
    exclude 'lib/arm64-v8a/libcrashlytics.so'
    exclude 'lib/armeabi/libcrashlytics-envelope.so'
    exclude 'lib/armeabi/libcrashlytics.so'
    exclude 'lib/mips64/libcrashlytics-envelope.so'
    exclude 'lib/mips64/libcrashlytics.so'
    exclude 'lib/mips/libcrashlytics-envelope.so'
    exclude 'lib/mips/libcrashlytics.so'
    exclude 'lib/x86_64/libcrashlytics-envelope.so'
    exclude 'lib/x86_64/libcrashlytics.so'
}
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
mksaint13
  • 286
  • 3
  • 2
22

This works for me:

(e.g: only armeabi & armeabi-v7a)

build.gradle

android{
    defaultConfig{
        ndk{
            abiFilters "armeabi", "armeabi-v7a"
        }
    }
}
Manuel Schmitzberger
  • 5,162
  • 3
  • 36
  • 45
4

Mike from Fabric and Crashlytics here. With Splits, currently, we don't know in advance which density to provide the tester, so just add this line to your specific flavor or variant, to use the universal APK that is generated.

ext.betaDistributionApkFilePath = "path to the universal split APK"

Also, if you're using NDK crash reporting, in case it matches the crash you're seeing, check out this link.

Mike Bonnell
  • 16,181
  • 3
  • 61
  • 77
  • Hi Mike! We already distribute the universal split APK via Crashlytics. Is it possible to distribute x86 and armv7 split separately, just like via PlayStore - by specifying different version codes for different split? Can your Beta app then resolve which APK version should download and install on device? The crash reporting works OK with APK splits, provided that they are distributed via PlayStore, not via Crashlytics Beta. Ideally, I would just like to tell gradle to use only armv7 and x86 native libraries from your AAR. – DoDo Jun 20 '15 at 16:34
  • Thanks for those additional details, right now we don't have a way to support that, but I've shared this idea with the team. – Mike Bonnell Jun 24 '15 at 17:21
  • @MikeBonnell is betaDistributionApkFilePath still supported? I need to set custom apk names but also upload to fabric/crashlytics.. I do ensure the betaDistributionApkFilePath is set before running :app:crashlyticsUploadDistribution{$variant.name}? – speedynomads Nov 24 '16 at 15:33
  • Yes, it's still supported. An alternate approach would be to use Fastlane.tools - https://github.com/fastlane/fastlane/tree/master/supply#readme – Mike Bonnell Nov 28 '16 at 16:58
-1

I had the same problem as you, but you actually helped me with the link you posted about APK Splits! In your case, try to add the following to your build.gradle inside the android closure:

    splits {
        abi {
            enable true
            reset()
            include 'armeabi-v7a', 'x86'
            universalApk true
        }
    }

The trick in there is to set the universalApk to true in order to generate only one APK with all the defined architectures, instead of splitting them up in several APKs.

Also don't forget the reset() which removes all the default values.

Jorge Galvão
  • 1,729
  • 1
  • 15
  • 28
  • 1
    This does not work. In my app I have included 'x86', 'armeabi-v7a', 'arm64-v8a', yet my universal APK still contains 'armeabi', 'mips', 'mips64' and 'x86_64'. I want only 'x86', 'armeabi-v7a' and 'arm64-v8a' in my universal APK. – DoDo Dec 15 '15 at 09:11
  • It works fine for me... I'm using Android Gradle plugin 1.3.1, target SDK 22 and Build Tools version 23.0.2. Also, it changes the name of the final apk file, it should now be called something like "-universal-.apk". You should also have one per library, such as "-x86-.apk" (those are not the ones you want). So maybe you are trying to use the old file if you haven't made a clean? – Jorge Galvão Jan 25 '16 at 16:48
  • Jorge, if you unzip "-universal-.apk", what are the contents of the "lib" folder inside the APK? For me, this folder contains architectures which I do not want (such as 'mips' and 'armeabi'), even though I included only 'armeabi-v7a' and 'x86'. – DoDo Jan 26 '16 at 09:30
  • @DoDo sorry for the late reply. After I unzip the apk I see only the `armeabi-v7a` and `x86` folders inside the `lib` folder. Have you included the `reset()` call as I mention in the example? – Jorge Galvão Jun 15 '19 at 07:49
  • Late reply?!? 3 years and 5 months have passed :-P. I am pretty sure that I copy pasted your code back in the days before reporting back that it did not work. However, the solution by @mksaint13 worked like a charm (and still works to this day). – DoDo Jun 16 '19 at 15:23