java - 如何为不同的构建风格打包不同的 *.so 文件?

标签 java android android-gradle-plugin build.gradle

我有一些针对不同构建风格的预构建 *.so 文件,例如

arm64-v8a, armeabi-v7a, x86, x86_64,
这些文件是android第三方库的。当我运行项目时,所有这些 *.so 文件都打包在 apk 中。但是这里我的问题是如何在不同的apks中打包不同的*.SO文件?你能为此提供 build.gradle 脚本吗?任何帮助将不胜感激?谢谢。对不起我的英语不好。

我的library.gradle是

apply plugin: 'com.android.library'

import com.android.builder.core.DefaultManifestParser

android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion

sourceSets {
    main {
        jni.srcDirs = []
        // Prevent gradle from building native code with ndk; we have our own Makefile for it.
        jniLibs.srcDirs = ['jni/libs', 'jni/loader/libs', 'private_libs/libs']
        // Where generated .so files are placed.
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        resources.srcDirs = ['src']
        aidl.srcDirs = ['src']
        renderscript.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
    }
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
    }
}

// Make per-variant version code
libraryVariants.all { variant ->
    def manifestParser = new DefaultManifestParser(android.sourceSets.main.manifest.srcFile)
    // get the version code of each flavor
    def version = manifestParser.getVersionName()
    //Custom APK name
    variant.outputs.all { output ->
        if (outputFileName != null && outputFileName.endsWith('.aar')) {
            outputFileName = "lib-${version}.aar"
        }
    }
}
}

class BuildNative extends Exec {}

tasks.withType(BuildNative) {
/*
Properties set for Android Studio own shell.
when you run gradlew from cli, OS shell env variables will be used

To be able to build from Android Studio, you have to set ndk.dir & sdk.dir
properties in local.properties in the root folder, like this (for example):
sdk.dir=/home/<username>/SDK/android-sdk-linux
ndk.dir=/home/<username>/SDK/android-ndk-r10b
 */
if (System.getenv('ANDROID_SDK') == null || System.getenv('ANDROID_NDK') == null) {
    Properties properties = new Properties()
    properties.load(project.rootProject.file('local.properties').newDataInputStream())
    environment 'ANDROID_NDK', properties.getProperty('ndk.dir')
    environment 'ANDROID_SDK', properties.getProperty('sdk.dir')
}
workingDir '..'
commandLine './compile-libvlc.sh'
}

task buildDebugARMv7(type: BuildNative) {
args('-a', "armeabi-v7a")
}
task buildDebugARM64(type: BuildNative) {
args('-a', "arm64-v8a")
}
task buildDebugx86(type: BuildNative) {
args('-a', "x86")
}
task buildDebugx86_64(type: BuildNative) {
args('-a', "x86_64")
}
task buildDebugMIPS(type: BuildNative) {
args('-a', "mips")
}
task buildDebugMIPS64(type: BuildNative) {
args('-a', "mips64")
}

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

clean {
// delete 'build', /*'jni/libs',*/ 'jni/obj'
}

dependencies {
api "com.android.support:support-annotations:$rootProject.ext.appCompatVersion"
api "com.android.support:support-v4:$rootProject.ext.appCompatVersion"
}

我的 app.gradle 是:

apply plugin: 'com.android.application'

