다른 앱이 자신의 Activity를 시작하도록 허용

자신의 앱이 다른 앱에 유용할 수 있는 작업을 수행할 수 있다면 Activity에서 적절한 인텐트 파일을 지정하여 다른 앱의 작업 요청에 응답할 수 있도록 준비되어 있어야 합니다.

예를 들어 사용자의 친구와 메시지 또는 사진을 공유할 수 있는 소셜 앱을 빌드하려면 ACTION_SEND 인텐트를 지원해야 합니다. 그런 다음, 사용자가 다른 앱에서 "공유" 작업을 시작하면 그림 1과 같이 선택기 대화상자("명확화 대화상자"라고도 함)에서 앱이 옵션으로 나타납니다.

그림 1. 선택기 대화상자

다른 앱이 이런 방식으로 자신의 Activity를 시작할 수 있도록 하기 위해서는 매니페스트 파일에서 해당 <activity> 요소에 대해 <intent-filter> 요소를 추가해야 합니다.

앱을 기기에 설치하면 시스템이 인텐트 필터를 식별하고 모든 설치된 앱에서 지원하는 인텐트의 내부 카탈로그에 해당 정보를 추가합니다. 앱이 암시적 인텐트로 startActivity() 또는 startActivityForResult()를 호출하면 시스템은 그 인텐트에 응답할 수 있는 Activity(들)을 찾습니다.

인텐트 필터 추가

Activity가 처리 가능한 인텐트를 올바르게 정의하려면 Activity가 받아들이는 데이터와 작업 유형 측면에서 추가하는 인텐트 필터가 최대한 구체적이어야 합니다.

Activity의 인텐트 필터가 Intent 객체의 다음 기준을 충족할 경우, 시스템이 주어진 Intent를 해당 Activity에 보낼 수 있습니다.

작업
수행할 작업의 이름을 지정하는 문자열입니다. 일반적으로, 플랫폼에서 정의하는 값 중 하나입니다(예: ACTION_SEND 또는 ACTION_VIEW).

<action> 요소를 사용하여 인텐트 필터에 지정합니다. 이 요소에 지정하는 값은 API 상수 대신 작업의 전체 문자열 이름이어야 합니다(다음 예제 참조).

데이터
인텐트와 관련된 데이터에 대한 설명입니다.

<data> 요소를 사용하여 인텐트 필터에 지정합니다. 이 요소에서 하나 이상의 속성을 사용하여 MIME 유형, URI 접두사, URI 구성표 또는 이들의 조합 그리고 수락된 데이터 유형을 나타내는 다른 요소들을 지정할 수 있습니다.

참고: Activity가 URI가 아닌 다른 종류의 "엑스트라" 데이터를 처리할 때와 같이 데이터 Uri에 대한 세부사항을 선언할 필요가 없는 경우, text/plain 또는 image/jpeg와 같이 Activity가 처리하는 데이터 유형을 선언하는 데 android:mimeType 속성만 지정하면 됩니다.

범주
인텐트를 처리하는 Activity의 특징을 지정할 수 있는 추가적인 방법을 제공합니다. 일반적으로 사용자 제스처 또는 이러한 제스처가 시작된 위치와 관련되어 있습니다. 시스템이 지원하는 범주는 여러 가지가 있지만 대부분은 거의 사용되지 않습니다. 하지만 모든 암시적 인텐트는 기본적으로CATEGORY_DEFAULT로 정의됩니다.

<category> 요소를 사용하여 인텐트 필터에 지정합니다.

인텐트 필터에서 Activity가 허용하는 기준을 선언할 수 있습니다. 이는 이러한 기준 각각을 <intent-filter> 요소 내에 해당 XML 요소를 중첩하여 선언하면 가능합니다.

예를 들어, 다음은 데이터 유형이 텍스트 또는 이미지인 경우 ACTION_SEND 인텐트를 처리하는 인텐트 필터가 지정된 Activity입니다.

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

팁: 선택기 대화상자에 있는 아이콘으로 Activity의 기본 아이콘과 다른 것을 사용하고자 할 경우 <intent-filter> 요소에 android:icon을 추가합니다.

수신되는 인텐트는 각각 하나의 작업 및 하나의 데이터 유형만 지정합니다. 하지만 <intent-filter> 각각에 <action>, <category><data> 요소에 대한 여러 인스턴스를 선언해도 문제가 되지는 않습니다.

작업 및 데이터의 두 쌍이 상호 배타적으로 동작할 경우, 어떤 데이터 유형과 페어링되었을 때 어떤 작업이 허용 가능한지를 지정하는 인텐트 필터를 각각 따로 생성해야 합니다.

예를 들어, Activity가 ACTION_SENDACTION_SENDTO 인텐트 모두에서 텍스트와 이미지 모두를 처리한다고 가정합니다. 이런 경우, 두 작업 각각에 별도의 인텐트 필터를 정의해야 합니다. 그 이유는 ACTION_SENDTO 인텐트는 데이터 Uri를 사용해서 send 또는 sendto URI 구성표를 사용하는 수신자 주소를 지정해야 하기 때문입니다. 예:

