Using Build Flavors - strukturyzacja folderów źródłowych i build.gradle poprawnie

Uwaga: odpowiedź edytowana po odpowiedzi Xaviera

Próbuję użyć różnych Build Flavors dla jednego projektu aplikacji w Android Studio. Jednak wydaje mi się, że mam straszny czas, aby skonfigurować go do odpowiedniego działania.

Kroki:

  1. Utwórz nowy projekt Android Studio o nazwie 'Test'.
  2. Open build.gradle* i dodał następujące wiersze:

    productFlavors {
    flavor1 {
        packageName 'com.android.studio.test.flavor1'
        }
    flavor2 {
        packageName 'com.android.studio.test.flavor2'
        }
    }
    
  3. Po ponownym uruchomieniu Android Studio, I zobacz 4 warianty budowy w sekcji warianty budowy. Co oznacza, że do tej pory udało nam się zebrać smaki produktów. **
  4. Utworzył nowy folder źródłowy dla flavor1 ; jednak nie jestem pewien, czy robię to dobrze. Oto jak to zrobiłem:

    • pamiętaj, że moja Nazwa pakietu dla tego projektu to: com.foo.test
    • kliknij prawym przyciskiem myszy na folderze src, dla flavor1 utworzyłem poszczególne foldery w Eksploratorze, w taki sposób, że struktura src/flavor1/java/com/foo/test/MainActivity.java.
    • powyższe zadziałało dobrze, ponieważ folder 'java' znajduje się w blue, co oznacza, że IDE zna swój aktywny katalog źródłowy. Ponadto pakiet został utworzony automatycznie. Pomimo tego, otrzymuję ostrzeżenie o znalezieniu duplikatu klasy. zobacz zrzut ekranu tutaj.
    • W przypadku flavor2 próbowałem utworzyć pakiet ręcznie, ale folder ' src 'dla flavor2 wydaje się nie być niebieski, dlatego opcje są różne po kliknięciu prawym przyciskiem myszy i 'New Package' nie jest dostępna dla mnie. Zobacz zdjęcie tutaj.
    • zauważ, że dla flavor1 stworzyłem również katalog 'res', który zmienia kolor na niebieski, ale mimo to nie oferuje możliwości tworzenia ani pliku zasobów Androida, ani katalogu zasobów Andorid, na wypadek, gdybym chciał użyć różnych resoruces dla różnych smaków.
Czy robię coś nie tak? Czy coś przeoczyłem? Daj mi znać, jeśli potrzebujesz więcej informacji.

*Mój projekt wydaje się zbuduj dwa .pliki gradle. Jeden znajduje się w katalogu głównym projektu (\GradleTest), ten jest pusty. Drugi znajduje się w katalogu głównym podfolderu \GradleTest, również oznaczony jako 'GradleTest' (GradleTest-GradleTest), jest to ten, który miał już kod po otwarciu; dlatego jest to ten, który edytowałem.

** sprawdziłem ustawienia gradle i najwyraźniej użyj auto-import było już włączone. pomimo tego, dokonywanie zmian w kompilacji.plik gradle nie aktualizuje automatycznie wariantów kompilacji. Uwaga: próbowałem również użyć Build - Rebuild Project, i/lub Build - Make Project, no-go. Nadal muszę zamknąć projekt i ponownie otworzyć, aby zmiany weszły w życie.

Author: daniel_c05, 2013-05-24

6 answers

Jeśli masz w preferencjach Studio, w sekcji Gradle możesz włączyć automatyczny import dla swojego projektu(domyślnie włączymy to później). Pozwoli to Studio ponownie zaimportować twoją kompilację.gradle za każdym razem, gdy go edytujesz.

Tworzenie smaków nie oznacza, że użyjesz do nich niestandardowego kodu, abyśmy nie tworzyli folderów. Musisz je stworzyć sam.

Jeśli spojrzysz na my IO talk zobaczysz, jak łączymy ze sobą wartości ze smaków i buduj Typ, aby utworzyć wariant.

Dla źródła Javy:

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

Są wszystkie 3 używane do utworzenia pojedynczego wyjścia. Oznacza to, że nie mogą zdefiniować tej samej klasy.

Jeśli chcesz mieć inną wersję tej samej klasy w dwóch smakach, musisz utworzyć ją w obu smakach.

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

