Skip to content

Most visited

Recently visited

navigation

다중 매니페스트 파일 병합

APK 파일은 하나의 AndroidManifest.xml 파일만 포함할 수 있지만 Android Studio 프로젝트는 메인 소스 세트, 빌드 변형, 가져온 라이브러리에서 제공하는 여러 파일을 포함할 수 있습니다. 그러므로 앱을 빌드할 때 Gradle 빌드는 모든 매니페스트 파일을 하나의 매니페스트 파일로 병합하고, 이를 APK에 패키지로 넣습니다.

매니페스트 병합 도구는 병합 추론과 특수 XML 특성에서 정의한 병합 기본 설정에 따라 각 파일에서 모든 XML 요소를 결합합니다. 이 페이지는 매니페스트 병합의 원리와 병합 기본 설정을 병합 충돌 해결에 적용하는 방법을 설명합니다.

팁:병합된 매니페스트를 사용하여 병합된 매니페스트 결과를 미리 보고 충돌 오류를 찾습니다.

병합 우선순위

병합 도구는 각 매니페스트 파일 우선순위에 따라 모든 매니페스트 파일을 하나의 파일로 순차 병합합니다. 예를 들어 매니페스트 파일이 3개 있을 경우 그림 1과 같이 우선순위가 가장 낮은 매니페스트가 다음으로 우선순위가 높은 파일과 병합되고, 이렇게 병합된 파일은 가장 우선순위가 높은 파일과 병합됩니다.

그림 1. 우선순위가 가장 낮은 파일(왼쪽)에서 가장 높은 파일(오른쪽)까지 매니페스트 파일 3개를 병합하는 과정

서로 병합할 수 있는 기본적인 매니페스트 파일 유형은 3가지가 있습니다. 각 유형의 병합 우선순위는 다음과 같습니다(우선순위가 높은 순).

  1. 빌드 변형의 매니페스트 파일

    변형에 여러 개의 소스 세트가 있다면 매니페스트 우선순위는 다음과 같습니다.

    1. 빌드 변형 매니페스트(예 src/demoDebug/)
    2. 빌드 유형 매니페스트(예: src/debug/)
    3. 제품 버전 매니페스트(예: src/demo/)

      버전 차원을 사용할 경우 매니페스트 우선순위는 각 차원이 flavorDimensions 속성에 등록된 순서(우선순위가 높은 순)와 같습니다.

  2. 앱 모듈의 메인 매니페스트 파일
  3. 포함된 라이브러리의 매니페스트 파일

    여러 개의 라이브러리가 있는 경우 매니페스트 우선순위는 종속성 순서(Gradle dependencies 블록에 나타나는 순서)와 같습니다.

예를 들어 라이브러리 매니페스트는 메인 매니페스트와 병합되고, 메인 매니페스트는 빌드 변형 매니페스트와 병합됩니다.

참고: 모든 소스 세트에서 병합 우선순위가 같습니다. 이 내용은 소스 세트로 빌드에 설명되어 있습니다.

중요: build.gradle 파일의 빌드 구성은 병합된 매니페스트 파일의 해당 특성을 재정의합니다. 예를 들어 build.gradle 파일의 minSdkVersion<uses-sdk> 매니페스트 요소의 해당 특성을 재정의합니다. 혼란을 피하기 위해 <uses-sdk> 요소는 제외하고 build.gradle 파일에서만 이 속성들을 정의해야 합니다. 자세한 내용은 빌드 구성을 참조하세요.

병합 충돌 추론

병합 도구는 특정 매니페스트의 모든 XML 요소를 다른 매니페스트의 해당 요소와 논리적으로 매칭할 수 있습니다. (매칭 원리에 대한 자세한 내용은 병합 정책 관련 부록을 참조하세요).

낮은 우선순위의 매니페스트 요소가 높은 우선순위 매니페스트의 요소와 일치하지 않으면 병합된 매니페스트에 추가됩니다. 그러나 일치하는 요소가 있으면 병합 도구가 각각의 모든 특성을 동일한 요소에 결합하려고 시도합니다. 두 개의 매니페스트에 값이 다른 동일한 특성이 포함된 것이 발견되면 병합 충돌이 발생합니다.

