Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

애플리케이션 기본 항목

Android 앱은 Kotlin, Java, C++ 언어를 사용하여 작성할 수 있습니다. Android SDK 도구는 모든 데이터 및 리소스 파일과 함께 코드를 컴파일하여 하나의 APK를 만듭니다. Android 패키지는 접미사가 .apk인 아카이브 파일입니다. 한 개의 APK 파일에는 Android 앱의 모든 콘텐츠가 들어 있으며, Android로 구동하는 기기가 앱을 설치할 때 바로 이 파일을 사용합니다.

각 Android 앱은 자체적인 보안 샌드박스에 속하며, 이는 다음과 같은 Android 보안 기능으로 보호됩니다.

  • Android 운영체제는 멀티유저 Linux 시스템으로, 여기서 각 앱은 각기 다른 사용자와 같습니다.
  • 기본적으로 시스템이 각 앱에 고유한 Linux ID를 할당합니다(이 ID는 시스템만 사용할 수 있으며 앱에서는 인식하지 못함). 시스템은 앱 안의 모든 파일에 대해 권한을 설정하여 해당 앱에 할당된 사용자 ID만 이에 액세스할 수 있도록 합니다.
  • 각 프로세스에는 자체적인 가상 머신(VM)이 있고, 그렇기 때문에 한 앱의 코드가 다른 앱과는 격리된 상태로 실행됩니다.
  • 기본적으로 모든 앱이 앱 자체의 Linux 프로세스에서 실행됩니다. Android 시스템은 앱의 구성 요소 중 어느 하나라도 실행해야 하는 경우 프로세스를 시작하고, 더 이상 필요 없거나 시스템이 다른 앱을 위해 메모리를 복구해야 하는 경우 해당 프로세스를 종료합니다.

Android 시스템은 이런 방식으로 최소 권한의 원리를 구현합니다. 다시 말해, 각 앱은 기본적으로 자신의 작업을 수행하기 위해 필요한 구성 요소에만 액세스 권한을 가지고 그 이상은 허용되지 않습니다. 이렇게 하면 대단히 안전한 환경이 구성되어 앱이 시스템에서 권한을 부여받지 못한 부분에는 액세스할 수 없게 됩니다. 그러나 앱이 다른 앱과 데이터를 공유하고 시스템 서비스에 액세스하는 방법은 여러 가지가 있습니다.

  • 두 개의 앱이 같은 Linux 사용자 ID를 공유하도록 설정할 수도 있습니다. 이 경우 두 앱은 서로 파일에 액세스할 수 있게 됩니다. 시스템 리소스를 절약하기 위해 사용자 ID가 동일한 앱들이 같은 Linux 프로세스에서 실행되고 같은 VM을 공유하도록 설정할 수도 있습니다. 또한 이러한 앱은 같은 인증서로 서명해야 합니다.
  • 앱은 사용자의 연락처, SMS 메시지, 마운트 가능한 저장소(SD 카드), 카메라, 블루투스를 비롯한 여러 가지 기기 데이터에 액세스할 권한을 요청할 수 있습니다. 사용자는 이러한 권한을 명시적으로 부여해야 합니다. 자세한 내용은 시스템 권한 사용을 참조하세요.

이 문서의 나머지에서는 다음과 같은 개념을 소개합니다.

  • 앱을 정의하는 핵심 프레임워크 구성 요소.
  • 구성 요소를 선언하고 앱에 필수적인 기기 특징을 선언할 수 있는 매니페스트 파일.
  • 앱 코드로부터 별도로 분리되어 있으며 앱이 다양한 기기 구성에 맞게 자신의 동작을 안정적으로 최적화할 수 있도록 하는 리소스.

앱 구성 요소

앱 구성 요소는 Android 앱의 필수적인 기본 구성 요소입니다. 각 구성 요소는 시스템이나 사용자가 앱에 들어올 수 있는 진입점입니다. 다른 구성 요소에 종속되는 구성 요소도 있습니다.

앱 구성 요소에는 네 가지 유형이 있습니다.

  • 액티비티
  • 서비스
  • Broadcast Receiver
  • 콘텐츠 제공자

