Skonfiguruj warianty kompilacji

Na tej stronie dowiesz się, jak skonfigurować warianty kompilacji, aby Tworzenie różnych wersji aplikacji z jednego projektu aby umożliwić prawidłowe zarządzanie zależnościami i konfiguracjami podpisywania.

Każdy wariant kompilacji reprezentuje inną wersję aplikacji, która które możesz stworzyć. Możesz na przykład utworzyć jedną wersję swojej aplikacji czyli bezpłatną z ograniczonym zestawem treści, oraz inną płatną wersję, zawiera więcej informacji. Możesz też tworzyć różne wersje aplikacji kierowane w zależności od poziomu interfejsu API lub innych wersji urządzeń.

Warianty kompilacji są wynikiem działania Gradle korzystającego z określonego argumentu do łączenia ustawień, kodu i zasobów skonfigurowanych w rodzajów budowy i smaków produktów. Chociaż nie konfigurujesz wariantów kompilacji musisz skonfigurować typy kompilacji i smaki produktów, które z nich korzystają.

Przykład: „demonstracja” rodzaj usługi może określać określone funkcje. i wymagań urządzeń, takich jak niestandardowy kod źródłowy, zasoby poziomy interfejsu API, podczas gdy typ kompilacji pozwala zastosować różne kompilacje i ustawień pakietów, takich jak opcje debugowania i klucze podpisywania. wariantem kompilacji, który łączy te 2 elementy, jest „demoDebug” wersji Twojej aplikacji i zawiera kombinacja konfiguracji i zasobów zawartych w „prezentacji” rodzaj produktu, „debugowanie” typ kompilacji i main/ zbiór źródeł.

Skonfiguruj typy kompilacji

Typy kompilacji możesz tworzyć i konfigurować w android pliku build.gradle.kts na poziomie modułu. Gdy tworzysz nowego modułu, Android Studio automatycznie utworzy kompilację do debugowania i kompilacji. . Mimo że typ kompilacji do debugowania nie jest widoczny w konfiguracji kompilacji Android Studio skonfiguruje go za pomocą debuggable true. Pozwala to na debugowanie aplikacji na bezpiecznych urządzeniach z Androidem konfiguruje podpisywanie aplikacji za pomocą ogólnego magazynu kluczy debugowania.

Jeśli chcesz dodać do konfiguracji typ kompilacji do debugowania lub zmienić określone ustawienia. Poniższy przykład określa applicationIdSuffix dla typu i konfiguracji kompilacji do debugowania „etap przejściowy” typ kompilacji inicjowany z użyciem ustawień typu kompilacji do debugowania:

Kotlin

android {
    defaultConfig {
        manifestPlaceholders["hostName"] = "www.example.com"
        ...
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
        }

        getByName("debug") {
            applicationIdSuffix = ".debug"
            isDebuggable = true
        }

        /**
         * The `initWith` property lets you copy configurations from other build types,
         * then configure only the settings you want to change. This one copies the debug build
         * type, and then changes the manifest placeholder and application ID.
         */
        create("staging") {
            initWith(getByName("debug"))
            manifestPlaceholders["hostName"] = "internal.example.com"
            applicationIdSuffix = ".debugStaging"
        }
    }
}

Odlotowe

android {
    defaultConfig {
        manifestPlaceholders = [hostName:"www.example.com"]
        ...
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            applicationIdSuffix ".debug"
            debuggable true
        }

        /**
         * The `initWith` property lets you copy configurations from other build types,
         * then configure only the settings you want to change. This one copies the debug build
         * type, and then changes the manifest placeholder and application ID.
         */
        staging {
            initWith debug
            manifestPlaceholders = [hostName:"internal.example.com"]
            applicationIdSuffix ".debugStaging"
        }
    }
}

Uwaga: gdy wprowadzasz zmiany w pliku konfiguracji kompilacji, Android Studio wymaga zsynchronizowania projektu z nowym konfiguracji. Aby zsynchronizować projekt, kliknij Sync Now (Synchronizuj teraz). na pasku powiadomień, który pojawia się po wprowadzeniu zmiany lub kliknięciu Synchronizuj projekt na pasku narzędzi. Jeśli Android Studio wykrywa błędy w konfiguracji, Pojawi się okno Wiadomości opisujące problem.

Aby dowiedzieć się więcej o wszystkich właściwościach, które można skonfigurować za pomocą typów kompilacji, przeczytaj BuildType.

Skonfiguruj smaki produktów

Tworzenie smaków produktów przypomina tworzenie typów kompilacji. Dodaj smaki produktów do Blok productFlavors w konfiguracji kompilacji i uwzględnić odpowiednie ustawienia. Gromady produktów obsługują te same właściwości, co defaultConfig, ponieważ defaultConfig należy do ProductFlavor. Oznacza to, że możesz podać podstawowe dane konfigurację dla wszystkich smaków w bloku defaultConfig, każdy rodzaj może zmienić dowolną z tych wartości domyślnych, np. applicationId. Do więcej informacji o identyfikatorze aplikacji znajdziesz w artykule Ustaw identyfikator aplikacji.

Uwaga: nadal musisz określić nazwę pakietu za pomocą atrybutu package. w pliku manifestu main/. Musisz także użyć tego atrybutu nazwy pakietu w kodzie źródłowym, aby odwołać się do klasy R lub rozwiązać względną aktywność lub rejestrację usługi. Dzięki temu możesz używać applicationId, aby nadać każdemu rodzajowi produktu unikalny identyfikator sposobu prezentacji i dystrybucji bez konieczności zmiany kodu źródłowego.

Wszystkie smaki muszą należeć do nazwanego wymiaru smaku, który jest grupą smaków produktów. Musisz przypisać wszystkie smaki do wymiaru smaku; W przeciwnym razie pojawi się następujący błąd kompilacji.

  Error: All flavors must now belong to a named flavor dimension.
  The flavor 'flavor_name' is not assigned to a flavor dimension.

Jeśli dany moduł określa tylko 1 wymiar, wtyczka Androida do obsługi Gradle automatycznie przypisuje do danego wymiaru wszystkie cechy danego modułu.

