9

Pracuję nad aplikacją na Androida za pomocą Android Studio (v 2.1, gradle plugin v 2.1.0). Moja aplikacja ma różne wersje, które mają wiele wspólnego kodu, więc postanowiłem użyć wymiarów smakowych i smaków produktu, aby dostosować kod i zasoby, kiedy i gdzie jest to wymagane. To działało, tak długo, jak miałem tylko dwa wymiary smakowe. Jako przykład, mój app.gradle byłAndroid Studio: kombinacja smaku produktu z więcej niż dwoma wymiarami smaku (grupami smakowymi)

… 
flavorDimensions "fruit", "color" 

productFlavors { 

    apple { 
     dimension "fruit" 
    } 
    pear { 
     dimension "fruit" 
    } 

    red { 
     dimension "color" 
    } 
    yellow { 
     dimension "color" 
    } 
} 
… 

i mój folder src był

src/ 
    appleRed/ 
    appleYellow/ 
    pearRed/ 
    pearYellow/ 

każdy z niestandardowej wersji mojego kodu. Znowu, jak w przykładzie

src/ 
    appleRed/java/com/example/ExampleFragment.java 
    appleYellow/java/com/example/ExampleFragment.java 
    pearRed/java/com/example/ExampleFragment.java 
    pearYellow/java/com/example/ExampleFragment.java 

oczywiście nie ma na przykład ExampleFragment w src/main.

W pewnym momencie rozwoju, musiałem obejmują bezpłatny i zapłacił wersję aplikacji. Myślałem, że może być łatwo osiągnięty poprzez dodanie nowego wymiaru smaku nazwie version oraz dwa smaki produkt o nazwie free i paid:

… 
flavorDimensions "fruit", "color”, “version” 

productFlavors { 

    apple { 
     dimension "fruit" 
    } 
    pear { 
     dimension "fruit" 
    } 

    red { 
     dimension "color" 
    } 
    yellow { 
     dimension "color" 
    } 

    free { 
     dimension "version" 
    } 
    paid { 
     dimension “version” 
    } 
} 
… 

ale nagle z niestandardowego kodu wygenerowanego przez połączenie fruit i color nie było wykryte przez Android Studio. Więc nie appleRed, appleYellow, pearRed ani pearYellow mogą być użyte do niestandardowego kodu, a jedynym sposobem udało mi się odzyskać moją konfigurację było wykorzystać wszystkie kombinacje wszystkich wymiarach trzy Smak:

src/ 
     appleRedFree/java/com/example/ExampleFragment.java 
     appleRedPaid/java/com/example/ExampleFragment.java 
     appleYellowFree/java/com/example/ExampleFragment.java 
     appleYellowPaid/java/com/example/ExampleFragment.java 
     pearRedFree/java/com/example/ExampleFragment.java 
     pearRedPaid/java/com/example/ExampleFragment.java 
     pearYellowFree/java/com/example/ExampleFragment.java 
     pearYellowPaid/java/com/example/ExampleFragment.java 

To nie jest dobrze, ponieważ ExampleFragment jest powielana w tej samej kombinacji fruitColor* (appleRedFree, appleRedPaid mają ten sam ExampleFragment). Ten sam problem występuje w przypadku zasobów (te w folderze res).

Moje pytania są następujące:

1) Czy jest to oczekiwane zachowanie z Gradle w Android Studio (tj, nie będąc w stanie połączyć podzbiór smaków produktów, po ich priorytet na podstawie ich wymiaru, gdy o więcej niż dwa wymiary smakowe)?

2) Biorąc pod uwagę fakt, że jest to oczekiwane zachowanie, czy istnieje inny sposób mogę osiągnąć mój dostosowywania bez kodu duplikaty lub bez konieczności pojedynczego pliku z if-oświadczenie wewnątrz (np, if (BuildConfig.FLAVOR_version == "free") ...)?

Pamiętaj, że mówię o niestandardowym kodzie, który może być skomplikowany, więc nie pytam o podstawowe dostosowanie, takie jak zmienna konfiguracji kompilacji, filtrowanie wariantów czy coś w tym stylu.

Odpowiedz

6

Chcesz użyć tego samego dodatkowego katalogu ze źródłami dla niektórych smaków;

appleRedFree + appleRedPaid --> src/appleRed
pearRedFree + pearRedPaid --> src/pearRed
appleYellowFree + appleYellowPaid --> src/appleYellow
pearYellowFree + pearYellowPaid --> src/pearYellow

Można ustawić sourceSet dla smaków:

android { 

    // Other stuff here 

    flavorDimensions "fruit", "color”, “version” 

    productFlavors { 

     apple { 
      dimension "fruit" 
     } 
     pear { 
      dimension "fruit" 
     } 

     red { 
      dimension "color" 
     } 
     yellow { 
      dimension "color" 
     } 

     free { 
      dimension "version" 
     } 
     paid { 
      dimension “version” 
     } 
    } 

    sourceSets { 
     appleRedFree { 
      java.srcDirs = ['src/main/java', 'src/appleRed/java'] 
     } 

     appleRedPaid { 
      java.srcDirs = ['src/main/java', 'src/appleRed/java'] 
     } 

     appleYellowFree { 
      java.srcDirs = ['src/main/java', 'src/appleYellow/java'] 
     } 

     appleYellowPaid { 
      java.srcDirs = ['src/main/java', 'src/appleYellow/java'] 
     } 

     pearRedFree { 
      java.srcDirs = ['src/main/java', 'src/pearRed/java'] 
     } 

     pearRedPaid { 
      java.srcDirs = ['src/main/java', 'src/pearRed/java'] 
     } 

     pearYellowFree { 
      java.srcDirs = ['src/main/java', 'src/pearYellow/java'] 
     } 

     pearRedPaid { 
      java.srcDirs = ['src/main/java', 'src/pearYellow/java'] 
     } 
    } 

    // Other stuff here 
} 
+0

nie działa. Synchronizacja projektu Gradle kończy się niepowodzeniem z błędem: 'Błąd: (46, 0) Nie można znaleźć metody appleRedFree() dla argumentów [build_5p3mtjx0cpg9la7ms46x7bgzz $ _run_closure2 $ _closure8 @ 5d22a1be] dla kontenera AndroidSourceSet." Czy zapomniałeś gdzieś umieścić wtyczkę 'apply plugin'? – Vangaorth

+1

@Vangaorth Ulepszyłem swoją odpowiedź. – Devrim

+0

Teraz działa! Należy również użyć najnowszej (w chwili pisania) wtyczki Gradle Android (2.3.0) i Gradle (3.3). Tak więc, w Android Studio, Plik -> Struktura projektu -> Karta Projekt, Wersja Gradle do wersji 3.3 i Wersja wtyczki Androida do wersji 2.3.0 – Vangaorth