인텐트 및 인텐트 필터

Intent는 다른 앱 구성요소에서 작업을 요청하는 데 사용할 수 있는 메시지 객체입니다. 인텐트는 여러 가지 방법으로 구성요소 간의 통신을 촉진하지만 다음과 같은 세 가지 기본적인 사용 사례가 있습니다.

  • 활동 시작

    Activity는 앱의 단일 화면을 나타냅니다. IntentstartActivity()에 전달하여 Activity의 새 인스턴스를 시작할 수 있습니다. Intent는 시작할 활동을 설명하고 필요한 데이터를 전달합니다.

    활동이 완료될 때 결과를 수신하려면 startActivityForResult()를 호출합니다. 활동은 활동의 onActivityResult() 콜백에서 별도의 Intent 객체로 결과를 수신합니다. 자세한 내용은 활동 가이드를 참조하세요.

  • 서비스 시작

    Service는 사용자 인터페이스 없이 백그라운드에서 작업을 실행하는 구성요소입니다. Android 5.0 (API 수준 21) 이상에서는 JobScheduler를 사용하여 서비스를 시작할 수 있습니다. JobScheduler에 관한 자세한 내용은 API-reference documentation를 참고하세요.

    Android 5.0 (API 수준 21) 이전 버전에서는 Service 클래스의 메서드를 사용하여 서비스를 시작할 수 있습니다. IntentstartService()에 전달하면 서비스를 시작하여 일회성 작업(예: 파일 다운로드)을 실행할 수 있습니다. Intent는 시작할 서비스를 설명하고 필요한 데이터를 전달합니다.

    서비스가 클라이언트-서버 인터페이스로 설계된 경우 IntentbindService()에 전달하여 다른 구성요소에서 서비스에 결합할 수 있습니다. 자세한 내용은 서비스 가이드를 참고하세요.

  • 브로드캐스트 전송

    브로드캐스트는 모든 앱이 수신할 수 있는 메시지입니다. 시스템은 시스템이 부팅되거나 기기가 충전을 시작할 때와 같은 시스템 이벤트에 다양한 브로드캐스트를 전송합니다. IntentsendBroadcast() 또는 sendOrderedBroadcast()에 전달하여 다른 앱에 브로드캐스트를 전달할 수 있습니다.

이 페이지의 나머지에서는 인텐트의 작동 원리와 사용 방법을 설명합니다. 관련 정보는 다른 앱과의 상호작용콘텐츠 공유를 참고하세요.

인텐트 유형

인텐트에는 두 가지 유형이 있습니다.

  • 명시적 인텐트는 전체 ComponentName를 지정하여 어느 애플리케이션이 인텐트를 충족할지 지정합니다. 시작하려는 활동 또는 서비스의 클래스 이름을 알고 있으므로 일반적으로 명시적 인텐트를 사용하여 자체 앱에서 구성요소를 시작합니다. 예를 들어 사용자 작업에 응답하여 앱 내에서 새 활동을 시작하거나 백그라운드에서 파일을 다운로드하는 서비스를 시작할 수 있습니다.
  • 암시적 인텐트는 특정 구성요소의 이름을 지정하지 않고 대신 실행할 일반 작업을 선언합니다. 그러면 다른 앱의 구성요소가 이를 처리할 수 있습니다. 예를 들어 사용자에게 지도상의 위치를 표시하고자 하는 경우, 암시적 인텐트를 사용하여 기능을 갖춘 다른 앱이 지도에 지정된 위치를 표시하도록 요청할 수 있습니다.

그림 1은 액티비티를 시작할 때 인텐트를 사용하는 법을 나타낸 것입니다. Intent 객체가 특정 활동 구성요소의 이름을 명시적으로 지정하면 시스템은 즉시 그 구성요소를 시작합니다.

그림 1. 시스템을 통해 암시적 인텐트가 전달되어 다른 활동을 시작하는 방법: [1] 활동 A는 작업 설명이 있는 Intent를 만들어 startActivity()에 전달합니다. [2] Android 시스템이 모든 앱에서 인텐트와 일치하는 인텐트 필터를 검색합니다. 일치 항목이 발견되면 [3] 시스템은 onCreate() 메서드를 호출하고 Intent에 전달하여 일치하는 활동 (활동 B)을 시작합니다.

암시적 인텐트를 사용하면 Android 시스템은 인텐트의 콘텐츠를 기기에 있는 다른 앱의 매니페스트 파일에 선언된 인텐트 필터와 비교하여 시작할 적절한 구성요소를 찾습니다. 인텐트가 인텐트 필터와 일치하면 시스템은 구성요소를 시작하고 구성요소에 Intent 객체를 전달합니다. 호환되는 인텐트 필터가 여러 개인 경우 시스템은 사용자가 사용할 앱을 선택할 수 있도록 대화상자를 표시합니다.

인텐트 필터는 앱의 매니페스트 파일에 있는 표현식으로, 구성요소가 수신하려는 인텐트의 유형을 지정합니다. 예를 들어 활동의 인텐트 필터를 선언하면 다른 앱이 특정 종류의 인텐트로 활동을 직접 시작할 수 있습니다. 마찬가지로 활동의 인텐트 필터를 선언하지 않으면 명시적 인텐트로만 활동을 시작할 수 있습니다.

주의: 앱을 안전하게 유지하려면 Service를 시작할 때 항상 명시적 인텐트를 사용하고 서비스의 인텐트 필터를 선언하지 마세요. 암시적 인텐트를 사용하여 서비스를 시작하면 어떤 서비스가 인텐트에 응답할지 확신할 수 없고 어떤 서비스가 시작하는지 사용자가 알 수 없으므로 보안 위험이 있습니다. Android 5.0 (API 수준 21)부터는 암시적 인텐트로 bindService()를 호출하면 시스템에서 예외가 발생합니다.

인텐트 빌드

Intent 객체는 Android 시스템에서 시작할 구성요소를 결정하는 데 사용하는 정보 (예: 인텐트를 수신해야 하는 정확한 구성요소 이름 또는 구성요소 카테고리)와 수신자 구성요소가 작업을 제대로 실행하기 위해 사용하는 정보 (예: 실행할 작업 및 작업할 데이터)를 전달합니다.