각 유형은 뚜렷한 목적을 수행하고 각자 나름의 수명 주기가 있어 구성 요소의 생성 및 소멸 방식을 정의합니다. 다음 섹션에서는 앱 구성 요소의 네 가지 유형에 대해 설명합니다.

액티비티
액티비티는 사용자와 상호작용하기 위한 진입점입니다. 이것은 사용자 인터페이스를 포함한 화면 하나를 나타냅니다. 예를 들어 이메일 앱이라면 새 이메일 목록을 표시하는 액티비티가 하나 있고, 이메일을 작성하는 액티비티가 또 하나, 그리고 이메일을 읽는 데 쓰는 액티비티가 또 하나 있을 수 있습니다. 여러 액티비티가 함께 작동하여 해당 이메일 앱에서 짜임새 있는 사용자 환경을 구성하는 것은 사실이지만, 각자 서로 독립되어 있습니다. 따라서 이메일 앱에서 허용할 경우 다른 앱이 이런 액티비티 중 하나를 시작할 수 있습니다. 예를 들어 카메라 앱이라면 이메일 앱 안의 액티비티를 시작하여 사용자가 새 이메일을 작성하고 사진을 공유하게 할 수 있습니다. 액티비티는 다음과 같이 시스템과 앱의 주요 상호작용을 돕습니다.
  • 사용자가 현재 관심을 가지고 있는 사항(화면에 표시된 것)을 추적하여 액티비티를 호스팅하는 프로세스를 시스템에서 계속 실행하도록 합니다.
  • 이전에 사용한 프로세스에 사용자가 다시 찾을 만한 액티비티(중단된 액티비티)가 있다는 것을 알고, 해당 프로세스를 유지하는 데 더 높은 우선순위를 부여합니다.
  • 앱이 프로세스를 종료하도록 도와서 이전 상태가 복원되는 동시에 사용자가 액티비티로 돌아갈 수 있게 합니다.
  • 앱이 서로 사용자 플로우를 구현하고 시스템이 이러한 플로우를 조정하기 위한 수단을 제공합니다. (여기에서는 가장 기본적인 예시를 제시합니다.)

액티비티 하나를 Activity 클래스의 하위 클래스로 구현합니다. Activity 클래스에 대한 자세한 내용은 액티비티 개발자 가이드를 참조하세요.

서비스
서비스는 여러 가지 이유로 백그라운드에서 앱을 계속 실행하기 위한 다목적 진입점입니다. 이는 백그라운드에서 실행되는 구성 요소로, 오랫동안 실행되는 작업을 수행하거나 원격 프로세스를 위한 작업을 수행합니다. 서비스는 사용자 인터페이스를 제공하지 않습니다. 예를 들어 서비스는 사용자가 다른 앱에 있는 동안에 백그라운드에서 음악을 재생하거나, 사용자와 액티비티 간의 상호작용을 차단하지 않고 네트워크를 통해 데이터를 가져올 수도 있습니다. 다른 구성 요소(예: 액티비티)가 서비스를 시작한 다음 실행되도록 두거나 자신에게 바인딩하여 상호작용하게 할 수도 있습니다. 사실 시스템에 앱 관리 방법을 지시하는 것은 서로 매우 뚜렷하게 구분되는 두 가지 의미 체계 서비스입니다. 시작된 서비스는 작업이 완료될 때까지 해당 서비스를 계속 실행하라고 시스템에 지시합니다. 백그라운드에서 일부 데이터를 동기화하거나 사용자가 앱에서 나간 후에도 음악을 재생하는 등의 서비스를 예로 들 수 있습니다. 백그라운드에서 데이터를 동기화하거나 음악을 재생하는 것은 각각 두 가지 유형의 시작된 서비스를 나타내는데, 이는 시스템이 서비스를 처리하는 방식을 변경합니다.
  • 음악 재생은 사용자가 바로 인식할 수 있는 작업입니다. 따라서 앱은 사용자에게 이와 관련된 알림을 보내고 음악 재생을 포그라운드로 옮기라고 시스템에 지시합니다. 이 경우, 시스템은 이 서비스의 프로세스가 계속 실행되도록 많은 노력을 기울여야 합니다. 이 서비스가 사라지면 사용자가 불만을 느낄 것이기 때문입니다.
  • 정기적인 백그라운드 서비스는 사용자가 실행되고 있다고 직접 인식할 수 없는 작업이므로 시스템은 좀 더 자유롭게 프로세스를 관리할 수 있습니다. 사용자와 좀 더 직접적인 관련이 있는 작업에 RAM이 필요할 경우 이 서비스를 종료할 수도 있습니다(그런 다음, 나중에 서비스를 다시 시작할 수도 있습니다).