<activity android:name="ShareActivity">
    <!-- filter for sending text; accepts SENDTO action with sms URI schemes -->
    <intent-filter>
        <action android:name="android.intent.action.SENDTO"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="sms" />
        <data android:scheme="smsto" />
    </intent-filter>
    <!-- filter for sending text or images; accepts SEND action and text or image data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

참고: 암시적 인텐트를 수신하려면 인텐트 필터 안에 CATEGORY_DEFAULT 범주를 반드시 포함해야 합니다. startActivity()startActivityForResult() 메서드는 모든 인텐트를 마치 CATEGORY_DEFAULT 범주를 선언한 것처럼 취급합니다. 인텐트 필터에서 이 범주를 선언하지 않으면 어떠한 암시적 인텐트도 Activity로 확인되지 않습니다.

소셜 공유 동작을 수행하는 ACTION_SEND 인텐트의 송수신에 대한 자세한 내용은 다른 앱에서 단순 데이터 수신 과정을 참조하세요. 단순 데이터 공유파일 공유에서 데이터 공유에 대한 유용한 정보를 확인할 수 있습니다.

Activity에서 인텐트 처리

Activity를 시작하는 데 사용된 Intent를 읽어 Activity에서 취할 작업을 결정할 수 있습니다.

Activity가 시작되면, getIntent()를 호출하여 Activity를 시작한 Intent를 검색합니다. 이 작업은 Activity의 수명 주기 동안 언제든지 가능하지만, 일반적으로 onCreate() 또는 onStart()와 같은 초기 콜백 과정에서 수행합니다.

예:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.main)

    val data: Uri? = intent?.data

    // Figure out what to do based on the intent type
    if (intent?.type?.startsWith("image/") == true) {
        // Handle intents with image data ...
    } else if (intent?.type == "text/plain") {
        // Handle intents with text ...
    }
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    // Get the intent that started this activity
    Intent intent = getIntent();
    Uri data = intent.getData();

    // Figure out what to do based on the intent type
    if (intent.getType().indexOf("image/") != -1) {
        // Handle intents with image data ...
    } else if (intent.getType().equals("text/plain")) {
        // Handle intents with text ...
    }
}

결과 반환

Activity를 호출한 Activity로 결과를 반환하고자 하는 경우, 간단하게 setResult()를 호출하여 결과 코드 및 결과 Intent를 지정하면 됩니다. 작업이 끝나고 사용자가 원래 Activity로 되돌아갈 경우, finish()를 호출하여 Activity를 종료(및 소멸)합니다. 예:

Kotlin

// Create intent to deliver some kind of result data
Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri")).also { result ->
    setResult(Activity.RESULT_OK, result)
}
finish()

Java

// Create intent to deliver some kind of result data
Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri"));
setResult(Activity.RESULT_OK, result);
finish();

결과 코드는 항상 결과와 함께 지정해야 합니다. 일반적으로 RESULT_OK 또는 RESULT_CANCELED입니다. 그런 다음 필요한 경우 Intent를 사용하여 추가 데이터를 제공할 수 있습니다.

참고: 결과는 기본적으로 RESULT_CANCELED로 설정됩니다. 따라서 작업을 완료하기 전과 개발자가 결과를 설정하기 전에 사용자가 Back 버튼을 누를 경우, 원래의 Activity는"취소" 결과를 받게 됩니다.

단순히 여러 가지 결과 옵션 중 하나를 나타내는 정수만 반환하면 되는 경우, 결과 코드를 0보다 큰 임의의 값으로 설정하면 됩니다. 결과 코드를 사용하여 정수만 제공하고 Intent를 포함할 필요는 없는 경우, setResult()를 호출하고 결과 코드만 전달하면 됩니다. 예:

Kotlin

setResult(RESULT_COLOR_RED)
finish()

Java

setResult(RESULT_COLOR_RED);
finish();

이런 경우, 가능한 결과는 몇 개에 불과할 것이므로 결과 코드는 로컬로 정의된 정수입니다(0보다 큼). 이는 자신의 앱에서 Activity에 결과를 반환할 때 유용합니다. 왜냐하면 결과를 수신한 Activity가 공용 상수를 참조하여 결과 코드의 값을 확인할 수 있기 때문입니다.

참고: startActivity() 또는 startActivityForResult()로 Activity가 시작되었는지 확인할 필요는 없습니다. Activity를 시작한 인텐트가 결과를 원할 경우, setResult()를 호출하기만 하면 됩니다. 원래의 Activity가 startActivityForResult()를 호출한 경우, 시스템은 개발자가 setResult()에 제공하는 결과를 Activity에 제공합니다. 그렇지 않을 경우 결과는 무시됩니다.