Intent에 포함된 기본 정보는 다음과 같습니다.

구성요소 이름
시작할 구성요소의 이름입니다.

이는 선택사항이지만 인텐트를 명시적으로 만드는 중요한 정보입니다. 즉, 인텐트는 구성요소 이름으로 정의된 앱 구성요소에만 전송되어야 합니다. 구성요소 이름이 없으면 인텐트는 암시적이며 시스템은 다른 인텐트 정보(예: 작업, 데이터, 카테고리(아래 설명 참고))에 기반하여 인텐트를 수신할 구성요소를 결정합니다. 앱에서 특정 구성요소를 시작해야 하는 경우 구성요소 이름을 지정해야 합니다.

참고: Service를 시작할 때는 항상 구성요소 이름을 지정해야 합니다. 그렇지 않으면 어떤 서비스가 인텐트에 응답할지 확신할 수 없고 사용자가 어떤 서비스가 시작되는지 볼 수 없습니다.

Intent의 이 필드는 ComponentName 객체로, 앱의 패키지 이름(예: com.example.ExampleActivity)을 포함하여 타겟 구성요소의 정규화된 클래스 이름을 사용하여 지정할 수 있습니다. 구성요소 이름은 setComponent(), setClass(), setClassName() 또는 Intent 생성자를 사용하여 설정할 수 있습니다.

조치
실행할 일반적인 작업 (예: 보기 또는 선택)을 지정하는 문자열입니다.

브로드캐스트 인텐트의 경우, 이것은 이미 실행되어 보고되고 있는 작업입니다. 작업은 대체로 나머지 인텐트의 구조, 특히 데이터 및 추가 항목에 포함된 정보를 결정합니다.

앱 내의 인텐트에서 사용할 작업 (또는 다른 앱이 앱의 구성요소를 호출하는 데 사용할 작업)을 직접 지정할 수 있지만 일반적으로 Intent 클래스나 다른 프레임워크 클래스에서 정의한 작업 상수를 지정합니다. 다음은 활동을 시작하는 일반적인 작업입니다.

ACTION_VIEW
활동에서 사용자에게 표시할 수 있는 몇 가지 정보(예: 갤러리 앱에서 볼 사진 또는 지도 앱에서 볼 주소)가 있는 경우 startActivity()가 있는 인텐트에서 이 작업을 사용합니다.
ACTION_SEND
공유 인텐트라고도 하며 사용자가 다른 앱(예: 이메일 앱 또는 소셜 공유 앱)을 통해 공유할 수 있는 데이터가 있는 경우 startActivity()가 있는 인텐트에서 이 인텐트를 사용해야 합니다.

일반 작업을 정의하는 상수에 관한 자세한 내용은 Intent 클래스 참조를 참고하세요. 다른 작업은 Android 프레임워크의 다른 위치에서 정의됩니다(예: 시스템의 설정 앱에서 특정 화면을 여는 작업의 경우 Settings).

setAction() 또는 Intent 생성자를 사용하여 인텐트의 작업을 지정할 수 있습니다.

직접 작업을 정의하는 경우 다음 예와 같이 앱의 패키지 이름을 접두사로 포함해야 합니다.

Kotlin

const val ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL"

Java

static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
데이터
작업할 데이터 또는 해당 데이터의 MIME 유형을 참조하는 URI (Uri 객체)입니다. 제공되는 데이터 유형은 일반적으로 인텐트의 작업에 따라 결정됩니다. 예를 들어 작업이 ACTION_EDIT이면 데이터에는 수정할 문서의 URI가 포함되어야 합니다.

인텐트를 만들 때 URI 외에 데이터 유형 (MIME 유형)을 지정하는 것이 중요한 경우가 많습니다. 예를 들어 이미지를 표시할 수 있는 활동은 URI 형식이 비슷하더라도 오디오 파일을 재생하지 못할 수 있습니다. 데이터의 MIME 유형을 지정하면 Android 시스템이 인텐트를 수신하는 데 가장 적합한 구성요소를 찾는 데 도움이 됩니다. 그러나 때로는 MIME 유형을 URI에서 추론할 수 있습니다(특히 데이터가 content: URI인 경우). content: URI는 데이터가 기기에 있고 ContentProvider에 의해 제어된다는 것을 나타내며, 이로 인해 데이터 MIME 유형이 시스템에 표시됩니다.

데이터 URI만 설정하려면 setData()를 호출합니다. MIME 유형만 설정하려면 setType()를 호출합니다. 필요한 경우 setDataAndType()를 사용하여 두 가지를 모두 명시적으로 설정할 수 있습니다.

주의: URI와 MIME 유형을 모두 설정하려는 경우 setData()setType()를 호출하면 안 됩니다. 이 둘은 서로의 값을 무효화하기 때문입니다. URI와 MIME 유형을 모두 설정하려면 항상 setDataAndType()를 사용하세요.

카테고리
인텐트를 처리해야 하는 구성요소의 종류에 관한 추가 정보가 포함된 문자열입니다. 인텐트에는 카테고리 설명이 원하는 만큼 배치할 수 있지만, 대부분의 인텐트에는 카테고리가 필요하지 않습니다. 다음은 몇 가지 일반적인 카테고리입니다.
CATEGORY_BROWSABLE
타겟 활동이 웹 브라우저에서 시작되어 이미지나 이메일 메시지와 같이 링크로 참조되는 데이터를 표시할 수 있습니다.
CATEGORY_LAUNCHER
활동은 작업의 초기 활동이며 시스템의 애플리케이션 런처에 나열됩니다.

카테고리의 전체 목록은 Intent 클래스 설명을 참고하세요.

addCategory()로 카테고리를 지정할 수 있습니다.