바인딩된 서비스는 다른 앱(또는 서비스)에서 서비스를 사용하고 싶다는 의향을 표현했기 때문에 실행됩니다. 이는 기본적으로 서비스가 다른 프로세스에 API를 제공하는 것입니다. 따라서 시스템은 프로세스 사이에 종속성이 있는지 알게 됩니다. 프로세스 A가 프로세스 B의 서비스에 바인딩되어 있을 경우, 시스템은 프로세스 A를 위해 프로세스 B(및 그 서비스)를 실행해야 한다는 것을 인식하게 됩니다. 또한, 사용자가 프로세스 A에 관심을 기울이고 있다면 시스템에서 프로세스 B도 사용자가 관심을 기울이는 것처럼 취급해야 합니다. 서비스는 (좋은 의미로든 나쁜 의미로든) 유연하기 때문에 각종 고차원적 시스템 개념의 매우 유용한 기본 구성 요소로 사용되었습니다. 라이브 배경화면, 알림 리스너, 화면 보호기, 입력 메서드, 접근성 서비스 및 여러 가지 기타 핵심 서비스 기능이 모두 애플리케이션에서 구현하고 시스템에서 애플리케이션을 실행할 때 바인딩하는 서비스로 빌드됩니다.

서비스는 Service 하위 클래스로 구현됩니다. Service 클래스에 대한 자세한 내용은 서비스 개발자 가이드를 참조하세요.

참고: Android 5.0(API 레벨 21) 이상을 대상으로 하는 앱의 경우 JobScheduler 클래스를 사용하여 작업을 예약하세요. JobScheduler에는 작업 일정을 최적으로 조정하여 전력 소모량을 줄이고 Doze API와 함께 작동하여 배터리를 절약해준다는 장점이 있습니다. 이 클래스 사용에 대한 자세한 내용은 JobScheduler 참조 문서를 참조하세요.

Broadcast Receiver
Broadcast Receiver는 시스템이 정기적인 사용자 플로우 밖에서 이벤트를 앱에 전달하도록 지원하는 구성 요소로, 앱이 시스템 전체의 브로드캐스트 알림에 응답할 수 있게 합니다. Broadcast Receiver도 앱으로 들어갈 수 있는 또 다른 명확한 진입점이기 때문에 현재 실행되지 않은 앱에도 시스템이 브로드캐스트를 전달할 수 있습니다. 예를 들어 앱이 사용자에게 예정된 이벤트에 대해 알리는 알림을 게시하기 위한 알람을 예약할 경우, 그 알람을 앱의 Broadcast Receiver에 전달하면 알람이 울릴 때까지 앱을 실행하고 있을 필요가 없습니다. 대다수의 브로드캐스트는 시스템에서 발생합니다. 예컨대 화면이 꺼졌거나 배터리가 부족하거나 사진을 캡처했다고 알리는 브로드캐스트가 대표적입니다. 앱도 브로드캐스트를 시작할 수 있습니다. 예를 들어 다른 앱에 일부 데이터가 기기에 다운로드되었고 이를 사용할 수 있다는 것을 알리는 데 사용합니다. Broadcast Receiver는 사용자 인터페이스를 표시하지 않지만, 상태 표시줄 알림을 생성하여 사용자에게 브로드캐스트 이벤트가 발생했다고 알릴 수 있습니다. 다만 Broadcast Receiver는 그저 다른 구성 요소로의 게이트웨이인 경우가 더 보편적이고, 극소량의 작업만 수행하도록 만들어진 경우가 많습니다. 예컨대 JobService를 예약하여 시작하여 JobScheduler가 포함된 이벤트를 기초로 어떤 작업을 수행하게 할 수 있습니다.

