The Android Developer Challenge is back! Submit your idea before December 2.

앱 매니페스트 개요

모든 앱 프로젝트는 프로젝트 소스 세트의 루트에 AndroidManifest.xml 파일(정확히 이 이름)이 있어야 합니다. 매니페스트 파일은 Android 빌드 도구, Android 운영체제 및 Google Play에 앱에 관한 필수 정보를 설명합니다.

매니페스트 파일은 다른 여러 가지도 설명하지만 특히 다음과 같은 내용을 선언해야 합니다.

  • 앱의 패키지 이름(일반적으로 코드의 네임스페이스와 일치). Android 빌드 도구는 프로젝트를 빌드할 때 이 이름으로 코드 엔터티의 위치를 확인합니다. 앱을 패키징할 때 빌드 도구가 이 값을 Gradle 빌드 파일의 애플리케이션 ID로 대체합니다. 이는 시스템과 Google Play에서 고유한 앱 식별자로 사용됩니다. 패키지 이름과 앱 ID에 대해 자세히 알아보세요.
  • 앱의 구성 요소(모든 액티비티, 서비스, Broadcast Receiver, 콘텐츠 제공자 포함). 각 구성 요소는 Kotlin이나 Java 클래스의 이름과 같은 기본 속성을 정의해야 합니다. 또한 자신이 처리할 수 있는 기기 구성의 종류, 그리고 구성 요소가 어떻게 시작되는지 설명하는 인텐트 필터와 같은 기능을 선언할 수도 있습니다. 앱 구성 요소에 대해 자세히 알아보세요.
  • 앱이 시스템 또는 다른 앱의 보호된 부분에 액세스하기 위해 필요한 권한. 이것은 다른 앱이 이 앱의 콘텐츠에 액세스하고자 하는 경우 반드시 있어야 하는 모든 권한도 선언합니다. 권한에 대해 자세히 알아보세요.
  • 앱에 필요한 하드웨어 및 소프트웨어 기능으로, 이에 따라 앱을 Google Play에서 설치할 수 있는 기기의 종류가 달라집니다. 기기 호환성에 대해 자세히 알아보세요.

Android Studio를 사용하여 앱을 빌드하고 있다면 매니페스트 파일이 생성되고, 앱을 빌드하는 동안(특히, 코드 템플릿을 사용하는 시점에서) 대부분의 기본적인 매니페스트 요소가 추가될 것입니다.

파일 기능

다음 섹션에서는 앱의 가장 중요한 특징 중 일부가 어떻게 매니페스트 파일에 반영되는지 설명합니다.

패키지 이름과 애플리케이션 ID

매니페스트 파일의 루트 요소는 앱의 패키지 이름에 대한 특성이 필요합니다(일반적으로는 프로젝트 디렉토리 구조와 일치—Java 네임스페이스).

예를 들어 다음 스니펫은 패키지 이름이 "com.example.myapp"인 루트 <manifest> 요소를 나타냅니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp"
    android:versionCode="1"
    android:versionName="1.0" >
    ...
</manifest>

앱을 최종 애플리케이션 패키지(APK)로 빌드하는 동안 Android 빌드 도구가 package 특성을 사용하는 목적은 두 가지입니다.

  • 빌드 도구는 앱에서 생성된 R.java 클래스의 네임스페이스로 이 이름을 적용합니다(앱 리소스에 액세스하는 데 사용).

    예: 위의 매니페스트와 함께 R 클래스가 com.example.myapp.R에서 생성됩니다.

  • 빌드 도구는 이 이름을 사용하여 매니페스트 파일에 선언되어 있는 상대 클래스 이름을 확인합니다.

    예: 위 매니페스트를 사용하면 <activity android:name=".MainActivity">로 선언된 액티비티가 com.example.myapp.MainActivity인 것으로 확인됩니다.

이와 같이, 매니페스트의 package 특성에 있는 이름은 액티비티와 기타 앱 코드가 들어 있는 프로젝트의 기본 패키지 이름과 항상 일치해야 합니다. 물론 프로젝트에 다른 하위 패키지가 있을 수도 있지만, 해당 파일들은 package 특성의 네임스페이스를 사용하여 R.java 클래스를 가져와야 합니다.

