다중 manifest 파일 병합

APK 파일에는 AndroidManifest.xml 파일이 하나만 포함될 수 있지만 Android 스튜디오 프로젝트에는 기본 소스 세트, 빌드 변형 및 가져온 라이브러리에서 제공하는 여러 파일이 포함될 수 있습니다. 따라서 앱을 빌드할 때 Gradle 빌드는 모든 manifest 파일을 APK에 패키징되는 단일 manifest 파일로 병합합니다.

manifest 병합 도구는 병합 휴리스틱을 따르고 특수 XML 속성으로 정의한 병합 환경설정을 준수하여 각 파일의 XML 요소를 모두 결합합니다. 이 페이지에서는 manifest 병합의 작동 방식과 병합 환경설정을 적용하여 병합 충돌을 해결하는 방법을 설명합니다.

팁: 병합된 manifest를 사용하여 병합된 manifest 결과를 미리 보고 충돌 오류를 찾으세요.

병합 우선순위

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

그림 1. 우선순위가 가장 낮은 파일(왼쪽)을 가장 높은 파일(오른쪽)로 manifest 파일 3개를 병합하는 과정

서로 병합할 수 있는 3가지 기본 manifest 파일이 있으며 이러한 파일의 병합 우선순위는 다음과 같습니다(높은 우선순위 순).

  1. 빌드 변형의 manifest 파일

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

    1. 빌드 변형 manifest(예: src/demoDebug/)
    2. 빌드 유형 manifest(예: src/debug/)
    3. 제품 버전 manifest(예: src/demo/)

      버전 차원을 사용한다면 manifest 우선순위는 각 차원이 flavorDimensions 속성에 나열된 순서(높은 우선순위 순)와 일치합니다.

  2. 앱 모듈의 기본 manifest 파일
  3. 포함된 라이브러리의 manifest 파일

    라이브러리가 여러 개 있는 경우 manifest 우선순위는 종속성 순서(Gradle dependencies 블록에 표시되는 순서)와 일치합니다.

예를 들어 라이브러리 manifest는 기본 manifest와 병합되고 기본 manifest는 빌드 변형 manifest와 병합됩니다.

중요: build.gradle 파일의 빌드 구성은 병합된 manifest 파일의 상응하는 속성을 모두 재정의합니다. 예를 들어 build.gradle 파일의 minSdkVersion<uses-sdk> manifest 요소의 일치하는 속성을 재정의합니다. 혼동을 피하려면 <uses-sdk> 요소를 제외하고 이러한 속성을 build.gradle 파일에서만 정의해야 합니다. 자세한 내용은 빌드 구성을 참조하세요.

병합 충돌 휴리스틱

병합 도구는 특정 manifest의 모든 XML 요소를 다른 manifest의 상응하는 요소와 논리적으로 매칭할 수 있습니다. 매칭 작동 방식에 관한 자세한 내용은 병합 정책에 관한 부록을 참조하세요.

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

표 1은 병합 도구에서 모든 속성을 동일한 요소로 결합하려고 할 때 가능한 결과를 보여줍니다.

표 1. 속성 값의 기본 병합 동작

우선순위가 높은 속성 우선순위가 낮은 속성 속성의 병합된 결과
값 없음 값 없음 값 없음(기본값 사용)
값 B 값 B
값 A 값 없음 값 A
값 A 값 A
값 B 충돌 오류 - 병합 규칙 마커를 추가해야 함