Broadcast Receiver는 BroadcastReceiver의 하위 클래스로 구현되며 각 브로드캐스트는 Intent 객체로 전달됩니다. 자세한 내용은 BroadcastReceiver 클래스를 참조하세요.

콘텐츠 제공자
콘텐츠 제공자는 파일 시스템, SQLite 데이터베이스, 웹상이나 앱이 액세스할 수 있는 다른 모든 영구 저장 위치에 저장 가능한 앱 데이터의 공유형 집합을 관리합니다. 다른 앱은 콘텐츠 제공자를 통해 해당 데이터를 쿼리하거나, 콘텐츠 제공자가 허용할 경우에는 수정도 가능합니다. 예를 들어 Android 시스템은 사용자의 연락처 정보를 관리하는 콘텐츠 제공자를 제공합니다. 적절한 권한을 가진 앱이라면 콘텐츠 제공자(예: ContactsContract.Data)를 쿼리하여 특정한 인물에 대한 정보를 읽고 쓸 수 있습니다. 콘텐츠 제공자를 데이터베이스에 대한 추상화로 생각하기 쉽습니다. 이런 일반적인 사례에 대해 콘텐츠 제공자에 빌드된 API 및 지원이 많기 때문입니다. 다만 시스템 설계 관점에서 볼 때 핵심 목적이 서로 다릅니다. 시스템의 경우 콘텐츠 제공자는 URI 구성표로 식별되고 이름이 지정된 데이터 항목을 게시할 목적으로 앱에 진입하기 위한 입구입니다. 따라서 앱에서 URI 네임스페이스에 넣을 데이터를 매핑할 방식을 결정하고, 해당 URI를 다른 엔터티에 전달할 수 있습니다. 이를 전달받은 엔터티는 URI를 사용하여 데이터에 액세스합니다. 시스템이 이렇게 할 수 있는 데에는 앱 관리에 몇 가지 특별한 점이 있기 때문입니다.
  • URI를 할당하더라도 앱을 계속 실행할 필요가 없으므로 URI를 소유한 앱이 종료된 후에도 URI를 유지할 수 있습니다. 시스템은 URI를 소유한 앱이 해당 URI에서 앱의 데이터를 검색할 때만 실행되도록 하면 됩니다.
  • 이 URI는 중요하고 조밀한 보안 모델을 제공합니다. 예를 들어 앱은 클립보드에 있는 이미지에 URI를 할당하고 콘텐츠 제공자가 검색하도록 하여, 다른 앱이 자유롭게 이미지에 액세스하지 못하게 막을 수 있습니다. 두 번째 앱이 클립보드에서 해당 URI에 액세스하려고 시도하면 시스템에서는 임시 URI 권한을 부여하여 그 앱이 데이터에 액세스하도록 허용할 수 있습니다. 따라서 두 번째 앱에서는 URI 뒤에 있는 데이터 외에 다른 것에는 액세스할 수 없습니다.

콘텐츠 제공자는 앱 전용이어서 공유되지 않는 데이터를 읽고 쓰는 데도 유용합니다.

콘텐츠 제공자는 ContentProvider의 하위 클래스로 구현되며, 다른 앱이 트랜잭션을 수행할 수 있도록 활성화하는 표준적인 API 집합을 구현해야 합니다. 자세한 내용은 콘텐츠 제공자 개발자 가이드를 참조하세요.

Android 시스템 디자인은 어떤 앱이든 다른 앱의 구성 요소를 시작할 수 있다는 점에서 독특한 측면이 있습니다. 예를 들어 사용자가 기기 카메라로 사진을 캡처하기를 바라는 경우, 그런 작업을 수행하는 다른 앱이 있을 가능성이 높습니다. 그러면 사진을 캡처하는 액티비티를 직접 개발하는 대신 여러분의 앱에서 그 앱을 사용하면 됩니다. 카메라 앱의 코드를 포함하거나 링크할 필요도 없습니다. 대신 사진을 캡처하는 카메라 앱에서 액티비티를 시작하기만 하면 됩니다. 작업이 완료되면 사진이 앱으로 반환되기까지 하여 바로 사용할 수 있습니다. 사용자에게는 마치 카메라가 앱의 일부분인 것처럼 보입니다.

