10

I'm busy adding FFmpegMediaMetadataRetriever pre-build .aar files to my project to reduce the Apk file size for each architecture.

This post added the following to his Gradle:

android {
splits {
        // Configures multiple APKs based on ABI.
        abi {
            // Enables building multiple APKs per ABI.
            enable true

            // By default all ABIs are included, so use reset() and include to specify that we only
            // want APKs for x86, armeabi-v7a, and mips.
            reset()

            // Specifies a list of ABIs that Gradle should create APKs for.
            include "x86", "x86_64", "armeabi-v7a", "arm64-v8a"

            // Specifies that we want to also generate a universal APK that includes all ABIs.
            universalApk false
        }
    }
    //...    
}

The FFmpegMediaMetadataRetriever library provide the following .aar files:

image


My questions:

  • Should I place the .aar files in my libs folder as it is (without creating folders for each architecture), or should I add it in a folder?
  • Which of the above .aar files should I use to support all architectures?
  • In the post he also talks about versioning, is this necessary (my application is live and I don't want to mess up the versioning - my current version is 21)?

He implemented versioning like this:

// Map for the version code that gives each ABI a value.
def abiCodes = ['x86':1, 'x86_64':2, 'armeabi-v7a':3, 'arm64-v8a':4]

// APKs for the same app that all have the same version information.
android.applicationVariants.all { variant ->
    // Assigns a different version code for each output APK.
    variant.outputs.each {
        output ->
            def abiName = output.getFilter(OutputFile.ABI)
            output.versionCodeOverride = abiCodes.get(abiName, 0) * 100000 + variant.versionCode
    }
}

I'm looking for someone that has perhaps used the .aar files of FFmpegMediaMetadataRetriever that can give me guidance on how to correctly implement it.

Edit 1

After learning more about different architectures/ABI's, I think it is safe to say that if I only include armeabi-v7a then most devices would be "covered"? (My minimum sdk is 16).

Does that then mean that I don't have to split the APK and I don't have to worry about versioning?

I can then just import the .aar - armv7-fmmr.aar as normal?

halfer
  • 19,824
  • 17
  • 99
  • 186
ClassA
  • 2,480
  • 1
  • 26
  • 57
  • 1
    _"In the post he also talks about versioning, is this necessary"_. Yes. From the Android developer documentation: _"Because the Google Play Store does not allow multiple APKs for the same app that all have the same version information, you need to ensure each APK has its own unique versionCode before you upload to the Play Store."_ – Michael Sep 12 '18 at 10:33
  • @Michael Got it, made the edit. Thank you. – ClassA Sep 12 '18 at 10:38
  • 1
    Regarding which libraries to use, you can remove the `arm-` and `mips-` versions. I'm guessing the `all` version is meant for if you want to build a single universal APK rather than separate APKs per ABI. Whether you want to support x86 and x86_64 is up to you. Such devices aren't very common, except maybe in the Chromebook segment. Another use case for x86 is if you want to run the app in an emulator (e.g. for UI tests), since the x86 Android emulator is much faster than the ARM emulator. – Michael Sep 12 '18 at 10:53
  • @Michael Yes `all` is for when I want to a universal APK. So you are saying that I should only add the following - `arm_64`,`armv7`? Will this "cover" most devices? – ClassA Sep 12 '18 at 11:00
  • 1
    I don't have a list of devices per ABI and Android version, but see e.g. [this answer](https://android.stackexchange.com/a/186348) for a bit more insight regarding x86/x86_64. The vast majority of Android devices has been and continues to be based on arm64-v8a and the older armeabi-v7a. – Michael Sep 12 '18 at 11:08
  • @Michael Thank you very much. How about my question about the folders? Should I add folders in my `libs` folder or can I just place the `.aar` files in my `libs` folder? – ClassA Sep 12 '18 at 11:28
  • 1
    I don't know much about working with AARs, so I can't really say. – Michael Sep 12 '18 at 11:50
  • @Michael Thank you for taking the time to comment. – ClassA Sep 12 '18 at 12:20

2 Answers2

2

You can generate different APK's using product flavors which specify the desired target ABI. You can then specify which FMMR gradle dependency or standalone AAR file to use depending on each product flavor. See this build.gradle file for reference:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.wseemann.example"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    flavorDimensions "version"
    productFlavors {
        fat {
            ndk {
                abiFilters "armeabi", "armeabi-v7a", "x86", "mips", "x86_64", "arm64-v8a"
            }
        }

        armeabi {
            ndk {
                abiFilter "armeabi"
            }
        }

        armeabi_v7a {
            ndk {
                abiFilter "armeabi-v7a"
            }
        }

        x86 {
            ndk {
                abiFilter "x86"
            }
        }

        mips {
            ndk {
                abiFilter "mips"
            }
        }

        x86_64 {
            ndk {
                abiFilter "x86_64"
            }
        }

        arm64_v8a {
            ndk {
                abiFilter "arm64-v8a"
            }
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0-rc01'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    // Product flavor, ABI specific dependencies
    fatImplementation 'com.github.wseemann:FFmpegMediaMetadataRetriever:1.0.14'
    armeabiImplementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-armeabi:1.0.14'
    armeabi_v7aImplementation'com.github.wseemann:FFmpegMediaMetadataRetriever-armeabi-v7a:1.0.14'
    x86Implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-x86:1.0.14'
    mipsImplementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-mips:1.0.14'
    x86_64Implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-x86_64:1.0.14'
    arm64_v8aImplementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-arm64-v8a:1.0.14'
}
William Seemann
  • 3,440
  • 10
  • 44
  • 78
0

First of all, you shouldn't take for granted, that armeabi-v7a will get you "covered". As per this blog post:

In August 2019, Play will require that new apps and app updates with native libraries provide 64-bit versions in addition to their 32-bit versions.

Edit after I had a look at the project you're mentioning

It should be enough to use all-fmmr.aar. It contains .so files for all architectures. If you then use apk splits, each apk will only contain single architecture.

I would also consider including the library via gradle:

dependencies {
    compile 'com.github.wseemann:FFmpegMediaMetadataRetriever:1.0.14'
}

Rest of the original answer is below

As per the project scrutcture, at least in our app and library, we don't have multiple .aar files. In single .aar there are multiple native libraries (.so) like this (you can open it as zip):

library.aar
+-jni
| +-armeabi-v7a
| | \-nativeLib.so 
| +-arm64-v8a
| | \-nativeLib.so 
| +-x86
| | \-nativeLib.so 
| \-etc. 
+-assets
+-drawable
+-res
+-classes.jar
\-etc.

You do not need to have separate .aar files in order for apk splits to work. You can have single .aar with native libs for multiple architectures and you will get multiple apks each for single arch.

If you already have multiple .aar files that you want to use and each has structure like this, but with only single architecture, then you do not need to create folders by architecture to hold them. Instead you can include them and hopefully they will get merged in the apk.

You can check if it works by looking inside the apk as it is just a zip. Inside there will be lib folder with native libs:

lib
+-armeabi-v7a
| \-nativeLib.so
\-etc.

Without the splits you should get single apk with multiple architectures in its lib folder. With the splits, you will get multiple apks wit single architecture each.

ferini
  • 1,908
  • 14
  • 17
  • Can you please elaborate on - `You do not need to have separate .aar files in order for apk splits to work. You can have single .aar with native libs for multiple architectures and you will get multiple apks each for single arch.` – ClassA Sep 13 '18 at 15:37
  • How would I go about doing this? You mentioned that I can use one `aar` with multiple native libraries, but the library only include the `aar` files shown in my question? – ClassA Sep 13 '18 at 15:43