위에 나열된 이러한 속성 (구성요소 이름, 작업, 데이터, 카테고리)은 인텐트를 정의하는 특성을 나타냅니다. Android 시스템은 이러한 속성을 읽어 어느 앱 구성요소를 시작해야 하는지 확인할 수 있습니다. 그러나 인텐트는 앱 구성요소로 확인되는 방식에 영향을 미치지 않는 추가 정보를 포함할 수 있습니다. 인텐트가 제공할 수 있는 기타 정보는 다음과 같습니다.

추가 항목
요청된 작업을 실행하는 데 필요한 추가 정보가 포함된 키-값 쌍입니다. 몇몇 작업이 특정한 종류의 데이터 URI를 사용하는 것과 마찬가지로, 몇몇 작업은 특정한 엑스트라도 사용합니다.

다양한 putExtra() 메서드를 사용하여 데이터를 추가할 수 있으며, 각 메서드는 키 이름과 값, 이렇게 두 개의 매개변수를 허용합니다. 모든 추가 데이터로 Bundle 객체를 만든 다음 putExtras()를 사용하여 IntentBundle를 삽입할 수도 있습니다.

예를 들어 ACTION_SEND로 이메일을 보내는 인텐트를 만들 때 EXTRA_EMAIL 키로 to 수신자를 지정하고 EXTRA_SUBJECT 키로 subject를 지정할 수 있습니다.

Intent 클래스는 표준화된 데이터 유형을 위한 여러 EXTRA_* 상수를 지정합니다. 자체 추가 키를 선언해야 하는 경우 (앱에서 수신하는 인텐트의 경우) 다음 예와 같이 앱의 패키지 이름을 접두사로 포함해야 합니다.

Kotlin

const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"

Java

static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";

주의: 다른 앱에서 수신할 것으로 예상되는 인텐트를 전송할 때는 Parcelable 또는 Serializable 데이터를 사용하지 마세요. 앱이 Bundle 객체의 데이터에 액세스하려고 하지만 파슬링되거나 직렬화된 클래스에 액세스할 수 없는 경우 시스템에서 RuntimeException이 발생합니다.

플래그
플래그는 인텐트의 메타데이터로 작동하는 Intent 클래스에서 정의됩니다. 플래그는 Android 시스템에 활동을 시작하는 방법 (예: 활동이 속해야 하는 작업) 및 활동이 시작된 후 활동을 처리하는 방법 (예: 최근 활동 목록에 포함되는지 여부)을 지시할 수 있습니다.

자세한 내용은 setFlags() 메서드를 참고하세요.

명시적 인텐트 예시

명시적 인텐트는 앱의 특정 활동이나 서비스와 같은 특정 앱 구성요소를 실행하는 데 사용하는 인텐트입니다. 명시적 인텐트를 만들려면 Intent 객체의 구성요소 이름을 정의합니다. 다른 모든 인텐트 속성은 선택사항입니다.

예를 들어 앱에서 파일을 다운로드하도록 설계된 DownloadService라는 서비스를 빌드했다면 다음 코드를 사용하여 서비스를 시작할 수 있습니다.

Kotlin

// Executed in an Activity, so 'this' is the Context
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
val downloadIntent = Intent(this, DownloadService::class.java).apply {
    data = Uri.parse(fileUrl)
}
startService(downloadIntent)

Java

// Executed in an Activity, so 'this' is the Context
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

Intent(Context, Class) 생성자는 앱에 Context를 제공하고 구성요소에 Class 객체를 제공합니다. 따라서 이 인텐트는 앱에서 DownloadService 클래스를 명시적으로 시작합니다.

서비스 빌드 및 시작에 관한 자세한 내용은 서비스 가이드를 참고하세요.

암시적 인텐트 예시

암시적 인텐트는 기기에서 작업을 실행할 수 있는 모든 앱을 호출할 수 있는 작업을 지정합니다. 암시적 인텐트 사용은 내 앱은 작업을 실행할 수 없지만 다른 앱에서는 할 수 있고 개발자는 사용자가 사용할 앱을 선택하도록 하고자 할 때 유용합니다.

예를 들어 사용자가 다른 사람과 공유하려는 콘텐츠가 있다면 ACTION_SEND 작업을 사용하여 인텐트를 만들고 공유할 콘텐츠를 지정하는 추가 항목을 추가합니다. 이 인텐트로 startActivity()를 호출하면 사용자는 콘텐츠를 공유할 앱을 선택할 수 있습니다.

Kotlin

// Create the text message with a string.
val sendIntent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, textMessage)
    type = "text/plain"
}

// Try to invoke the intent.
try {
    startActivity(sendIntent)
} catch (e: ActivityNotFoundException) {
    // Define what your app should do if no activity can handle the intent.
}

Java

// Create the text message with a string.
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");

// Try to invoke the intent.
try {
    startActivity(sendIntent);
} catch (ActivityNotFoundException e) {
    // Define what your app should do if no activity can handle the intent.
}

startActivity()가 호출되면 시스템은 설치된 모든 앱을 검사하여 이러한 종류의 인텐트('text/plain' 데이터를 전달하는 ACTION_SEND 작업이 포함된 인텐트)를 처리할 수 있는 앱을 파악합니다. 이를 처리할 수 있는 앱이 하나뿐인 경우 해당 앱이 즉시 열리고 인텐트가 제공됩니다. 다른 앱에서 처리할 수 없다면 앱은 발생하는 ActivityNotFoundException를 포착할 수 있습니다. 인텐트를 허용하는 활동이 여러 개인 경우 시스템은 그림 2와 같은 대화상자를 표시하므로 사용자는 어떤 앱을 사용할지 선택할 수 있습니다.

다른 앱을 실행하는 방법에 관한 자세한 내용은 사용자를 다른 앱으로 보내기에 관한 가이드에도 나와 있습니다.

그림 2. 선택기 대화상자

앱 선택기 강제 적용

암시적 인텐트에 응답하는 앱이 두 개 이상인 경우 사용자는 사용할 앱을 선택하고 해당 앱을 작업의 기본 선택으로 만들 수 있습니다. 기본값을 선택하는 기능은 사용자가 항상 동일한 앱을 사용하려는 작업(예: 웹페이지를 열 때)을 실행할 때 유용합니다(사용자는 웹브라우저 하나만 선호함).