시스템이 구성 요소를 시작할 때 그 앱에 대한 프로세스를 시작하고(이미 실행 중이지 않은 경우), 해당 구성 요소에 필요한 클래스를 인스턴스화합니다. 예를 들어 여러분의 앱이 카메라 앱 내에서 사진을 캡처하는 액티비티를 시작하면, 해당 액티비티는 여러분 앱의 프로세스가 아니라 카메라 앱에 속한 프로세스에서 실행됩니다. 그러므로 대부분의 다른 시스템에서 실행되는 앱과 달리 Android 앱은 단일한 진입 지점이 없습니다(예를 들어 main() 함수가 없음).

시스템이 다른 앱에 대한 액세스를 제한하는 파일 권한을 가지고 각 앱을 별도의 프로세스에서 실행하기 때문에, 여러분의 앱은 다른 앱에서 직접 구성 요소를 활성화할 수 없습니다. 다만 Android 시스템으로는 이것이 가능합니다. 다른 앱에 있는 구성 요소를 활성화하려면 시스템에 메시지를 전달하여 특정 구성 요소를 시작하고자 하는 인텐트를 밝혀야 합니다. 그러면 시스템이 대신 해당 구성 요소를 활성화해줍니다.

구성 요소 활성화

구성 요소 유형 네 가지 중 세 가지(액티비티, 서비스, Broadcast Receiver)는 인텐트라는 비동기식 메시지로 활성화됩니다. 인텐트는 런타임에서 각 구성 요소를 서로 바인딩합니다. 이것은 일종의 메신저라고 생각하면 됩니다. 즉 구성 요소가 어느 앱에 속하든 관계없이 다른 구성 요소로부터 작업을 요청하는 역할을 합니다.

인텐트는 Intent 객체로 생성되며, 이것이 특정 구성 요소(명시적 인텐트)를 활성화할지 아니면 구성 요소의 특정 유형(암시적 인텐트)을 활성화할지 나타내는 메시지를 정의합니다.

액티비티와 서비스의 경우, 인텐트는 수행할 작업을 정의하며(예: 무언가를 보거나 보내는 작업), 시작되는 구성 요소가 알아야 할 것이 많이 있기는 하지만 그중에서도 작업을 수행할 데이터의 URI를 지정할 수 있습니다. 예를 들어 인텐트는 액티비티에 이미지를 표시하거나 웹 페이지를 열라는 요청을 전달할 수 있습니다. 경우에 따라 결과를 수신하기 위해 액티비티를 시작할 수 있습니다. 이 경우, 액티비티도 Intent에서 결과를 반환합니다. 예를 들어 인텐트를 발행하여 사용자가 개인 연락처를 선택하게 하고 이를 반환할 수 있습니다. 반환 인텐트에는 선택된 연락처를 가리키는 URI가 포함됩니다.

Broadcast Receiver의 경우, 인텐트는 단순히 브로드캐스트될 알림을 정의합니다. 예를 들어 기기 배터리 잔량이 낮다는 것을 나타내는 브로드캐스트에는 배터리 부족을 나타내는 알려진 작업 문자열만 포함됩니다.

액티비티, 서비스, Broadcast Receiver와 달리 콘텐츠 제공자는 인텐트로 활성화되지 않습니다. ContentResolver가 보낸 요청의 대상으로 지정되면 활성화됩니다. 콘텐츠 확인자는 콘텐츠 제공자와의 모든 직접적인 트랜잭션을 처리하여 제공자와의 트랜잭션을 수행하는 구성 요소가 그런 처리를 하지 않는 대신 ContentResolver 객체에서 메서드를 호출하게 합니다. 이렇게 되면 콘텐츠 제공자와 정보를 요청하는 구성 요소 사이에 추상화 계층이 하나 남습니다(보안 목적).

각 유형의 구성 요소를 활성화하는 데는 각기 별도의 메서드가 있습니다.

인텐트 사용에 관한 자세한 내용은 인텐트 및 인텐트 필터 문서를 참조하세요. 다음의 문서는 특정 구성 요소, 즉 액티비티, 서비스, BroadcastReceiver콘텐츠 제공자를 활성화하는 방법에 대한 자세한 정보를 제공합니다.

매니페스트 파일