표 1은 병합 도구가 모든 특성을 동일한 요소로 결합할 때 나올 가능성이 있는 결과를 보여줍니다.

표 1. 특성 값의 병합 동작

우선순위가 높은 특성 우선순위가 낮은 특성 특성의 병합 결과
값 없음 값 없음 값 없음(기본값 사용)
값 B 값 B
값 A 값 없음 값 A
값 A 값 A
값 B 충돌 오류병합 규칙 마커 추가 필요

그러나 병합 충돌을 피하기 위해 병합 도구가 다른 방식으로 동작하는 경우가 몇 가지 있습니다.

특성 간에 발생하는 다른 모든 충돌의 경우 오류를 수신합니다. 우선순위가 높은 매니페스트 파일에 특수한 특성을 추가하여 병합 도구에 오류 해결 방법을 지시해야 합니다(병합 규칙 마커에 대한 다음 섹션 참조).

특성 기본값을 사용하지 마세요. 모든 고유한 특성은 동일한 요소에 결합되므로 우선순위가 높은 매니페스트가 선언 없이 특성 기본값을 사용하면 예상치 못한 결과가 발생할 수 있습니다. 예를 들어 우선순위가 높은 매니페스트가 android:launchMode 특성을 선언하지 않는다면 "standard"의 기본값을 사용합니다. 그러나 우선순위가 낮은 매니페스트가 다른 값으로 이 특성을 선언한다면 이 값이 병합된 매니페스트에 적용됩니다(기본값 재정의). 그러므로 각 특성을 원하는 대로 명시적으로 정의해야 합니다. (각 특성의 기본값은 매니페스트 참조에 기록됩니다.)

병합 규칙 마커

병합 규칙 마커는 병합 충돌 해결 방법에 대한 기본 설정을 표현하거나 원하지 않는 요소와 특성을 제거하는 데 사용할 수 있는 XML 특성입니다. 전체 요소에 마커를 적용하거나 요소의 특정 특성에만 마커를 적용할 수 있습니다.

두 개의 매니페스트 파일을 병합할 경우 병합 도구는 우선순위가 높은 매니페스트 파일에서 해당 마커를 검색합니다.

모든 마커는 Android tools 네임스페이스에 속하므로 먼저 다음과 같이 <manifest> 요소에서 이 네임스페이스를 선언해야 합니다.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp"
    xmlns:tools="http://schemas.android.com/tools">

Node 마커

전체 XML 요소(특정 매니페스트 요소의 모든 특성 및 모든 하위 태그)에 병합 규칙을 적용하려면 다음 특성을 사용합니다.

tools:node="merge"
충돌이 없으면 병합 충돌 추론을 사용하여 이 태그의 모든 특성과 모든 중첩된 요소를 병합합니다. 이것은 요소의 기본 동작입니다.

우선순위가 낮은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:windowSoftInputMode=”stateUnchanged”>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

우선순위가 높은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:screenOrientation=”portrait”
    tools:node="merge”>
</activity>

병합된 매니페스트 결과:

<activity android:name=”com.example.ActivityOne”
    android:screenOrientation=”portrait”
    android:windowSoftInputMode=”stateUnchanged”>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
tools:node="merge-only-attributes"
이 태그의 특성만 병합하고 중첩된 요소는 병합하지 않습니다.

우선순위가 낮은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:windowSoftInputMode=”stateUnchanged”>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <data android:type="image/*" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

우선순위가 높은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:screenOrientation=”portrait”
    tools:node="merge-only-attributes”>
</activity>

병합된 매니페스트 결과:

<activity android:name=”com.example.ActivityOne”
    android:screenOrientation=”portrait”
    android:windowSoftInputMode=”stateUnchanged”>
