diff --git a/CHANGES.md b/CHANGES.md
index 05d189ed12..d064cc5f39 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -16,6 +16,7 @@ Improvements 🙌:
  - Drawer: move settings access and add sign out action (#2171)
  - Filter room member (and banned users) by name (#2184)
  - Implement "Jump to read receipt" and "Mention" actions on the room member profile screen
+ - Direct share (#2029)
 
 Bugfix 🐛:
  - Improve support for image/audio/video/file selection with intent changes (#1376)
diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml
index 3f178a3d20..723bf2f0e2 100644
--- a/vector/src/main/AndroidManifest.xml
+++ b/vector/src/main/AndroidManifest.xml
@@ -74,6 +74,10 @@
 
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
+
+            <meta-data
+                android:name="android.app.shortcuts"
+                android:resource="@xml/shortcuts" />
         </activity-alias>
 
         <activity android:name=".features.home.HomeActivity" />
diff --git a/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt b/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt
index 171cc7b3d9..1edfbff64f 100644
--- a/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt
+++ b/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt
@@ -33,6 +33,7 @@ import javax.inject.Inject
 private val useAdaptiveIcon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
 private const val adaptiveIconSizeDp = 108
 private const val adaptiveIconOuterSidesDp = 18
+private const val directShareCategory = "im.vector.app.SHORTCUT_SHARE"
 
 class ShortcutCreator @Inject constructor(
         private val context: Context,
@@ -65,6 +66,10 @@ class ShortcutCreator @Inject constructor(
                 .setShortLabel(roomSummary.displayName)
                 .setIcon(bitmap?.toProfileImageIcon())
                 .setIntent(intent)
+
+                // Make it show up in the direct share menu
+                .setCategories(setOf(directShareCategory))
+
                 .build()
     }
 
diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareAction.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareAction.kt
index eef4e32dff..4e9f024b15 100644
--- a/vector/src/main/java/im/vector/app/features/share/IncomingShareAction.kt
+++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareAction.kt
@@ -16,12 +16,13 @@
 
 package im.vector.app.features.share
 
-import org.matrix.android.sdk.api.session.room.model.RoomSummary
 import im.vector.app.core.platform.VectorViewModelAction
+import org.matrix.android.sdk.api.session.room.model.RoomSummary
 
 sealed class IncomingShareAction : VectorViewModelAction {
     data class SelectRoom(val roomSummary: RoomSummary, val enableMultiSelect: Boolean) : IncomingShareAction()
     object ShareToSelectedRooms : IncomingShareAction()
+    data class ShareToRoom(val roomSummary: RoomSummary) : IncomingShareAction()
     data class ShareMedia(val keepOriginalSize: Boolean) : IncomingShareAction()
     data class FilterWith(val filter: String) : IncomingShareAction()
     data class UpdateSharedData(val sharedData: SharedData) : IncomingShareAction()
diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt
index 5e776fb17a..c9a8ec51c2 100644
--- a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt
@@ -19,6 +19,7 @@ package im.vector.app.features.share
 import android.app.Activity
 import android.content.ClipDescription
 import android.content.Intent
+import android.os.Build
 import android.os.Bundle
 import android.view.View
 import android.widget.Toast
@@ -71,13 +72,28 @@ class IncomingShareFragment @Inject constructor(
         setupToolbar(incomingShareToolbar)
         attachmentsHelper = AttachmentsHelper(requireContext(), this).register()
 
+        viewModel.observeViewEvents {
+            when (it) {
+                is IncomingShareViewEvents.ShareToRoom            -> handleShareToRoom(it)
+                is IncomingShareViewEvents.EditMediaBeforeSending -> handleEditMediaBeforeSending(it)
+                is IncomingShareViewEvents.MultipleRoomsShareDone -> handleMultipleRoomsShareDone(it)
+            }.exhaustive
+        }
+
         val intent = vectorBaseActivity.intent
         val isShareManaged = when (intent?.action) {
-            Intent.ACTION_SEND -> {
+            Intent.ACTION_SEND          -> {
                 var isShareManaged = attachmentsHelper.handleShareIntent(requireContext(), intent)
                 if (!isShareManaged) {
                     isShareManaged = handleTextShare(intent)
                 }
+
+                // Direct share
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && intent.hasExtra(Intent.EXTRA_SHORTCUT_ID)) {
+                    val roomId = intent.getStringExtra(Intent.EXTRA_SHORTCUT_ID)!!
+                    sessionHolder.getSafeActiveSession()?.getRoomSummary(roomId)?.let { viewModel.handle(IncomingShareAction.ShareToRoom(it)) }
+                }
+
                 isShareManaged
             }
             Intent.ACTION_SEND_MULTIPLE -> attachmentsHelper.handleShareIntent(requireContext(), intent)
@@ -101,13 +117,6 @@ class IncomingShareFragment @Inject constructor(
         sendShareButton.setOnClickListener { _ ->
             handleSendShare()
         }
-        viewModel.observeViewEvents {
-            when (it) {
-                is IncomingShareViewEvents.ShareToRoom -> handleShareToRoom(it)
-                is IncomingShareViewEvents.EditMediaBeforeSending -> handleEditMediaBeforeSending(it)
-                is IncomingShareViewEvents.MultipleRoomsShareDone -> handleMultipleRoomsShareDone(it)
-            }.exhaustive
-        }
     }
 
     private fun handleMultipleRoomsShareDone(viewEvent: IncomingShareViewEvents.MultipleRoomsShareDone) {
diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt
index aa4d8ad03e..9014565e08 100644
--- a/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareViewModel.kt
@@ -22,17 +22,17 @@ import com.airbnb.mvrx.ViewModelContext
 import com.jakewharton.rxrelay2.BehaviorRelay
 import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
-import org.matrix.android.sdk.api.query.QueryStringValue
-import org.matrix.android.sdk.api.session.Session
-import org.matrix.android.sdk.api.session.content.ContentAttachmentData
-import org.matrix.android.sdk.api.session.room.model.Membership
-import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
 import im.vector.app.core.extensions.exhaustive
 import im.vector.app.core.extensions.toggle
 import im.vector.app.core.platform.VectorViewModel
 import im.vector.app.features.attachments.isPreviewable
 import im.vector.app.features.attachments.toGroupedContentAttachmentData
 import im.vector.app.features.home.room.list.BreadcrumbsRoomComparator
+import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.content.ContentAttachmentData
+import org.matrix.android.sdk.api.session.room.model.Membership
+import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
 import org.matrix.android.sdk.rx.rx
 import java.util.concurrent.TimeUnit
 
@@ -96,6 +96,7 @@ class IncomingShareViewModel @AssistedInject constructor(
         when (action) {
             is IncomingShareAction.SelectRoom           -> handleSelectRoom(action)
             is IncomingShareAction.ShareToSelectedRooms -> handleShareToSelectedRooms()
+            is IncomingShareAction.ShareToRoom          -> handleShareToRoom(action)
             is IncomingShareAction.ShareMedia           -> handleShareMediaToSelectedRooms(action)
             is IncomingShareAction.FilterWith           -> handleFilter(action)
             is IncomingShareAction.UpdateSharedData     -> handleUpdateSharedData(action)
@@ -134,6 +135,11 @@ class IncomingShareViewModel @AssistedInject constructor(
         }
     }
 
+    private fun handleShareToRoom(action: IncomingShareAction.ShareToRoom) = withState { state ->
+        val sharedData = state.sharedData ?: return@withState
+        _viewEvents.post(IncomingShareViewEvents.ShareToRoom(action.roomSummary, sharedData, showAlert = false))
+    }
+
     private fun handleShareMediaToSelectedRooms(action: IncomingShareAction.ShareMedia) = withState { state ->
         (state.sharedData as? SharedData.Attachments)?.let {
             shareAttachments(it.attachmentData, state.selectedRoomIds, proposeMediaEdition = false, compressMediaBeforeSending = !action.keepOriginalSize)
diff --git a/vector/src/main/res/xml/shortcuts.xml b/vector/src/main/res/xml/shortcuts.xml
new file mode 100644
index 0000000000..a005de24a2
--- /dev/null
+++ b/vector/src/main/res/xml/shortcuts.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
+    <share-target android:targetClass="im.vector.app.features.share.IncomingShareActivity">
+        <data android:mimeType="*/*" />
+        <category android:name="im.vector.app.SHORTCUT_SHARE" />
+    </share-target>
+</shortcuts>
\ No newline at end of file