그러나 APK가 컴파일되고 나면 package 특성도 앱의 전체적으로 고유한 애플리케이션 ID를 나타낸다는 점을 유의해야 합니다. 빌드 도구가 package 이름에 기초하여 위의 작업을 수행하고 나면, 프로젝트의 build.gradle 파일(Android Studio 프로젝트에 사용)에 있는 applicationId 속성에 지정된 값으로 package 값을 대체합니다. package 특성의 최종값은 전체적으로 고유해야 합니다. 이것이 앱을 시스템과 Google Play에서 식별할 수 있는 유일하게 보증된 방법이기 때문입니다.

매니페스트의 package 이름과 build.gradle 파일의 applicationId를 구분하려면 다소 혼란스러울 수 있습니다. 하지만 이 두 가지를 동일하게 유지한다면 걱정할 필요가 없습니다.

그러나 코드의 네임스페이스(그리고 매니페스트의 package 이름)를 빌드 파일의 applicationId와 다르게 지정하려면 애플리케이션 ID 설정이 미치는 영향을 충분히 이해해야 합니다. 해당 페이지에서는 빌드 파일의 applicationId와 별개로 매니페스트의 package 이름을 안전하게 수정하고, 다른 빌드 구성에 대해 애플리케이션 ID를 변경하는 방법을 설명합니다.

앱 구성 요소

앱에서 생성하는 각각의 앱 구성 요소에 대해 매니페스트 파일에서 해당하는 XML 요소를 선언해야 합니다.

매니페스트 파일에서 XML 요소를 선언하지 않고 이 구성 요소를 하위 클래스로 지정하면 시스템에서 이를 시작할 수 없습니다.

하위 클래스의 이름은 완전한 패키지 이름을 사용하여 name 특성으로 지정해야 합니다. 예를 들어 Activity 하위 클래스를 선언하려면 다음과 같이 할 수 있습니다.

<manifest ... >
    <application ... >
        <activity android:name="com.example.myapp.MainActivity" ... >
        </activity>
    </application>
</manifest>

그러나 name 값의 첫 번째 문자가 마침표일 경우 앱의 패키지 이름(<manifest> 요소의 package 특성에서 얻은 이름)이 해당 이름 앞에 붙습니다. 예를 들어 다음 액티비티 이름은 `"com.example.myapp.MainActivity"`으로 해석됩니다.

<manifest package="com.example.myapp" ... >
    <application ... >
        <activity android:name=".MainActivity" ... >
            ...
        </activity>
    </application>
</manifest>

하위 패키지(예: com.example.myapp.purchases) 안에 앱 구성 요소가 있을 경우, name 값으로 누락된 하위 패키지 이름(예: ".purchases.PayActivity")을 추가하거나 완전히 자격을 충족하는 패키지 이름을 사용해야 합니다.

인텐트 필터

앱 액티비티, 서비스, Broadcast Receiver는 인텐트로 활성화됩니다. 인텐트는 실행할 작업을 설명하는 Intent 객체로 정의되는 메시지입니다. 여기에는 작업할 데이터, 작업을 수행해야 하는 구성 요소의 카테고리 및 기타 지침이 포함됩니다.

앱이 인텐트를 시스템에 발행하면 시스템은 각 앱의 매니페스트 파일에 선언된 인텐트 필터에 기초하여 인텐트를 처리할 수 있는 앱 구성 요소를 찾습니다. 시스템은 일치하는 구성 요소의 인스턴스를 시작하고 해당 구성 요소에 Intent 객체를 전달합니다. 두 개 이상의 앱이 인텐트를 처리할 경우 사용자는 어느 앱을 사용할지 선택할 수 있습니다.

앱 구성 요소는 인텐트 필터(<intent-filter> 요소로 정의)를 몇 개든 가질 수 있으며, 각 인텐트 필터는 해당 구성 요소의 각 기능을 설명합니다.

자세한 내용은 인텐트 및 인텐트 필터 문서를 참조하세요.

아이콘 및 레이블

어떤 매니페스트 요소는 해당 앱 구성 요소에 대해 각각 작은 아이콘과 텍스트 레이블을 사용자에게 각각 표시하기 위한 iconlabel 특성이 있습니다.

