提问者:小点点

基于构建风格的Gradle交换jniLibs资源


我正在尝试交换res/raw文件夹和jniLibs/armeabi文件夹中的一些资源,这取决于它是release buildType还是debug buildType。我目前也有两种产品口味。

build.gradle文件:

apply plugin: 'com.android.application'

android {
    dexOptions {
        preDexLibraries = false
    }

    compileSdkVersion 21
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.example.test"
        minSdkVersion 17
        targetSdkVersion 22
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_7
            targetCompatibility JavaVersion.VERSION_1_7
        }
    }

    productFlavors{
        phone{
            applicationId "com.example.testPhone"
        }
        tablet{
            applicationId "com.example.testTablet"
        }
    }

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

    sourceSets{
        release{
            res.srcDirs = ['androidRelease/res/raw']
        }
    }
}

dependencies {
    compile project(':facebook')

}

使用Source ceSet是正确的方法吗?如果是,应该创建什么文件夹,以便它仅基于build dType交换适当的资源,而不管productFlavors

编辑:它甚至可以交换jniLibs原始文件夹资源?

文件夹结构:

src/main/jniLibs/armeabi
phoneRelease/jniLibs/armeabi
tabletRelease/jniLibs/armeabi 

文件夹结构正确吗。?

编辑2:根据Xavier的回答,渐变应该是这样的:

android {

      sourcesets {
        phone {
          jniLibs.srcDirs = ['phoneRelease/jniLibs/']
          res.srcDirs = ['androidRelease/res/raw']
        }
        tablet {
          jniLibs.srcDirs = ['tabletRelease/jniLibs/']
          res.srcDirs = ['androidRelease/res/raw']
        }
      }
    }

我一直在阅读很多相互矛盾的答案,其中一些提到您只需要根据构建变量使用单独的文件夹,还有一些提到必须使用sourceSet?谢谢


共3个答案

匿名用户

其中一些提到您只需要根据构建变量使用单独的文件夹,还有一些提到必须使用sourceSet?

Gradle/Gradle for Android具有预期的源集结构:

  • res/
  • Java/
  • jniLibs/
  • 资产中的资产/
  • 等等

sourceset闭包起作用的地方是,对于给定的sourceset,您需要不同的结构:

  • Android资源在foo/

每个构建类型、产品风格和构建变体都可以有一个单独的源集(就像仪器测试的androidTest一样),与main一起使用。它们的名称与构建类型/产品风味/构建变体相同。这些将在股票结构中,除非您使用Source ceSets来更改内容。

所以,一路回到:

我正在尝试交换res/raw文件夹和jniLibs/armeabi文件夹中的一些资源,这取决于它是版本构建类型还是调试构建类型

对于资源,其他源集覆盖main。因此,如果您有src/main/res/src/main/debug/src/main/release/,您正在执行调试构建,无论src/main/release/被忽略(因为我们没有做release)和src/main/res/中的任何内容src/main/debug/将被使用。如果两个(src/main/res/raw/boom.oggsrc/debug/res/raw/boom.ogg中有相同的资源,debug一个优于main一个。

我没有尝试过通过构建变量来改变jniLibs/。我的猜测是,它的行为更像Java代码,在构建变体的源集中的内容与main中的内容之间不能有冲突,但这只是猜测。因此,您可以在src/debug/jniLibs/中获得编译JNI代码的调试版本,在src/release/jniLibs/中获得编译JNI代码的发布版本。只有在src/main/jniLibs/中才有任何不变的库。话虽如此,正如我提到的,我还没有尝试过这个,所以这里可能会有打嗝。

因此,我希望您在build中没有sourceset闭包。gradle,只需使用stock sourcesets结构,即可用于各种位:

src/
  main/
    ...
  debug/
    jniLibs/
    res/
      raw/
  release
    jniLibs/
    res/
      raw/

匿名用户

通常在src/main/下的任何内容都可以放在不同的文件夹中:

src/<element>/AndroidManifest.xml
src/<element>/java
src/<element>/res
src/<element>/assets
src/<element>/resources
src/<element>/jni
src/<element>/jniLibs
src/<element>/aidl
src/<element>/rs

其中元素构建类型产品风格的名称。如果您的变体包含这样一个元素(构建类型或风格),那么除了src/main

请注意,如果您已经配置了该位置,则该位置确实不相关。重要的是有一个android.sourcesets.main元素包含所有变体共有的源,每个变体都有一组源集。

例如,如果您有一个flavorphoneRelease,它实际上使用了以下源集:

android.sourcesets.main
android.sourcesets.phone
android.sourcesets.release
android.sourcesets.phoneRelease

如果您有另一个变体tabletree,它将使用以下内容:

android.sourcesets.main
android.sourcesets.tablet
android.sourcesets.release
android.sourcesets.phoneRelease

因此,手机/平板电脑源集是不同的,并且是您放置变体特定源的地方,除非您想更具体地使用手机版本/表格租赁源集(尽管这些源集通常使用较少)默认情况下,这些将是src/phone/src/tablet/(或src/phoneRelease/…),但只要连接到Android系统,您就可以随意更改。源集*对象它会很好的。

例如,做:

android {
  sourcesets {
    phone {
      jniLibs.srcDirs = ['phoneRelease/jniLibs/']
    }
    tablet {
      jniLibs.srcDirs = ['tabletRelease/jniLibs/']
    }
  }
}

很好。但是请注意,您只更改了jniLibs文件夹,而没有更改其他源元素(java、res等)

如果您保留main源集的默认位置,我会将所有内容保留在src/

您可以在此处查看有关源集以及如何组合多个源集的更多信息:http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-源集和依赖项

匿名用户

使用口味来改变源集,

productFlavors{
    phone{
    }
    tablet{
    }
}

现在构造你的代码,

src
  main
  phone
  tablet

main中的代码在两种口味之间是通用的,但是phone平板电脑中的代码仅在构建相应的口味时包含。就这样,你不需要做其他任何事情。

phonetablet下的结构与main下的结构相同(resjava等)。您还可以有一个自定义的AndroidManifest。xml,位于flavor目录下。Gradle试图合并flavor的AndroidManifest。xml,其中一个位于主目录中。在某些情况下,您必须提供如何合并的规则。