다중 APK 빌드

주의: 2021년 8월 이후 모든 앱을 App Bundle로 게시해야 합니다. Google Play에 앱을 게시하면 Android App Bundle을 빌드하고 업로드합니다. 날짜 그렇게 하면 Google Play에서 앱에 최적화된 APK를 자동으로 생성하고 코드 및 리소스만 다운로드하므로 앱을 실행해야 합니다 다중 APK 게시는 AAB 형식을 지원하지 않는 스토어에 게시하는 경우 이 경우 각 APK를 직접 빌드, 서명, 관리해야 합니다.

모든 대상 기기를 지원하려면 단일 APK를 빌드하는 것이 더 낫지만 그렇게 하면 여러 지원 화면 밀도 또는 Application Binary 인터페이스 (ABI). APK 크기를 줄이는 한 가지 방법은 여러 APK가 포함되어 있는 특정 화면 밀도 또는 ABI를 위한 파일이 포함됩니다.

Gradle은 각 밀도 또는 ABI에 관련된 코드와 리소스만 포함되어 있는 별도의 APK를 만들 수 있습니다. 이 페이지에서는 빌드를 구성하여 다중 APK를 생성하는 방법을 설명합니다. 다른 버전의 앱을 만들어야 하는 경우 화면 밀도나 ABI를 기반으로 하지 않는 빌드 경우 대신 빌드 변형을 사용하세요.

다중 APK를 위한 빌드 구성

다중 APK를 위한 빌드를 구성하려면 splits 블록을 모듈 수준 build.gradle 파일에 추가합니다. splits 블록, 제공 Gradle이 생성하는 방법을 지정하는 density 블록 Gradle의 원하는 방식을 지정하는 abi 블록 또는 밀도별 APK ABI별 APK를 생성합니다. 밀도와 ABI 블록을 모두 제공할 수 있습니다. 각 밀도와 ABI 조합을 위한 APK를 만듭니다.

화면 밀도를 위한 다중 APK 구성

다양한 화면 밀도를 위한 별도의 APK를 만들려면 density 블록 내에 splits 블록. density 블록에서 원하는 화면 밀도 및 호환되는 화면 크기의 목록입니다. 사용 가능한 호환되는 화면 크기에 따라 <ph type="x-smartling-placeholder"></ph> <compatible-screens> 요소.

아래 Gradle DSL 옵션은 화면 밀도를 위한 다중 APK를 구성하는 데 사용됩니다.

Groovy의 경우 enable, Kotlin 스크립트의 경우 isEnable
이 요소를 true로 설정하면 Gradle이 다중 APK를 생성합니다. 자동으로 조정됩니다. 기본값은 false
exclude
Gradle에 추가하고 싶지 않은 밀도를 쉼표로 구분된 목록으로 지정 생성할 수 있습니다. 다음의 경우 exclude 사용 대부분의 밀도를 위한 APK를 생성하고 싶지만 일부 밀도를 제외해야 함 앱에서 지원하지 않는 밀도를 모두 지원합니다.
reset()

화면 밀도의 기본 목록을 삭제합니다. include 요소를 사용하여 원하는 밀도 지정 추가합니다.

다음 스니펫은 밀도 목록을 reset()를 호출하여 ldpixxhdpi 를 사용하여 목록을 지운 다음 include를 사용합니다.

reset()                  // Clears the default list from all densities
                         // to no densities.
include "ldpi", "xxhdpi" // Specifies the two densities to generate APKs
                         // for.
include
Gradle이 생성하도록 할 밀도를 쉼표로 구분된 목록으로 지정합니다. . reset()와 함께 사용하여 정확한 밀도 목록입니다.
compatibleScreens

쉼표로 구분된 호환 가능한 화면 크기의 목록을 지정합니다. 이것은 일치하는 매니페스트의 <compatible-screens> 노드 있습니다.

이 설정을 사용하면 두 화면을 편리하게 관리할 수 있습니다. 동일한 build.gradle 섹션에서 밀도 및 화면 크기를 조정할 수 있습니다. 그러나 <compatible-screens>에서 기기 유형을 제한할 수 있음 확인할 수 있습니다. 다양한 기술을 지원하는 다른 방법으로 자세히 알아보려면 화면 호환성 개요를 참고하세요.