각각의 경우에 상위 요소에 설정된 아이콘과 레이블은 모든 하위 요소에 대해 기본 iconlabel 값이 됩니다. 예를 들어 <application> 요소에 설정된 아이콘과 레이블이 앱의 각 구성 요소(예: 모든 액티비티)에 대한 기본 아이콘과 레이블이 됩니다.

구성 요소의 <intent-filter>에 설정된 아이콘과 레이블은 구성 요소가 인텐트를 수행하기 위한 옵션으로 제시될 때마다 사용자에게 표시됩니다. 기본적으로 이 아이콘은 상위 구성 요소(<activity> 또는 <application> 요소)에 대해 어떤 아이콘이 선언되든 이를 상속하지만, 선택기 대화상자에서 더욱 잘 보여주고 싶은 고유한 작업을 제공하는 인텐트 필터의 아이콘이 있다면 해당 아이콘으로 변경할 수도 있습니다. 자세한 내용은 다른 앱이 액티비티를 시작하도록 허용을 참조하세요.

권한

Android 앱은 민감한 사용자 데이터(예: 연락처, SMS) 또는 특정 시스템 기능(예: 카메라, 인터넷 액세스)에 액세스하기 위한 권한을 요청해야 합니다. 각 권한은 고유한 레이블로 식별됩니다. 예를 들어 SMS 메시지를 보내야 하는 앱은 매니페스트에 다음과 같은 줄이 있어야 합니다.

<manifest ... >
    <uses-permission android:name="android.permission.SEND_SMS"/>
    ...
</manifest>

Android 6.0(API 레벨 23)부터 사용자는 런타임에서 일부 앱 권한을 승인하거나 거절할 수 있게 됩니다. 그러나 앱이 어떤 Android 버전을 지원하든 매니페스트에서 <uses-permission> 요소로 모든 권한 요청을 선언해야 합니다. 권한이 부여되면 앱이 보호된 기능을 사용할 수 있습니다. 권한이 부여되지 않으면 그러한 기능에 액세스하려는 시도가 실패합니다.

앱은 권한을 사용하여 자체적인 구성 요소를 보호할 수도 있습니다. Android에서 정의된 권한(android.Manifest.permission에서 설명) 또는 다른 앱에서 선언된 권한을 사용할 수 있습니다. 또한, 앱에서 권한을 정의할 수도 있습니다. 새 권한을 선언할 때는 <permission> 요소를 사용합니다.

자세한 내용은 권한 개요를 참조하세요.

기기 호환성

매니페스트 파일에서는 앱에 필요한 하드웨어 또는 소프트웨어 기능을 선언할 수 있고, 따라서 앱과 호환되는 기기 유형도 선언할 수 있습니다. Google Play Store에서는 앱에 필요한 기능이나 시스템 버전을 제공하지 않는 기기에 앱 설치를 허용하지 않습니다.

어느 기기가 앱과 호환되는지 정의하는 매니페스트 태그가 여러 가지 있습니다. 가장 일반적으로 사용하는 태그의 몇 가지 예를 들자면 다음과 같습니다.

<uses-feature>

<uses-feature> 요소를 사용하여 앱에 필요한 하드웨어 및 소프트웨어 기능을 선언할 수 있습니다. 예를 들어 나침반 센서가 없는 기기에서 앱이 기본적인 기능을 실행할 수 없다면, 필요에 따라 다음과 같이 매니페스트 태그를 사용하여 나침반 센서를 선언할 수 있습니다.

<manifest ... >
    <uses-feature android:name="android.hardware.sensor.compass"
                  android:required="true" />
    ...
</manifest>

참고: Chromebooks에 앱을 제공하고 싶을 경우 고려해야 할 중요한 하드웨어 및 소프트웨어 기능 제한이 있습니다. 자세한 내용은 Chromebooks의 앱 매니페스트 호환성을 참조하세요.

<uses-sdk>

각 후속 플랫폼 버전에 이전 버전에서 사용할 수 없는 새 API가 추가되는 경우가 종종 있습니다. 앱이 호환되는 최소 버전을 나타내려면 매니페스트에 <uses-sdk> 태그와 해당 태그의 minSdkVersion 특성을 포함해야 합니다.