.

Poniższy przykładowy kod tworzy wymiar rodzaju o nazwie „version” i dodaje „demo” i „pełny” smaków produktów. Te smaki dają applicationIdSuffix i versionNameSuffix:

Kotlin

android {
    ...
    defaultConfig {...}
    buildTypes {
        getByName("debug"){...}
        getByName("release"){...}
    }
    // Specifies one flavor dimension.
    flavorDimensions += "version"
    productFlavors {
        create("demo") {
            // Assigns this product flavor to the "version" flavor dimension.
            // If you are using only one dimension, this property is optional,
            // and the plugin automatically assigns all the module's flavors to
            // that dimension.
            dimension = "version"
            applicationIdSuffix = ".demo"
            versionNameSuffix = "-demo"
        }
        create("full") {
            dimension = "version"
            applicationIdSuffix = ".full"
            versionNameSuffix = "-full"
        }
    }
}

Odlotowe

android {
    ...
    defaultConfig {...}
    buildTypes {
        debug{...}
        release{...}
    }
    // Specifies one flavor dimension.
    flavorDimensions "version"
    productFlavors {
        demo {
            // Assigns this product flavor to the "version" flavor dimension.
            // If you are using only one dimension, this property is optional,
            // and the plugin automatically assigns all the module's flavors to
            // that dimension.
            dimension "version"
            applicationIdSuffix ".demo"
            versionNameSuffix "-demo"
        }
        full {
            dimension "version"
            applicationIdSuffix ".full"
            versionNameSuffix "-full"
        }
    }
}

Uwaga: jeśli masz starszą aplikację (utworzoną przed sierpień 2021 r.), które rozpowszechniasz za pomocą plików APK w Google Play, aby dystrybuować aplikację za pomocą wielu plików APK. support w Google Play, przypisz tę samą wartość applicationId do wszystkich wariantów i przydzielić każdemu z nich inny versionCode Do rozpowszechniania różnych wersji aplikacji jako osobnych aplikacji w Google Play, musisz przypisać różne applicationId w każdej z wariantów.

Po utworzeniu i skonfigurowaniu odmian produktów kliknij Synchronizuj teraz na pasku powiadomień. Po zakończeniu synchronizacji Gradle automatycznie tworzy warianty kompilacji na podstawie typu kompilacji i produktu smaków i nazwanych według <product-flavor><Build-Type> Jeśli na przykład utworzono „demonstracja” i „pełny” produktów z funkcją wartości domyślnej „debuguj” oraz „release” typów kompilacji, Gradle tworzy te warianty kompilacji:

  • demoDebug
  • demoRelease
  • fullDebug
  • fullRelease

Aby wybrać wariant kompilacji do skompilowania uruchom, kliknij Kompilacja > Wybierz Utwórz wariant i wybierz wariant kompilacji z menu. Aby zacząć dostosowywać każdy wariant kompilacji, dodając do niego własne funkcje, musisz utworzyć źródło i nim zarządzać zestawień, jak opisano na tej stronie.

Zmienianie identyfikatora aplikacji dla wariantów kompilacji

Gdy tworzysz pakiet APK lub AAB dla swojej aplikacji, narzędzia do kompilacji oznaczają aplikację tagiem identyfikator aplikacji zdefiniowany w bloku defaultConfig w tabeli build.gradle.kts zgodnie z poniższym przykładem. Jeśli jednak chcesz utworzyć różne wersje pliku wyświetlać się jako osobne strony w Sklepie Google Play (np. „bezpłatna”) i „profesjonalista” , musisz utworzyć oddzielne utwórz warianty, które różnią się identyfikator aplikacji.

W tym przypadku zdefiniuj każdy wariant kompilacji jako osobny smak produktu. Dla każdego smaku wewnątrz bloku productFlavors można ponownie zdefiniować applicationId możesz też dołączyć segment do domyślnego identyfikatora aplikacji przy użyciu funkcji applicationIdSuffix, jak pokazano tutaj:

Kotlin

android {
    defaultConfig {
        applicationId = "com.example.myapp"
    }
    productFlavors {
        create("free") {
            applicationIdSuffix = ".free"
        }
        create("pro") {
            applicationIdSuffix = ".pro"
        }
    }
}

Odlotowe

android {
    defaultConfig {
        applicationId "com.example.myapp"
    }
    productFlavors {
        free {
            applicationIdSuffix ".free"
        }
        pro {
            applicationIdSuffix ".pro"
        }
    }
}

W ten sposób identyfikator aplikacji dla „bezpłatnej” smak produktu to „com.example.mojaaplikacja.free”.

Możesz też użyć parametru applicationIdSuffix, aby dołączyć segment na podstawie typ kompilacji, jak tutaj:

Kotlin

android {
    ...
    buildTypes {
        getByName("debug") {
            applicationIdSuffix = ".debug"
        }
    }
}

Odlotowe

android {
    ...
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
        }
    }
}

Ponieważ Gradle stosuje konfigurację typu kompilacji po rodzaju usługi, identyfikator aplikacji „bezpłatne debugowanie”; wariant kompilacji to „com.example.mojaaplikacja.free.debug”. Jest to przydatne, gdy chcesz mieć zarówno na tym samym urządzeniu, na którym są debugowane i kompilowane, bo żadne dwie aplikacje nie mogą mieć ten sam identyfikator aplikacji.

Jeśli masz starszą aplikację (utworzoną przed sierpniem) 2021), którą rozpowszechniasz w Google Play za pomocą plików APK i chcesz użyć tych samych informacji o aplikacji do dystrybuować wiele plików APK, są kierowane na inną konfigurację urządzenia, np. na poziom API, użyj tego samego identyfikatora aplikacji dla każdego wariantu kompilacji, ale przy każdym Plik APK zawiera inny plik versionCode. Więcej informacji: Obsługa wielu plików APK. Publikowanie nie wpływa to na pakiety aplikacji na Androida, ponieważ korzysta on z jednego artefaktu kod wersji i identyfikator aplikacji.