Android 시스템이 앱 구성 요소를 시작하려면 시스템은 우선 앱의 매니페스트 파일, AndroidManifest.xml을 읽어서 해당 구성 요소가 존재하는지 확인합니다. 앱은 이 파일 안에 모든 구성 요소를 선언해야 하며, 이 파일은 앱 프로젝트 디렉토리의 루트에 있어야 합니다.

매니페스트는 앱의 구성 요소를 선언하는 것 이외에도 많은 역할을 합니다. 예를 들면 다음과 같습니다.

  • 앱이 요구하는 모든 사용자 권한(예: 인터넷 액세스, 사용자의 연락처에 대한 읽기 액세스)을 식별합니다.
  • 앱이 어느 API를 사용하는지를 근거로 앱에서 요구하는 최소 API 레벨을 선언합니다.
  • 앱에서 사용하거나 요구하는 하드웨어 및 소프트웨어 기능(예: 카메라, 블루투스 서비스, 멀티터치 화면)을 선언합니다.
  • 앱이 링크되어야 하는 API 라이브러리(Android 프레임워크 API 제외)(예: Google Maps라이브러리)를 선언합니다.

구성 요소 선언

매니페스트의 주요 작업은 시스템에 앱의 구성 요소에 대해 알리는 것입니다. 예를 들어 매니페스트 파일은 액티비티를 다음과 같이 선언할 수 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:icon="@drawable/app_icon.png" ... >
        <activity android:name="com.example.project.ExampleActivity"
                  android:label="@string/example_label" ... >
        </activity>
        ...
    </application>
</manifest>

<application> 요소에서 android:icon 특성은 앱을 식별하는 아이콘에 대한 리소스를 가리킵니다.

<activity> 요소에서는 android:name 특성이 Activity 하위 클래스의 완전히 정규화된 클래스 이름을 나타내며 android:label 특성은 액티비티의 사용자에게 표시되는 레이블로 사용할 문자열을 나타냅니다.

다음 요소를 사용하여 모든 앱 구성 요소를 선언해야 합니다.

소스에는 포함시키지만 매니페스트에서는 선언하지 않는 액티비티, 서비스, 콘텐츠 제공자는 시스템에 표시되지 않으며, 따라서 실행될 수 없습니다. 그러나 Broadcast Receiver는 매니페스트에서 선언해도 되고 코드를 사용해 (BroadcastReceiver 객체로) 동적으로 생성한 다음 시스템에 등록해도 됩니다. 이때 registerReceiver()를 호출하는 방법을 사용합니다.

앱에 맞는 매니페스트 파일을 구성하는 방법에 대한 자세한 내용은 AndroidManifest.xml 파일을 참조하세요.

구성 요소 기능 선언

위에서 설명한 바와 같이, 활성화 상태의 구성 요소에서는 Intent를 사용하여 액티비티, 서비스 및 Broadcast Receiver를 시작할 수 있습니다. 그렇게 하려면 Intent를 사용하여 대상 구성 요소를 인텐트 내에서 명시적으로 명명하면 됩니다(구성 요소 클래스 이름을 사용). 또한 암시적 인텐트를 사용할 수도 있습니다. 암시적 인텐트는 수행할 작업의 유형을 설명하고, 원한다면 작업을 수행할 대상인 데이터를 설명할 수도 있습니다. 암시적 인텐트를 사용하면 시스템이 작업을 수행할 수 있는 기기에서 구성 요소를 찾아서 작업을 시작할 수 있습니다. 인텐트가 설명한 작업을 수행할 수 있는 구성 요소가 여러 개인 경우, 어느 것을 사용할지는 사용자가 선택합니다.

주의: 인텐트를 사용하여 Service에 바인딩할 경우에는 명시적 인텐트를 사용하여 앱을 보호하세요. 암시적 인텐트를 사용하여 서비스를 시작하면 보안 위험을 초래합니다. 인텐트에 어느 서비스가 응답할 것인지 확신할 수 없고, 사용자는 어느 서비스가 시작되는지 볼 수 없기 때문입니다. Android 5.0(API 레벨 21)부터 시스템은 개발자가 암시적 인텐트로 bindService()를 호출하면 예외를 발생시킵니다. 서비스에 대해 인텐트 필터를 선언하지 마세요.

