【问题标题】:Unable to add 64 bit library to my App, Play Store rejects it无法将 64 位库添加到我的应用程序,Play 商店拒绝它
【发布时间】:2019-10-15 15:58:10
【问题描述】:

我有一个使用 FFmpeg 处理视频的应用。从现在开始,就有了 64 位原生库的新需求。我一直在尝试使用 64 位二进制文​​件编译我的应用程序,但没有成功。

  • 我尝试导出静态编译的二进制文件,然后添加了一个库模块来编译它们(因为在构建 apk 或捆绑包时看到静态文件可能存在一些问题)。
  • 我添加了 Android 建议的 abiFilters 代码,然后我尝试排除 x86 和 x86_64,因为在某处读取它们可能会导致问题,并且使用这些架构的设备数量低于 4%。通过从 abi 过滤器中排除(在应用程序和库模块中)来做到这一点。添加了拆分,包括用于 armeabi 32 和 64 的 abis,不包括用于 x86,并为应用程序和库中的每个 abi 设置唯一的版本代码(过滤器似乎无法正常工作*参见图片)。

这些都不起作用,当我探索我的 apk 添加 64 位资产但在 lib 下只出现 32 位(我相信这是 PlayStore 抱怨的原因)。 * 见附图

我真的不明白我错过了什么。这是我的 gradle 文件: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'
            }
        }
    }
}

应用分级:

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()
}

谁能帮我找出问题所在?我错过了什么?

** 我正在使用:

  • Android Studio 3.5.1 稳定版
  • gradle-5.4.1

【问题讨论】:

    标签: android google-play 64-bit android-assets android-ffmpeg


    【解决方案1】:

    您是否按照Android documentation 中的所有这些步骤操作?

    你好吗build your application

    对于拆分问题,试试这个:

     splits {
          abi {
                reset()
                include "armeabi-v7a", "arm64-v8a"
              }
       }
    

    【讨论】:

      【解决方案2】:

      你的 gradle 应该是这样的

      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'
      
      }
      

      现在添加一些虚拟 c++ 代码,如下所示,因为 google 只需要 64 位架构的设备,它不在 FFmpgeg 中,所以我们只需添加简单的我们自己的库,这样就可以解决了。。。 p>

      为此在您的主目录中创建 cpp 文件夹并将以下文件放入其中。

      # 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} )
      

      并如下创建cpp文件

      #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());
      }
      

      然后生成签名的apk并尝试上传。

      【讨论】:

      • 是的,它的工作游戏商店接受了上传,只需在文本文件中的“native-lib”之前的任何地方添加 .cpp,这样它就不应该给你一个运行时错误。
      猜你喜欢
      • 2019-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-03
      • 1970-01-01
      • 1970-01-01
      • 2021-08-01
      • 1970-01-01
      相关资源
      最近更新 更多