화면 밀도를 기반으로 하는 각 APK에는 특정 제한이 있는 <compatible-screens> 태그 여러 화면 유형을 게시하더라도 마찬가지입니다. APK—일부 새 기기가 다중 APK 필터와 일치하지 않습니다. 따라서 Gradle은 항상 애셋이 포함된 추가적인 범용 APK 생성 를 포함하지 않으며 <compatible-screens> 태그 게시 범용 APK와 함께 밀도별 APK를 사용하여 APK와 일치하지 않는 기기가 <compatible-screens> 태그

다음 예에서는 각 객체에 대해 별도의 APK를 생성합니다. 화면 밀도(ldpi, xxhdpi, xxxhdpi입니다. 이 작업은 exclude를 사용하여 이 세 개의 밀도를 모두 선택합니다.

Groovy

android {
  ...
  splits {

    // Configures multiple APKs based on screen density.
    density {

      // Configures multiple APKs based on screen density.
      enable true

      // Specifies a list of screen densities you don't want Gradle to create multiple APKs for.
      exclude "ldpi", "xxhdpi", "xxxhdpi"

      // Specifies a list of compatible screen size settings for the manifest.
      compatibleScreens 'small', 'normal', 'large', 'xlarge'
    }
  }
}

Kotlin

android {
    ...
    splits {

        // Configures multiple APKs based on screen density.
        density {

            // Configures multiple APKs based on screen density.
            isEnable = true

            // Specifies a list of screen densities you don't want Gradle to create multiple APKs for.
            exclude("ldpi", "xxhdpi", "xxxhdpi")

            // Specifies a list of compatible screen size settings for the manifest.
            compatibleScreens("small", "normal", "large", "xlarge")
        }
    }
}

다양한 빌드 맞춤설정에 관한 자세한 내용은 화면 유형 및 기기에 맞게 버전을 조정하는 방법은 제한됨 선언 화면 지원을 참조하세요.

ABI를 위한 다중 APK 구성

다양한 ABI를 위한 별도의 APK를 만들려면 splits 블록 내에 abi 블록을 추가합니다. abi 블록에 포함할 수 있습니다.

다음 Gradle DSL 옵션은 ABI:

Groovy의 경우 enable 또는 Kotlin 스크립트의 경우 isEnable
이 요소를 true로 설정하면 Gradle이 여러 정의된 ABI를 기반으로 하는 APK 기본값은 false입니다.
exclude
Gradle이 사용하지 않도록 할 ABI의 쉼표로 구분된 목록을 지정합니다. 생성할 수 있습니다. 생성하려면 exclude를 사용하세요. 대부분의 ABI를 위한 APK이지만 앱에서 지원하지 않는 몇 가지 ABI를 제외해야 함 도움이 될 수 있습니다
reset()

ABI의 기본 목록을 지웁니다. include 요소를 사용하여 추가하려는 ABI를 지정합니다.

다음 스니펫은 ABI 목록을 x86로 설정하고 reset()를 호출하여 목록을 x86_64합니다. 그런 다음 include 사용:

reset()                 // Clears the default list from all ABIs to no ABIs.
include "x86", "x86_64" // Specifies the two ABIs we want to generate APKs for.
include
Gradle이 APK를 생성하도록 할 ABI의 쉼표로 구분된 목록을 지정합니다. 정의합니다. 정확한 결과를 지정할 때만 reset()와 함께 사용합니다. ABI의 목록을 가져옵니다.
Groovy는 universalApk, Groovy는 isUniversalApk Kotlin 스크립트

true이면 Gradle은 API에 액세스할 수 있습니다. 범용 APK에는 단일 APK를 포함할 수 없습니다. 기본값은 false입니다.

이 옵션은 splits.abi 블록에서 사용할 수 있습니다. 다중 APK 빌드 시 Gradle은 항상 범용 APK를 생성하여 에는 모든 화면 밀도를 위한 코드와 리소스가 포함되어 있습니다.

다음 예에서는 각 ABI를 위한 별도의 APK인 x86x86_64를 생성합니다. reset()를 사용하면 됩니다. 빈 ABI 목록으로 시작하고 그 뒤에 include 각각 APK를 가져오는 ABI의 목록입니다.

Groovy

android {
  ...
  splits {

    // Configures multiple APKs based on ABI.
    abi {

      // Enables building multiple APKs per ABI.
      enable true

      // By default all ABIs are included, so use reset() and include to specify that you only
      // want APKs for x86 and x86_64.

      // Resets the list of ABIs for Gradle to create APKs for to none.
      reset()

      // Specifies a list of ABIs for Gradle to create APKs for.
      include "x86", "x86_64"

      // Specifies that you don't want to also generate a universal APK that includes all ABIs.
      universalApk false
    }
  }
}

Kotlin

android {
  ...
  splits {

    // Configures multiple APKs based on ABI.
    abi {

      // Enables building multiple APKs per ABI.
      isEnable = true

      // By default all ABIs are included, so use reset() and include to specify that you only
      // want APKs for x86 and x86_64.

      // Resets the list of ABIs for Gradle to create APKs for to none.
      reset()

      // Specifies a list of ABIs for Gradle to create APKs for.
      include("x86", "x86_64")

      // Specifies that you don't want to also generate a universal APK that includes all ABIs.
      isUniversalApk = false
    }
  }
}

지원되는 ABI 목록은 지원됨 ABI에 관해 이를 설명합니다.

네이티브/C++ 코드가 없는 프로젝트

네이티브/C++ 코드가 없는 프로젝트의 경우 Build Variants 패널에는 열: ModuleActive Build Variant와 같은 변형을 생성합니다.

Build 변형 패널
그림 1. Build Variants 패널에는 네이티브/C++ 코드

Active Build 변형 값은 모듈은 배포되어 편집기에 표시되는 빌드 변형을 결정합니다. 변형 간에 전환하려면 모듈의 Active Build Variant 셀을 클릭합니다. 목록 필드에서 원하는 옵션을 선택합니다.

네이티브/C++ 코드가 있는 프로젝트

네이티브/C++ 코드가 있는 프로젝트의 경우 Build Variants 패널에는 세 가지 열: Module, Active Build VariantActive ABI를 포함하는 사전 정의되는 클래스를 제공합니다.

그림 2. Build Variants 패널에는 Active ABI 열이 프로젝트를 빌드하는 방법을 배웠습니다.

모듈의 Active Build Variant 값 배포되어 편집기에 표시되는 빌드 변형을 결정합니다. 네이티브 모듈의 경우 Active ABI 값에 따라 편집기가 배포 대상에 영향을 미치지 않습니다

빌드 유형 또는 ABI를 변경하려면 다음 단계를 따르세요.

  1. Active Build Variant의 셀을 클릭합니다. 또는 Active ABI 열을 사용해야 합니다.
  2. 목록에서 원하는 변형 또는 ABI를 선택합니다. 필드를 확인합니다. 새 동기화가 자동으로 실행됩니다.

앱 또는 라이브러리 모듈의 열을 변경하면 모든 열에 변경사항이 적용됩니다. 종속 행입니다.

버전 관리 구성

기본적으로 Gradle이 다중 APK를 생성할 때 각 APK는 모듈 수준에 지정된 버전 정보 build.gradle 또는 build.gradle.kts 파일. 왜냐하면 Google Play 스토어에서는 앱이 모두 포함된 다중 APK를 허용하지 않습니다. 같은 버전 정보를 가지고 있다면 각 APK에 고유한 <ph type="x-smartling-placeholder"></ph> versionCode해야 합니다.

모듈 수준 build.gradle 파일을 다음과 같이 구성할 수 있습니다. 각 APK의 versionCode를 재정의합니다. 매핑을 생성함 구성하는 각 ABI와 밀도에 고유한 숫자 값을 할당하는 APK를 여러 개 사용하는 경우 출력 버전 코드를 defaultConfig 내에 정의된 버전 코드를 결합하거나 숫자 값이 포함된 productFlavors 블록 밀도 또는 ABI를 통해 분류할 수 있습니다

다음 예에서 x86 ABI의 APK는 versionCode의 2004와 x86_64 ABI를 가져옵니다. versionCode가 3004가 됩니다.

1000과 같이 큰 단위로 버전 코드를 할당하면 나중에 앱을 업데이트해야 하는 경우 고유한 버전 코드를 할당할 수 있습니다. 대상 예를 들어 defaultConfig.versionCode가 후속 업데이트에서 Gradle은 2005의 versionCodex86 APK 및 3005를 x86_64 APK로 변환합니다.

도움말: 빌드에 범용 APK가 포함된 경우 빌드에 범용 APK를 할당하세요. versionCode입니다. Google Play 스토어에서는 대상 기기와 호환되며 가장 높은 versionCode가 있는 앱 버전을 설치하므로 낮은 versionCode를 범용 APK에 할당하면 Google Play 스토어에서는 범용 APK로 대체하기 전에 APK 중 하나를 설치하려고 시도하게 됩니다. 다음 샘플 코드 범용 APK를 재정의하지 않고 기본 versionCode입니다.

Groovy

android {
  ...
  defaultConfig {
    ...
    versionCode 4
  }
  splits {
    ...
  }
}

// Map for the version code that gives each ABI a value.
ext.abiCodes = ['armeabi-v7a':1, x86:2, x86_64:3]

// For per-density APKs, create a similar map:
// ext.densityCodes = ['mdpi': 1, 'hdpi': 2, 'xhdpi': 3]

import com.android.build.OutputFile

// For each APK output variant, override versionCode with a combination of
// ext.abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode
// is equal to defaultConfig.versionCode. If you configure product flavors that
// define their own versionCode, variant.versionCode uses that value instead.
android.applicationVariants.all { variant ->

  // Assigns a different version code for each output APK
  // other than the universal APK.
  variant.outputs.each { output ->

    // Stores the value of ext.abiCodes that is associated with the ABI for this variant.
    def baseAbiVersionCode =
            // Determines the ABI for this variant and returns the mapped value.
            project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))

    // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes,
    // the following code doesn't override the version code for universal APKs.
    // However, because you want universal APKs to have the lowest version code,
    // this outcome is desirable.
    if (baseAbiVersionCode != null) {

      // Assigns the new version code to versionCodeOverride, which changes the
      // version code for only the output APK, not for the variant itself. Skipping
      // this step causes Gradle to use the value of variant.versionCode for the APK.
      output.versionCodeOverride =
              baseAbiVersionCode * 1000 + variant.versionCode
    }
  }
}