I wtedy twój kod w src / main / java może zrobić

import com.foo.A

W zależności od wybranego smaku, odpowiednia wersja com.foo.A jest używany.

Oznacza to również obie wersje musi mieć takie samo API (przynajmniej jeśli chodzi o API używane przez klasy w src/main/java/...

Edit to match revised question

Dodatkowo, ważne jest umieszczenie tej samej klasy a tylko w folderach źródłowych, które wzajemnie się wykluczają. W tym przypadku src/flavor1/java i src/flavor2 / java nigdy nie są wybierane razem, ale main i flavor1 są.

Jeśli chcesz podać inną wersję aktywności w innym smaku, nie umieszczaj jej w src / main / java.

Zauważ, że jeśli masz 3 smaki i potrzebujesz tylko niestandardowego dla flavor1, podczas gdy flavor2 i flavor3 współdzieliły tę samą aktywność, możesz utworzyć wspólne foldery źródłowe dla tych dwóch innych aktywności. Masz całkowitą elastyczność w tworzeniu nowych folderów źródłowych i konfigurowaniu zestawu źródeł, aby z nich korzystać.

Do pozostałych punktów:

To normalne, że drugi folder źródłowy smaku nie jest niebieski. Musisz przełączyć się na drugi smak, aby go włączyć, a następnie będziesz mógł tworzyć pakiety i klasy wewnątrz. Do tego czasu Studio nie uważa go za folder źródłowy. Mamy nadzieję, że poprawimy to w przyszłości, aby IDE uświadomiło sobie te nieaktywne foldery źródłowe.

Myślę, że to normalne, że nie można tworzyć plików zasobów w folderze res. System menu nie został zaktualizowany, aby poradzić sobie z tymi wszystkimi dodatkowymi folderami zasobów. To przyjdzie później.

 208
Author: Xavier Ducrohet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-10 14:07:14

"smaki produktów" na Androida

Czasami pytano mnie, jak pracować z różnymi hostami, ikonami, a nawet nazwami pakietów, deppując na różnych wersjach tej samej aplikacji.

Istnieje wiele powodów, aby to zrobić i jeden prosty sposób: smaki produktów.

Możesz zdefiniować na swojej kompilacji.gradle script takie rzeczy opisywałem wcześniej.

smaki produktu Część artykułu jest napisana z myślą o produkcie smaki, więc czym one są? Jeśli chodzi o dokumentację Androida:

Smak produktu definiuje dostosowaną wersję aplikacji zbudowanej przez projekt. Pojedynczy projekt może mieć różne smaki, które zmieniają wygenerowaną aplikację.

Jak można je zdefiniować? Musisz pisać na swojej budowie.gradle jakie smaki chcesz zdefiniować:

productFlavors {  
        ...
        devel {
            ...
        }

        prod {
            ...
        }
    }

Teraz będziemy mieli dwa różne smaki naszej aplikacji. Możesz to sprawdzić na Android Studio również w wariantach kompilacji tab

Warianty budowy

wiele nazw pakietów

Co zrobić, jeśli chcesz mieć zainstalowaną w telefonie jedną aplikację ze stanem deweloperskim i jedną ze stanem produkcyjnym. Jak być może wiesz, możesz zainstalować tylko jedną aplikację o tej samej nazwie pakietu(jeśli spróbujesz zainstalować jakiś nowy APK z tym samym, który jest zainstalowany w telefonie, spróbuje go zaktualizować).

Jedyne, co musisz zrobić, to zdefiniować go na każdym produkcie smaki:

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

Wysyłanie żądań do wielu hostów w zależności od smaku Tak jak wcześniej, musisz podać kilka paramów w polu konfiguracji smaku produktu.

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

        }
    }
}

Jako przykład spróbujemy pokazać, w jaki sposób można zintegrować to z Retrofit, aby wysłać żądanie do odpowiedniego serwera bez obsługi, który serwer kierujesz i w oparciu o smak. W tym przypadku jest to fragment aplikacji Zuul na Androida:

public class RetrofitModule {

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

}

Jak widać wystarczy użyć BuildConfigclass, aby uzyskać dostęp do zmiennej, którą właśnie zdefiniowałeś.

Dowolna zmienna dostępna za pomocą Twojego kodu Zmienna HOST nie jest jedyną, którą możesz ujawnić w kodzie. Możesz to zrobić z czym chcesz:

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