Wskazówka: jeśli musisz podać identyfikator aplikacji w pliku manifestu, możesz użyć zmiennej ${applicationId} w dowolnym w pliku manifestu. Podczas kompilacji Gradle zastępuje ten tag rzeczywistym identyfikator aplikacji. Więcej informacji znajdziesz w sekcji Wstawianie kompilacji do pliku manifestu.

Łącz różne smaki produktów z wymiarami smakowymi

W niektórych przypadkach warto połączyć konfiguracje różnych usług smaków. Możesz na przykład utworzyć różne konfiguracje dla „pełny” i „demo” smaki produktów oparte na poziomie interfejsu API. Aby to zrobić: dzięki wtyczce Androida do obsługi Gradle możesz utworzyć wiele grup smaków produktów wymiarów.

Podczas tworzenia aplikacji Gradle łączy usługę konfiguracji smaku z każdego zdefiniowanego wymiaru, a także konfiguracji typu kompilacji, aby utworzyć ostateczny wariant kompilacji. Gradle nie łączyć smaki produktów należące do tych samych wymiarów smaku.

Poniższa próbka kodu korzysta z flavorDimensions, aby utworzyć „tryb”. smak do grupowania „pełnych” danych, i „demo” smaki produktów i „interfejs API” smak wymiar, aby pogrupować konfiguracje typów produktów na podstawie poziomu interfejsu API:

Kotlin

android {
  ...
  buildTypes {
    getByName("debug") {...}
    getByName("release") {...}
  }

  // Specifies the flavor dimensions you want to use. The order in which you
  // list the dimensions determines their priority, from highest to lowest,
  // when Gradle merges variant sources and configurations. You must assign
  // each product flavor you configure to one of the flavor dimensions.
  flavorDimensions += listOf("api", "mode")

  productFlavors {
    create("demo") {
      // Assigns this product flavor to the "mode" flavor dimension.
      dimension = "mode"
      ...
    }

    create("full") {
      dimension = "mode"
      ...
    }

    // Configurations in the "api" product flavors override those in "mode"
    // flavors and the defaultConfig block. Gradle determines the priority
    // between flavor dimensions based on the order in which they appear next
    // to the flavorDimensions property, with the first dimension having a higher
    // priority than the second, and so on.
    create("minApi24") {
      dimension = "api"
      minSdk = 24
      // To ensure the target device receives the version of the app with
      // the highest compatible API level, assign version codes in increasing
      // value with API level.
      versionCode = 30000 + (android.defaultConfig.versionCode ?: 0)
      versionNameSuffix = "-minApi24"
      ...
    }

    create("minApi23") {
      dimension = "api"
      minSdk = 23
      versionCode = 20000  + (android.defaultConfig.versionCode ?: 0)
      versionNameSuffix = "-minApi23"
      ...
    }

    create("minApi21") {
      dimension = "api"
      minSdk = 21
      versionCode = 10000  + (android.defaultConfig.versionCode ?: 0)
      versionNameSuffix = "-minApi21"
      ...
    }
  }
}
...

Odlotowe

android {
  ...
  buildTypes {
    debug {...}
    release {...}
  }

  // Specifies the flavor dimensions you want to use. The order in which you
  // list the dimensions determines their priority, from highest to lowest,
  // when Gradle merges variant sources and configurations. You must assign
  // each product flavor you configure to one of the flavor dimensions.
  flavorDimensions "api", "mode"

  productFlavors {
    demo {
      // Assigns this product flavor to the "mode" flavor dimension.
      dimension "mode"
      ...
    }

    full {
      dimension "mode"
      ...
    }

    // Configurations in the "api" product flavors override those in "mode"
    // flavors and the defaultConfig block. Gradle determines the priority
    // between flavor dimensions based on the order in which they appear next
    // to the flavorDimensions property, with the first dimension having a higher
    // priority than the second, and so on.
    minApi24 {
      dimension "api"
      minSdkVersion 24
      // To ensure the target device receives the version of the app with
      // the highest compatible API level, assign version codes in increasing
      // value with API level.

      versionCode 30000 + android.defaultConfig.versionCode
      versionNameSuffix "-minApi24"
      ...
    }

    minApi23 {
      dimension "api"
      minSdkVersion 23
      versionCode 20000  + android.defaultConfig.versionCode
      versionNameSuffix "-minApi23"
      ...
    }

    minApi21 {
      dimension "api"
      minSdkVersion 21
      versionCode 10000  + android.defaultConfig.versionCode
      versionNameSuffix "-minApi21"
      ...
    }
  }
}
...

Liczba wariantów kompilacji utworzonych przez Gradle jest równa iloczynowi parametru liczbę smaków w każdym wymiarze smaku oraz liczbę typów konstrukcji, konfiguracji. Gdy Gradle nadaje nazwę każdemu wariantowi kompilacji lub powiązanym z nim artefaktom, smaki należące do wymiaru o wyższym priorytecie pojawiają się jako pierwsze, a po nich występują tych z wymiarów o niższym priorytecie, a po nich typ kompilacji.

Zastosowanie zgodnie z poprzednią konfiguracją kompilacji, Gradle tworzy w sumie 12, kompiluj warianty o tym schemacie nazewnictwa:

  • Wariant kompilacji: [minApi24, minApi23, minApi21][Demo, Full][Debug, Release]
  • Powiązany plik APK: app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk
  • Na przykład
    Wariant kompilacji: minApi24DemoDebug
    Powiązany plik APK: app-minApi24-demo-debug.apk

Oprócz katalogów zbioru źródłowego, które możesz tworzyć dla poszczególnych rodzaju produktu i wersji kompilacji, można również tworzyć katalogi zbiorów źródłowych, dla każdej kombinacji smaków produktów. Możesz na przykład utworzyć i dodasz źródła Java do katalogu src/demoMinApi24/java/, a Gradle używa tych źródeł tylko podczas tworzenia wariantu, który łączy te 2 różne smaki.