그러나 여러 앱이 인텐트에 응답할 수 있고 사용자가 매번 다른 앱을 사용하기를 원할 수도 있는 경우 선택기 대화상자를 명시적으로 표시해야 합니다. 선택기 대화상자는 사용자에게 작업에 사용할 앱을 선택하도록 요청합니다 (사용자는 작업에 사용할 기본 앱을 선택할 수 없음). 예를 들어 앱에서 ACTION_SEND 작업으로 '공유'를 실행하면 사용자는 현재 상황에 따라 다른 앱을 사용하여 공유하기를 원할 수 있으므로 항상 그림 2와 같이 선택기 대화상자를 사용해야 합니다.

선택기를 표시하려면 다음 예와 같이 createChooser()를 사용하여 Intent를 만들어 startActivity()에 전달합니다. 이 예에서는 createChooser() 메서드에 전달된 인텐트에 응답하는 앱의 목록이 포함된 대화상자를 표시하고 제공된 텍스트를 대화상자 제목으로 사용합니다.

Kotlin

val sendIntent = Intent(Intent.ACTION_SEND)
...

// Always use string resources for UI text.
// This says something like "Share this photo with"
val title: String = resources.getString(R.string.chooser_title)
// Create intent to show the chooser dialog
val chooser: Intent = Intent.createChooser(sendIntent, title)

// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(packageManager) != null) {
    startActivity(chooser)
}

Java

Intent sendIntent = new Intent(Intent.ACTION_SEND);
...

// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);

// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}

안전하지 않은 인텐트 실행 감지

앱은 인텐트를 실행하여 앱 내부의 구성요소 간에 이동하거나 다른 앱을 대신하여 작업을 실행할 수 있습니다. 플랫폼 보안을 개선하기 위해 Android 12 (API 수준 31) 이상에서는 앱이 안전하지 않은 인텐트를 실행하는 경우 경고하는 디버깅 기능을 제공합니다. 예를 들어 앱이 중첩된 인텐트(다른 인텐트에 추가 항목으로 전달되는 인텐트)를 안전하지 않은 방식으로 실행할 수 있습니다.

앱이 다음 두 작업을 모두 실행하면 시스템에서 안전하지 않은 인텐트 실행을 감지하고 StrictMode 위반이 발생합니다.

  1. 앱은 전달된 인텐트의 추가 항목에서 중첩된 인텐트를 분리합니다.
  2. 앱은 인텐트를 startActivity(), startService() 또는 bindService()로 전달하는 등 즉시 중첩된 인텐트를 사용하여 앱 구성요소를 시작합니다.

이 상황을 파악하고 앱을 변경하는 방법에 관한 자세한 내용은 Medium의 Android 중첩 인텐트에 관한 블로그 게시물을 참고하세요.

안전하지 않은 인텐트 실행 확인

앱에서 안전하지 않은 인텐트 실행을 확인하려면 다음 코드 스니펫과 같이 VmPolicy를 구성할 때 detectUnsafeIntentLaunch()를 호출하세요. 앱에서 StrictMode 위반을 감지하면 잠재적으로 민감한 정보를 보호하기 위해 앱 실행을 중지하는 것이 좋습니다.

Kotlin

fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        // Other StrictMode checks that you've previously added.
        // ...
        .detectUnsafeIntentLaunch()
        .penaltyLog()
        // Consider also adding penaltyDeath()
        .build())
}

Java

protected void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
        // Other StrictMode checks that you've previously added.
        // ...
        .detectUnsafeIntentLaunch()
        .penaltyLog()
        // Consider also adding penaltyDeath()
        .build());
}

더 책임감 있는 인텐트 사용

안전하지 않은 인텐트 실행 및 StrictMode 위반 가능성을 최소화하려면 다음 권장사항을 따르세요.

인텐트 내 필수 추가 항목만 복사하고 필요한 정리 및 검증을 실행합니다. 앱은 한 인텐트에서 새 구성요소를 실행하는 데 사용되는 다른 인텐트로 추가 항목을 복사할 수 있습니다. 이는 앱이 putExtras(Intent)putExtras(Bundle)를 호출할 때 발생합니다. 앱이 이러한 작업 중 하나를 실행하면 수신 구성요소에서 예상하는 추가 항목만 복사합니다. 복사본을 수신하는 다른 인텐트가 내보내지 않은 구성요소를 실행하는 경우 추가 항목을 정리하고 검증한 후 구성요소를 실행하는 인텐트에 복사합니다.

앱의 구성요소를 불필요하게 내보내지 마세요. 예를 들어 내부 중첩 인텐트를 사용하여 앱 구성요소를 실행하려면 구성요소의 android:exported 속성을 false로 설정합니다.

중첩된 인텐트 대신 PendingIntent를 사용하세요. 이렇게 하면 다른 앱이 포함된 IntentPendingIntent를 분리할 때 다른 앱이 내 앱의 ID를 사용하여 PendingIntent를 실행할 수 있습니다. 이 구성을 사용하면 다른 앱이 내보내지 않은 구성요소를 비롯한 모든 구성요소를 내 앱에서 안전하게 실행할 수 있습니다.

그림 2의 다이어그램은 시스템이 (클라이언트) 앱에서 다른 (서비스) 앱으로, 그리고 다시 앱으로 제어를 전달하는 방법을 보여줍니다.

  1. 앱은 다른 앱의 활동을 호출하는 인텐트를 만듭니다. 이 인텐트 내에서 PendingIntent 객체를 추가로 추가합니다. 이 대기 중인 인텐트는 앱의 구성요소를 호출하며, 이 구성요소는 내보내지 않습니다.
  2. 앱의 인텐트를 수신하면 다른 앱은 중첩된 PendingIntent 객체를 추출합니다.
  3. 다른 앱은 PendingIntent 객체에서 send() 메서드를 호출합니다.
  4. 제어 기능을 앱에 다시 전달한 후 시스템은 앱의 컨텍스트를 사용하여 대기 중인 인텐트를 호출합니다.

그림 2. 중첩된 대기 중 인텐트를 사용할 때의 앱 간 통신 다이어그램

