From 994fef71c827c6d6fe7e716b691886c7f8f53eea Mon Sep 17 00:00:00 2001
From: Rubin Raithel <33808743+Coronon@users.noreply.github.com>
Date: Mon, 31 Oct 2022 09:05:56 +0100
Subject: [PATCH] fix(share_plus): return correct share result on android
(#1301)
---
.../android/src/main/AndroidManifest.xml | 9 +++++
.../dev/fluttercommunity/plus/share/Share.kt | 6 +--
.../plus/share/SharePlusPendingIntent.kt | 39 +++++++++++++++++++
.../plus/share/SharePlusPlugin.kt | 2 -
.../plus/share/ShareSuccessManager.kt | 34 ++++------------
.../main/res/xml/flutter_share_file_paths.xml | 5 ++-
6 files changed, 62 insertions(+), 33 deletions(-)
create mode 100644 packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPendingIntent.kt
diff --git a/packages/share_plus/share_plus/android/src/main/AndroidManifest.xml b/packages/share_plus/share_plus/android/src/main/AndroidManifest.xml
index 8bbbe44d82..40801f1d83 100644
--- a/packages/share_plus/share_plus/android/src/main/AndroidManifest.xml
+++ b/packages/share_plus/share_plus/android/src/main/AndroidManifest.xml
@@ -1,6 +1,8 @@
+
+
+
+
+
+
+
diff --git a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/Share.kt b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/Share.kt
index e2c1d3248b..95cfca5f06 100644
--- a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/Share.kt
+++ b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/Share.kt
@@ -33,7 +33,7 @@ internal class Share(
*/
private val immutabilityIntentFlags: Int by lazy {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- PendingIntent.FLAG_IMMUTABLE
+ PendingIntent.FLAG_MUTABLE
} else {
0
}
@@ -71,7 +71,7 @@ internal class Share(
PendingIntent.getBroadcast(
context,
0,
- Intent(ShareSuccessManager.BROADCAST_CHANNEL),
+ Intent(context, SharePlusPendingIntent::class.java),
PendingIntent.FLAG_UPDATE_CURRENT or immutabilityIntentFlags
).intentSender
)
@@ -129,7 +129,7 @@ internal class Share(
PendingIntent.getBroadcast(
context,
0,
- Intent(ShareSuccessManager.BROADCAST_CHANNEL),
+ Intent(context, SharePlusPendingIntent::class.java),
PendingIntent.FLAG_UPDATE_CURRENT or immutabilityIntentFlags
).intentSender
)
diff --git a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPendingIntent.kt b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPendingIntent.kt
new file mode 100644
index 0000000000..284ccd507a
--- /dev/null
+++ b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPendingIntent.kt
@@ -0,0 +1,39 @@
+package dev.fluttercommunity.plus.share
+
+import android.content.*
+import android.os.Build
+
+/**
+ * This helper class allows us to use FLAG_MUTABLE on the PendingIntent used in the Share class,
+ * as it allows us to make the underlying Intent explicit, therefore avoiding any risks an implicit
+ * mutable Intent may carry.
+ *
+ * When the PendingIntent is sent, the system will instantiate this class and call `onReceive` on it.
+ */
+internal class SharePlusPendingIntent: BroadcastReceiver() {
+ companion object {
+ /**
+ * Static member to access the result of the system instantiated instance
+ */
+ var result: String = ""
+ }
+
+ /**
+ * Handler called after an action was chosen. Called only on success.
+ */
+ override fun onReceive(context: Context, intent: Intent) {
+ // Extract chosen ComponentName
+ val chosenComponent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ // Only available from API level 33 onwards
+ intent.getParcelableExtra(Intent.EXTRA_CHOSEN_COMPONENT, ComponentName::class.java)
+ } else {
+ // Deprecated in API level 33
+ intent.getParcelableExtra(Intent.EXTRA_CHOSEN_COMPONENT)
+ }
+
+ // Unambiguously identify the chosen action
+ if (chosenComponent != null) {
+ result = chosenComponent.flattenToString()
+ }
+ }
+}
diff --git a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPlugin.kt b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPlugin.kt
index b3b831ed10..d53a508ddb 100644
--- a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPlugin.kt
+++ b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/SharePlusPlugin.kt
@@ -15,14 +15,12 @@ class SharePlusPlugin : FlutterPlugin, ActivityAware {
override fun onAttachedToEngine(binding: FlutterPluginBinding) {
methodChannel = MethodChannel(binding.binaryMessenger, CHANNEL)
manager = ShareSuccessManager(binding.applicationContext)
- manager.register()
share = Share(context = binding.applicationContext, activity = null, manager = manager)
val handler = MethodCallHandler(share, manager)
methodChannel.setMethodCallHandler(handler)
}
override fun onDetachedFromEngine(binding: FlutterPluginBinding) {
- manager.discard()
methodChannel.setMethodCallHandler(null)
}
diff --git a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/ShareSuccessManager.kt b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/ShareSuccessManager.kt
index 36e1a4c50e..3ac7116f0b 100644
--- a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/ShareSuccessManager.kt
+++ b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/ShareSuccessManager.kt
@@ -9,31 +9,18 @@ import java.util.concurrent.atomic.AtomicBoolean
* Handles the callback based status information about a successful or dismissed
* share. Used to link multiple different callbacks together for easier use.
*/
-internal class ShareSuccessManager(private val context: Context) : BroadcastReceiver(),
- ActivityResultListener {
+internal class ShareSuccessManager(private val context: Context) : ActivityResultListener {
private var callback: MethodChannel.Result? = null
private var isCalledBack: AtomicBoolean = AtomicBoolean(true)
- /**
- * Register listener. Must be called before any share sheet is opened.
- */
- fun register() {
- context.registerReceiver(this, IntentFilter(BROADCAST_CHANNEL))
- }
-
- /**
- * Deregister listener. Must be called before the base activity is invalidated.
- */
- fun discard() {
- context.unregisterReceiver(this)
- }
-
/**
* Set result callback that will wait for the share-sheet to close and get either
* the componentname of the chosen option or an empty string on dismissal.
*/
fun setCallback(callback: MethodChannel.Result): Boolean {
return if (isCalledBack.compareAndSet(true, false)) {
+ // Prepare all state for new share
+ SharePlusPendingIntent.result = ""
isCalledBack.set(false)
this.callback = callback
true
@@ -51,7 +38,7 @@ internal class ShareSuccessManager(private val context: Context) : BroadcastRece
* Must be called if `.startActivityForResult` is not available to avoid deadlocking.
*/
fun unavailable() {
- returnResult("dev.fluttercommunity.plus/share/unavailable")
+ returnResult(RESULT_UNAVAILABLE)
}
/**
@@ -70,7 +57,7 @@ internal class ShareSuccessManager(private val context: Context) : BroadcastRece
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
return if (requestCode == ACTIVITY_CODE) {
- returnResult("")
+ returnResult(SharePlusPendingIntent.result)
true
} else {
false
@@ -78,16 +65,11 @@ internal class ShareSuccessManager(private val context: Context) : BroadcastRece
}
/**
- * Handler called after a sharesheet was closed. Called only on success.
+ * Companion object holds constants used throughout the plugin when attempting to return
+ * the share result.
*/
- override fun onReceive(context: Context, intent: Intent) {
- returnResult(
- intent.getParcelableExtra(Intent.EXTRA_CHOSEN_COMPONENT).toString()
- )
- }
-
companion object {
- const val BROADCAST_CHANNEL = "dev.fluttercommunity.plus/share/success"
const val ACTIVITY_CODE = 17062003
+ const val RESULT_UNAVAILABLE = "dev.fluttercommunity.plus/share/unavailable"
}
}
diff --git a/packages/share_plus/share_plus/android/src/main/res/xml/flutter_share_file_paths.xml b/packages/share_plus/share_plus/android/src/main/res/xml/flutter_share_file_paths.xml
index 4e78448e9e..cb820aec00 100644
--- a/packages/share_plus/share_plus/android/src/main/res/xml/flutter_share_file_paths.xml
+++ b/packages/share_plus/share_plus/android/src/main/res/xml/flutter_share_file_paths.xml
@@ -1,4 +1,5 @@
-
-
+
+
+