Zbiory źródłowe, które tworzysz dla rodzaju produktów kombinacje mają wyższy priorytet niż zbiory źródłowe, które należą do poszczególnych smak poszczególnych produktów. Aby dowiedzieć się więcej o zbiorach źródłowych i sposobie Gradle scala zasoby, przeczytaj sekcję na temat tworzenia .

Filtruj warianty

Gradle tworzy wariant kompilacji dla każdej możliwej kombinacji produktu smaki i typy kompilacji. Jednak w pewnych okolicznościach i tworzyć warianty, których nie potrzebujesz lub które nie mają sensu i kontekstu projektu. Aby usunąć określone konfiguracje wariantów kompilacji: utwórz filtr wariantu w build.gradle.kts na poziomie modułu .

Na przykładzie konfiguracji kompilacji z poprzedniej sekcji załóżmy, że na potrzeby wersji demonstracyjnej chcesz obsługiwać tylko interfejsy API poziomu 23 i wyższych wersji aplikacji. Za pomocą variantFilter, aby odfiltrować cały wariant kompilacji konfiguracje, które łączą interfejs „minApi21” i „demo” smaki produktu:

Kotlin

android {
  ...
  buildTypes {...}

  flavorDimensions += listOf("api", "mode")
  productFlavors {
    create("demo") {...}
    create("full") {...}
    create("minApi24") {...}
    create("minApi23") {...}
    create("minApi21") {...}
  }
}

androidComponents {
    beforeVariants { variantBuilder ->
        // To check for a certain build type, use variantBuilder.buildType == "<buildType>"
        if (variantBuilder.productFlavors.containsAll(listOf("api" to "minApi21", "mode" to "demo"))) {
            // Gradle ignores any variants that satisfy the conditions above.
            variantBuilder.enable = false
        }
    }
}
...

Odlotowe

android {
  ...
  buildTypes {...}

  flavorDimensions "api", "mode"
  productFlavors {
    demo {...}
    full {...}
    minApi24 {...}
    minApi23 {...}
    minApi21 {...}
  }

  variantFilter { variant ->
      def names = variant.flavors*.name
      // To check for a certain build type, use variant.buildType.name == "<buildType>"
      if (names.contains("minApi21") && names.contains("demo")) {
          // Gradle ignores any variants that satisfy the conditions above.
          setIgnore(true)
      }
  }
}
...

Gdy dodasz do konfiguracji kompilacji filtr wariantu i kliknij Synchronizuj Teraz na pasku powiadomień Gradle ignoruje warianty kompilacji, które spełniają na podanych warunkach. Warianty kompilacji nie pojawiają się już w menu po kliknięciu Kompilacja > Na pasku menu wybierz Utwórz wariant. lub Utwórz warianty w pasku narzędzi.

Tworzenie zbiorów źródłowych

Domyślnie Android Studio tworzy main/ zbiór źródeł i katalogi dla wszystko, co chcesz udostępniać między wszystkimi wariantami kompilacji. Musisz jednak mogą tworzyć nowe zbiory źródłowe, aby kontrolować, które pliki Gradle kompiluje i pakiety do określonych typów kompilacji, smaków produktów, kombinacji smaków (gdy używasz atrybutu smak) wymiarów) i tworzenia wariantów.

Możesz na przykład zdefiniować podstawowe funkcje w zbiorze źródłowym main/ i wykorzystaj rodzaj produktu zestawy źródeł umożliwiające zmianę marki aplikacji w przypadku różnych klientów; uwzględniaj specjalne uprawnienia i funkcje logowania tylko w przypadku wariantów kompilacji korzystających z typu kompilacji do debugowania.

Gradle wymaga, aby pliki i katalogi zbioru źródłowego były uporządkowane w określonej podobnie jak w zbiorze źródłowym main/. Na przykład Gradle wymaga plików klas Kotlin lub Javy, które są charakterystyczne dla w katalogach src/debug/kotlin/ lub src/debug/java/.

Wtyczka Androida do obsługi Gradle zapewnia przydatne zadanie Gradle, które pokazuje jak uporządkować pliki w przypadku poszczególnych typów budowli, smaki i tworzenia różnych wersji. Na przykład ten przykład z danych wyjściowych zadania opisuje, gdzie Gradle spodziewa się znaleźć określone pliki do „debugowania”. kompilacja typ:

------------------------------------------------------------
Project :app
------------------------------------------------------------

...

debug
----
Compile configuration: debugCompile
build.gradle name: android.sourceSets.debug
Java sources: [app/src/debug/java]
Kotlin sources: [app/src/debug/kotlin, app/src/debug/java]
Manifest file: app/src/debug/AndroidManifest.xml
Android resources: [app/src/debug/res]
Assets: [app/src/debug/assets]
AIDL sources: [app/src/debug/aidl]
RenderScript sources: [app/src/debug/rs]
JNI sources: [app/src/debug/jni]
JNI libraries: [app/src/debug/jniLibs]
Java-style resources: [app/src/debug/resources]

Aby wyświetlić dane wyjściowe, wykonaj te czynności:

  1. Kliknij Gradle na pasku okna narzędzi.
  2. Przejdź do MyApplication (aplikacja) > Lista zadań > android oraz kliknij dwukrotnie sourceSets.

    Aby wyświetlić folder Tasks, musisz pozwolić Gradle utworzyć listę zadań podczas synchronizacji. Aby to zrobić:

    1. Kliknij Plik > Ustawienia > Funkcja eksperymentalna (Android Studio > Ustawienia > Eksperymentalne) w systemie macOS).
    2. Odznacz Nie listę zadań Gradle podczas synchronizacji.
  3. Po wykonaniu zadania Gradle otworzy się okno Uruchom z wyświetlonym dane wyjściowe.

Uwaga: w danych wyjściowych zadania znajdziesz też informacje o tym, jak uporządkować zbiory źródłowe. plików, których chcesz użyć do testowania aplikacji, np. test/ i androidTest/ testowania zbiorów źródłowych.