Możesz uzyskać do nich dostęp w następujący sposób:

BuildConfig.HOST  
BuildConfig.FLAVOR  
BuildConfig.REPORT_CRASHES  

Różne ikony na smak Jeśli chcesz mieć różne ikony dla smaku, dzięki czemu możesz wizualnie wykryć, którą otwierasz (możesz to zrobić również po nazwie... Ale to nie może zmieścić przestrzeń!), po prostu trzeba zdefiniować nowe struktury katalogów dla każdego ze smaków.

W przykładzie, którego właśnie użyłem, są dwa smaki: devel i prod. Następnie możemy zdefiniować dwie nowe struktury katalogów, dzięki czemu możemy zdefiniować zasoby, które chcemy:

Struktura

To działa z innymi rodzajami zasobów, takimi jak strings.xml, integers.xml, arrays.xml, itp.

Konfiguracja Ustawień Podpisywania

Aby ręcznie skonfigurować konfiguracje podpisywania dla typu release build przy użyciu Gradle konfiguracja budowy:

1.Utwórz keystore. Keystore to plik binarny zawierający zestaw kluczy prywatnych. Musisz trzymać klucz w bezpiecznym miejscu. 2.Utwórz klucz prywatny. Klucz prywatny reprezentuje podmiot, który ma być identyfikowany z aplikacją, taki jak osoba lub firma. 3.Dodaj konfigurację podpisywania do kompilacji na poziomie modułu.plik gradle:

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

}

Wygeneruj podpisany APK:

Aby wygenerować podpisany APK, wybierz Build > Generate Podpisany APK z menu głównego. Pakiet w app / build / apk / app-release.apk jest teraz podpisany kluczem wydania.

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

 18
Author: A-Droid Tech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-12 10:28:12

Wydaje się, że musisz przeładować swój projekt po dodaniu nowych smaków w build.gradle. Następnie zobaczysz 4 warianty kompilacji w widoku warianty kompilacji(uzyskasz do nich dostęp z lewej krawędzi okna).

Jeśli chodzi o dodatkowe katalogi źródłowe, wydaje się, że trzeba je tworzyć ręcznie: src/flavor1/java i src/flavor2/java. Zobaczysz, że zmiana smaku w widoku "Build Variants" zmieni aktualnie aktywne katalogi źródłowe (katalog jest niebieski, gdy jest active source directory )

Wreszcie, "gradle stworzy nowe zestawy źródeł dla twoich nowych smaków" oznacza, że gradle stworzy obiekty android.sourceSets.flavor1 i android.sourceSets.flavor2 i będziesz mógł ich używać w swojej kompilacji.Gradle script. Ale te obiekty są tworzone dynamicznie, dlatego nie widzisz ich w build.gradle (proponuję przeczytać to: http://www.gradle.org/docs/current/userguide/tutorial_using_tasks.html szczególnie 6.6: wyjaśnia tworzenie dynamicznych zadań. Skrypt gradle jest to groovy script, więc proponuję zapoznać się również z groovy)

 7
Author: ben75,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-24 15:19:56

Miałem ten sam problem, kiedy migrowałem mój projekt do Gradle. Problem polegał na tym, że kompilator nie znalazł odpowiedniego folderu zasobów. Naprawiłem to, dodając to pod elementem android w build."gradle": {]}

sourceSets {
        main {
            res.srcDirs = ['myProject/res']
        }
    }
 2
Author: Tomer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-03 14:44:31

Coś, co jest ważne i zablokowało mnie na jakiś czas, to to, że nazwa smaku, która musi pasować do pakietu, w przeciwieństwie do pakietu zdefiniowanego wewnątrz definicji smaku w gradle. Na przykład:

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

Dopasuje

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

Ale

src/foobar/java/com/foo/A.java nie będzie używany do kompilacji flavor1.

 0
Author: bitrock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-09 03:37:22

W gradle:

Dla typów budowania potrzebujesz tylko:

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

A potem do smaków dodajesz te, których potrzebujesz

productFlavors {
    pro {
        applicationIdSuffix '.paid'
        buildConfigField 'boolean', 'PRO', 'true'
    }
    free {
        applicationIdSuffix '.free'
        buildConfigField 'boolean', 'PRO', 'false'
    }
}
 0
Author: TouchBoarder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-29 16:40:09