Kotlin

android {
  ...
  defaultConfig {
    ...
    versionCode = 4
  }
  splits {
    ...
  }
}

// Map for the version code that gives each ABI a value.
val abiCodes = mapOf("armeabi-v7a" to 1, "x86" to 2, "x86_64" to 3)

// For per-density APKs, create a similar map:
// val densityCodes = mapOf("mdpi" to 1, "hdpi" to 2, "xhdpi" to 3)

import com.android.build.api.variant.FilterConfiguration.FilterType.*

// For each APK output variant, override versionCode with a combination of
// abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode
// is equal to defaultConfig.versionCode. If you configure product flavors that
// define their own versionCode, variant.versionCode uses that value instead.
androidComponents {
    onVariants { variant ->

        // Assigns a different version code for each output APK
        // other than the universal APK.
        variant.outputs.forEach { output ->
            val name = output.filters.find { it.filterType == ABI }?.identifier

            // Stores the value of abiCodes that is associated with the ABI for this variant.
            val baseAbiCode = abiCodes[name]
            // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes,
            // the following code doesn't override the version code for universal APKs.
            // However, because you want universal APKs to have the lowest version code,
            // this outcome is desirable.
            if (baseAbiCode != null) {
                // Assigns the new version code to output.versionCode, which changes the version code
                // for only the output APK, not for the variant itself.
                output.versionCode.set(baseAbiCode * 1000 + (output.versionCode.get() ?: 0))
            }
        }
    }
}