Gdy utworzysz nowy wariant kompilacji, Android Studio nie utworzy źródła ustawić katalogi, ale udostępnia kilka opcji, które mogą Ci pomóc. Dla: Aby na przykład utworzyć katalog java/ na potrzeby debugowania typ kompilacji:

  1. Otwórz panel Projekt i wybierz Widok projektu w menu u góry panelu.
  2. Wejdź na MyProject/app/src/.
  3. Kliknij prawym przyciskiem myszy katalog src i wybierz Nowość > Katalog
  4. W menu w sekcji Zestawy źródeł Gradle wybierz full/java.
  5. Naciśnij Enter.

Android Studio tworzy katalog zbioru źródłowego dla typu kompilacji do debugowania oraz a następnie utworzy w nim katalog java/. Ewentualnie Android Studio może utworzyć katalogi, gdy dodasz nowy plik do projektu dla konkretnego wariantu kompilacji.

Aby np. utworzyć plik XML z wartościami dla „debugowania” typ kompilacji:

  1. W panelu Projekt kliknij prawym przyciskiem myszy src i wybierz New (Nowy) > XML > Plik XML wartości.
  2. Wpisz nazwę pliku XML lub zachowaj nazwę domyślną.
  3. W menu Docelowy zestaw źródeł wybierz debugowanie.
  4. Kliknij Zakończ.

Parametr „debugowanie” typ kompilacji został określony jako docelowy zbiór źródeł, Android Studio automatycznie tworzy niezbędne katalogi, który utworzy plik XML. Powstała struktura katalogów będzie wyglądać tak rysunek 1.

Rysunek 1. Nowe katalogi zbiorów źródłowych na potrzeby „debugowania” kompilacja typu.

Aktywne zestawy źródeł mają zielony wskaźnik na ikonie wskazujący, że są aktywne. Zbiór źródłowy debug ma sufiks [main], co oznacza, że zostanie scalony do zbioru źródłowego main.

Wykonując tę samą procedurę, możesz również utworzyć katalogi zbiorów źródłowych dla: typów produktów, np. src/demo/, i wersji kompilacji, takich jak src/demoDebug/ Można również tworzyć zestawy źródeł testowych kierowane na określone warianty kompilacji, src/androidTestDemoDebug/ Więcej informacji: testowania zbiorów źródłowych.

Zmień konfiguracje domyślnego zestawu źródeł

Jeśli masz źródła, które nie są uporządkowane w pliku domyślnego zestawu źródeł struktury, której oczekuje Gradle, zgodnie z opisem w poprzedniej sekcji na temat tworząc zbiory źródłowe, możesz użyć funkcji sourceSets, aby zmienić miejsce, w którym Gradle ma zbierać dane dla poszczególnych komponentów zbioru źródłowego.

Blok sourceSets musi być w bloku android. Nie musisz przenosić pliki źródłowe; wystarczy podać w Gradle tylko ścieżki względem build.gradle.kts na poziomie modułu, gdzie Gradle może pliki przypisane do poszczególnych komponentów zbioru źródłowego. Aby dowiedzieć się, które komponenty i określić, czy można je zmapować na wiele plików lub katalogów, zobacz dokumentację API wtyczki Android Gradle.

Ten przykładowy kod mapuje źródła z katalogu app/other/ do niektórych komponentów zbioru źródłowego main i zmienia wartość katalog główny zestawu źródłowego androidTest:

Kotlin

android {
  ...
  // Encapsulates configurations for the main source set.
  sourceSets.getByName("main") {
    // Changes the directory for Java sources. The default directory is
    // 'src/main/java'.
    java.setSrcDirs(listOf("other/java"))

    // If you list multiple directories, Gradle uses all of them to collect
    // sources. Because Gradle gives these directories equal priority, if
    // you define the same resource in more than one directory, you receive an
    // error when merging resources. The default directory is 'src/main/res'.
    res.setSrcDirs(listOf("other/res1", "other/res2"))

    // Note: Avoid specifying a directory that is a parent to one
    // or more other directories you specify. For example, avoid the following:
    // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings']
    // Specify either only the root 'other/res1' directory or only the
    // nested 'other/res1/layouts' and 'other/res1/strings' directories.

    // For each source set, you can specify only one Android manifest.
    // By default, Android Studio creates a manifest for your main source
    // set in the src/main/ directory.
    manifest.srcFile("other/AndroidManifest.xml")
    ...
  }

  // Create additional blocks to configure other source sets.
  sourceSets.getByName("androidTest") {
      // If all the files for a source set are located under a single root
      // directory, you can specify that directory using the setRoot property.
      // When gathering sources for the source set, Gradle looks only in locations
      // relative to the root directory you specify. For example, after applying the
      // configuration below for the androidTest source set, Gradle looks for Java
      // sources only in the src/tests/java/ directory.
      setRoot("src/tests")
      ...
  }
}
...

Odlotowe

android {
  ...
  sourceSets {
    // Encapsulates configurations for the main source set.
    main {
      // Changes the directory for Java sources. The default directory is
      // 'src/main/java'.
      java.srcDirs = ['other/java']

      // If you list multiple directories, Gradle uses all of them to collect
      // sources. Because Gradle gives these directories equal priority, if
      // you define the same resource in more than one directory, you receive an
      // error when merging resources. The default directory is 'src/main/res'.
      res.srcDirs = ['other/res1', 'other/res2']

      // Note: Avoid specifying a directory that is a parent to one
      // or more other directories you specify. For example, avoid the following:
      // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings']
      // Specify either only the root 'other/res1' directory or only the
      // nested 'other/res1/layouts' and 'other/res1/strings' directories.

      // For each source set, you can specify only one Android manifest.
      // By default, Android Studio creates a manifest for your main source
      // set in the src/main/ directory.
      manifest.srcFile 'other/AndroidManifest.xml'
      ...
    }

    // Create additional blocks to configure other source sets.
    androidTest {

      // If all the files for a source set are located under a single root
      // directory, you can specify that directory using the setRoot property.
      // When gathering sources for the source set, Gradle looks only in locations
      // relative to the root directory you specify. For example, after applying the
      // configuration below for the androidTest source set, Gradle looks for Java
      // sources only in the src/tests/java/ directory.
      setRoot 'src/tests'
      ...
    }
  }
}
...

