다른 앱에서 간단한 데이터 받기

앱은 데이터를 다른 앱으로 보낼 수 있을 뿐 아니라 다른 앱의 데이터를 받을 수도 있습니다. 사용자가 애플리케이션과 상호작용하는 방식 및 다른 애플리케이션에서 받을 데이터 유형을 생각해 보세요. 예를 들어 소셜 네트워크 애플리케이션이라면 다른 앱에서 흥미로운 웹 URL 같은 텍스트 콘텐츠를 받고 싶을 수 있습니다.

Compose 탐색을 사용하는 앱에서 다른 앱이 보낸 데이터를 받는 과정은 두 단계로 이루어집니다.

  1. 매니페스트에서 <intent-filter> 선언: AndroidManifest.xml 파일의 활동에 인텐트 필터를 추가해야 합니다. 이렇게 하면 애플리케이션이 특정 작업(예: ACTION_SEND) 및 MIME 유형 (예: text/plain)을 받을 수 있다고 Android OS에 알립니다.

  2. Compose 탐색 그래프에서 navDeepLink 정의: 활동의 onCreate 또는 onNewIntent 메서드 내에서 인텐트를 수동으로 가로채고 파싱하는 대신 Compose 탐색의 딥 링크 지원을 사용합니다. 작업 및 MIME 유형과 일치하는 navDeepLink를 콘텐츠를 표시해야 하는 컴포저블 대상에 직접 연결합니다. NavController는 자동으로 인텐트를 가로채고 사용자를 해당 화면으로 직접 라우팅합니다.

직접 공유 타겟은 앱 내의 특정 활동으로 연결되는 딥 링크입니다. 어떤 사람이나 그룹을 나타내는 경우가 많으며 Android Sharesheet에 표시됩니다. 예를 들어 메시지 앱은 어떤 사람과 관련하여 이 사람과 나눈 대화로 직접 딥 링크를 통해 연결되는 직접 공유 타겟을 제공할 수 있습니다. 자세한 안내는 직접 공유 타겟 제공을 참고하세요.

MIME 유형 지원

