앱은 다른 앱으로 데이터를 보낼 수 있는 것처럼 다른 앱에서 데이터를 받을 수도 있습니다. 사용자가 애플리케이션과 상호작용하는 방식과 다른 애플리케이션에서 수신하려는 데이터 유형을 생각해 보세요. 예를 들어 소셜 네트워킹 애플리케이션은 다른 앱에서 흥미로운 웹 URL과 같은 텍스트 콘텐츠를 수신하는 데 관심이 있을 수 있습니다.
Compose Navigation을 사용하는 앱에서 다른 앱이 전송한 데이터를 수신하는 과정은 다음 세 단계로 이루어집니다.
매니페스트에서
<intent-filter>선언:AndroidManifest.xml파일의 활동에 인텐트 필터를 추가해야 합니다. 이렇게 하면 Android OS에 애플리케이션이 특정 작업(예:ACTION_SEND)과 MIME 유형 (예:text/plain)을 수신할 수 있다고 알립니다.Compose 탐색 그래프에서
navDeepLink를 정의합니다. 작업 및 MIME 유형과 일치하는navDeepLink를 콘텐츠를 표시해야 하는 구성 가능한 대상에 직접 연결합니다.NavController는 수신 인텐트를 자동으로 가로채고 사용자를 해당 화면으로 직접 라우팅합니다.수신 데이터 페이로드 추출: 대상 화면에서 인텐트 추가 항목 (예:
EXTRA_TEXT또는EXTRA_STREAM)에 액세스하여 공유 콘텐츠를 가져오고 UI 상태를 업데이트합니다.
다이렉트 공유 타겟은 앱 내 특정 활동으로 연결되는 딥 링크입니다. 이러한 타겟은 주로 사람이나 그룹을 나타내며 Android Sharesheet에 표시됩니다. 예를 들어 메시지 앱은 특정 사용자와의 대화로 딥 링크가 설정된 다이렉트 공유 타겟을 제공할 수 있습니다. 자세한 내용은 다이렉트 공유 타겟 제공을 참고하세요.
지원되는 MIME 유형
이상적으로는 앱이 가능한 한 광범위한 MIME 유형을 수신할 수 있어야 합니다.
예를 들어 텍스트, 이미지, 동영상을 전송하도록 설계된 메시지 앱은 text/*, image/*, video/* 수신을 지원하는 것이 이상적입니다. 다음은 Android에서 데이터를 주고받는 데 사용되는 몇 가지 일반적인 MIME 유형입니다.
| 수신자는 | 발신자는 |
|---|---|
text/* |
|
image/* |
|
video/* |
|
| 지원되는 파일 확장자 | application/pdf |
MIME 미디어 유형의 IANA 공식 레지스트리를 참조하세요.
효과적인 공유 타겟 만들기
사용자가 특정 활동과 연결된 공유 타겟을 탭하면 앱에서 공유 콘텐츠를 사용하기 전에 사용자가 공유 콘텐츠를 확인하고 수정할 수 있도록 합니다. 이는 텍스트 데이터에서 특히 중요합니다.
앱에서 데이터 수신
Compose를 사용하여 앱에서 공유 데이터를 수신하려면 매니페스트에서 인텐트 필터를 선언하고, 수신 인텐트를 딥 링크를 통해 적절한 화면으로 라우팅하고, 인텐트에서 페이로드를 추출하여 UI를 업데이트해야 합니다.
매니페스트 업데이트하기
인텐트 필터는 앱 구성요소가 허용하는 인텐트를 시스템에 알립니다. 다른 앱으로 데이터 전송 과정에서 ACTION_SEND 작업으로 인텐트를 구성한 방법과 마찬가지로, 이 작업으로 인텐트를 수신하는 인텐트 필터를 만듭니다. <intent-filter> 요소를 사용하여 매니페스트에서 인텐트 필터를 정의합니다. 예를 들어 앱이 텍스트 콘텐츠 수신을 처리하는 경우 모든 유형의 이미지를 하나 이상 포함하는 매니페스트는 다음 스니펫과 같습니다.
<activity android:name=".ui.MyActivity" android:exported="true">
<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 내에서 콘텐츠를 적절하게 처리하는 것은 개발자의 몫입니다.
탐색 그래프에서 딥 링크 정의
Compose Navigation에서 콘텐츠를 표시해야 하는 구성 가능한 대상에 navDeepLink를 직접 연결합니다. 다른 앱이 인텐트 필터와 일치하는 데이터를 공유하면 Compose Navigation은 사용자를 이 대상으로 직접 라우팅합니다.
composable( route = "incoming_share", deepLinks = listOf( navDeepLink { action = Intent.ACTION_SEND mimeType = "text/plain" }, navDeepLink { action = Intent.ACTION_SEND mimeType = "image/*" }, navDeepLink { action = Intent.ACTION_SEND_MULTIPLE mimeType = "image/*" } ) ) { SharesheetHandler() }
navDeepLink는 수신 인텐트의 작업 및 MIME 유형과 일치하여 올바른 대상 화면으로 이동합니다. 목적지에 도달하면 핸들러는 인텐트를 검사하여 수신된 페이로드 (예: 단일 이미지와 여러 이미지)를 확인하고 해당 추가 항목을 추출합니다.
수신되는 콘텐츠 처리하기
Intent에서 전송한 콘텐츠를 가져오려면 컴포저블 내의 LocalActivity.current에서 현재 활동을 읽은 다음 인텐트를 검사하여 다음에 실행할 작업을 결정합니다. 이 활동을 시스템의 다른 부분 (예: 런처)에서 시작할 수 있는 경우 인텐트를 검사할 때 이 점을 고려하세요.
수신 데이터를 확인할 때는 각별히 주의해야 합니다. 잘못된 MIME 유형이 설정되거나 전송되는 이미지가 매우 클 수 있습니다. 기본 UI 스레드가 아닌 코루틴 (예: Dispatchers.IO)을 사용하여 비동기식으로 바이너리 데이터 또는 과도한 I/O 작업 (예: 대용량 이미지 디코딩 또는 파일 쓰기)을 처리합니다.
@Composable fun SharesheetHandler() { val activity = LocalActivity.current val intent = activity?.intent when (intent?.action) { Intent.ACTION_SEND -> { if (intent.type == "text/plain") { 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 } } } private fun handleSendText(intent: Intent) { intent.getStringExtra(Intent.EXTRA_TEXT)?.let { // Update UI state with the shared text } } private fun handleSendImage(intent: Intent) { val imageUri = IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java) imageUri?.let { // Update UI state with the shared image } } private fun handleSendMultipleImages(intent: Intent) { val imageUris = IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java) imageUris?.let { // Update UI state with the shared images } }
인텐트 추가 항목 (예: EXTRA_STREAM)에서 바이너리 데이터 또는 URI를 추출할 때는 위의 handleSendImage 및 handleSendMultipleImages 함수와 같이 AndroidX Core 라이브러리의 IntentCompat.getParcelableExtra() 또는 IntentCompat.getParcelableArrayListExtra()를 사용합니다. Android 13 (API 수준 33)에서는 예상 클래스 유형을 사용하는 유형 안전 메서드를 위해 매개변수화되지 않은 Intent.getParcelableExtra(String) 메서드를 지원 중단합니다.
데이터를 수신한 후 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 UI state with the shared image and the EXTRA_TEXT if available }
사용자가 앱을 인식하게 만들기
앱은 Android Sharesheet 및 인텐트 리졸버에서 아이콘과 라벨로 표시됩니다. 두 가지 모두 매니페스트에 정의되어 있습니다. 활동 또는 인텐트 필터 라벨을 설정하여 더 많은 컨텍스트를 제공할 수 있습니다.
Android 10 (API 수준 29)부터 Android Sharesheet는 application 태그의 매니페스트에 설정된 아이콘만 사용합니다. Android는 intent-filter 및 activity 태그에 설정된 아이콘을 무시합니다.
리치 콘텐츠 받기
ACTION_SEND 인텐트를 사용하면 활동 또는 탐색 수준에서 Android Sharesheet 및 인텐트 리졸버로부터 데이터를 수신할 수 있지만, 앱은 직접적인 UI 상호작용을 통해 리치 콘텐츠 (예: 이미지, 동영상, 오디오 파일, 스타일이 지정된 텍스트)를 수신할 수도 있습니다. 이러한 메커니즘에는 다음이 포함됩니다.
- 클립보드에서 붙여넣기 (길게 터치 메뉴)
- 소프트웨어 키보드(IME)에서 직접 미디어(예: 스티커 또는 GIF) 삽입
- 멀티 윈도우 또는 화면 분할 모드에서 다른 앱의 콘텐츠를 드래그 앤 드롭
뷰 기반 UI에서 Android 12 (API 수준 31) 및 AndroidX Core 1.7은 통합 OnReceiveContentListener API를 도입합니다. 이 리스너는 클립보드, 키보드, 드래그 앤 드롭의 콘텐츠 처리를 단일 콜백으로 통합합니다. 뷰에서 이를 구현하는 방법에 관한 자세한 안내는 리치 콘텐츠 수신을 참고하세요.
Jetpack Compose에서는 Modifier.contentReceiver 수정자 또는 드래그 앤 드롭 수정자를 사용하여 UI 구성요소 (예: 텍스트 필드)에 삽입된 리치 콘텐츠 수신을 처리할 수 있습니다.