암시적 인텐트 수신

앱이 수신할 수 있는 암시적 인텐트를 알리려면 매니페스트 파일에서 <intent-filter> 요소를 사용하여 각 앱 구성요소의 인텐트 필터를 하나 이상 선언합니다. 각 인텐트 필터는 인텐트의 작업, 데이터, 카테고리를 기반으로 허용하는 인텐트의 유형을 지정합니다. 시스템은 인텐트가 인텐트 필터 중 하나를 통과할 수 있는 경우에만 암시적 인텐트를 앱 구성요소에 전달합니다.

참고: 명시적 인텐트는 구성요소가 선언한 인텐트 필터와 관계없이 항상 타겟에 전달됩니다.

앱 구성요소는 고유한 작업마다 별도의 필터를 선언해야 합니다. 예를 들어 이미지 갤러리 앱의 한 활동에 두 개의 필터가 있을 수 있습니다. 하나는 이미지를 보고 다른 필터는 이미지를 편집합니다. 활동이 시작되면 Intent를 검사하고 Intent의 정보에 기반하여 동작 방식을 결정합니다 (편집기 컨트롤 표시 여부 등).

각 인텐트 필터는 앱의 매니페스트 파일에 있는 <intent-filter> 요소로 정의되며 상응하는 앱 구성요소 (예: <activity> 요소)에 중첩됩니다.

<intent-filter> 요소가 포함된 각 앱 구성요소에서 android:exported 값을 명시적으로 설정합니다. 이 속성은 앱 구성요소에 다른 앱이 액세스할 수 있는지 여부를 나타냅니다. 인텐트 필터에 LAUNCHER 카테고리가 포함된 활동과 같은 일부 상황에서는 이 속성을 true로 설정하는 것이 유용합니다. 그 외의 경우에는 이 속성을 false로 설정하는 것이 더 안전합니다.

경고: 앱의 활동이나 서비스, broadcast receiver가 인텐트 필터를 사용하고 android:exported 값을 명시적으로 설정하지 않으면 Android 12 이상을 실행하는 기기에 앱을 설치할 수 없습니다.

<intent-filter> 내에서 다음 세 가지 요소 중 하나 이상을 사용하여 허용할 인텐트 유형을 지정할 수 있습니다.

<action>
name 속성에서 허용된 인텐트 작업을 선언합니다. 값은 클래스 상수가 아니라 작업의 리터럴 문자열 값이어야 합니다.
<data>
데이터 URI (scheme, host, port, path) 및 MIME 유형의 다양한 측면을 지정하는 하나 이상의 속성을 사용하여 허용된 데이터 유형을 선언합니다.
<category>
name 속성에서 허용된 인텐트 카테고리를 선언합니다. 값은 클래스 상수가 아니라 작업의 리터럴 문자열 값이어야 합니다.

참고: 암시적 인텐트를 수신하려면 인텐트 필터에 CATEGORY_DEFAULT 카테고리를 포함해야 합니다. startActivity() 메서드와 startActivityForResult() 메서드는 마치 모든 인텐트에서 CATEGORY_DEFAULT 카테고리를 선언한 것처럼 인텐트를 취급합니다. 인텐트 필터에서 이 카테고리를 선언하지 않으면 암시적 인텐트는 활동으로 확인되지 않습니다.

예를 들어 다음은 데이터 유형이 텍스트일 때 ACTION_SEND 인텐트를 수신하는 인텐트 필터가 있는 활동 선언입니다.

<activity android:name="ShareActivity" android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

<action>, <data> 또는 <category>의 인스턴스를 두 개 이상 포함하는 필터를 만들 수 있습니다. 이러한 경우 구성요소가 이러한 필터 요소의 모든 조합을 처리할 수 있는지 확인해야 합니다.

여러 종류의 인텐트를 처리하되 작업, 데이터 및 카테고리 유형의 특정 조합으로만 처리하고 싶다면 인텐트 필터를 여러 개 만들어야 합니다.

암시적 인텐트는 인텐트를 세 가지 요소 각각과 비교하여 필터에 대해 테스트됩니다. 인텐트가 구성 요소에 전달되려면 세 가지 테스트를 모두 통과해야 합니다. 그중 하나라도 일치하지 않으면 Android 시스템은 인텐트를 구성요소에 전달하지 않습니다. 그러나 구성요소에 여러 인텐트 필터가 있을 수 있으므로 구성요소의 필터 중 하나를 통과하지 않는 인텐트도 다른 필터에서 통과할 수 있습니다. 시스템이 인텐트를 확인하는 방법에 관한 자세한 내용은 인텐트 확인에 관한 아래의 섹션을 참고하세요.

주의: 인텐트 필터를 사용하는 것은 다른 앱이 구성요소를 시작하지 못하도록 하는 안전한 방법은 아닙니다. 인텐트 필터는 구성요소가 특정 종류의 암시적 인텐트에만 응답하도록 제한하지만, 개발자가 구성요소 이름을 확인하면 다른 앱에서 명시적 인텐트를 사용하여 앱 구성요소를 시작할 가능성이 있습니다. 자체 앱만 구성요소 중 하나를 시작할 수 있는 것이 중요하다면 매니페스트에서 인텐트 필터를 선언하지 마세요. 대신 구성요소의 exported 속성을 "false"로 설정하세요.

마찬가지로 실수로 다른 앱의 Service를 실행하지 않으려면 항상 명시적 인텐트를 사용하여 자체 서비스를 시작하세요.

참고: 모든 활동의 경우 매니페스트 파일에서 인텐트 필터를 선언해야 합니다. 그러나 broadcast receiver의 필터는 registerReceiver()를 호출하여 동적으로 등록할 수 있습니다. 그런 다음 unregisterReceiver()를 사용하여 수신자를 등록 취소할 수 있습니다. 이렇게 하면 앱이 실행되는 동안 지정된 기간에만 특정 브로드캐스트를 수신 대기할 수 있습니다.

필터 예시

인텐트 필터 동작 중 일부를 보여주기 위해 소셜 공유 앱의 매니페스트 파일에서 가져온 예를 보여드리겠습니다.