대체 버전 코드 체계에 관한 더 많은 예를 보려면 버전 코드 할당을 참고하세요.

다중 APK 빌드

모듈 수준 build.gradle 또는 build.gradle.kts 파일을 사용하여 여러 APK를 빌드하려면 클릭하세요. 빌드 > Build APK를 빌드하여 현재 APK를 모든 APK를 빌드합니다. Project 창에서 선택한 모듈을 선택합니다. Gradle이 APK 생성 프로젝트의 build/outputs/apk/에 있는 각 밀도 또는 ABI 관련 를 참조하세요.

Gradle은 다중 APK를 구성하는 각 밀도 또는 ABI를 위한 APK를 빌드합니다. 밀도와 ABI 모두를 위해 다중 APK를 사용 설정하면 Gradle은 각 밀도와 ABI 조합을 위한 APK를 만듭니다.

예를 들어 build.gradle 스니펫을 사용하면 mdpihdpi 밀도와 x86x86_64 ABI:

Groovy

...
  splits {
    density {
      enable true
      reset()
      include "mdpi", "hdpi"
    }
    abi {
      enable true
      reset()
      include "x86", "x86_64"
    }
  }

Kotlin

...
  splits {
    density {
      isEnable = true
      reset()
      include("mdpi", "hdpi")
    }
    abi {
      isEnable = true
      reset()
      include("x86", "x86_64")
    }
  }