</activity>
tools:node="remove"
병합된 매니페스트에서 이 요소를 제거합니다. 이 요소를 삭제하기만 하면 될 것 같지만 병합된 매니페스트에서 필요 없는 요소를 발견했는데 통제할 수 없는 우선순위가 낮은 매니페스트 파일이 제공하는 요소라면 (예: 가져온 라이브러리) 이 방법을 사용해야 합니다.

우선순위가 낮은 매니페스트:

<activity-alias android:name=”com.example.alias”>
  <meta-data android:name=”cow”
      android:value=”@string/moo”/>
  <meta-data android:name=”duck”
      android:value=”@string/quack”/>
</activity-alias>

우선순위가 높은 매니페스트:

<activity-alias android:name=”com.example.alias”>
  <meta-data android:name=”cow”
      tools:node=”remove”/>
</activity-alias>

병합된 매니페스트 결과:

<activity-alias android:name=”com.example.alias”>
  <meta-data android:name=”duck”
      android:value=”@string/quack”/>
</activity-alias>
tools:node="removeAll"
tools:node="remove"와 비슷하지만 (동일한 상위 요소 내에서) 이 요소 유형과 일치하는 모든 요소를 제거합니다.

우선순위가 낮은 매니페스트:

<activity-alias android:name=”com.example.alias”>
  <meta-data android:name=”cow”
      android:value=”@string/moo”/>
  <meta-data android:name=”duck”
      android:value=”@string/quack”/>
</activity-alias>

우선순위가 높은 매니페스트:

<activity-alias android:name=”com.example.alias”>
  <meta-data tools:node=”removeAll”/>
</activity-alias>

병합된 매니페스트 결과:

<activity-alias android:name=”com.example.alias”>
</activity-alias>
tools:node="replace"
우선순위가 낮은 요소를 완전히 대체합니다. 즉, 우선순위가 낮은 매니페스트에 일치하는 요소가 있으면 이를 무시하고 이 매니페스트에 나타난 것과 똑같이 이 요소를 사용합니다.

우선순위가 낮은 매니페스트:

<activity-alias android:name=”com.example.alias”>
  <meta-data android:name=”cow”
      android:value=”@string/moo”/>
  <meta-data android:name=”duck”
      android:value=”@string/quack”/>
</activity-alias>

우선순위가 높은 매니페스트:

<activity-alias android:name=”com.example.alias”
    tools:node=”replace”>
  <meta-data android:name=”fox”
      android:value=”@string/dingeringeding”/>
</activity-alias>

병합된 매니페스트 결과:

<activity-alias android:name=”com.example.alias”>
  <meta-data android:name=”fox”
      android:value=”@string/dingeringeding”/>
</activity-alias>
tools:node="strict"
우선순위가 낮은 매니페스트에서 이 요소가 우선순위가 높은 매니페스트의 요소와 정확히 일치하지 않을 때마다 빌드 실패를 생성합니다( 다른 병합 규칙 마커에 의해 해결되는 경우 제외). 이는 병합 충돌 추론을 재정의합니다. 예를 들어 우선순위가 낮은 매니페스트에 단순히 추가 특성을 포함하면 빌드가 실패합니다. (기본 동작에서는 병합된 매니페스트에 추가 특성을 추가합니다.)

우선순위가 낮은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:windowSoftInputMode=”stateUnchanged”>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

우선순위가 높은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:screenOrientation=”portrait”
    tools:node="strict”>
</activity>

매니페스트 병합 오류가 생성됩니다. strict 모드에서는 두 개의 매니페스트 요소가 다를 수 없습니다. 따라서 이 차이를 해결하기 위해 다른 병합 규칙 마커를 적용해야 합니다. ( 위의 tools:node="merge" 예시에서 보았듯이 원래 이 두 개의 요소는 문제없이 병합됩니다.)

특성 마커

매니페스트 태그의 특정 특성에만 병합 규칙을 적용하려면 다음 특성을 사용합니다. 각 특성은 쉼표로 구분한 하나 이상의 특성 이름(특성 네임스페이스 포함)을 허용합니다.