시스템은 기기에 설치된 다른 앱의 매니페스트 파일에 제공된 인텐트 필터와 수신된 인텐트를 비교하는 방법으로 인텐트에 응답할 수 있는 구성 요소를 식별합니다.

앱의 매니페스트에서 액티비티를 선언하는 경우, 선택적으로 해당 액티비티의 기능을 선언하는 인텐트 필터를 포함시켜서 다른 앱으로부터의 인텐트에 응답하게 할 수 있습니다. <intent-filter> 요소를 해당 구성 요소의 선언 요소에 대한 하위 요소로 추가하면 구성 요소에 대한 인텐트 필터를 선언할 수 있습니다.

예를 들어 새 이메일을 작성하는 액티비티가 포함된 이메일 앱을 빌드한다고 가정해보겠습니다. 이때 (새 이메일을 전송하기 위해) "send" 인텐트에 응답하는 인텐트 필터를 선언하려면 다음과 같이 하면 됩니다.

<manifest ... >
    ...
    <application ... >
        <activity android:name="com.example.project.ComposeEmailActivity">
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <data android:type="*/*" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

다른 앱이 ACTION_SEND 작업이 포함된 인텐트를 생성하고 이를 startActivity()로 전달하면 사용자가 이메일 초안을 작성하고 이를 전송할 수 있는 액티비티를 시작할 수 있습니다.

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

앱 요구사항 선언

Android로 구동되는 기기는 수없이 많지만 모두 특징이 같고, 똑같은 기능을 제공하는 것은 아닙니다. 앱에 필요한 기능이 없는 기기에 앱을 설치하는 불상사를 방지하려면, 앱이 지원하는 기기 유형에 대한 프로필을 명확하게 정의하는 것이 중요합니다. 그러려면 매니페스트 파일에 기기와 소프트웨어 요구사항을 선언하면 됩니다. 이와 같은 선언은 대부분 정보성일 뿐이며 시스템은 이를 읽지 않는 것이 일반적이지만, Google Play와 같은 외부 서비스는 사용자가 본인의 기기에서 앱을 검색할 때 필터링을 제공하기 위해 이와 같은 선언도 읽습니다.

예를 들어 앱에 카메라가 필요하고 Android 2.1(API 레벨 7)에 도입된 API를 사용하는 경우, 이와 같은 내용을 매니페스트 파일에 요구사항으로 선언하려면 다음과 같이 합니다.

<manifest ... >
    <uses-feature android:name="android.hardware.camera.any"
                  android:required="true" />
    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
    ...
</manifest>

예시에서 보여준 선언을 한 다음에는, 카메라가 없고 Android 버전이 2.1 이하인 기기는 Google Play에서 앱을 설치할 수 없습니다. 그러나 앱이 카메라를 사용하기는 하지만 필수는 아니라고 선언할 수도 있습니다. 이 경우에는 앱이 required 특성을 false에 설정하고 런타임에 확인하여 해당 기기에 카메라가 있는지, 경우에 따라서는 모든 카메라 기능을 비활성화할 수 있는지 알아봅니다.

여러 가지 기기와 앱의 호환성을 관리하는 방법에 대한 자세한 내용은 기기 호환성 문서를 참조하세요.

앱 리소스

Android 앱은 코드만으로 이루어지지 않습니다. 소스 코드와 별도로 이미지, 오디오 파일, 그리고 앱의 시각적 표현과 관련된 것 등의 여러 리소스가 필요합니다. 예를 들어 액티비티 사용자 인터페이스의 애니메이션, 메뉴, 스타일, 색상, 레이아웃을 XML 파일로 정의해야 합니다. 앱 리소스를 사용하면 코드를 수정하지 않고 앱의 다양한 특성을 쉽게 업데이트할 수 있습니다. 일련의 대체 리소스를 제공함으로써 다양한 기기 구성에 맞게 앱을 최적화할 수도 있습니다(예: 여러 가지 언어 및 화면 크기).

