Making your app a share target lets users send content from other apps directly into yours. This exercise implements a complete share-target flow: receive text and images, then add Direct Share shortcuts.
Step 1: Declare the Intent Filter
<!-- AndroidManifest.xml -->
<activity android:name=".ShareActivity" android:exported="true">
<!-- Receive plain text (URLs, notes) -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<!-- Receive a single image -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<!-- Receive multiple images -->
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
Step 2: Handle the Incoming Intent
class ShareActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_share)
handleSharedContent(intent)
}
private fun handleSharedContent(intent: Intent) {
when {
// Single text/URL
intent.action == Intent.ACTION_SEND &&
intent.type?.startsWith("text/") == true -> {
val sharedText = intent.getStringExtra(Intent.EXTRA_TEXT) ?: return
val sharedSubject = intent.getStringExtra(Intent.EXTRA_SUBJECT)
displaySharedText(sharedText, sharedSubject)
}
// Single image
intent.action == Intent.ACTION_SEND &&
intent.type?.startsWith("image/") == true -> {
val imageUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)
} else {
@Suppress("DEPRECATION")
intent.getParcelableExtra(Intent.EXTRA_STREAM) as? Uri
}
imageUri?.let { displaySharedImage(it) }
}
// Multiple images
intent.action == Intent.ACTION_SEND_MULTIPLE &&
intent.type?.startsWith("image/") == true -> {
val imageUris = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java)
} else {
@Suppress("DEPRECATION")
intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)
}
imageUris?.forEach { displaySharedImage(it) }
}
}
}
private fun displaySharedText(text: String, subject: String?) {
binding.titleText.text = subject ?: "Shared Link"
binding.contentText.text = text
}
private fun displaySharedImage(uri: Uri) {
// Grant temporary read permission before loading
binding.imageView.load(uri) // Coil handles URI permissions
}
}
Step 3: Add Direct Share Targets (ChooserTarget API)
Direct Share shows contact shortcuts directly in the share sheet. Implement ChooserTargetService (legacy) or the modern ShortcutManager approach:
// Modern approach: publish sharing shortcuts via ShortcutManager
class ShareShortcutManager(private val context: Context) {
fun publishShareTargets(contacts: List<Contact>) {
val shortcuts = contacts.take(4).map { contact ->
ShortcutInfoCompat.Builder(context, "contact_${contact.id}")
.setShortLabel(contact.name)
.setIcon(IconCompat.createWithBitmap(contact.avatar))
.setIntent(
Intent(context, ShareActivity::class.java).apply {
action = Intent.ACTION_SEND
putExtra("recipient_id", contact.id)
}
)
.setCategories(setOf("com.example.myapp.directshare"))
.setLongLived(true) // Required for share targets
.build()
}
ShortcutManagerCompat.pushDynamicShortcut(context, shortcuts.first())
ShortcutManagerCompat.addDynamicShortcuts(context, shortcuts)
}
}
<!-- Declare share target in shortcuts.xml -->
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<share-target android:targetClass="com.example.ShareActivity">
<data android:mimeType="*/*" />
<category android:name="com.example.myapp.directshare" />
</share-target>
</shortcuts>
<!-- Reference in AndroidManifest activity -->
<activity android:name=".MainActivity">
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity>
Step 4: Test with adb
# Test text sharing
adb shell am start \
-a android.intent.action.SEND \
-t text/plain \
--es android.intent.extra.TEXT "https://example.com" \
-n com.example.myapp/.ShareActivity
# Verify your app appears in the share sheet
# Open any app → Share → check for your app
Common Pitfalls
| Problem | Fix |
|---|---|
getParcelableExtra deprecated warning | Use Build.VERSION.SDK_INT >= TIRAMISU branch with typed version |
| Image not loading — permission denied | Don't store the URI; load immediately before Activity is destroyed |
| App not appearing in share sheet | Check android:exported="true" and intent filter MIME types |
| Direct Share contacts not showing | Call pushDynamicShortcut after user selects contacts; set setLongLived(true) |
| Crash on null intent | Always null-check EXTRA_STREAM and EXTRA_TEXT |