그러나 병합 충돌을 피하기 위해 병합 도구가 다르게 동작하는 상황도 있습니다.

  • <manifest> 요소의 속성은 함께 병합되지 않습니다. 우선순위가 가장 높은 manifest의 속성만 사용됩니다.
  • <uses-feature><uses-library> 요소의 android:required 속성은 OR 병합을 사용하므로 충돌이 있으면 "true"가 적용되고 하나의 manifest에 필요한 기능 또는 라이브러리가 항상 포함됩니다.
  • <uses-sdk> 요소의 속성은 항상 우선순위가 높은 manifest의 값을 사용하지만 다음 상황에서는 예외입니다.
    • 우선순위가 낮은 manifest에 더 높은 minSdkVersion 값이 있다면 overrideLibrary 병합 규칙을 적용하지 않는 한 오류가 발생합니다.
    • 우선순위가 낮은 manifest에 더 낮은 targetSdkVersion 값이 있으면 병합 도구는 우선순위가 높은 manifest의 값을 사용하지만, 가져온 라이브러리가 계속 제대로 작동하는지 확인하는 데 필요한 모든 시스템 권한도 추가합니다(예를 들어 더 높은 Android 버전에서 권한 제한이 증가된 경우). 이 동작에 관한 자세한 내용은 암시적 시스템 권한 관련 섹션을 참조하세요.
  • <intent-filter> 요소는 manifest 간에 일치하지 않습니다. 각각 고유하게 취급되며 병합된 manifest의 공통 상위 요소에 추가됩니다.

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

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

병합 규칙 마커

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

manifest 파일 두 개를 병합할 때 병합 도구는 우선순위가 높은 manifest 파일에서 이러한 마커를 찾습니다.

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

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

노드 마커

전체 XML 요소(주어진 manifest 요소의 모든 속성 및 모든 하위 태그)에 병합 규칙을 적용하려면 다음 속성을 사용합니다.

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

우선순위가 낮은 manifest:

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

우선순위가 높은 manifest:

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

병합된 manifest 결과:

    <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"
이 태그의 속성만 병합하고 중첩된 요소는 병합하지 않습니다.

우선순위가 낮은 manifest:

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

우선순위가 높은 manifest:

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

병합된 manifest 결과:

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

우선순위가 낮은 manifest:

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

우선순위가 높은 manifest:

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

병합된 manifest 결과:

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

우선순위가 낮은 manifest:

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

우선순위가 높은 manifest:

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

병합된 manifest 결과:

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

우선순위가 낮은 manifest:

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

우선순위가 높은 manifest:

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

병합된 manifest 결과:

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

우선순위가 낮은 manifest:

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

우선순위가 높은 manifest:

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

manifest 병합 오류가 생성됩니다. strict 모드에서는 두 개의 manifest 요소가 다를 수 없습니다. 따라서 다른 병합 규칙 마커를 적용하여 이 차이를 해결해야 합니다. 일반적으로 위 tools:node="merge" 예와 같이 이 두 개의 요소는 문제없이 병합됩니다.

속성 마커

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

tools:remove="attr, ..."
병합된 manifest에서 지정된 속성을 삭제합니다. 이러한 속성을 대신 삭제할 수 있을 것 같지만 우선순위가 낮은 manifest 파일에 포함된 이러한 속성을 병합된 manifest에 들어가지 않도록 하려면 이 방법을 사용해야 합니다.

우선순위가 낮은 manifest:

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

우선순위가 높은 manifest:

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

병합된 manifest 결과:

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

우선순위가 낮은 manifest:

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

우선순위가 높은 manifest:

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

병합된 manifest 결과:

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

우선순위가 낮은 manifest:

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

우선순위가 높은 manifest:

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

manifest 병합 오류가 생성됩니다. 다른 병합 규칙 마커를 적용하여 충돌을 해결해야 합니다. 주의: 기본 동작이므로 tools:strict="screenOrientation"를 삭제해도 위 예의 결과는 동일합니다.

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

우선순위가 낮은 manifest:

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

우선순위가 높은 manifest:

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

병합된 manifest 결과:

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

마커 선택기

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

예를 들어 다음 manifest의 경우 remove 병합 규칙은 com.example.lib1 라이브러리의 우선순위가 낮은 manifest 파일에만 적용됩니다.

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

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

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

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