Android 프로젝트에 포함하는 리소스마다 SDK 빌드 도구가 고유한 정수 ID를 정의하므로, 이를 사용하여 앱 코드에서의 리소스나 XML로 정의된 다른 리소스에서 참조할 수 있습니다. 예를 들어 앱에 logo.png라는 이름의 이미지 파일이 들어 있다면(res/drawable/ 디렉토리에 저장), SDK 도구가 R.drawable.logo라는 리소스 ID를 생성합니다. 이것을 사용하여 이미지를 참조하고 사용자 인터페이스에 삽입할 수 있습니다. 이 ID는 각 앱의 정수로 매핑되며, 이것을 사용하여 이미지를 참조할 수도 있고 이것을 사용자 인터페이스에 삽입할 수도 있습니다.

소스 코드와는 별개로 리소스를 제공하는 것의 가장 중요한 측면 중 하나는 여러 가지 기기 구성에 맞게 대체 리소스를 제공할 능력을 갖추게 된다는 점입니다. 예를 들어 UI 문자열을 XML로 정의하면 이러한 문자열을 다른 언어로 번역한 뒤 해당 문자열을 별개의 파일에 저장할 수 있습니다. 그러면 Android가 리소스 디렉토리 이름에 추가하는 언어 한정자(예를 들어 프랑스어 문자열 값의 경우 res/values-fr/) 및 사용자의 언어 설정을 기반으로 적절한 언어 문자열을 UI에 적용합니다.

Android는 대체 리소스에 대해 다양한 한정자를 지원합니다. 한정자란 리소스 디렉토리의 이름에 포함하는 짧은 문자열로, 이를 사용해 해당 리소스를 사용할 기기 구성을 정의합니다. 예를 들어 기기의 화면 방향과 크기에 따라 액티비티에 여러 가지 레이아웃을 생성해야 할 때가 많습니다. 기기 화면이 세로 방향(세로로 긺)인 경우 버튼이 세로 방향으로 되어 있는 레이아웃을 사용하는 것이 좋지만, 화면이 가로 방향(가로로 넓음)인 경우 버튼이 가로 방향으로 정렬되어야 합니다. 방향에 따라 레이아웃을 변경하려면 서로 다른 두 가지 레이아웃을 정의하여 적절한 한정자를 각 레이아웃의 디렉토리 이름에 적용하면 됩니다. 그러면 시스템이 현재 기기 방향에 따라 적절한 레이아웃을 자동으로 적용합니다.

애플리케이션에 포함할 수 있는 여러 가지 종류의 리소스와 각기 다른 기기 구성에 따라 대체 리소스를 생성하는 방법에 대한 자세한 내용은 리소스 제공을 참조하세요. 모범 사례와 안정적인 프로덕션 품질의 앱을 설계하는 방법에 대한 자세한 내용은 앱 아키텍처 가이드를 참조하세요.

추가 리소스

동영상 및 코드 튜토리얼로 학습하고 있다면 Udacity 과정 Developing Android Apps with Kotlin을 확인하거나 온라인 가이드의 다른 페이지를 참조하세요.

계속 읽기:

인텐트 및 인텐트 필터
Intent API를 사용하여 앱 구성 요소(예: 액티비티, 서비스)를 활성화하는 방법, 앱 구성 요소를 다른 앱이 사용할 수 있도록 하는 방법 등에 대한 정보입니다.
액티비티
Activity 클래스의 인스턴스를 생성하는 방법에 관한 정보로, 애플리케이션에 사용자 인터페이스가 있는 독특한 화면을 제공합니다.
리소스 제공
Android 앱이 앱 코드와는 별개의 앱 리소스에 대해 구조화된 방식에 관한 정보로, 특정 기기 구성에 맞게 대체 리소스를 제공하는 방법도 포함되어 있습니다.

혹시 다음과 같은 내용에도 흥미가 있으신가요?

기기 호환성
여러 가지 유형의 기기에서 Android의 작동 방식과 앱을 각 기기에 맞춰 최적화하는 방법, 또는 여러 가지 기기에 대해 앱의 가용성을 제한하는 방법 등에 관한 정보입니다.
시스템 권한
Android가 특정 API에 대한 앱의 액세스를 제한하기 위해 권한 시스템을 사용하는 방법으로, 해당 API를 사용하려면 앱에 대해 사용자의 승인이 필요합니다.