Использование Build Flavors - структурирование исходных папок и build.gradle правильно

Обратите внимание: Ответ отредактирован после ответа Xavier

Я пытаюсь использовать различные Build Flavors для одного и того же проекта приложения в Android Studio. Тем не менее, мне кажется, что у меня ужасное время настроить его на работу соответствующим образом.

Шаги:

  • Создайте новый проект Android Studio под названием "Тест".
  • Откройте build.gradle * и добавьте следующие строки:

    productFlavors {
    flavor1 {
        packageName 'com.android.studio.test.flavor1'
        }
    flavor2 {
        packageName 'com.android.studio.test.flavor2'
        }
    }
    
  • После перезагрузки Android Studio теперь я вижу варианты 4 сборки в разделе "Варианты сборки". Это означало, что мы добились успеха в создании продукта. **
  • Создал новую папку источника для flavor1; однако я не уверен, правильно ли я делаю это. Вот как я это сделал:

    • Имейте в виду, что имя моего пакета для этого проекта: com.foo.test
    • Щелкните правой кнопкой мыши по папке src, для flavor1, я фактически создал отдельные папки в проводнике, так что структура src/flavor1/java/com/foo/test/MainActivity.java.
    • Это хорошо работает, поскольку папка "java" находится в синем, что означает, что IDE знает свою активную исходную директорию. Кроме того, пакет был автоматически создан. Несмотря на это, я получаю предупреждение о поиске дублированного класса. Смотрите снимок экрана здесь
    • Для flavor2 я попытался создать пакет вручную, но папка "src" для flavor2 кажется не синим цветом, поэтому при щелчке правой кнопкой мыши разные опции, и "Новый пакет" недоступен для меня. Смотрите изображение здесь.
    • Обратите внимание, что для flavor1 я также создал каталог "res", который становится синим, но, несмотря на это, не предлагает возможности создать либо файл ресурсов Android, либо каталог ресурсов Andorid, если я захочу для использования разных резорбентов для разных вкусов.

Я что-то делаю неправильно? Или я чего-то не хватает? Дайте мне знать, если вам нужна дополнительная информация.

* У моего проекта есть два файла build.gradle. Один из них расположен в корне папки проекта (\ GradleTest), этот пуст. Второй, расположенный в корне подпапки \GradleTest, также обозначенный как "GradleTest" (GradleTest-GradleTest), это тот, который уже имел код при открытии; поэтому это тот, который я редактировал.

** Я проверил настройки gradle и, видимо, Использовать автоматический импорт был уже включен. Несмотря на это, внося изменения в файл build.gradle автоматически не обновляет варианты сборки. Примечание. Я также попытался использовать Build - Rebuild Project и/или Build - Make Project, no-go. Мне все еще нужно закрыть проект и повторно открыть, чтобы изменения вступили в силу.

Ответ 1

Если вы получили настройки Studio, в разделе Gradle вы можете включить авто-импорт для своего проекта (мы включим его по умолчанию позже). Это позволит Studio повторно импортировать файл build.gradle всякий раз, когда вы его редактируете.

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

Если вы посмотрите мой IO-разговор, вы увидите, как мы смешиваем вместе значения из вкусов и типа сборки, чтобы создать вариант.

Для источника Java:

src/main/java
src/flavor1/java
src/debug/java

все 3 используются для создания одного вывода. Это означает, что они не могут определить один и тот же класс.

Если вы хотите иметь другую версию того же класса в двух вариантах, вам нужно создать его в обоих вариантах.

src/flavor1/java/com/foo/A.java
src/flavor2/java/com/foo/A.java

И тогда ваш код в src/main/java может сделать

import com.foo.A

в зависимости от выбранного вкуса, используется правая версия com.foo.A.

