반응형

안드로이드 프로젝트에는 반드시 포함되어야 하는 파일이 있습니다. 그건 바로 AndroidManifest.xml 파일입니다. Manifest 파일은 프로젝트의 Source Set의 루트(별도의 설정을 하지 않았다면 src/main)에 위치해야 합니다. 

매니페스트 파일은 앱에 대한 필수적인 정보를 안드로이드 빌드 툴과 Android OS, 그리고 구글 플레이에 제공합니다.

 

매니페스트 파일에는 많은 정보를 담을 수 있지만 그중에서도 특히 선언되어야 하는 정보가 있습니다.

  1. 앱의 패키지 이름
  2. 앱에서 사용되는 컴포넌트(액티비티, 서비스, 브로드캐스트 리시버, 컨텐트 프로바이더)
  3. 권한(Permission)
  4. 앱에서 요구하는 하드웨어와 소프트웨어 특징

지금부터 위 4가지에 대해 하나하나 자세히 살펴보도록 하겠습니다.

 

Package name and Application ID

매니페스트 파일의 Root element(<manifest></manifest>) 에는 해당 앱의 패키지 네임이 반드시 기재되어야 합니다.

 

예를 들어 "com.ready.example" 이라는 패키지 네임의 manifest 파일을 생성해보겠습니다.

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

그렇다면 manifest 의 패키지 네임은 언제 어디서 사용될까요?

이는 우리가 앱을 빌드하여 APK 를 추출하는 과정에서 Android Build Tool 에 의해 다음 2가지 목적으로 사용됩니다.

  • App Resource 에 접근하는데 사용되는 R 클래스의 네임스페이스로 적용됩니다.
    위 예에서는 com.ready.example.R 클래스가 생성됩니다.
  • 매니페스트 파일 내에서 선언된 상대경로에 적용됩니다.
    예를 들어 <activity android:name=".MainActivity> 라고 선언했다면 이는 "com.ready.example.MainActivity" 를 가리키게 됩니다.

매니페스트의 package 속성으로 선언된 패키지 경로는 프로젝트의 base package name 과 매칭 되어야 합니다. 만약 프로젝트 내 sub-package 를 갖고 있더라도 R 클래스는 sub-package 의 경로가 아닌 매니페스트 내 package 속성에 따라 생성됩니다.

 

하지만 package 속성이 불변인 것은 아닙니다. 안드로이드 빌드 툴은 APK 를 추출할 때 위와 같은 작업을 처리한 후에 package 속성의 값을 build.gradle 에 선언된 applicationId 로 교체해 버립니다. 이는 구글 플레이 스토어에 등록된 각 앱들을 구분하기 위해 package 값을 유니크하게 해야할 필요가 있기 때문입니다.

 

이 경우에 Manifest 파일에 선언된 package 이름과 build.gradle 에 선언된 applicationId 값이 같다면 문제가 없지만, 다를 경우에는 상황에 따라 충돌이 발생할 수 있습니다.

 

 

App Components

아시겠지만 안드로이드에는 4대 컴포넌트(Activity, Service, Broadcast Receiver, Content Provider)라 불리는 녀석들이 있습니다.

이 컴포넌트들을 앱에서 사용한다면 매니페스트 파일에 등록해줘야 하는데요. Manifest 파일 내에서 각각 다음 태그를 통해 선언할 수 있습니다.

  • <activity> : Activity
  • <service> : Service
  • <receiver> : Broadcast Receiver
  • <provider> : Content Provider

만약 컴포넌트의 서브 클래스를 구현하여 사용하면서 매니페스트 파일에 선언해주지 않는다면, 시스템은 해당 컴포넌트에 대해 실행할 수 없습니다.

 

4대 컴포넌트들은 각각 인텐트에 의해 활성화됩니다. 여기서 인텐트란 메세지 객체로, 어떤 행동을 수행할지에 대한 명령이나 작업에 필요한 데이터를 포함합니다. 안드로이드 개발하면서 인텐트는 굉장히 중요한 역할을 하는 녀석이기 때문에 추후에 따로 다루는 포스트를 작성하도록 하겠습니다.

 

아무튼, 앱이 인텐트를 시스템에 발행하면 시스템은 각 앱의 매니페스트에 선언된 intent-filter 에 기초하여 처리할 수 있는 인텐트를 컴포넌트를 찾게 됩니다. 만약 여러 개의 앱이 인텐트를 다룰 수 있다면, 사용자가 해당 인텐트를 어떤 앱에게 넘길지 선택할 수 있습니다.

 

그리고 매니페스트에 선언된 컴포넌트들과 <application> 은 유저에게 보여줄 수 있는 icon 과 label 속성을 갖고 있습니다. 그리고 xml 로 구성하다보면 트리 구조기 때문에 부모-자식 관계가 생기는데요. 이때 자식 element에 icon 과 label 이 설정되어있지 않다면 부모에 설정된 값이 기본 값으로 설정되게 됩니다. 그렇기 때문에 각 컴포넌트마다 설정하지 않고 앱 전체에 기본 값을 설정하려면 <application> 에 설정하면 됩니다.

 

 

Permissions

매니페스트 하면 빼놓을 수 없는 역할이 권한 설정인데요. 이 권한이라는 것은 안드로이드 진영에서 민감하게 다루고 있는 관심사 중 하나입니다. 안드로이드 앱은 민감한 유저 정보나 카메라나 인터넷 등 특정 시스템 기능을 사용할 때 반드시 권한을 요청해야합니다.

 

예를 들어 SMS 전송에 대한 권한을 요청하기 위해서는 Manifest 파일에 다음과 같이 설정하면 됩니다.

 

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

 

그리고 Android 6.0 버전(API Level 23) 이상에서는 몇몇 권한에 대해서 사용자에게 동적으로 요청하여 승인이나 거절을 받아야 하는데요. 이것과는 별개로 앱에서 필요로 하는 모든 권한에는 Manifest 파일에 <uses-permission> 요소를 설정해줘야 합니다. 

 

권한 관련해서도 다룰 내용이 매우 많지만 오늘의 주제는 매니페스트 파일이기 때문에 권한과 관련된 내용은 별도 포스팅에서 자세히 다루도록 하겠습니다.

 

 

Device Compatibility

Manifest 파일에는 앱이 필요로 하는 하드웨어나 소프트웨어 특징을 명시할 수 있습니다. 예를 들어, 카메라 앱을 만들 경우에 카메라가 필수로 있어야 하니 카메라가 있는 기기에서만 Play Store 에서 해당 앱이 다운로드 될 수 있도록 명시하는 것입니다. 아마 태블릿을 이용하시는 분이라면 플레이 스토어에서 특정 앱을 설치하려 할 때 "다운로드 받을 수 없는 기기입니다." 라고 문구 뜬 걸 볼 수 있었을 겁니다.

 

매니페스트 파일에 <uses-feature> 태그를 사용하면 명시할 수 있습니다. 예를 들어 compass sensor 가 있는 기기에서만 다운로드 가능하게 하기 위해서는 아래와 같이 매니페스트 파일을 작성하면 됩니다.

 

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

 

또 매니페스트 파일에는 <uses-sdk> 태그를 통해 요구되는 sdk 버전을 명시할 수도 있는데요. 하지만, 안드로이드 스튜디오로 프로젝트를 구성한 경우에는 build.gradle 에 선언된 minSdkVersion 이 manifest 의 <uses-sdk> 속성을 재정의하기 때문에 min sdk 설정에 대해서는 매니페스트 파일이 아닌 build.gradle 에 선언하는 것이 좋습니다.

 

 

반응형
반응형