tools:remove="attr, ..."
병합된 매니페스트에서 지정된 특성을 제거합니다. 이 특성을 삭제하기만 하면 될 것 같지만 우선순위가 낮은 매니페스트에 이 특성이 포함되지 않고 이 특성을 병합된 매니페스트에 포함시키고 싶지 않다면 이 방법을 사용해야 합니다.

우선순위가 낮은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:windowSoftInputMode=”stateUnchanged”>

우선순위가 높은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:screenOrientation=”portrait”
    tools:remove=”android:windowSoftInputMode”>

병합된 매니페스트 결과:

<activity android:name=”com.example.ActivityOne”
    android:screenOrientation=”portrait”>
tools:replace="attr, ..."
우선순위가 낮은 매니페스트의 지정된 특성을 이 매니패스트의 특성으로 대체합니다. 즉, 항상 우선순위가 높은 매니페스트 값을 유지합니다.

우선순위가 낮은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:theme=”@oldtheme”
    android:exported=”false”
    android:windowSoftInputMode=”stateUnchanged”>

우선순위가 높은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:theme=”@newtheme”
    android:exported=”true”
    android:screenOrientation=”portrait”
    tools:replace=”android:theme,android:exported”>

병합된 매니페스트 결과:

<activity android:name=”com.example.ActivityOne”
    android:theme=”@newtheme”
    android:exported=”true”
    android:screenOrientation=”portrait”
    android:windowSoftInputMode=”stateUnchanged”>
tools:strict="attr, ..."
우선순위가 낮은 매니페스트의 이 특성이 우선순위가 높은 매니페스트의 특성과 정확히 일치하지 않을 때마다 빌드 실패를 생성합니다. 이는 모든 특성의 기본 동작입니다.단, 병합 충돌 추론에서 설명한 특수 동작을 하는 특성은 예외입니다.

우선순위가 낮은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:screenOrientation=”landscape”>
</activity>

우선순위가 높은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:screenOrientation=”portrait”
    tools:strict="android:screenOrientation”>
</activity>

