Використання збірок ароматів - правильно структурувати папки з джерелами та build.gradle


166

Зверніть увагу: відповідь відредаговано після відповіді Ксав'є

Я намагаюся використовувати різні збірки ароматів для одного проекту програми в Android Studio. Однак мені здається, що у мене жахливий час налаштувати його на належну роботу.

Кроки:

  1. Створіть новий проект Android Studio, названий "Тест".
  2. Відкрийте build.gradle * та додайте наступні рядки:

    productFlavors {
    flavor1 {
        packageName 'com.android.studio.test.flavor1'
        }
    flavor2 {
        packageName 'com.android.studio.test.flavor2'
        }
    }
  3. Після перезавантаження Android Studio я тепер бачу 4 варіанти складання в розділі «Варіанти збірки». Це означає, що ми успішно розбирали ароматизатори продукту. **
  4. Створено нову папку Source для смаку1 ; однак я не впевнений, чи роблю це правильно. Ось як я це зробив:

    • Майте на увазі, що моя назва пакету для цього проекту: com.foo.test
    • Клацніть правою кнопкою миші на srcпапці, щоб отримати смак1, я фактично створив окремі папки в Explorer, таким чином, що це структура src/flavor1/java/com/foo/test/MainActivity.java.
    • Вище написано добре, оскільки папка 'java' синього кольору , тобто IDE знає свій активний каталог джерел. Також пакет автоматично був створений. Незважаючи на це, я отримую попередження про знайдений дублікат класу. Дивіться скріншот тут.
    • Для аромату2 я спробував створити пакет вручну, але папка 'src' для смаку2 не виглядає синім кольором, тому параметри відрізняються при натисканні правою кнопкою миші, і «Новий пакет» мені не доступний. Дивіться зображення тут.
    • Зауважте, що для смаку1 я також створив каталог 'res', який синіє, але, незважаючи на це, не пропонує можливості створювати ні файл ресурсів Android, ні каталог ресурсів Andorid, якщо я хотів би використовувати різні resoruces для різних смаків.

Чи я щось роблю не так? Або я щось пропускаю? Повідомте мене, якщо вам потрібна додаткова інформація.

* Мій проект, схоже, має два файли build.gradle. Той, що знаходиться у корені папки проекту (\ GradleTest), цей порожній. Друга, розташована в корені підпапки \ GradleTest, також позначена "GradleTest" (GradleTest-GradleTest), це та, яка вже мала код при відкритті; отже, це я редагував.

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


Зауважте, що applicationIdтепер підтримується замість packageName.
Хамзе Собох

Відповіді:


220

Якщо ви потрапили в налаштування Студії, у розділі 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 / taste1 / java та src / taste2 / java ніколи не вибираються разом, але основні та аромат1 є.

Якщо ви хочете надати іншу версію діяльності з різним ароматом, не кладіть її в src / main / java.

Зауважте, що якщо у вас було 3 аромати, і ви хотіли лише спеціального для аромату1, а смак2 та аромат3 ділилися однаковою діяльністю, ви могли б створити загальну папку з джерелом для цих двох інших дій. Ви маєте повну гнучкість у створенні нових папок джерела та налаштування набору джерел для їх використання.

Про Ваші інші пункти:

Це нормально, щоб папка другого джерела смаку не була синьою. Вам потрібно перейти на 2-й аромат, щоб увімкнути його, і тоді ви зможете створювати пакети та класи всередині. До цього студія не вважає це вихідною папкою. Ми сподіваємось, що це в майбутньому покращиться, щоб IDE дізнався про ці неактивні папки-джерела.

Я думаю, що також нормально, що ви не можете створювати файли ресурсів у папці res. Система меню не була оновлена ​​для роботи з усіма цими додатковими папками ресурсів. Це прийде пізніше.


