如何为不同的Build风格打包不同的* .so文件?

时间:2018-05-21 11:51:12

标签: java android android-gradle 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
    }
}
}

3 个答案:

答案 0 :(得分:3)

最后我发现了如何做到这一点,我从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使用APK打包预构建的本机库,请修改默认的源集配置以包含预构建的.so文件的目录,如下所示。请记住,您不需要这样做就可以包含链接到Gradle的CMake构建脚本的工件。

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 {...}
}

答案 1 :(得分:0)

通过在app.gradle中添加此脚本,它就像魅力一样

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

答案 2 :(得分:0)

另一种解决方案是根据您的口味要求指定jniLibs.srcDirs,如下所示:

android {
...
   sourceSets {
      def flavor = getCurrentFlavor()
      if (flavor == ‘device’ || flavor == ‘production’) {
         jniLibs.srcDirs = ['libs']//or whatever path you have
      }
   ...

getCurrentFlavor()处获得构建样式名称的位置。您可以在此处找到操作方法:

How to get current flavor in gradle