android {

packagingOptions {

}

dexOptions {
    maxProcessCount 8
    javaMaxHeapSize "2g"
    preDexLibraries true
    keepRuntimeAnnotatedClasses false
}

compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion

flavorDimensions "target", "abi"

defaultConfig {
    applicationId "com.example"
    minSdkVersion rootProject.ext.minSdkVersion
    targetSdkVersion rootProject.ext.targetSdkVersion
    versionCode rootProject.ext.versionCode
    versionName rootProject.ext.versionName
    vectorDrawables.useSupportLibrary true
    multiDexEnabled true
}

signingConfigs {
    release {
        storeFile file("D:\\Keystore\\aaaaaaaa.jks")
        storePassword "aaaaaaa"
        keyAlias "avbbaaaaaa"
        keyPassword "ababababa"
    }
}

buildTypes {
    release {
        signingConfig null
        minifyEnabled true
        shrinkResources false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

lintOptions {
    checkReleaseBuilds false
    // Or, if you prefer, you can continue to check for errors in release builds,
    // but continue the build even when errors are found:
    abortOnError false
}

dataBinding {
    enabled = true
}

productFlavors {
    vanilla {
        dimension "target"
        versionCode = 1
    }
    chrome {
        minSdkVersion 19
        dimension "target"
        versionCode = 2
    }
    ARMv7 {
        dimension "abi"
        versionCode = 4
    }
    x86 {
        dimension "abi"
        versionCode = 5
    }
    MIPS {
        dimension "abi"
        versionCode = 6
    }
    ARMv8 {
        dimension "abi"
        versionCode = 7
    }
    x86_64 {
        dimension "abi"
        versionCode = 8
    }
    MIPS64 {
        dimension "abi"
        versionCode = 9
    }
}
}

最佳答案

最后我找到了如何做到这一点,我从 https://developer.android.com/studio/projects/gradle-external-native-builds 得到了这个解决方案.希望你也能从这里有所收获。

android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake or ndk-build script.
    externalNativeBuild {

      // For ndk-build, instead use the ndkBuild block.
      cmake {

        // Passes optional arguments to CMake.
        arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"

        // Sets a flag to enable format macro constants for the C compiler.
        cFlags "-D__STDC_FORMAT_MACROS"

        // Sets optional flags for the C++ compiler.
        cppFlags "-fexceptions", "-frtti"
      }
    }
  }

  buildTypes {...}

  productFlavors {
    ...
    demo {
      ...
      externalNativeBuild {
        cmake {
          ...
          // Specifies which native libraries or executables to build and package
          // for this product flavor. The following tells Gradle to build only the
          // "native-lib-demo" and "my-executible-demo" outputs from the linked
          // CMake project. If you don't configure this property, Gradle builds all
          // executables and shared object libraries that you define in your CMake
          // (or ndk-build) project. However, by default, Gradle packages only the
          // shared libraries in your APK.
          targets "native-lib-demo",
                  // You need to specify this executable and its sources in your CMakeLists.txt
                  // using the add_executable() command. However, building executables from your
                  // native sources is optional, and building native libraries to package into
                  // your APK satisfies most project requirements.
                  "my-executible-demo"
        }
      }
    }

    paid {
      ...
      externalNativeBuild {
        cmake {
          ...
          targets "native-lib-paid",
                  "my-executible-paid"
        }
      }
    }
  }

  // Use this block to link Gradle to your CMake or ndk-build script.
  externalNativeBuild {
    cmake {...}
    // or ndkBuild {...}
  }
}

包括预构建的本地库

如果您希望 Gradle 将预构建的 native 库与您的 APK 打包在一起,请修改默认源集配置以包含预构建的 .so 文件的目录,如下所示。请记住,您不需要执行此操作来包含链接到 Gradle 的 CMake 构建脚本的 Artifact 。

android {
    ...
    sourceSets {
        main {
            jniLibs.srcDirs 'imported-lib/src/', 'more-imported-libs/src/'
        }
    }
}

指定 ABI

默认情况下,Gradle 会为 NDK 支持的 ABI 将您的原生库构建到单独的 .so 文件中,并将它们全部打包到您的 APK 中。如果您希望 Gradle 仅构建和打包原生库的某些 ABI 配置,您可以在模块级 build.gradle 文件中使用 ndk.abiFilters 标志指定它们,如下所示:

android {
  ...
  defaultConfig {
    ...
    externalNativeBuild {
      cmake {...}
      // or ndkBuild {...}
    }

    // Similar to other properties in the defaultConfig block,
    // you can configure the ndk block for each product flavor
    // in your build configuration.
    ndk {
      // Specifies the ABI configurations of your native
      // libraries Gradle should build and package with your APK.
      abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
                   'arm64-v8a'
    }
  }
  buildTypes {...}
  externalNativeBuild {...}
}

关于java - 如何为不同的构建风格打包不同的 *.so 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50448281/

相关文章:

android - 如何获取构建变体输出目录

java - 转换输出文件不存在

java - 在实体和 DTO 之间映射非空字段的最佳方法是什么?

java - Browsermob 导致 IntelliJ 创建的 jar 文件出错

安卓开发 : Improve EditText Scrolling?

java - ParseFile 的图像 URL?

android - 自动化gradle从代码构建应用程序包(.apk)

java - QueryDSL,Hibernate 在删除父表行时删除子表行

java - 有没有办法找到页面上的所有 View.GONE 元素?

android - 使用或不使用反向地理编码来索引具有约 500,000 行的 MySQL 表?