Pamiętaj, że katalog źródłowy może należeć tylko do jednego zbioru źródłowego. Na przykład nie można udostępnić te same źródła testowe z zbiorami źródłowymi test i androidTest. Ten jest to, że Android Studio tworzy osobne moduły IntelliJ dla każdego zbioru źródłowego i nie może obsługiwać zduplikowanych źródeł treści w zbiorach źródłowych.

Tworzenie z użyciem zbiorów źródłowych

Katalogi zbioru źródłowego mogą zawierać kod i zasoby które chcesz spakować tylko z określonymi konfiguracjami. Jeśli na przykład jesteś tworząc plik „demoDebug” wariant kompilacji, który jest iloczynem krzyżowym atrybutu „demo” rodzaj produktu i „debugowanie” typu kompilacji, Gradle przygląda się i nadaje im następujący priorytet:

  1. src/demoDebug/ (zestaw źródeł wariantów kompilacji)
  2. src/debug/ (zestaw źródłowy typu kompilacji)
  3. src/demo/ (zestaw źródeł smaku produktu)
  4. src/main/ (zestaw głównego źródła)

Zbiory źródłowe utworzone dla kombinacji smaków produktów muszą zawierać wszystkie wymiary smaków. Na przykład zbiór źródeł wersji kompilacji musi być kombinacją typu kompilacji i wszystkich typów wymiarów. Scalanie kodu i zasobów obejmujących foldery, które obejmują wiele, ale nie wszystkie nie są obsługiwane.

Jeśli połączysz kilka produktów smaków, priorytet między smakami produktu zależy od smaku. wymiarów, do których należą. Gdy wyświetla się wymiary smaku z atrybutem android.flavorDimensions, a także smaki produktów, które należą do pierwszego podanego przez Ciebie wymiaru smaku, który ma wyższy priorytet niż należące do drugiego wymiaru smaku i tak dalej. Dodatkowo: zestawy źródłowe tworzone dla kombinacji smaków produktów mają wyższy niż zbiory źródłowe, które należą do konkretnego smaku produktów.

Kolejność priorytetów określa, który zbiór źródłowy ma wyższy gdy Gradle łączy kod i zasoby. Ponieważ demoDebug/ katalog zbioru źródłowego prawdopodobnie zawiera pliki, które są specyficzne dla tej kompilacji wariantu, jeśli demoDebug/ zawiera plik zdefiniowany również w debug/, Gradle używa pliku w folderze demoDebug/ zbiór źródeł. Podobnie Gradle udostępnia pliki w typie kompilacji i rodzaju usługi. źródło ma wyższy priorytet niż te same pliki w usłudze main/. Gradle uwzględnia tę kolejność priorytetów podczas stosowania tych reguł kompilacji:

  • Cały kod źródłowy w katalogach kotlin/ i java/ jest skompilowany razem, aby wygenerować jeden wynik.

    Uwaga: w przypadku danego wariantu kompilacji Gradle przesyła kompilację jeśli natrafi na co najmniej 2 katalogi zbioru źródłowego, które zostały zdefiniowane tę samą klasę Kotlin lub Java. Na przykład podczas tworzenia aplikacji do debugowania nie można zdefiniować zarówno src/debug/Utility.kt, jak i src/main/Utility.kt, ponieważ Gradle sprawdza tych katalogów w procesie kompilacji i zwraca „zduplikowaną klasę” . Jeśli chcesz mieć różne wersje usługi Utility.kt dla różnych typów kompilacji, każdy z nich musi definiować własną wersję pliku i nie uwzględniaj go w zbiorze źródłowym main/.

  • Pliki manifestu są scalone w jeden plik manifestu. Nadaj priorytet w takiej samej kolejności jak na liście w poprzednim przykładzie. Oznacza to, że ustawienia w pliku manifestu kompilacji zastępują ustawienia w pliku manifestu dla rodzaju produktów i tak dalej. Aby się uczyć znajdziesz więcej informacji o scalaniu manipulacji.
  • Pliki w katalogach values/ są scalane razem. Jeśli 2 pliki mają taką samą nazwę, np. 2 pliki strings.xml, priorytet jest przyznawany w takiej samej kolejności jak z listy z poprzedniego przykładu. Oznacza to, że wartości zdefiniowane w pliku w zbiorze źródłowym typu kompilacji zastąpią wartości zdefiniowane w tym samym pliku w rodzaju produktu itd.
  • Zasoby w katalogach res/ i asset/ są łączone w pakiety. Jeśli istnieją zasoby o tej samej nazwie zdefiniowane w co najmniej dwa zbiory źródłowe, priorytet jest nadany w tej samej kolejności co lista z poprzedniego przykładu.
  • Gradle udostępnia zasoby i pliki manifestu dołączone do biblioteki które mają najniższy priorytet przy tworzeniu aplikacji.

Deklarowanie zależności

Aby skonfigurować zależność dla określonego wariantu kompilacji lub testowania zbioru źródeł źródłowych, poprzedź nazwę wariantu kompilacji lub zbioru źródeł testowania przed Implementation słowo kluczowe, tak jak w tym przykładzie:

Kotlin

dependencies {
    // Adds the local "mylibrary" module as a dependency to the "free" flavor.
    "freeImplementation"(project(":mylibrary"))

    // Adds a remote binary dependency only for local tests.
    testImplementation("junit:junit:4.12")

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation("com.android.support.test.espresso:espresso-core:3.5.1")
}

Odlotowe

dependencies {
    // Adds the local "mylibrary" module as a dependency to the "free" flavor.
    freeImplementation project(":mylibrary")

    // Adds a remote binary dependency only for local tests.
    testImplementation 'junit:junit:4.12'

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.5.1'
}

Więcej informacji o konfigurowaniu zależności znajdziesz Więcej informacji znajdziesz w artykule Dodawanie zależności kompilacji.

Zarządzanie zależnościami z uwzględnieniem wariantów