그러나 <uses-sdk> 요소의 특성은 build.gradle 파일의 해당 속성으로 재정의된다는 것에 유의하세요. Android Studio를 사용하고 있다면 여기에 minSdkVersiontargetSdkVersion 값을 대신 사용해야 합니다.

android {
  defaultConfig {
    applicationId 'com.example.myapp'

    // Defines the minimum API level required to run the app.
    minSdkVersion 15

    // Specifies the API level used to test the app.
    targetSdkVersion 28

    ...
  }
}

build.gradle 파일에 대한 자세한 내용은 빌드 구성하는 방법을 참조하세요.

각 기기에 대해 앱의 지원을 선언하는 방법에 대한 자세한 내용은 기기 호환성 개요를 참조하세요.

파일 규칙

이 섹션에서는 매니페스트 파일에 포함되는 모든 요소 및 특성에 일반적으로 적용되는 규칙에 대해 설명합니다.

요소
<manifest><application> 요소만 필수입니다. 두 요소는 각각 한 번만 실행되어야 합니다. 다른 요소는 대부분 한 번도 실행되지 않거나 한 번 이상 실행되어도 됩니다. 다만 이들 중 일부가 있어야만 매니페스트 파일에 쓸모가 있습니다.

모든 값은 요소 내의 문자 데이터로서가 아니라 특성을 통해 설정됩니다.

같은 레벨에 있는 여러 요소는 보통 순서가 지정되지 않습니다. 예를 들어 <activity>, <provider><service> 요소는 어느 순서로든 배치할 수 있습니다. 이 규칙에는 두 가지 중요한 예외 사항이 있습니다.

특성
엄밀히 말해서 모든 특성은 선택 사항입니다. 그러나 어떤 요소의 목적을 달성하기 위해 반드시 선언해야 하는 특성이 많습니다. 실제로 선택 사항이라 할 수 있는 특성의 경우 참조 문서에서 기본값을 확인할 수 있습니다.

루트 <manifest> 요소의 몇 가지 특성을 제외하고 모든 특성 이름은 접두사 android:로 시작됩니다. 예를 들어 android:alwaysRetainTaskState가 있습니다. 이 접두사는 범용이기 때문에 특성을 이름으로 참조하는 경우 관련 문서에서 이를 생략하는 경우가 일반적입니다.

여러 개의 값
둘 이상의 값을 지정할 수 있는 경우, 한 요소 안에 여러 값이 나열되지 않고 해당 요소가 거의 항상 반복됩니다. 예를 들어 한 인텐트 필터가 여러 개의 작업을 나열할 수 있습니다.
<intent-filter ... >
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.INSERT" />
    <action android:name="android.intent.action.DELETE" />
    ...
</intent-filter>
리소스 값
어떤 특성은 사용자에게 표시되는 값이 설정됩니다(예: 액티비티의 제목 또는 앱 아이콘). 이런 특성에 대한 값은 사용자 언어나 다른 기기 구성에 따라 달라질 수 있으므로(예를 들어 기기 픽셀 밀도에 따라 다른 아이콘 크기 제공) 매니페스트 파일에 하드코딩하지 말고 리소스 또는 테마에서 값을 설정해야 합니다. 그러면 실제 값을 각 기기 구성에 제공하는 대체 리소스에 따라 변경할 수 있습니다.

리소스는 다음과 같은 형식의 값으로 표현됩니다.

"@[package:]type/name"

앱에서 리소스를 제공할 경우 package 이름을 생략할 수 있습니다(라이브러리 리소스가 앱 리소스에 병합되므로 라이브러리 종속성에서 제공할 경우에는 포함합니다). Android 프레임워크의 리소스를 사용하고자 할 때 그 외에 유효한 패키지 이름은 android뿐입니다.

type은 리소스의 유형(예: string 또는 drawable)이고 name은 특정 리소스를 식별하는 이름입니다. 다음은 이에 대한 예입니다.

<activity android:icon="@drawable/smallPic" ... >

