diff --git a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/MethodCallHandler.kt b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/MethodCallHandler.kt index 8329b826e9..a4bff43e0d 100644 --- a/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/MethodCallHandler.kt +++ b/packages/share_plus/share_plus/android/src/main/kotlin/dev/fluttercommunity/plus/share/MethodCallHandler.kt @@ -8,52 +8,39 @@ import java.io.IOException /** Handles the method calls for the plugin. */ internal class MethodCallHandler( private val share: Share, - private val manager: ShareSuccessManager + private val manager: ShareSuccessManager, ) : MethodChannel.MethodCallHandler { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + expectMapArguments(call) + // The user used a *WithResult method val isResultRequested = call.method.endsWith("WithResult") // We don't attempt to return a result if the current API version doesn't support it - val isWithResult = isResultRequested && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 + val isWithResult = + isResultRequested && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 - when (call.method) { - "shareUri" -> { - expectMapArguments(call) - share.share( - call.argument("uri") as String, - subject = null, - withResult= false - ) - if (!isWithResult) { - result.success(null) - } - } - "share", "shareWithResult" -> { - expectMapArguments(call) - if (isWithResult && !manager.setCallback(result)) return + if (isWithResult && !manager.setCallback(result)) return - // Android does not support showing the share sheet at a particular point on screen. - share.share( - call.argument("text") as String, - call.argument("subject") as String?, - isWithResult, - ) + try { + when (call.method) { + "shareUri" -> { + share.share( + call.argument("uri") as String, subject = null, withResult = false + ) + success(isWithResult, isResultRequested, result) + } - if (!isWithResult) { - if (isResultRequested) { - result.success("dev.fluttercommunity.plus/share/unavailable") - } else { - result.success(null) - } + "share", "shareWithResult" -> { + share.share( + call.argument("text") as String, + call.argument("subject") as String?, + isWithResult, + ) + success(isWithResult, isResultRequested, result) } - } - "shareFiles", "shareFilesWithResult" -> { - expectMapArguments(call) - if (isWithResult && !manager.setCallback(result)) return - // Android does not support showing the share sheet at a particular point on screen. - try { + "shareFiles", "shareFilesWithResult" -> { share.shareFiles( call.argument>("paths")!!, call.argument?>("mimeTypes"), @@ -61,19 +48,28 @@ internal class MethodCallHandler( call.argument("subject"), isWithResult, ) - - if (!isWithResult) { - if (isResultRequested) { - result.success("dev.fluttercommunity.plus/share/unavailable") - } else { - result.success(null) - } - } - } catch (e: IOException) { - result.error("Share failed", e.message, null) + success(isWithResult, isResultRequested, result) } + + else -> result.notImplemented() + } + } catch (e: Throwable) { + manager.clear() + result.error("Share failed", e.message, e) + } + } + + private fun success( + isWithResult: Boolean, + isResultRequested: Boolean, + result: MethodChannel.Result + ) { + if (!isWithResult) { + if (isResultRequested) { + result.success("dev.fluttercommunity.plus/share/unavailable") + } else { + result.success(null) } - else -> result.notImplemented() } } 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 d73758b486..3fdb20dea1 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 @@ -41,6 +41,14 @@ internal class ShareSuccessManager(private val context: Context) : ActivityResul returnResult(RESULT_UNAVAILABLE) } + /** + * Must be called on error to avoid deadlocking. + */ + fun clear() { + isCalledBack.set(true) + callback = null + } + /** * Send the result to flutter by invoking the previously set callback. */