구성 예의 출력에는 다음 네 개의 APK가 포함됩니다.

  • app-hdpiX86-release.apk: hdpi 밀도와 x86 ABI
  • app-hdpiX86_64-release.apk: hdpi 밀도와 x86_64 ABI
  • app-mdpiX86-release.apk: mdpi 밀도와 x86 ABI
  • app-mdpiX86_64-release.apk: mdpi 밀도와 x86_64 ABI

화면 밀도에 기반한 다중 APK를 빌드할 때 Gradle은 항상 밀도별 APK 외에 모든 밀도의 코드 및 리소스를 포함하는 범용 APK를 생성합니다.

여러 APK를 빌드할 때 ABI, Gradle은 모든 API를 위한 코드와 리소스가 포함된 APK만 ABI에 universalApk true을 지정하는 경우 build.gradle 파일의 splits.abi 블록 (Groovy의 경우) 또는 isUniversalApk = true build.gradle.kts 파일의 splits.abi 블록 (Kotlin 스크립트의 경우).

APK 파일 이름 형식

다중 APK를 빌드할 때 Gradle은 다음을 사용하여 APK 파일 이름을 생성합니다. 스키마:

modulename-screendensityABI-buildvariant.apk

체계 구성요소는 다음과 같습니다.

modulename
빌드 중인 모듈 이름을 지정합니다.
screendensity
화면 밀도를 위한 다중 APK가 사용 설정된 경우 화면을 지정합니다. APK의 밀도(예: mdpi)
ABI

ABI를 위한 다중 APK를 사용하는 경우 다음과 같이 APK의 ABI를 지정합니다. x86 형식으로 전송합니다.

화면 밀도와 ABI 모두를 위한 다중 APK가 사용 설정된 경우 Gradle은 밀도 이름을 ABI 이름과 연결합니다. 예를 들면 다음과 같습니다. mdpiX86 ABI별로 universalApk가 사용 설정된 경우 APK, Gradle은 범용 APK의 ABI 부분으로 universal 사용 파일 이름

buildvariant
빌드 중인 빌드 변형을 지정합니다(예: debug).

예를 들어, mdpi 화면 밀도 APK를 빌드하여 APK 파일 이름은 myApp-mdpi-debug.apk 발표곡 myApp 버전을 빌드하도록 구성된 myApp 버전을 mdpi 화면 밀도와 x86 ABI의 APK 파일 이름은 다음과 같습니다. myApp-mdpiX86-release.apk입니다.