프로젝트에 리소스를 추가하는 방법에 대한 자세한 내용은 리소스 제공을 참조하세요.

대신 테마에 정의된 값을 적용하려면 첫 문자는 @가 아니라 ?가 되어야 합니다.

"?[package:]type/name"

문자열 값
특성 값이 문자열인 경우, 문자를 이스케이프 처리하려면 이중 백슬래시(\\)를 사용해야 합니다(예: 줄바꿈의 경우 \\n 또는 유니코드 문자의 경우 \\uxxxx).

매니페스트 요소 참조 문서

다음 표에서는 AndroidManifest.xml 파일에 있는 모든 유효한 요소에 대한 참조 문서의 링크를 제공합니다.

<action> 인텐트 필터에 작업을 추가합니다.
<activity> 액티비티 구성 요소를 선언합니다.
<activity-alias> 액티비티의 별명을 선언합니다.
<application> 애플리케이션을 선언합니다.
<category> 인텐트 필터에 카테고리 이름을 추가합니다.
<compatible-screens> 애플리케이션과 호환되는 각 화면 구성을 지정합니다.
<data> 인텐트 필터에 데이터 사양을 추가합니다.
<grant-uri-permission> 상위 콘텐츠 제공자가 액세스할 권한이 있는 앱 데이터의 하위 집합을 지정합니다.
<instrumentation> 애플리케이션과 시스템의 상호작용을 모니터링할 수 있는 Instrumentation 클래스를 선언합니다.
<intent-filter> 액티비티, 서비스 또는 Broadcast Receiver가 응답할 수 있는 인텐트 유형을 지정합니다.
<manifest> AndroidManifest.xml 파일의 루트 요소입니다.
<meta-data> 상위 구성 요소에 제공할 수 있는 추가적인 임의의 데이터 항목에 대한 이름-값 쌍입니다.
<path-permission> 콘텐츠 제공자 내에서 특정 데이터 하위 집합에 대한 경로와 필수 권한을 정의합니다.
<permission> 이 애플리케이션 또는 다른 애플리케이션의 각 구성 요소나 기능에 대한 액세스를 제한하는 데 사용하는 보안 권한을 선언합니다.
<permission-group> 관련 권한의 논리적 집합에 대한 이름을 선언합니다.
<permission-tree> 권한 트리의 기본 이름을 선언합니다.
<provider> 콘텐츠 제공자 구성 요소를 선언합니다.
<receiver> Broadcast Receiver 구성 요소를 선언합니다.
<service> 서비스 구성 요소를 선언합니다.
<supports-gl-texture> 앱이 지원하는 단일 GL 텍스처 압축을 선언합니다.
<supports-screens> 앱이 지원하는 화면 크기를 선언하고 앱이 지원하는 것보다 큰 화면에 대해서는 화면 호환성 모드를 활성화합니다.
<uses-configuration> 애플리케이션이 요구하는 특정 입력 기능을 나타냅니다.
<uses-feature> 애플리케이션이 사용하는 단일 하드웨어 또는 소프트웨어 기능을 선언합니다.
<uses-library> 애플리케이션과 링크되어야 하는 공유 라이브러리를 지정합니다.
<uses-permission> 앱이 올바르게 작동하기 위해 사용자가 반드시 부여해야 하는 시스템 권한입니다.
<uses-permission-sdk-23> 앱이 특정 권한을 원한다는 것을 지정합니다. 단, 오직 Android 6.0(API 레벨 23) 이상을 실행하는 기기에서 설치되는 경우에만 해당됩니다.
<uses-sdk> 하나 이상의 Android 플랫폼 버전과의 애플리케이션 호환성을 API 레벨 정수로 표시할 수 있습니다.

매니페스트 파일의 예시

아래의 XML은 앱의 두 가지 액티비티를 선언하는 단순 예시 AndroidManifest.xml입니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1"
    android:versionName="1.0"
    package="com.example.myapp">

    <!-- Beware that these values are overridden by the build.gradle file -->
    <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="26" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <!-- This name is resolved to com.example.myapp.MainActivity
             based upon the package attribute -->
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".DisplayMessageActivity"
            android:parentActivityName=".MainActivity" />
    </application>
</manifest>