<activity android:name="MainActivity" android:exported="true">
    <!-- This activity is the main entry, should appear in app launcher -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="ShareActivity" android:exported="false">
    <!-- This activity handles "SEND" actions with text data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="application/vnd.google.panorama360+jpg"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
    </intent-filter>
</activity>

첫 번째 활동인 MainActivity는 앱의 기본 진입점, 즉 사용자가 런처 아이콘으로 앱을 처음 실행할 때 열리는 활동입니다.

  • ACTION_MAIN 작업은 이것이 기본 진입점이며 어떠한 인텐트 데이터도 예상하지 않음을 나타냅니다.
  • CATEGORY_LAUNCHER 카테고리는 이 활동의 아이콘이 시스템의 앱 런처에 배치되어야 함을 나타냅니다. <activity> 요소가 icon로 아이콘을 지정하지 않으면 시스템은 <application> 요소의 아이콘을 사용합니다.

이들 두 가지가 짝을 이루어야 액티비티가 앱 시작 관리자에 나타날 수 있습니다.

두 번째 활동인 ShareActivity는 텍스트 및 미디어 콘텐츠 공유를 용이하게 하기 위한 것입니다. 사용자는 MainActivity에서 이 활동으로 이동하여 활동을 시작할 수도 있지만, 두 인텐트 필터 중 하나와 일치하는 암시적 인텐트를 실행하는 다른 앱에서 직접 ShareActivity에 입력할 수도 있습니다.

참고: MIME 유형 application/vnd.google.panorama360+jpgGoogle 파노라마 API로 처리할 수 있는 파노라마 사진을 지정하는 특수 데이터 유형입니다.

인텐트를 다른 앱의 인텐트 필터와 일치

다른 앱이 Android 13 (API 수준 33) 이상을 타겟팅한다면 내 인텐트가 다른 앱에 있는 <intent-filter> 요소의 작업 및 카테고리와 일치하는 경우에만 앱의 인텐트를 처리할 수 있습니다. 시스템에서 일치하는 항목을 찾지 못하면 ActivityNotFoundException이 발생합니다. 전송 앱은 이 예외를 처리해야 합니다.

마찬가지로 Android 13 이상을 타겟팅하도록 앱을 업데이트하는 경우, 외부 앱에서 발생한 모든 인텐트는 앱이 선언한 <intent-filter> 요소의 작업 및 카테고리와 일치하는 경우에만 외부 앱에서 발생한 모든 인텐트가 앱의 내보낸 구성요소로 전달됩니다. 이 동작은 전송 앱의 타겟 SDK 버전과 관계없이 발생합니다.

다음과 같은 경우에는 인텐트 일치가 적용되지 않습니다.

  • 인텐트 필터를 선언하지 않는 구성요소에 전달된 인텐트
  • 동일한 앱 내에서 발생한 인텐트
  • 시스템에서 발생한 인텐트. 즉, '시스템 UID'(uid=1000)에서 전송되는 인텐트입니다. 시스템 앱에는 android:sharedUserIdandroid.uid.system으로 설정하는 앱과 system_server가 포함됩니다.
  • 루트에서 발생한 인텐트

인텐트 일치 자세히 알아보기

보류 인텐트 사용

PendingIntent 객체는 Intent 객체를 둘러싼 래퍼입니다. PendingIntent의 기본 목적은 외부 애플리케이션에 포함된 Intent를 내 앱의 자체 프로세스에서 실행되는 것처럼 사용할 수 있는 권한을 부여하는 것입니다.

보류 인텐트의 주요 사용 사례는 다음과 같습니다.

  • 사용자가 알림으로 작업을 실행할 때 인텐트가 실행되도록 선언합니다(Android 시스템의 NotificationManagerIntent를 실행).
  • 사용자가 앱 위젯으로 작업을 실행할 때 인텐트가 실행되도록 선언합니다(홈 화면 앱이 Intent을 실행함).
  • 향후 지정된 시간에 인텐트가 실행되도록 선언합니다 (Android 시스템의 AlarmManagerIntent를 실행함).

Intent 객체가 특정 유형의 앱 구성요소 (Activity, Service 또는 BroadcastReceiver)에서 처리하도록 설계되어 있는 것처럼 PendingIntent도 동일한 고려사항을 고려하여 만들어야 합니다. 대기 중인 인텐트를 사용하면 앱은 startActivity()와 같은 호출이 있는 인텐트를 실행하지 않습니다. 대신, PendingIntent를 만들 때 각 생성자 메서드를 호출하여 의도한 구성요소 유형을 선언해야 합니다.

앱이 다른 앱에서 대기 중인 인텐트를 수신하지 않는 한 위의 PendingIntent를 만드는 메서드는 유일한 PendingIntent 메서드일 수 있습니다.

각 메서드는 현재 앱 Context, 래핑하려는 Intent, 인텐트 사용 방법을 지정하는 하나 이상의 플래그 (예: 인텐트를 두 번 이상 사용할 수 있는지 여부)를 사용합니다.

대기 중인 인텐트 사용에 관한 자세한 내용은 알림앱 위젯 API 가이드와 같이 각 사용 사례의 문서를 참고하세요.

변경 가능 여부 지정

앱이 Android 12 이상을 타겟팅한다면 앱에서 만드는 각 PendingIntent 객체의 변경 가능 여부를 지정해야 합니다. 지정된 PendingIntent 객체가 변경 가능하거나 변경 불가능하다고 선언하려면 각각 PendingIntent.FLAG_MUTABLE 또는 PendingIntent.FLAG_IMMUTABLE 플래그를 사용합니다.

앱에서 변경 가능 여부 플래그를 설정하지 않고 PendingIntent 객체를 만들려고 하면 시스템에서 IllegalArgumentException이 발생하고 다음 메시지가 Logcat에 표시됩니다.

