Приложение с множеством вкусов на основе библиотеки с множеством вкусов в Android Gradle

102

У моего приложения есть несколько вариантов для систем биллинга приложений на нескольких рынках.

У меня есть одна библиотека, в которой используется общий базовый код для всех моих проектов. Поэтому я решил добавить эти платежные системы в эту библиотеку как разновидности продукта.

Вопрос в том, может ли библиотека Android содержать разные продукты?

Если да, то как я могу включить разные вкусы в соответствующий вкус приложения?

Я много искал и ничего не нашел об этом сценарии. Единственная близкая вещь, которую я нашел, это http://tools.android.com/tech-docs/new-build-system/user-guide :

dependencies {
    flavor1Compile project(path: ':lib1', configuration: 'flavor1Release')
    flavor2Compile project(path: ':lib1', configuration: 'flavor2Release')
}

Я изменил конфигурацию на разные вещи, но это не сработало!

Я использую android studio 0.8.2.

Али
источник
после многих поисков я не нашел способа достичь этого, даже я 3.4.2обновляю плагин Android до последней версии и градиент до последней версии 5.5.1, он все еще не выдерживает время компиляции, или сбой при связывании ресурсов в aapt, или не удается найти символ, который внутри библиотеки модуль
VinceStyling

Ответы:

141

Наконец я узнал, как это сделать, я объясню это другим, столкнувшимся с такой же проблемой:

Ключевой частью является установка для publishNonDefault значения true в библиотеке build.gradle. Затем вы должны определить зависимости, как предложено в руководстве пользователя.

Весь проект будет таким:

Библиотека build.gradle:

apply plugin: 'com.android.library'

android {        
    ....
    publishNonDefault true
    productFlavors {
        market1 {}
        market2 {}
    }
}

проект build.gradle:

apply plugin: 'com.android.application'

android {
    ....
    productFlavors {
        market1 {}
        market2 {}
    }
}

dependencies {
    ....
    market1Compile project(path: ':lib', configuration: 'market1Release')
    market2Compile project(path: ':lib', configuration: 'market2Release')
}

Теперь вы можете выбрать вариант приложения и панель «Варианты сборки», и библиотека будет выбрана соответствующим образом, а вся сборка и запуск будут выполняться на основе выбранного варианта.

Если у вас есть несколько модулей приложения на основе библиотеки, Android Studio будет жаловаться на конфликт выбора варианта. Ничего страшного, просто проигнорируйте его.

введите описание изображения здесь

Али
источник
Спасибо, что поделились, теперь я могу избавиться от обходного пути defaultPublishConfig.
Delblanco
2
При запуске AS 1.1.0 вышеупомянутое решение, похоже, все еще работает, однако 1) выбор сборок для отладки / выпуска потерян, и у меня, кажется, все еще возникают проблемы с AIDL, обнаруженным в библиотеке, которые очень часто не могут создать соответствующий код. Есть мысли по этому поводу?
3c71 02
1
@IgorGanapolsky buildTypes тут ни при чем. В каждом варианте есть все типы сборки (обычно отладка и выпуск), и все они работают с этим подходом.
Али
1
@ An-droid он определяет библиотеку, которая будет использоваться для вкуса market1!
Али
1
Почему установлен тип сборки «релиз»? Выбирается ли тип сборки «релиз» во время сборки отладки?
WindRider
35

Есть одна проблема с ответом Али . Мы теряем одно очень важное измерение в наших вариантах сборки. Если мы хотим иметь все параметры (в моем примере ниже 4 (2 x 2)), нам просто нужно добавить пользовательские конфигурации в файл build.gradle основного модуля, чтобы иметь возможность использовать все multi-разновидности multi-buildType в Build Variants. Мы также должны установить publishNonDefault в true в файле build.gradle библиотечного модуля .

Пример решения:

Библиотека build.gradle

android {

    publishNonDefault true

    buildTypes {
        release {
        }
        debug {
        }
    }
    productFlavors {
        free {
        }
        paid {
        }
    }
}

Приложение build.gradle

android {

    buildTypes {
        debug {
        }
        release {
        }
    }
    productFlavors {
        free {
        }
        paid {
        }
    }
}

configurations {
    freeDebugCompile
    paidDebugCompile
    freeReleaseCompile
    paidReleaseCompile
}