Wtyczka Androida do obsługi Gradle w wersji 3.0.0 lub nowszej zawiera nowy mechanizm zależności, który automatycznie dopasowuje warianty podczas korzystania z biblioteki. Oznacza to, że ma ona debug wariant aplikacji. automatycznie pobiera wariant debug biblioteki i tak dalej. Działa też, gdy używasz smaki: wariant aplikacji freeDebug będzie używać tego pola freeDebug biblioteki wersji.

Aby wtyczka dokładnie dopasowywała wersje, musisz: udostępniać pasujące wartości zastępcze, jak opisano w poniżej, gdy bezpośrednie dopasowanie nie jest możliwe.

Załóżmy na przykład, że aplikacja konfiguruje typ kompilacji o nazwie „etap przejściowy”, ale jeden z tych zależne od biblioteki. Gdy wtyczka próbuje utworzyć „staging” wersji nie wie, której wersji biblioteki użyć, i zobaczysz podobny komunikat o błędzie na:

Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
    project :app

Naprawianie błędów kompilacji związanych z dopasowaniem wariantów

Wtyczka zawiera elementy DSL, które pomagają kontrolować sposób rozpoznawania sytuacji przez Gradle w którym przypadku bezpośrednie dopasowanie wariantu aplikacji do zależności jest niemożliwe.

Poniżej znajdziesz listę problemów związanych z dopasowywaniem zależności uwzględniających warianty oraz sposobem aby rozwiązać je przy użyciu właściwości DSL:

  • Aplikacja zawiera typ kompilacji, którego nie ma zależność biblioteczna.

    Na przykład aplikacja zawiera element „przejściowy” ale zależność obejmuje tylko „debuguj” i „release” typów kompilacji.

    Zwróć uwagę, że problem nie występuje, gdy zależność biblioteki zawiera kompilację których Twoja aplikacja nie obsługuje. To dlatego, że wtyczka nigdy żądań, które kompilują typ z zależności.

    Użyj matchingFallbacks, aby określić alternatywne dopasowania dla danego typu kompilacji. jak tutaj:

    Kotlin

    // In the app's build.gradle.kts file.
    android {
        buildTypes {
            getByName("debug") {}
            getByName("release") {}
            create("staging") {
                // Specifies a sorted list of fallback build types that the
                // plugin can try to use when a dependency does not include a
                // "staging" build type. You may specify as many fallbacks as you
                // like, and the plugin selects the first build type that's
                // available in the dependency.
                matchingFallbacks += listOf("debug", "qa", "release")
            }
        }
    }

    Odlotowe

    // In the app's build.gradle file.
    android {
        buildTypes {
            debug {}
            release {}
            staging {
                // Specifies a sorted list of fallback build types that the
                // plugin can try to use when a dependency does not include a
                // "staging" build type. You may specify as many fallbacks as you
                // like, and the plugin selects the first build type that's
                // available in the dependency.
                matchingFallbacks = ['debug', 'qa', 'release']
            }
        }
    }
    
  • W przypadku danego wymiaru smaku, który występuje zarówno w aplikacji, jak i w jej bibliotece aplikacja zawiera smaki, których nie ma biblioteka.

    Na przykład zależności aplikacji i jej biblioteki obejmują „poziom” smaku. Opcja „Poziom” wymiar w aplikacji zawiera słowo „bezpłatne” i „płatne” smaków, ale też zależność obejmuje tylko słowo „demo” i „płatne” smaków tego samego wymiaru.

    Pamiętaj, że w przypadku danego wymiaru smaku występuje zarówno w aplikacji, jak i w jej bibliotece nie ma problemu, jeśli biblioteka zawiera rodzaj usługi, nie działa. Dzieje się tak, ponieważ wtyczka nigdy nie żąda tego rodzaju z zależności.

    Użyj matchingFallbacks, aby określić alternatywne dopasowania słowa kluczowego „bezpłatne” w aplikacji smak produktu, jak tutaj:

    Kotlin

    // In the app's build.gradle.kts file.
    android {
        defaultConfig{
        // Don't configure matchingFallbacks in the defaultConfig block.
        // Instead, specify fallbacks for a given product flavor in the
        // productFlavors block, as shown below.
      }
        flavorDimensions += "tier"
        productFlavors {
            create("paid") {
                dimension = "tier"
                // Because the dependency already includes a "paid" flavor in its
                // "tier" dimension, you don't need to provide a list of fallbacks
                // for the "paid" flavor.
            }
            create("free") {
                dimension = "tier"
                // Specifies a sorted list of fallback flavors that the plugin
                // can try to use when a dependency's matching dimension does
                // not include a "free" flavor. Specify as many
                // fallbacks as you like; the plugin selects the first flavor
                // that's available in the dependency's "tier" dimension.
                matchingFallbacks += listOf("demo", "trial")
            }
        }
    }
    

    Odlotowe

    // In the app's build.gradle file.
    android {
        defaultConfig{
        // Don't configure matchingFallbacks in the defaultConfig block.
        // Instead, specify fallbacks for a given product flavor in the
        // productFlavors block, as shown below.
      }
        flavorDimensions 'tier'
        productFlavors {
            paid {
                dimension 'tier'
                // Because the dependency already includes a "paid" flavor in its
                // "tier" dimension, you don't need to provide a list of fallbacks
                // for the "paid" flavor.
            }
            free {
                dimension 'tier'
                // Specifies a sorted list of fallback flavors that the plugin
                // can try to use when a dependency's matching dimension does
                // not include a "free" flavor. Specify as many
                // fallbacks as you like; the plugin selects the first flavor
                // that's available in the dependency's "tier" dimension.
                matchingFallbacks = ['demo', 'trial']
            }
        }
    }
    
  • Zależność biblioteki obejmuje wymiar smaku, którego nie ma Twoja aplikacja.

    Na przykład zależność biblioteki obejmuje smaki dla „minApi” ale Twoja aplikacja zawiera rodzaje tylko „poziomu” . Gdy chcesz utworzyć kod „freeDebug” wersji Twojej aplikacji, wtyczka nie wie, czy użyć parametru „minApi23Debug” lub „minApi18Debug” wersji zależności.

    Pamiętaj, że problem nie występuje, jeśli aplikacja zawiera wymiar smaku określony w bibliotece. już nie. Dzieje się tak, ponieważ wtyczka pasuje tylko do wymiarów, które w zależności. Jeśli na przykład zależność nie zawiera wymiaru dla interfejsów ABI, kod „freeX86Debug” Twojej aplikacji używa parametru „freeDebug” wersji zależności.

    Użyj missingDimensionStrategy w bloku defaultConfig, aby określić domyślny rodzaj, który wtyczka wybiera dla każdego brakującego wymiaru, jak widać w z tego przykładu. Możesz też zastąpić swój wybór w productFlavors dzięki czemu każdy rodzaj może określać inną strategię dopasowania dla brakującego wymiaru.

    Kotlin

    // In the app's build.gradle.kts file.
    android {
        defaultConfig{
        // Specifies a sorted list of flavors that the plugin can try to use from
        // a given dimension. This tells the plugin to select the "minApi18" flavor
        // when encountering a dependency that includes a "minApi" dimension.
        // You can include additional flavor names to provide a
        // sorted list of fallbacks for the dimension.
        missingDimensionStrategy("minApi", "minApi18", "minApi23")
        // Specify a missingDimensionStrategy property for each
        // dimension that exists in a local dependency but not in your app.
        missingDimensionStrategy("abi", "x86", "arm64")
        }
        flavorDimensions += "tier"
        productFlavors {
            create("free") {
                dimension = "tier"
                // You can override the default selection at the product flavor
                // level by configuring another missingDimensionStrategy property
                // for the "minApi" dimension.
                missingDimensionStrategy("minApi", "minApi23", "minApi18")
            }
            create("paid") {}
        }
    }
    

    Odlotowe

    // In the app's build.gradle file.
    android {
        defaultConfig{
        // Specifies a sorted list of flavors that the plugin can try to use from
        // a given dimension. This tells the plugin to select the "minApi18" flavor
        // when encountering a dependency that includes a "minApi" dimension.
        // You can include additional flavor names to provide a
        // sorted list of fallbacks for the dimension.
        missingDimensionStrategy 'minApi', 'minApi18', 'minApi23'
        // Specify a missingDimensionStrategy property for each
        // dimension that exists in a local dependency but not in your app.
        missingDimensionStrategy 'abi', 'x86', 'arm64'
        }
        flavorDimensions 'tier'
        productFlavors {
            free {
                dimension 'tier'
                // You can override the default selection at the product flavor
                // level by configuring another missingDimensionStrategy property
                // for the 'minApi' dimension.
                missingDimensionStrategy 'minApi', 'minApi23', 'minApi18'
            }
            paid {}
        }
    }
    