PACKAGE_NAME: Targeting S+ (version 31 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.

가능한 경우 변경 불가능한 대기 중인 인텐트 만들기

대부분의 경우 앱에서는 다음 코드 스니펫과 같이 변경 불가능한 PendingIntent 객체를 만들어야 합니다. PendingIntent 객체를 변경할 수 없다면 다른 앱은 인텐트를 수정하여 인텐트 호출 결과를 조정할 수 없습니다.

Kotlin

val pendingIntent = PendingIntent.getActivity(applicationContext,
        REQUEST_CODE, intent,
        /* flags */ PendingIntent.FLAG_IMMUTABLE)

Java

PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
        REQUEST_CODE, intent,
        /* flags */ PendingIntent.FLAG_IMMUTABLE);

그러나 특정 사용 사례에서는 대신 변경 가능한 PendingIntent 객체가 필요합니다.

  • 알림에서 바로 답장 작업 지원 직접 회신에서는 답장과 연결된 PendingIntent 객체의 클립 데이터를 변경해야 합니다. 일반적으로 FILL_IN_CLIP_DATAfillIn() 메서드에 플래그로 전달하여 이 변경을 요청합니다.
  • CarAppExtender 인스턴스를 사용하여 알림을 Android Auto 프레임워크와 연결합니다.
  • PendingIntent 인스턴스를 사용하여 대화창에 대화를 배치합니다. 변경 가능한 PendingIntent 객체를 사용하면 시스템에서 FLAG_ACTIVITY_MULTIPLE_TASKFLAG_ACTIVITY_NEW_DOCUMENT와 같은 올바른 플래그를 적용할 수 있습니다.
  • requestLocationUpdates() 또는 유사한 API를 호출하여 기기 위치 정보 요청 변경 가능한 PendingIntent 객체를 사용하면 시스템에서 위치 수명 주기 이벤트를 나타내는 인텐트 추가 항목을 추가할 수 있습니다. 이러한 이벤트에는 위치 변경 및 공급업체 이용 가능 상태가 포함됩니다.
  • AlarmManager를 사용하여 알람을 예약합니다. 변경 가능한 PendingIntent 객체를 사용하면 시스템에서 EXTRA_ALARM_COUNT 인텐트를 추가로 추가할 수 있습니다. 이 추가 항목은 반복 알람이 트리거된 횟수를 나타냅니다. 이 추가 항목을 포함하는 인텐트는 반복 알람이 여러 번 트리거되었는지(예: 기기가 절전 모드일 때)에 관해 앱에 정확하게 알릴 수 있습니다.

앱에서 변경 가능한 PendingIntent 객체를 만드는 경우 명시적 인텐트를 사용하여 ComponentName을 채우는 것이 좋습니다. 이렇게 하면 다른 앱이 PendingIntent를 호출하고 제어 기능을 앱에 다시 전달할 때마다 앱의 동일한 구성요소가 항상 시작됩니다.

대기 중인 인텐트 내에서 명시적 인텐트 사용

다른 앱이 내 앱의 대기 중인 인텐트를 사용하는 방법을 더 잘 정의하려면 항상 대기 중인 인텐트를 명시적 인텐트로 래핑합니다. 이 권장사항을 따르려면 다음 단계를 따르세요.

  1. 기본 인텐트의 작업, 패키지, 구성요소 필드가 설정되었는지 확인합니다.
  2. Android 6.0 (API 수준 23)에 추가된 FLAG_IMMUTABLE를 사용하여 대기 중인 인텐트를 만듭니다. 이 플래그는 PendingIntent를 수신하는 앱이 채워지지 않은 속성을 채우지 못하게 합니다. 앱의 minSdkVersion22 이하이면 다음 코드를 사용하여 안전성과 호환성을 함께 제공할 수 있습니다.

    if (Build.VERSION.SDK_INT >= 23) {
      // Create a PendingIntent using FLAG_IMMUTABLE.
    } else {
      // Existing code that creates a PendingIntent.
    }

인텐트 확인

시스템은 활동을 시작하라는 암시적 인텐트를 수신하면 다음 세 가지 측면에 따라 인텐트 필터와 비교하여 인텐트에 가장 적합한 활동을 검색합니다.

  • 액션
  • 데이터(URI와 데이터 유형 둘 다).
  • 카테고리.

다음 섹션에서는 앱 매니페스트 파일의 인텐트 필터 선언에 따라 인텐트를 적절한 구성요소에 일치시키는 방법을 설명합니다.

작업 테스트

허용된 인텐트 작업을 지정하기 위해 인텐트 필터는 다음 예와 같이 0개 이상의 <action> 요소를 선언할 수 있습니다.

<intent-filter>
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
    ...
</intent-filter>

이 필터를 통과하려면 Intent에 지정된 작업이 필터에 나열된 작업 중 하나와 일치해야 합니다.

필터에 작업이 나열되지 않으면 인텐트가 일치될 항목이 없으므로 모든 인텐트가 테스트에 실패합니다. 그러나 Intent이 작업을 지정하지 않으면 필터에 작업이 1개 이상 포함되어 있으면 테스트를 통과합니다.

카테고리 테스트

허용된 인텐트 카테고리를 지정하기 위해 인텐트 필터는 다음 예와 같이 0개 이상의 <category> 요소를 선언할 수 있습니다.

<intent-filter>
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    ...
</intent-filter>

인텐트가 카테고리 테스트를 통과하려면 Intent의 모든 카테고리가 필터의 카테고리와 일치해야 합니다. 그 반대는 필요하지 않습니다. 인텐트 필터가 Intent에 지정된 것보다 더 많은 카테고리를 선언할 수 있고 Intent은 여전히 통과합니다. 따라서 카테고리가 없는 인텐트는 필터에 선언된 카테고리와 관계없이 항상 이 테스트를 통과합니다.

참고: Android는 startActivity()startActivityForResult()에 전달된 모든 암시적 인텐트에 CATEGORY_DEFAULT 카테고리를 자동으로 적용합니다. 활동이 암시적 인텐트를 수신하려면 이전 <intent-filter> 예와 같이 인텐트 필터에 "android.intent.category.DEFAULT" 카테고리를 포함해야 합니다.

데이터 테스트

허용된 인텐트 데이터를 지정하기 위해 인텐트 필터는 다음 예와 같이 0개 이상의 <data> 요소를 선언할 수 있습니다.