dependencies {

    freeDebugCompile project(path: ':lib', configuration: 'freeDebug')
    paidDebugCompile project(path: ':lib', configuration: 'paidDebug')
    freeReleaseCompile project(path: ':lib', configuration: 'freeRelease')
    paidReleaseCompile project(path: ':lib', configuration: 'paidRelease')

}
AppiDevo
источник
После того, как я проделал то же самое в Моем приложении, Error:java.lang.RuntimeException: Error: more than one library with package nameпроизошел
Четан Джоши
22

Обновление для Android Plugin 3.0.0 и выше

Согласно официальной документации Android - перенос конфигураций зависимостей для локальных модулей ,

Благодаря разрешению зависимостей с учетом вариантов вам больше не нужно использовать зависящие от вариантов конфигурации, такие как freeDebugImplementation, для локальных зависимостей модуля - плагин позаботится об этом за вас.

Вместо этого вам следует настроить свои зависимости следующим образом:

dependencies {
    // This is the old method and no longer works for local
    // library modules:
    // debugImplementation project(path: ':library', configuration: 'debug')
    // releaseImplementation project(path: ':library', configuration: 'release')

    // Instead, simply use the following to take advantage of
    // variant-aware dependency resolution. You can learn more about
    // the 'implementation' configuration in the section about
    // new dependency configurations.
    implementation project(':library')

    // You can, however, keep using variant-specific configurations when
    // targeting external dependencies. The following line adds 'app-magic'
    // as a dependency to only the "debug" version of your module.

    debugImplementation 'com.example.android:app-magic:12.3'
}

Итак, в ответе Али измените

dependencies {
    ....
    market1Compile project(path: ':lib', configuration: 'market1Release')
    market2Compile project(path: ':lib', configuration: 'market2Release')
}

к

implementation project(':lib')

И плагин автоматически позаботится о конкретных вариантах конфигурации. Надеюсь, это поможет другим обновить плагин Android Studio до версии 3.0.0 и выше.

Суровый4789
источник
7

Мой Android-плагин - 3.4.0, и я считаю, что сейчас он не нуждается в настройках. Все, что вам нужно, это убедиться, что в приложениях flavourDimensions и productFlavors содержится один продуктFlavor с одинаковыми настройками flavourDimensions и productFlavors в библиотеках.

В build.gradle mylibrary

apply plugin: 'com.android.library'

android {        
    ....
    flavorDimensions "mylibFlavor"

    productFlavors {
        market1
        market2
    }
}

build.gradle приложения:

apply plugin: 'com.android.application'

android {
    ....
    flavorDimensions "mylibFlavor", "appFlavor"
    productFlavors {
        market1 {
            dimension "mylibFlavor"
        }
        market2 {
            dimension "mylibFlavor"
        }
        common1 {
            dimension "appFlavor"
        }
        common2 {
            dimension "appFlavor"
        }
    }
}

dependencies {
    ....
    implementation project(path: ':mylibrary')
}

После синхронизации вы можете переключить все параметры в окне вариантов сборки: введите описание изображения здесь

JiajiaGu
источник
Но что, если я не хочу, чтобы в основном модуле приложения были такие же вкусы? Предположим, у меня есть несколько модулей приложения, которые имеют свои собственные вкусы, и один общий модуль, который имеет свои собственные вкусы, и я хочу использовать в своем приложении мою библиотеку с определенным вкусом. Как бы Вы это сделали? Нет смысла копировать мои разновидности библиотеки во все приложения.
Billda
@Billda Вам не нужно копировать все, просто сохраните один и тот же productFlavor в приложении, для моего примера я могу сохранить market1 или market2 в build.gradle приложения.
JiajiaGu
2

Чтобы варианты работали с библиотекой AAR, вам необходимо определить defaultPublishConfig в файле build.gradle вашего модуля библиотеки Android.

Для получения дополнительной информации см .: Публикация библиотеки .

Публикация библиотеки

По умолчанию библиотека публикует только свой вариант выпуска. Этот вариант будет использоваться всеми проектами, ссылающимися на библиотеку, независимо от того, какой вариант они создают сами. Это временное ограничение из-за ограничений Gradle, над устранением которых мы работаем. Вы можете контролировать, какой вариант будет опубликован:

android {defaultPublishConfig "debug"}

