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

앱이 다른 앱에 데이터를 전송할 수 있는 것처럼 다른 앱에서 데이터를 수신할 수도 있습니다. 사용자가 애플리케이션과 상호작용하는 방식과 다른 애플리케이션에서 수신할 데이터 유형을 생각해 보세요. 예를 들어 소셜 네트워킹 애플리케이션은 다른 앱에서 흥미로운 웹 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

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

훌륭한 공유 대상 만들기

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

활동으로 데이터 수신

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

매니페스트 업데이트하기

인텐트 필터는 앱 구성요소가 수락하는 인텐트를 시스템에 알립니다. 다른 앱에 간단한 데이터 보내기 과정에서 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 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
    }
}

데이터를 수신한 후 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 태그에 설정된 아이콘을 무시합니다.