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

}

Использует sourceSet правильный способ сделать это? Если это так, то какая папка должна быть создана так, чтобы она меняла местами соответствующие ресурсы только на buildType и независимо от productFlavors?

EDIT: возможно ли обмен файлами jniLibs и raw на папки?

Структура папки:

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

Правильно ли создана структура папок.

ИЗМЕНИТЬ 2: На основе ответа Xavier, если gradle выглядит следующим образом:

android {

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

Я продолжаю читать много противоречивых ответов, некоторые из них отмечают, что вам просто нужны отдельные папки на основе варианта сборки, а некоторые упоминают о необходимости использовать sourceSet? Спасибо!

Ответ 1

некоторые из них упоминают, что вам просто нужны отдельные папки на основе варианта сборки, а некоторые упоминают о необходимости использования sourceSet?

Gradle/Gradle для Android имеет ожидаемую структуру для источника:

  • Ресурсы Android в res/
  • Дерево исходных текстов Java в java/
  • Предварительно скомпилированные библиотеки JNI в jniLibs/
  • Активы в assets/
  • Etc.

Если закрытие sourceSets вступает в игру, если для данного набора источников вам нужна другая структура:

  • Ресурсы Android в foo/
  • Дерево исходных текстов Java в bar/
  • Предварительно скомпилированные библиотеки JNI в ickyNativeStuff/
  • Активы в assetsBecauseThatSeemsLikeADecentName/
  • Etc.

Каждый тип сборки, вкус продукта и вариант сборки могут иметь отдельный набор источников (например, androidTest для контрольно-измерительного тестирования), чтобы идти вместе с main. Они называются так же, как вариант типа сборки/продукта/сборки. Они будут находиться в структуре запасов, если вы не используете sourceSets для изменения вещей.

Итак, переверните все пути назад:

Я пытаюсь поменять местаки в папке res/raw и папке jniLibs/armeabi на основе того, является ли ее release buildType или debug buildType

В случае ресурсов другие наборы источников накладываются main. Итак, если у вас есть src/main/res/... и src/main/debug/... и src/main/release/..., и вы делаете сборку debug, все, что находится в src/main/release/..., игнорируется (поскольку мы не делаем release) и все, что находится в src/main/res/... и src/main/debug/.... Если в обоих случаях есть один и тот же ресурс (src/main/res/raw/boom.ogg и src/debug/res/raw/boom.ogg), debug выполняет одно из следующих действий: main.

Я не экспериментировал с переменным jniLibs/ по варианту сборки. Я предполагаю, что он будет больше похож на Java-код, где у вас не могут быть конфликты между тем, что есть в исходном варианте сборки, и тем, что находится в main, но это просто предположение. Таким образом, вы можете иметь отладочную версию скомпилированного кода JNI в src/debug/jniLibs/ и версию выпуска вашего скомпилированного кода JNI в src/release/jniLibs/. Только в src/main/jniLibs/ любые библиотеки, которые не меняются. Это, как я уже упоминал, я не пробовал, и поэтому здесь могут быть икоты.

Итак, я бы ожидал, что у вас не будет закрытия sourceSets в build.gradle, и просто используйте структуру исходных множеств для ваших различных бит:

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

Ответ 2

Все, что обычно под 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

Где element - это имя build type или product flavor. Если ваш вариант включает такой элемент (тип сборки или аромат), то этот набор источников также используется дополнительно до src/main

Обратите внимание, что местоположение действительно не актуально, если вы его настроили. Важно то, что существует элемент android.sourcesets.main, который содержит источники, общие для всех вариантов, и каждый вариант имеет набор наборов источников.

Например, если у вас есть аромат phoneRelease, он действительно использует следующие источники:

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

Если у вас есть другой вариант tabletRelease, он будет использовать следующее:

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

Таким образом, набор исходных текстов phone/tablet отличается, и вы должны указывать источники, специфичные для варианта, если вы не хотите быть более конкретными и использовать набор источников phoneRelease/tabletRelease (хотя это менее используются вообще.) По умолчанию это будут src/phone/... и src/tablet/... (или src/phoneRelease/...), но вы можете изменить это, как хотите, и до тех пор, пока оно подключено к объектам android.sourcesets.*, все будет в порядке.

например:

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-Sourcesets-and-Dependencies

Ответ 3

Чтобы использовать ароматы для изменения наборов источников,

productFlavors{
    phone{
    }
    tablet{
    }
}

Теперь создайте свой код,

src
  main
  phone
  tablet

Код в main является общим для обоих вариантов, но код в phone или tablet включен только в том случае, когда создается соответствующий аромат. Чтобы это, вам больше не нужно ничего делать.

Структура под phone и tablet такая же, как в main (res, java и т.д.). Вы также можете создать пользовательский AndroidManifest.xml в каталоге аромата. Gradle пытается объединить аромат AndroidManifest.xml с одним из основных. В некоторых случаях вам необходимо предоставить правила для слияния.