3

I have an app that uses FFmpeg for processing videos. Since now there is the new requirement of 64 bit native libraries. I have been trying to compile my app with the 64 bit binaries without success.

  • I've tried exporting the statically compiled binaries then added a library module that compiles them (since saw there might be some problems with the static ones when building an apk or bundle).
  • I've added the abiFilters code suggested by Android, then I've tried excluding x86 and x86_64 since read somewhere they might be causing problems and the amount of devices using those architectures are under 4%. did this by excluding from abi filters (in App and Library modules). Added splits including abis for armeabi 32 and 64 and excluding for x86, and setting unique version codes for each abi in app and library (somehow the filters seem to be not working *See pic).

None of that worked, when I explore my apk adds the 64 bit assets but under lib only 32 bit appears(Which I believe is the reason PlayStore is complaining). * See attached picture enter image description here

I don't really understand what I'm missing. here are my gradle files: FFmpegANdroid library gradle:

apply plugin: 'com.android.library'
//apply plugin: 'com.github.dcendents.android-maven'
apply plugin: "com.jfrog.bintray"

// This is the library version used when deploying the artifact
version = '0.3.2'

android {
    compileSdkVersion build_versions.compile_sdk_ver
    buildToolsVersion build_versions.build_tools_ver
    defaultConfig {
        minSdkVersion build_versions.min_sdk_ver
        targetSdkVersion build_versions.target_sdk_ver
        versionName "FFMPEG"
        ndk {
            abiFilters  "armeabi-v7a", "arm64-v8a"
        }
    }

    sourceSets.main {
        assets.srcDirs = ['assets']
        jni.srcDirs = [] //disable automatic ndk-build
        jniLibs.srcDirs = ['libs']
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
splits {
    splits {
        abi {
            include "armeabi-v7a", "arm64-v8a"
            exclude "x86","x86_64"
        }
    }
}
libraryVariants.all { variant ->
    variant.outputs.each { output ->
        // For each separate APK per architecture, set a unique version code as described here:
        // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
        def versionCodes = ["armeabi-v7a":1, "arm64-v8a":2]
        def abi = output.getFilter(com.android.build.OutputFile.ABI)
        if (abi != null) {  // null for the universal-debug, universal-release variants
            output.versionCodeOverride =
                    versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
        }
    }
}
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    androidTestImplementation 'com.squareup.assertj:assertj-android:1.0.0'
    implementation third_party_deps.writingminds.ffmpegandroid
}



/*install {
repositories.mavenInstaller {
    // This generates POM.xml with proper parameters
    pom {
        project {
            packaging POM_PACKAGING

            // Add your description here
            name 'FFmpeg Android'
            description = POM_DESCRIPTION
            url POM_URL

            // Set your license
            licenses {
                license {
                    name POM_LICENCE_NAME
                    url POM_LICENCE_URL
                }
            }
            developers {
                developer {
                    id POM_DEVELOPER_ID
                    name POM_DEVELOPER_NAME
                    email 'hitesh@writingminds.com'
                }
            }
            scm {
                connection POM_SCM_URL
                developerConnection POM_SCM_URL
                url POM_URL

            }
        }
    }
}
}*/

task sourcesJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier = 'sources'
}

task javadoc(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}
artifacts {
    archives javadocJar
    archives sourcesJar
 }

Properties properties = new Properties()


properties.load(project.rootProject.file('local.properties').newDataInputStream())

// https://github.com/bintray/gradle-bintray-plugin
bintray {
    user = properties.getProperty("bintray.user")
    key = properties.getProperty("bintray.apikey")

    configurations = ['archives']
    pkg {
        repo = "maven"
        // it is the name that appears in bintray when logged
        name = "ffmpeg-android"
        websiteUrl = "https://github.com/writingminds/ffmpeg-android-java"
        vcsUrl = "https://github.com/writingminds/ffmpeg-android-java.git"
        licenses = ["GPL-3.0"]
        publish = true
        version {
            gpg {
                sign = true
                passphrase = properties.getProperty("bintray.gpg.password")
            }
            mavenCentralSync {
                sync = true
                user = properties.getProperty("bintray.oss.user") //OSS user token
                password = properties.getProperty("bintray.oss.password") //OSS user password
                close = '1'
            }
        }
    }
}

App gradle:

import org.apache.tools.ant.taskdefs.condition.Os
import com.android.build.OutputFile

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion build_versions.compile_sdk_ver
    buildToolsVersion build_versions.build_tools_ver
    defaultConfig {
        minSdkVersion build_versions.min_sdk_ver
        targetSdkVersion build_versions.target_sdk_ver
        applicationId "com.mydomain.myapp"
        versionCode app.version_code
        versionName app.version_name
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        ndk {
            abiFilters  "armeabi-v7a", "arm64-v8a"
        }
    }
    def keystoreProperties = Os.isFamily(Os.FAMILY_WINDOWS) ?
            "KeyStoreWin.properties" : "KeyStore.properties"
    Properties props = new Properties()
    props.load(new FileInputStream(file(project.property(keystoreProperties))))

    signingConfigs {
        storeSignature {
            storeFile file(props['KEYSTORE'])
            storePassword props['KEYSTORE_PASSWD']
            keyAlias props['KEYSTORE_ALIAS']
            keyPassword props['KEYSTORE_ALIAS_PASSWD']
        }
    }
    buildTypes {
        debug {
            debuggable true
            versionNameSuffix app.deb_version_name
            signingConfig signingConfigs.storeSignature
        }
        release {
            signingConfig signingConfigs.storeSignature
            debuggable false
            versionNameSuffix app.rel_version_name
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            renderscriptDebuggable false
        }
    }
    splits {
        abi {
            include "armeabi-v7a", "arm64-v8a"
            exclude "x86","x86_64"
        }
    }
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // For each separate APK per architecture, set a unique version code as described here:
            // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
            def versionCodes = ["armeabi-v7a":1, "arm64-v8a":2]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }
        }
    }
    bundle {
        language {
            enableSplit = true
        }
        density {
            enableSplit = true
        }
        abi {
            enableSplit = true
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project(':FFmpegAndroid')
    implementation official_deps.androidx.appcompat
    implementation official_deps.kotlin.kotlin_stdlib_jdk7

    implementation official_deps.androidx.navigation_fragment_ktx
    implementation official_deps.androidx.navigation_ui_ktx

    //Constraint Layout
    implementation official_deps.androidx.constraintlayout
    //Lyfecycle
    implementation official_deps.androidx.lifecycle_extensions
    implementation official_deps.androidx.cardview
    implementation official_deps.androidx.recyclerview
    //Support for Material Components
    implementation official_deps.material.material

    implementation third_party_deps.retrofit2.retrofit
    implementation third_party_deps.okhttp3.okhttp
    implementation third_party_deps.okhttp3.okhttp_urlconnection
    implementation third_party_deps.okhttp3.logging_interceptor
    implementation third_party_deps.retrofit2.converter_gson

    implementation official_deps.anko.anko_sdk25_coroutines
    implementation official_deps.anko.anko_appcompat_v7_coroutines

    //Room
    implementation official_deps.androidx.room_ktx
    kapt official_deps.androidx.kapt_room_compiler

    //Support for Dagger 2
    implementation official_deps.dagger.dagger
    kapt official_deps.dagger.kapt_dagger_compiler

    //Gson
    implementation official_deps.gson.gson

    implementation third_party_deps.otaliastudios.cameraview

    implementation third_party_deps.mp4parser.isoparser

    implementation official_deps.androidx.core


}

repositories {
    mavenCentral()
}

Can anyone help me identifying the problem? what am I missing?

** I'm using:

  • Android Studio 3.5.1 stable
  • gradle-5.4.1
alexm
  • 1,285
  • 18
  • 36

2 Answers2

0

Did you followed all this steps in Android documentation ?.

How you build your application?

For split issue, try this :

 splits {
      abi {
            reset()
            include "armeabi-v7a", "arm64-v8a"
          }
   }
issamux
  • 1,336
  • 1
  • 19
  • 35
0

Your gradle should look like this

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.qp.ffmpegdemo"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 2
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    implementation project(path: ':FFmpegAndroid')
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

   implementation 'com.writingminds:FFmpegAndroid:0.3.2'

}

Now add some dummy c++ code as like below because google need only 64bit architecture for device which is not in FFmpgeg so just we have to add simple our own lib so it will be solved.

For that create cpp folder in your main dir and put the following file in it.

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib.cpp

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib.cpp

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

and create the cpp file as below

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_qp_ffmpegdemo_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

then generate signed apk and try to upload.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Chirag Thummar
  • 665
  • 6
  • 16
  • yes its working the play store accepted the upload, just add .cpp everywhere before 'native-lib' in the text file so it should not give you a run time error. – Raj Bedi Jun 19 '21 at 18:39