앱은 최대한 다양한 MIME 유형을 받을 수 있어야 합니다. 예를 들어 텍스트, 이미지, 동영상을 보내도록 설계된 메시지 앱은 text/*, image/*, video/* 수신을 지원하는 것이 좋습니다. 다음은 Android에서 간단한 데이터를 보내고 받을 때의 몇 가지 일반적인 MIME 유형입니다.

수신자가 등록하는 항목 발신자가 보내는 항목
text/*
  • text/plain
  • text/rtf
  • text/html
  • text/json
image/*
  • image/jpg
  • image/png
  • image/gif
video/*
  • video/mp4
  • video/3gp
지원되는 파일 확장자 application/pdf

IANA 공식 MIME 미디어 유형 레지스트리를 참고하세요.

좋은 공유 타겟 만들기

사용자가 특정 활동과 연결된 공유 타겟을 탭할 때 공유 타겟을 사용하기 전에 공유 콘텐츠를 확인하고 편집할 수 있어야 합니다. 이 기능은 텍스트 데이터의 경우 특히 중요합니다.

활동이 포함된 데이터 받기

활동이 포함된 데이터를 받으려면 매니페스트를 업데이트하고, 수신 콘텐츠를 처리하고, 사용자가 앱을 인식하도록 해야 합니다.

매니페스트 업데이트하기

인텐트 필터는 앱 구성요소에서 허용되는 인텐트를 시스템에 알립니다. 다른 앱에 단순 데이터 보내기 강의에서 ACTION_SEND 작업으로 인텐트를 구성한 방식과 비슷하게 이 작업을 사용하여 인텐트를 받을 수 있도록 인텐트 필터를 만듭니다. 매니페스트에서 <intent-filter> 요소를 사용하여 인텐트 필터를 정의합니다. 예를 들어 앱이 텍스트 콘텐츠를 받는 작업을 처리하는 경우 모든 유형의 이미지를 하나 이상 포함하는 매니페스트는 다음 스니펫과 같습니다.

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

다른 앱이 인텐트를 구성하고 startActivity()에 전달하여 이러한 항목 중 하나를 공유하려고 시도하면 내 애플리케이션 이 Android Sharesheet나 인텐트 리졸버에 하나의 옵션으로 나열됩니다. 사용자가 내 앱을 선택하면 해당하는 활동 (이전 예에서 .ui.MyActivity)이 시작됩니다. 그런 다음, 원하는 대로 코드 및 UI 내에서 콘텐츠를 적절하게 처리하면 됩니다.

수신되는 콘텐츠 처리하기

Intent가 전송한 콘텐츠를 처리하려면 getIntent()를 호출하여 Intent 객체를 가져옵니다. 객체를 가져온 후에는 콘텐츠를 검사하여 다음에 할 작업을 결정할 수 있습니다. 이 활동을 시스템의 다른 부분 (예: 런처)에서 시작할 수 있는 경우에는 인텐트를 검사할 때 이 점을 고려해야 합니다.

수신 데이터를 각별히 주의하여 확인하세요. 다른 애플리케이션에서 어떤 데이터가 들어올지 알 수 없습니다. 예를 들어 잘못된 MIME 유형이 설정되거나 전송되는 이미지가 매우 클 수 있습니다. 또한, 기본('UI') 스레드가 아니라 별도의 스레드에서 바이너리 데이터를 처리해야 한다는 점도 기억하세요.

@Composable
fun SharesheetHandler() {
    val context = LocalContext.current
    val intent = (context as? Activity)?.intent

    when (intent?.action) {
        ACTION_SEND -> {
            if ("text/plain" == intent.type) {
                handleSendText(intent) // Handle text being sent.
            } else if (intent.type?.startsWith("image/") == true) {
                handleSendImage(intent) // Handle single image being sent
            }
        }

        Intent.ACTION_SEND_MULTIPLE -> {
            if (intent.type?.startsWith("image/") == true) {
                handleSendMultipleImages(intent) // Handle multiple images being sent
            }
        }

        else -> {
            // Handle other intents, such as being started from the home screen
        }
    }
}

fun handleSendText(intent: Intent) {
    intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
        // Update ViewModel state to change state of text being shared
    }
}

fun handleSendImage(intent: Intent) {
    IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
        // Update ViewModel state to change state of image being shared
    }
}

fun handleSendMultipleImages(intent: Intent) {
    IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
        // Update ViewModel state to change state of image(s) being shared
    }
}

데이터를 받은 후 UI를 업데이트하려면 TextField 를 채우기만 하면 됩니다. 재미있는 사진 필터를 이미지에 적용하는 것과 같이 더 복잡한 방법도 있습니다. 어떤 방법을 선택할지는 앱에 따라 다릅니다.

스크린샷 URL 공유

스크린샷을 찍을 때 스크린샷과 연결된 URL을 공유할 수 있습니다. 이렇게 하면 사용자 환경이 개선됩니다. URL을 수신할 때는 다음 예와 같이 인텐트에서 EXTRA_TEXT 필드를 가져와야 합니다.

IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
    // Handle the EXTRA_TEXT as well
    val extraText = intent.getCharSequenceExtra(Intent.EXTRA_TEXT)
    // Update ViewModel state to change state image being shared and the EXTRA_TEXT
    // if available
}

사용자가 앱을 인식하게 만들기

앱은 Android Sharesheet 및 인텐트 리졸버에서 아이콘라벨로 표현됩니다. 아이콘과 라벨은 둘 다 매니페스트에 정의되어 있습니다. 활동 또는 인텐트 필터 라벨을 설정하여 더 자세한 컨텍스트를 제공할 수 있습니다.

Android 10 (API 수준 29)부터 Android Sharesheet에서는 매니페스트에서 application 태그에 설정된 아이콘만 사용합니다. Android는 intent-filteractivity 태그에 설정된 아이콘을 무시합니다.