기본적으로 기본 manifest 파일보다 minSdkVersion 값이 라이브러리를 가져오면 오류가 발생하여 라이브러리를 가져올 수 없습니다. 병합 도구가 이 충돌을 무시하고 앱의 낮은 minSdkVersion 값을 유지하면서 라이브러리를 가져오려면 overrideLibrary 속성을 <uses-sdk> 태그에 추가합니다. 속성 값은 하나 이상의 라이브러리 패키지 이름(쉼표로 구분)일 수 있으므로 기본 manifest의 minSdkVersion을 재정의할 수 있는 라이브러리를 표시합니다.

예를 들어 앱의 기본 manifest가 다음과 같이 overrideLibrary를 적용합니다.

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

그러면 다음 manifest가 <uses-sdk> 태그와 관련된 오류 없이 병합될 수 있으며 병합된 manifest는 앱 manifest에서 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의 값이 다른 병합된 manifest에 다음과 같이 영향을 줄 수 있습니다.

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

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

표 2. 통합 도구가 병합된 manifest에 추가할 수 있는 권한 목록

우선순위가 낮은 manifest 선언 병합된 manifest에 추가되는 권한
targetSdkVersion은 3 이하임 WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE
targetSdkVersion은 15 이하이고 READ_CONTACTS를 사용함 READ_CALL_LOG
targetSdkVersion은 15 이하이고 WRITE_CONTACTS를 사용함 WRITE_CALL_LOG

병합된 manifest 검사 및 충돌 찾기

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

병합된 manifest 뷰는 그림 2와 같이 왼쪽에는 병합된 manifest 결과를 표시하고 오른쪽에는 병합된 각 manifest 파일 관련 정보를 표시합니다. 우선순위가 낮은 manifest 파일에서 병합된 요소는 왼쪽에서 다른 색상으로 강조표시됩니다. 각 색상의 키는 오른쪽의 Manifest Sources에서 지정됩니다.

그림 2. 병합된 manifest 뷰

빌드의 일부이지만 요소 또는 속성에 영향을 미치지 않은 manifest 파일은 오른쪽의 Other Manifest Files에 나열됩니다.

요소의 원래 위치에 관한 정보를 확인하려면 왼쪽에서 요소를 클릭합니다. 오른쪽의 Merging Log에 세부정보가 표시됩니다.

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

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

부록: 병합 정책

manifest 병합 도구는 하나의 manifest 파일의 모든 XML 요소를 다른 파일의 상응하는 요소와 논리적으로 매칭할 수 있습니다. 병합 도구는 '매칭 키'를 사용하여 각 요소를 매칭합니다. 고유한 속성 값(예: android:name) 또는 태그 자체의 자연적인 고유성(예: <supports-screen> 요소는 하나만 있을 수 있음)을 사용합니다. 두 개의 manifest에 동일한 XML 요소가 있는 경우 도구가 세 개의 병합 정책 중 하나를 사용하여 두 요소를 병합합니다.

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

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

표 3. manifest 요소 병합 정책 및 매칭 키

요소 병합 정책 매칭 키
<action> 병합 android:name 속성
<activity> 병합 android:name 속성
<application> 병합 <manifest> 당 하나만 있음
<category> 병합 android:name 속성
<data> 병합 <intent-filter> 당 하나만 있음
<grant-uri-permission> 병합 <provider> 당 하나만 있음
<instrumentation> 병합 android:name 속성
<intent-filter> 유지 매칭 없음. 상위 요소 내에서 여러 선언이 허용됨
<manifest> 하위 요소만 병합 파일 당 하나만 있음
<meta-data> 병합 android:name 속성
<path-permission> 병합 <provider> 당 하나만 있음
<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> 당 하나만 있음
<uses-configuration> 병합 <manifest> 당 하나만 있음
<uses-feature> 병합 android:name 속성(존재하지 않으면 android:glEsVersion 속성)
<uses-library> 병합 android:name 속성
<uses-permission> 병합 android:name 속성
<uses-sdk> 병합 <manifest> 당 하나만 있음
맞춤 요소 병합 매칭 없음. 병합 도구에 알려지지 않았으므로 항상 병합된 manifest에 포함됨