<intent-filter>
    <data android:mimeType="video/mpeg" android:scheme="http" ... />
    <data android:mimeType="audio/mpeg" android:scheme="http" ... />
    ...
</intent-filter>

<data> 요소는 URI 구조와 데이터 유형 (MIME 미디어 유형)을 지정할 수 있습니다. URI의 각 부분은 별도의 속성(scheme, host, port, path)입니다.

<scheme>://<host>:<port>/<path>

다음 예시는 이 특성에 사용 가능한 값을 보여줍니다.

content://com.example.project:200/folder/subfolder/etc

이 URI에서 스키마는 content, 호스트는 com.example.project, 포트는 200, 경로는 folder/subfolder/etc입니다.

이러한 각 속성은 <data> 요소에서 선택사항이지만 선형 종속 항목도 있습니다.

  • 구성표가 지정되지 않으면 호스트가 무시됩니다.
  • 호스트가 지정되지 않으면 포트가 무시됩니다.
  • 구성표와 호스트가 둘 다 지정되지 않으면 경로가 무시됩니다.

인텐트의 URI가 필터의 URI 사양과 비교될 때는 필터에 포함된 URI의 부분에만 비교됩니다. 예:

  • 필터가 스키마만 지정하는 경우 해당 스키마가 있는 모든 URI가 필터와 일치합니다.
  • 필터가 스키마와 권한은 지정하지만 경로는 지정하지 않는 경우 동일한 스키마와 권한이 있는 모든 URI는 경로와 관계없이 필터를 통과합니다.
  • 필터가 스키마, 권한, 경로를 지정하는 경우 동일한 스키마, 권한, 경로를 가진 URI만 필터를 통과합니다.

참고: 경로 사양에는 경로 이름이 부분적으로만 일치하도록 요구하기 위해 와일드 카드 별표 (*)를 포함할 수 있습니다.

데이터 테스트는 인텐트의 URI와 MIME 유형 둘 다를 필터에 지정된 URI 및 MIME 유형과 비교합니다. 규칙은 다음과 같습니다.

  1. URI도 MIME 유형도 포함되지 않은 인텐트는 필터가 URI나 MIME 유형을 지정하지 않은 경우에만 테스트를 통과합니다.
  2. URI는 있지만 MIME 유형은 없는 인텐트 (URI에서 명시적이지도 않고 추론할 수도 없음)는 URI가 필터의 URI 형식과 일치하고 필터가 MIME 유형을 지정하지 않는 경우에만 테스트를 통과합니다.
  3. MIME 유형은 들어 있지만 URI는 없는 인텐트는 필터가 동일한 MIME 유형을 나열하고 URI 형식을 지정하지 않는 경우에만 테스트를 통과합니다.
  4. URI와 MIME 유형을 둘 다 포함하는 인텐트 (URI에서 명시적이거나 추론할 수 없음)는 유형이 필터에 나열된 유형과 일치하는 경우에만 테스트의 MIME 유형 부분을 통과합니다. URI가 필터의 URI와 일치하거나 content: 또는 file: URI가 있고 필터가 URI를 지정하지 않은 경우 테스트의 URI 부분을 통과합니다. 즉, 구성요소가 MIME 유형 나열하는 경우 구성요소가 content:file: 데이터를 지원하는 것으로 간주됩니다.

참고: 인텐트가 URI 또는 MIME 유형을 지정하는 경우 <intent-filter><data> 요소가 없으면 데이터 테스트가 실패합니다.

마지막 규칙인 규칙 (d)는 구성요소가 파일 또는 콘텐츠 제공업체에서 로컬 데이터를 가져올 수 있다는 기대치를 반영합니다. 따라서 필터는 데이터 유형만 나열할 수 있으며 content:file: 스키마의 이름을 명시적으로 지정할 필요가 없습니다. 다음 예는 <data> 요소가 구성요소가 콘텐츠 제공자에서 이미지 데이터를 가져와 표시할 수 있다고 Android에 알리는 일반적인 사례를 보여줍니다.

<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>

데이터 유형은 지정하고 URI는 지정하지 않는 필터가 가장 일반적일 것입니다. 사용 가능한 대부분의 데이터를 콘텐츠 제공자가 제공하기 때문입니다.

다른 보편적인 구성을 예로 들자면 구성표와 데이터 유형을 가진 필터가 있겠습니다. 예를 들어 다음과 같은 <data> 요소는 작업을 실행하기 위해 구성요소가 네트워크에서 동영상 데이터를 검색할 수 있다고 Android에 알립니다.

<intent-filter>
    <data android:scheme="http" android:mimeType="video/*" />
    ...
</intent-filter>

인텐트 일치

인텐트를 인텐트 필터와 일치시켜 활성화할 타겟 구성요소를 탐색할 뿐만 아니라 기기의 구성요소 집합에 관해 알아봅니다. 예를 들어 Home 앱은 ACTION_MAIN 작업과 CATEGORY_LAUNCHER 카테고리를 지정하는 인텐트 필터가 있는 모든 활동을 찾아 앱 런처를 채웁니다. IntentFilter 클래스 문서에 설명된 대로 인텐트의 작업과 카테고리가 필터와 일치하는 경우에만 일치가 성공합니다.

애플리케이션은 홈 앱과 같은 방식으로 인텐트 매칭을 사용합니다. PackageManager에는 특정 인텐트를 허용할 수 있는 모든 구성요소를 반환하는 query...() 메서드 집합과 인텐트에 응답하는 데 가장 적합한 구성요소를 결정하는 유사한 일련의 resolve...() 메서드가 있습니다. 예를 들어 queryIntentActivities()는 인수로 전달된 인텐트를 실행할 수 있는 모든 활동의 목록을 반환하고 queryIntentServices()는 유사한 서비스 목록을 반환합니다. 두 메서드 모두 구성요소를 활성화하지 않으며, 응답할 수 있는 항목만 나열합니다. broadcast receiver를 위한 유사한 메서드인 queryBroadcastReceivers()가 있습니다.