Это также означает, что обе версии A должны иметь один и тот же API (по крайней мере, когда дело доходит до API, используемого классами в src/main/java/...

Изменить для соответствия пересмотренному вопросу

Кроме того, важно поставить один и тот же класс A только в исходные папки, которые являются взаимоисключающими. В этом случае src/flavor1/java и src/flavor2/java никогда не выбираются вместе, но основной и flavor1 являются.

Если вы хотите предоставить другую версию действия с различным вкусом, не помещайте ее в src/main/java.

Заметьте, что если у вас было 3 аромата и вам нужен только один вкус для аромата1, в то время как flavor2 и flavor3 использовали одну и ту же активность, вы могли бы создать общие исходные папки для этих двух других действий. У вас есть полная гибкость в создании новых исходных папок и настройка исходного набора для их использования.

В других пунктах:

Это нормально, что вторая папка источника аромата не синяя. Вам нужно переключиться на второй вкус, чтобы включить его, а затем вы сможете создавать пакеты и классы внутри. До тех пор Studio не считает его исходной папкой. Мы, надеюсь, улучшим это в будущем, чтобы дать IDE информацию об этих неактивных исходных папках.

Я также считаю, что вы не можете создавать файлы ресурсов в папке res. Система меню не была обновлена, чтобы иметь дело со всеми этими дополнительными папками ресурсов. Это произойдет позже.

Ответ 2

"Ароматизаторы продуктов" на Android

Меня иногда спрашивали о том, как работать с разными хостами, значками или даже с именами пакетов, в зависимости от разных версий одного и того же приложения.

Есть много причин для этого и один простой способ: Product Flavors.

Вы можете определить на своем build.gradle script такие вещи, которые я описал ранее.

Ароматизаторы продукта Часть этой статьи написана, думая о вкусах продукта, и что они? Что касается документации Android:

Атрибут продукта определяет настраиваемую версию сборки приложения проектом. Один проект может иметь разные вкусы, которые меняют сгенерированное приложение.

Как вы можете определить их? Вы должны написать на свой build.gradle, какие вкусы вы хотите определить:

productFlavors {  
        ...
        devel {
            ...
        }

        prod {
            ...
        }
    }

Теперь у нас будет два разных вкуса нашего приложения. Вы можете проверить его на Android Studio тоже на вкладке "Варианты сборки"

Варианты сборки

Несколько имен пакетов

Что делать, если вы хотите установить на свой телефон одно приложение с состоянием разработки и одно для состояния производства. Как вы знаете, вы можете установить только одно приложение с тем же именем пакета (если вы попытаетесь установить какой-то новый APK с тем же, который установлен на вашем телефоне, он попытается обновить его).

Единственное, что вам нужно сделать, это определить его на каждом из ваших продуктов:

android {  
    productFlavors {
        devel {
            applicationId "zuul.com.android.devel"
        }
        prod {
            applicationId "zuul.com.android"
        }
    }
}

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

android {  
    productFlavors {
        devel {
            applicationId "zuul.com.android.devel"
            buildConfigField 'String', 'HOST', '"http://192.168.1.34:3000"'

        }

        prod {
            applicationId "zuul.com.android"
               buildConfigField 'String', 'HOST', '"http://api.zuul.com"'

        }
    }
}

В качестве примера мы попытаемся показать вам, как вы можете интегрировать это с помощью Retrofit для отправки запроса на соответствующий сервер без обработки того сервера, на который вы указываете, и на основе его вкуса. В этом случае это выдержка из приложения Zuul android:

public class RetrofitModule {

    public ZuulService getRestAdapter() {
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(BuildConfig.HOST)
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();
        return restAdapter.create(ZuulService.class);
    }

}

Как вы можете видеть, вам просто нужно использовать BuildConfigclass для доступа к только что определенной переменной.

Любая переменная, доступная через ваш код Переменная HOST не является единственной, которую вы можете открыть в своем коде. Вы можете сделать это с тем, что хотите:

prod {  
    applicationId "zuul.com.android"
    buildConfigField 'String', 'HOST', '"http://api.zuul.com"'
    buildConfigField 'String', 'FLAVOR', '"prod"'
    buildConfigField "boolean", "REPORT_CRASHES", "true"
}

Доступ к ним можно получить следующим образом:

BuildConfig.HOST  
BuildConfig.FLAVOR  
BuildConfig.REPORT_CRASHES  

Различные значки на каждый аромат Если вы хотите иметь разные значки для каждого аромата, чтобы вы могли визуально определить, какой из них вы открываете (вы можете сделать это и по имени... Но это не может соответствовать пространству!), Вам просто нужно определить новый каталог структуры для каждого из ароматов.

В примере, который я только что использовал, есть два варианта: devel и prod. Затем мы могли бы определить две новые структуры каталогов, чтобы мы могли определить нужные нам ресурсы:

Структура

Это работает с другими типами ресурсов, такими как strings.xml, integers.xml, arrays.xml и т.д.

Настройка параметров подписи

Чтобы вручную настроить конфигурации подписи для типа выпуска, используя Gradle конфигурацию сборки:

1.Создание хранилища ключей. Хранилище ключей - это двоичный файл, содержащий набор закрытых ключей. Вы должны хранить хранилище в безопасном и безопасном месте. 2. Создайте закрытый ключ. Закрытый ключ представляет собой объект, который должен быть идентифицирован с приложением, например, лицом или компанией. 3. Внесите конфигурацию подписи в файл build.gradle на уровне модуля:

android {
...
defaultConfig {...}
signingConfigs {
    release {
        storeFile file("myreleasekey.keystore")
        storePassword "password"
        keyAlias "MyReleaseKey"
        keyPassword "password"
    }
}
buildTypes {
    release {
        ...
        signingConfig signingConfigs.release
    }
}

}

Создать подписанный APK:

Чтобы создать подписанный APK, выберите "Создать" > "Создать подписанный APK" в главном меню. Пакет в app/build/apk/app-release.apk теперь подписан с вашим ключом освобождения.

ref: https://developer.android.com/studio/build/build-variants.html#signing,http://blog.brainattica.com/how-to-work-with-flavours-on-android/

Ответ 3

Кажется, вам нужно перезагрузить проект после добавления новых ароматов в build.gradle. После этого вы увидите 4 варианта сборки в представлении "Варианты сборки" (вы получаете доступ к нему из левого края окна).

Что касается дополнительных исходных каталогов, кажется, вам нужно создать их вручную: src/flavor1/java и src/flavor2/java. Вы увидите, что изменение аромата в представлении "Варианты сборки" изменит текущие активные исходные каталоги (каталог является синим, если он является активным исходным каталогом).

Наконец, "gradle создаст новые исходные наборы для ваших новых вкусов" означает, что gradle создаст объекты android.sourceSets.flavor1 и android.sourceSets.flavor2, и вы сможете использовать их в своем build.gradle script. Но эти объекты создаются динамически, поэтому вы не видите их в build.gradle (я предлагаю вам прочитать это: http://www.gradle.org/docs/current/userguide/tutorial_using_tasks.html Особенно 6.6: это объясняет создание динамической задачи. gradle script - это groovy script, поэтому я предлагаю вам также ознакомиться с groovy)

Ответ 4

У меня была такая же проблема, когда я перенес свой проект на Gradle. Проблема заключалась в том, что сборка не нашла нужную папку ресурсов. Я исправил это, добавив это под элементом android в файле build.gradle:

sourceSets {
        main {
            res.srcDirs = ['myProject/res']
        }
    }

Ответ 5

Что-то, что важно и заблокировало меня довольно долго, - это имя вкуса, которое должно соответствовать пакету, в отличие от пакета, определенного внутри определения вкуса в gradle. Например:

src/flavor1/java/com/foo/A.java

будет соответствовать

productFlavors {
  flavor1 {
    packageName 'com.android.studio.test.foobar'
  }
}

но

src/foobar/java/com/foo/A.java не будет использоваться для сборки flavor1.

Ответ 6

В gradle:

Для типов сборки вам нужно только:

buildTypes {
   release{
    //proguard, signing etc.
   }
   debug {
    //development
   }
  }
}

И затем для ароматов вы добавляете те, которые вам нужны

productFlavors {
    pro {
        applicationIdSuffix '.paid'
        buildConfigField 'boolean', 'PRO', 'true'
    }
    free {
        applicationIdSuffix '.free'
        buildConfigField 'boolean', 'PRO', 'false'
    }
}