Więcej informacji: matchingFallbacks i missingDimensionStrategy w dokumentacji DSL wtyczki Androida do obsługi Gradle.

Skonfiguruj ustawienia podpisywania

Gradle nie podpisuje pliku APK ani pakietu AAB kompilacji wersji, chyba że wyraźnie zdefiniujesz konfiguracji podpisywania tej kompilacji. Jeśli nie masz jeszcze klucza podpisywania, wygeneruj klucz przesyłania i magazyn kluczy w Android Studio.

Aby ręcznie skonfigurować konfiguracje podpisywania dla typu kompilacji wersji przy użyciu konfiguracji kompilacji Gradle:

  1. Utwórz magazyn kluczy. magazyn kluczy to plik binarny, który zawiera zestaw kluczy prywatnych. Magazyn kluczy musisz przechowywać w bezpiecznym miejscu. i bezpieczne miejsce.
  2. Utwórz klucz prywatny. klucz prywatny jest używany do podpisywania aplikacji. w celach rozpowszechniania i nigdy nie są dołączane do aplikacji ani ujawniane nieupoważnionym osobom trzecim.
  3. Dodaj konfigurację podpisywania do build.gradle.kts na poziomie modułu plik:

    Kotlin

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

    Odlotowe

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

Uwaga: w tym hasła do klucza wersji i magazyn kluczy w pliku kompilacji nie jest dobrą praktyką dotyczącą bezpieczeństwa. Zamiast tego skonfiguruj plik kompilacji, aby uzyskiwać te hasła ze zmiennych środowiskowych lub poproś proces kompilacji haseł.

Aby uzyskać te hasła ze zmiennych środowiskowych:

Kotlin

storePassword = System.getenv("KSTOREPWD")
keyPassword = System.getenv("KEYPWD")

Odlotowe

storePassword System.getenv("KSTOREPWD")
keyPassword System.getenv("KEYPWD")

Magazyn kluczy możesz też załadować z pliku właściwości lokalnych. Ze względów bezpieczeństwa nie dodaj ten plik do elementu sterującego źródła. Zamiast tego skonfiguruj je lokalnie dla każdego Google Play. Więcej informacji można znaleźć na stronie Usuń dane podpisywania z plików kompilacji.

Po zakończeniu tego procesu możesz rozpowszechniać aplikację i ją opublikować w Google Play.

Ostrzeżenie: przechowuj magazyn kluczy i klucz prywatny w bezpiecznym i upewnić się, że masz bezpieczne kopie zapasowe. Jeśli używasz podpisywania aplikacji przez Google Play jeśli utracisz klucz przesyłania, poproś o zresetuj za pomocą Konsoli Play. Jeśli publikujesz aplikację bez podpisywania aplikacji przez Google Play (w przypadku aplikacji utworzonych przed sierpniem 2021 roku) oraz utracisz klucz podpisywania aplikacji, stracisz możliwość publikowania aktualizacji aplikacji, zawsze podpisywać wszystkie wersje aplikacji tym samym kluczem.

Podpisywanie aplikacji na Wear OS

Gdy publikujesz aplikacje na Wear OS, zarówno pakiet APK na zegarek, jak i opcjonalny plik APK na telefon muszą być podpisane ten sam klucz. Więcej informacji o pakowaniu i podpisywaniu aplikacji na Wear OS znajdziesz tutaj: Pakować i rozpowszechniać aplikacje na Wear.