Обратите внимание, что это имя конфигурации публикации ссылается на полное имя варианта. Релиз и отладка применимы только при отсутствии разновидностей. Если вы хотите изменить опубликованный вариант по умолчанию при использовании ароматов, вы должны написать:

android {defaultPublishConfig "Flame1Debug"}

Давид Лев
источник
1

На данный момент это невозможно, хотя, если я правильно помню, они хотят добавить эту функцию. (Изменить 2: ссылка , ссылка2 )

Изменить: на данный момент я использую defaultPublishConfigвозможность объявить, какой вариант библиотеки опубликован:

android {
    defaultPublishConfig fullRelease
    defaultPublishConfig demoRelease 
}
Дельбланко
источник
1
Итак, каждый раз, когда я собираюсь компилировать приложение, я должен изменить это в build.gradle библиотеки?
Али
Ну да ... каждый раз, когда вы хотите скомпилировать приложение с другим вкусом.
Delblanco
На самом деле, когда я определяю разновидности для библиотечного модуля, унаследованный пакет R не находит модуль приложения.
Али
Вы синхронизировали файлы Gradle в AS?
Delblanco
@Delblanco Это похоже на ручной труд и очень хрупкий (разработчики ленивы и забывают изменять свои файлы build.gradle).
Игорь Ганапольский 03
1

Я знаю, что эта тема закрыта, но просто обновление с gradle 3.0, см. Это: https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#variant_aware и grep matchingFallbacksи missingDimensionStrategy. Теперь гораздо проще объявить зависимости между разновидностями модулей.

... и в этом конкретном случае с gradle3.0, поскольку ароматы имеют одно и то же имя, gradle будет отображать их волшебным образом, никакой конфигурации не требуется.

AlexG
источник
Мне кажется, что этот сгенерированный во время выполнения материал пропускается. Например, генерация simonvt-> schematics больше не работает для меня по-новому. : - /
Стефан Шпренгер
1

Я также столкнулся с проблемой компиляции модулей для различных вариантов.

Что я нашел:

Похоже, нам не нужно добавлять publishNonDefault true в build.gradleфайл lib , поскольку Gradle 3.0.1 .

После декомпиляции класса BaseExtension обнаружил следующее:

public void setPublishNonDefault(boolean publishNonDefault) {
   this.logger.warn("publishNonDefault is deprecated and has no effect anymore. All variants are now published.");
}

И вместо:

dependencies {
...
   Compile project(path: ':lib', configuration: 'config1Debug')
}

Мы должны использовать:

dependencies {
...
   implementation project(':lib')
}

Только самое главное - добавить configurations {...} часть в файл build.gradle.

Итак, окончательный вариант приложения build.gradle файла :

buildTypes {
   debug {
      ...
   }

   release {
      ...
   }
}

flavorDimensions "productType", "serverType"
productFlavors {
   Free {
      dimension "productType"
      ...
   }
   Paid {
      dimension "productType"
      ...
   }
   Test {
      dimension "serverType"
      ...
   }
   Prod {
      dimension "serverType"
      ...
   }
}

configurations {
   FreeTestDebug
   FreeTestRelease
   FreeProdDebug
   FreeProdRelease
   PaidTestDebug
   PaidTestRelease
   PaidProdDebug
   PaidProdRelease
}

dependencies {
   implementation fileTree(dir: 'libs', include: ['*.jar'])
   implementation project(':lib')
   ...
}

Также вы можете использовать варианты фильтра, чтобы ограничить варианты сборки.

Ps не забудьте включить в settings.gradleфайл модули , например:

include ':app'
include ':lib'
project(':lib').projectDir = new File('app/libs/lib')
Серджио
источник
сэр, вы можете объяснить, как скрипт будет определять погоду, включать ли библиотеку в определенную конфигурацию или нет? Я имею в виду, что у меня есть случай, когда мне нужно использовать некоторую библиотеку для определенного аромата, но мне не нужно использовать его для другого аромата
Jenya Kirmiza 03
Не попал в такую ​​ситуацию. Но в руководстве Google developer.android.com/studio/build/dependencies рекомендуется добавить префикс перед командой "implementation" в блоке "dependencies {...}". Т.е. зависимости {payImplementation project (': lib')}, или dependencies {debugImplementation project (': lib')}, или любые зависимости с несколькими вариантами комбинации {payProdDebugImplementation project (': lib')}. Проверьте это и дайте нам отзыв :)
Серджио