매니페스트 병합 오류가 생성됩니다. 충돌을 해결하기 위해 다른 병합 규칙 마커를 적용해야 합니다. (명심할 점: 이는 기본 동작이므로 tools:strict="screenOrientation”을 제거한다면 위의 예시와 결과가 같습니다.)

다음과 같이 하나의 요소에 여러 개의 마커를 적용할 수 있습니다.

우선순위가 낮은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:theme=”@oldtheme”
    android:exported=”false”
    android:allowTaskReparenting="true"
    android:windowSoftInputMode=”stateUnchanged”>

우선순위가 높은 매니페스트:

<activity android:name=”com.example.ActivityOne”
    android:theme=”@newtheme”
    android:exported=”true”
    android:screenOrientation=”portrait”
    tools:replace=”android:theme,android:exported”
    tools:remove=”android:windowSoftInputMode”>

병합된 매니페스트 결과:

<activity android:name=”com.example.ActivityOne”
    android:theme=”@newtheme”
    android:exported=”true”
    android:allowTaskReparenting="true"
    android:screenOrientation=”portrait”>

Markerselector

가져온 특정 라이브러리에만 병합 규칙 마커를 적용하고 싶다면 라이브러리 패키지 이름으로 tools:selector 특성을 추가합니다.

예를 들어 다음 매니페스트는 com.example.lib1 라이브러리의 우선순위가 낮은 매니페스트 파일에만remove 병합 규칙을 적용합니다.

<permission android:name="permissionOne"
    tools:node="remove"
    tools:selector="com.example.lib1">

다른 소스의 우선순위가 낮은 매니페스트라면 remove 병합 규칙을 무시합니다.

참고: 특성 마커와 함께 병합 규칙을 사용할 경우 마커에서 지정된 모든 특성에 병합 규칙이 적용됩니다.

가져온 라이브러리에 대해 <uses-sdk> 재정의

기본적으로 메인 매니페스트 파일보다 minSdkVersion 값이 라이브러리를 가져오면 오류가 발생하고, 라이브러리를 가져올 수 없습니다. 병합 도구가 이 충돌을 무시하고 앱의 낮은 minSdkVersion 값을 그대로 둔 채 라이브러리를 가져오게 하려면 overrideLibrary 특성을 <uses-sdk> 태그에 추가합니다. 특성 값은 하나 이상의 라이브러리 패키지 이름입니다 (쉼표로 구분). 이 라이브러리가 메인 매니페스트의 minSdkVersion을 재정의할 수 있다는 것을 나타냅니다.

예를 들어 앱의 메인 매니페스트는 다음과 같이 overrideLibrary를 적용합니다.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.app"
          xmlns:tools="http://schemas.android.com/tools">
  <uses-sdk android:targetSdkVersion="22" android:minSdkVersion="2"
            tools:overrideLibrary="com.example.lib1, com.example.lib2"/>
...

그 후에는 &lt;uses-sdk> 태그와 관련된 오류 없이 다음 매니페스트를 병합할 수 있습니다. 병합된 매니페스트는 앱 매니페스트의 minSdkVersion="2"를 그대로 유지합니다.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.lib1">
   <uses-sdk android:minSdkVersion="4" />
...

암시적 시스템 권한

앱에서 자유롭게 액세스할 수 있었던 일부 Android API는 최신 Android 버전에서 시스템 권한으로 제한되었습니다. 이러한 API 액세스를 기대하는 앱이 작동 중단되지 않도록 최신 Android 버전에서는 앱에서 targetSdkVersion이 제한을 추가한 버전보다 낮은 값으로 설정된 경우 권한 없이 해당 API에 계속 액세스할 수 있습니다. 이 동작은 API에 액세스할 수 있는 암시적 권한을 앱에 효과적으로 부여합니다. 따라서 병합된 매니페스트는 다음과 같은 방식으로 targetSdkVersion에 다양한 값을 설정할 수 있습니다.

우선순위가 낮은 매니페스트 파일에서 암시적 권한을 제공하는 targetSdkVersion의 값이 낮고 우선순위가 높은 매니페스트에 동일한 암시적 권한이 없을 경우 (targetSdkVersion이 제한이 추가된 버전 이상일 경우) 병합 도구는 병합된 매니페스트에 명시적으로 시스템 권한을 추가합니다.

예를 들어, 앱에서 targetSdkVersion이 4 이상으로 설정되었는데 targetSdkVersion이 3 이하로 설정된 라이브러리를 가져오면, 병합 도구가 병합된 매니페스트에 WRITE_EXTERNAL_STORAGE 권한을 추가합니다. 표 2는 병합된 매니페스트에 추가할 수 있는 모든 권한이 표시되어 있습니다.

참고: 앱의 targetSdkVersion을 23 이상으로 설정하면 앱이 권한으로 보호된 API에 액세스하려고 시도할 때 위험한 권한에 대해 런타임 권한을 요청합니다. 자세한 내용은 시스템 권한 사용을 참조하세요.

표 2. 병합 도구가 병합된 매니페스트에 추가할 수 있는 권한 목록

우선순위가 낮은 매니페스트가 선언 병합된 매니페스트에 추가된 권한
targetSdkVersion이 3 이하 WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE
targetSdkVersion이 15 이하이고 READ_CONTACTS 사용 READ_CALL_LOG 사용
targetSdkVersion이 15 이하이고 WRITE_CONTACTS 사용 WRITE_CALL_LOG

병합된 매니페스트 검사 및 충돌 찾기

APK를 빌드하기 전이라도 Android Studio에서 AndroidManifest.xml 파일을 열고 편집기 아래의 Merged Manifest 탭을 클릭하면 병합된 매니페스트를 미리 볼 수 있습니다.

Merged Manifest 뷰는 그림 2와 같이 왼쪽에 병합된 매니페스트 결과를 표시하고 오른쪽에는 각 병합된 매니페스트 파일 관련 정보를 표시합니다. 요소는 우선순위가 낮은 매니페스트 파일부터 병합되며 왼쪽에 다양한 색상으로 강조표시됩니다. 각 색상의 키는 오른쪽의 Manifest Sources에 지정되어 있습니다.

그림 2. 병합된 매니페스트 뷰

빌드의 일부이지만 오른쪽의 Other Manifest Files에 등록된 요소 또는 특성에 영향을 미치지 않는 매니페스트 파일입니다.

요소의 원래 위치에 대한 정보를 확인하려면 왼쪽에서 요소를 클릭합니다. 오른쪽의 Merging Log에 상세 정보가 나타납니다.

충돌이 발생하면 오른쪽의 Merging Errors아래 병합 규칙 마커를 사용하여 충돌을 해결하기 위한 권장 사항과 함께 표시됩니다. 오류는 Event Log 창(View > Tool Windows > Event Log 선택)에도 출력됩니다.

병합 결정 트리의 전체 로그를 확인하려면 모듈의 build/outputs/logs/ 디렉토리에서 manifest-merger-buildVariant-report.txt라는 로그 파일을 참조하세요.

부록: 병합 정책

매니페스트 병합 도구는 어떤 매니페스트 파일의 모든 XML 요소를 다른 파일의 해당 요소와 논리적으로 매칭할 수 있습니다. 병합기는 "매칭 키"를 사용하여 각 요소를 매칭합니다. 고유한 특성 값(예: android:name) 또는 태그 자체의 자연적인 고유성(예: <supports-screen> 요소는 하나만 존재 가능)을 이용합니다. 두 개의 매니페스트에 동일한 XML 요소가 있는 경우 도구가 세 개의 병합 정책 중 하나를 사용하여 두 요소를 병합합니다.

병합
충돌하지 않는 모든 특성을 같은 태그로 결합하고 각각의 병합 정책에 따라 하위 요소를 병합합니다. 서로 충돌하는 특성이 있으면 병합 규칙 마커로 병합합니다.
하위 요소만 병합
특성을 결합하거나 병합하지 않고(우선순위가 가장 높은 매니페스트가 제공한 특성만 유지) 병합 정책에 따라 하위 요소만 병합합니다.
유지
요소는 '그대로' 두고 병합된 파일의 공통 상위 요소에 요소를 추가합니다. 같은 요소에 대해 여러 개의 선언이 존재할 수 있을 경우에만 사용합니다.

표 1은 각 요소 유형, 사용한 병합 정책 유형, 두 매니페스트에서 요소 매칭을 판별하는 데 사용되는 키를 보여줍니다.

표 3. 매니페스트 요소 병합 정책 및 매칭 키

요소 병합 정책 매칭 키
<action> 병합 android:name 특성
<activity> 병합 android:name 특성
<application> 병합 <manifest>당 1개
<category> 병합 android:name 특성
<data> 병합 <intent-filter>당 1개
<grant-uri-permission> 병합 <provider>당 1개
<instrumentation> 병합 android:name 특성
<intent-filter> 유지 매칭 없음, 상위 요소에 다수의 선언 허용
<manifest> 하위 요소만 병합 파일당 1개
<meta-data> 병합 android:name 특성
<path-permission> 병합 <provider>당 1개
<permission-group> 병합 android:name 특성
<permission> 병합 android:name 특성
<permission-tree> 병합 android:name 특성
<provider> 병합 android:name 특성
<receiver> 병합 android:name 특성
<screen> 병합 android:screenSize 특성
<service> 병합 android:name 특성
<supports-gl-texture> 병합 android:name 특성
<supports-screen> 병합 <manifest>당 1개
<uses-configuration> 병합 <manifest>당 1개
<uses-feature> 병합 android:name 특성(존재하지 않을 경우 android:glEsVersion 특성)
<uses-library> 병합 android:name 특성
<uses-permission> 병합 android:name 특성
<uses-sdk> 병합 <manifest>당 1개
사용자설정 요소 병합 매칭 없음, 병합 도구에 알려지지 않았을 수 있으므로 항상 병합된 매니페스트에 포함
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)