1
Я додав нові елементи в кінці своєї відповіді, але дублікат має сенс. Ви не можете мати однаковий клас і в src / main / java, і в src / taste1 / java, як обидва використовуються при виборі arom1. У своїй відповіді зауважте, як я кладу в той самий клас лише смак1 / java та смак2 / java, оскільки вони є ексклюзивними та ніколи не вмикаються разом.
Ксав'є Дюкрохет

Ей, Ксав'є, чи можете ви дати мені більш детальну характеристику того, як я можу використовувати іншу версію діяльності у своїх смаках? У мене є тестовий проект, де я хочу використовувати різні версії моєї MainActivity, але в обох apk (смак1 та смак2) є лише версія main / java. Коли я не ставлю MainActivity всередині main / java, додаток виходить із ладу, коли я його запускаю.
JensJensen

@XavierDucrohet як щодо того, щоб мати різні ресурси, а також різний код на основі ароматів, але чи є вони в різних модулях, щоб ми могли включити один чи інший модуль на основі аромату, не потребуючи змішування коду та ресурсів в одному кореневому проекті? Це підтримується?
Валеріо Сантінеллі

3
@ValerioSantinelli Можна зробити залежність від смаку. ВикористанняflavorCompile ...
Ксав'є Дюкрохет

@XavierDucrohet Я спробував те, що ви запропонували, але це не працює, як я очікував. Ви можете побачити , як мій проект структурований там: stackoverflow.com/q/24410995/443136
Valerio Santinelli

19

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

Мене іноді запитують, як працювати з різними хостами, іконками чи навіть іменами пакетів, залежно від різних версій одного додатка.

Є багато причин для цього і один простий шлях: Ароматизатори продукту.

Ви можете визначити на сценарії build.gradle такі речі, які я описав раніше.

Ароматизатори продукту Частина цієї статті написана, думаючи про ароматизатори продукту, тож, що вони? Що стосується документації на 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 тепер підписаний вашим ключем випуску.

посилання: https://developer.android.com/studio/build/build-variants.html#signing,http://blog.brainattica.com/how-to-work-with-flavours-on-android/



7

Здається, вам потрібно перезавантажити проект, додавши нові аромати build.gradle. Після цього ви побачите 4 варіанти складання у вікні "Варіанти збирання" (ви отримуєте доступ до нього з лівого краю вікна).

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

І, нарешті, «Gradle створить нові sourceSets для ваших нових смаків» означає , що Gradle буде створювати об'єкти android.sourceSets.flavor1і , android.sourceSets.flavor2і ви можете використовувати їх в build.gradle сценарії. Але ці об'єкти створюються динамічно, тому ви не бачите їх у build.gradle(я пропоную вам прочитати це: http://www.gradle.org/docs/current/userguide/tutorial_using_tasks.html Особливо 6.6: це пояснює Створення динамічного завдання. Сценарій Gradle - це важкий сценарій, тому я пропоную вам ознайомитись і з groovy)


2
Я думаю, що примітка про імпорт - це Build VariantsВид, я цього не помічав.
Chris.Jenkins

2

У мене виникло те саме питання, коли я мігрував свій проект у Gradle. Проблема полягала в тому, що збірка не знайшла потрібну папку ресурсів. Я виправив це, додавши це під елементом Android у build.gradle:

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

0

Щось важливе і заблокувало мене досить довго, це те, що назва аромату, яке повинно відповідати пакету, на відміну від пакета, визначеного всередині визначення аромату в градусах. Наприклад:

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

відповідатиме

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

але

src/foobar/java/com/foo/A.java не використовуватиметься для створення аромату1.


0

У градусі:

Для типів збірки вам потрібно лише:

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

А потім для ароматів ви додаєте потрібні

productFlavors {
    pro {
        applicationIdSuffix '.paid'
        buildConfigField 'boolean', 'PRO', 'true'
    }
    free {
        applicationIdSuffix '.free'
        buildConfigField 'boolean', 'PRO', 'false'
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.