Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UIActivityViewController crashing on iPads #50

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ group 'com.shekarmudaliyar.social_share'
version '1.0-SNAPSHOT'

buildscript {
ext.kotlin_version = '1.3.50'
ext.kotlin_version = '1.5.30'
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.android.tools.build:gradle:4.2.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Expand Down
1 change: 1 addition & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.shekarmudaliyar.social_share">
<meta-data android:name="flutterEmbedding" android:value="2"/>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import android.net.Uri
import android.os.Build
import android.util.Log
import androidx.annotation.NonNull
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat.startActivity
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import androidx.core.content.FileProvider
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
Expand All @@ -18,19 +19,21 @@ import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
import java.io.File

/** SocialSharePlugin */
class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {
class SocialSharePlugin:FlutterPlugin, MethodCallHandler, ActivityAware {
private lateinit var channel: MethodChannel
private var activity: Activity? = null
private var activeContext: Context? = null
private var context: Context? = null

companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "social_share")
channel.setMethodCallHandler(SocialSharePlugin(registrar))
}
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
context = flutterPluginBinding.applicationContext
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "social_share")
channel.setMethodCallHandler(this)
}

@RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
activeContext = if (activity != null) activity!!.applicationContext else context!!

if (call.method == "shareInstagramStory") {
//share on instagram story
val stickerImage: String? = call.argument("stickerImage")
Expand All @@ -39,29 +42,28 @@ class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {
val backgroundTopColor: String? = call.argument("backgroundTopColor")
val backgroundBottomColor: String? = call.argument("backgroundBottomColor")
val attributionURL: String? = call.argument("attributionURL")
val file = File(registrar.activeContext().cacheDir,stickerImage)
val stickerImageFile = FileProvider.getUriForFile(registrar.activeContext(), registrar.activeContext().applicationContext.packageName + ".com.shekarmudaliyar.social_share", file)
val file = File(activeContext!!.cacheDir,stickerImage)
val stickerImageFile = FileProvider.getUriForFile(activeContext!!, activeContext!!.applicationContext.packageName + ".com.shekarmudaliyar.social_share", file)

val intent = Intent("com.instagram.share.ADD_TO_STORY")
intent.type = "image/*"
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra("interactive_asset_uri", stickerImageFile)
if (backgroundImage!=null) {
//check if background image is also provided
val backfile = File(registrar.activeContext().cacheDir,backgroundImage)
val backgroundImageFile = FileProvider.getUriForFile(registrar.activeContext(), registrar.activeContext().applicationContext.packageName + ".com.shekarmudaliyar.social_share", backfile)
val backfile = File(activeContext!!.cacheDir,backgroundImage)
val backgroundImageFile = FileProvider.getUriForFile(activeContext!!, activeContext!!.applicationContext.packageName + ".com.shekarmudaliyar.social_share", backfile)
intent.setDataAndType(backgroundImageFile,"image/*")
}

intent.putExtra("content_url", attributionURL)
intent.putExtra("top_background_color", backgroundTopColor)
intent.putExtra("bottom_background_color", backgroundBottomColor)
Log.d("", registrar.activity().toString())
Log.d("", activity!!.toString())
// Instantiate activity and verify it will resolve implicit intent
val activity: Activity = registrar.activity()
activity.grantUriPermission("com.instagram.android", stickerImageFile, Intent.FLAG_GRANT_READ_URI_PERMISSION)
if (activity.packageManager.resolveActivity(intent, 0) != null) {
registrar.activeContext().startActivity(intent)
activity!!.grantUriPermission("com.instagram.android", stickerImageFile, Intent.FLAG_GRANT_READ_URI_PERMISSION)
if (activity!!.packageManager.resolveActivity(intent, 0) != null) {
activeContext!!.startActivity(intent)
result.success("success")
} else {
result.success("error")
Expand All @@ -74,22 +76,22 @@ class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {
val attributionURL: String? = call.argument("attributionURL")
val appId: String? = call.argument("appId")

val file = File(registrar.activeContext().cacheDir,stickerImage)
val stickerImageFile = FileProvider.getUriForFile(registrar.activeContext(), registrar.activeContext().applicationContext.packageName + ".com.shekarmudaliyar.social_share", file)
val file = File(activeContext!!.cacheDir,stickerImage)
val stickerImageFile = FileProvider.getUriForFile(activeContext!!, activeContext!!.applicationContext.packageName + ".com.shekarmudaliyar.social_share", file)
val intent = Intent("com.facebook.stories.ADD_TO_STORY")
intent.type = "image/*"
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra("com.facebook.platform.extra.APPLICATION_ID", appId)
intent.putExtra("interactive_asset_uri", stickerImageFile)
intent.putExtra("content_url", attributionURL)
intent.putExtra("top_background_color", backgroundTopColor)
intent.putExtra("bottom_background_color", backgroundBottomColor)
Log.d("", registrar.activity().toString())
Log.d("", activity!!.toString())
// Instantiate activity and verify it will resolve implicit intent
val activity: Activity = registrar.activity()
activity.grantUriPermission("com.facebook.katana", stickerImageFile, Intent.FLAG_GRANT_READ_URI_PERMISSION)
if (activity.packageManager.resolveActivity(intent, 0) != null) {
registrar.activeContext().startActivity(intent)
activity!!.grantUriPermission("com.facebook.katana", stickerImageFile, Intent.FLAG_GRANT_READ_URI_PERMISSION)
if (activity!!.packageManager.resolveActivity(intent, 0) != null) {
activeContext!!.startActivity(intent)
result.success("success")
} else {
result.success("error")
Expand All @@ -103,8 +105,8 @@ class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {

if (image!=null) {
//check if image is also provided
val imagefile = File(registrar.activeContext().cacheDir,image)
val imageFileUri = FileProvider.getUriForFile(registrar.activeContext(), registrar.activeContext().applicationContext.packageName + ".com.shekarmudaliyar.social_share", imagefile)
val imagefile = File(activeContext!!.cacheDir,image)
val imageFileUri = FileProvider.getUriForFile(activeContext!!, activeContext!!.applicationContext.packageName + ".com.shekarmudaliyar.social_share", imagefile)
intent.type = "image/*"
intent.putExtra(Intent.EXTRA_STREAM,imageFileUri)
} else {
Expand All @@ -116,16 +118,17 @@ class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {
//create chooser intent to launch intent
//source: "share" package by flutter (https://github.com/flutter/plugins/blob/master/packages/share/)
val chooserIntent: Intent = Intent.createChooser(intent, null /* dialog title optional */)
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

registrar.activeContext().startActivity(chooserIntent)
activeContext!!.startActivity(chooserIntent)
result.success(true)

} else if (call.method == "copyToClipboard") {
//copies content onto the clipboard
val content: String? = call.argument("content")
val clipboard =registrar.context().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipboard =context!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("", content)
clipboard.primaryClip = clip
clipboard.setPrimaryClip(clip)
result.success(true)
} else if (call.method == "shareWhatsapp") {
//shares content on WhatsApp
Expand All @@ -135,7 +138,7 @@ class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {
whatsappIntent.setPackage("com.whatsapp")
whatsappIntent.putExtra(Intent.EXTRA_TEXT, content)
try {
registrar.activity().startActivity(whatsappIntent)
activity!!.startActivity(whatsappIntent)
result.success("true")
} catch (ex: ActivityNotFoundException) {
result.success("false")
Expand All @@ -149,7 +152,7 @@ class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {
intent.data = Uri.parse("sms:" )
intent.putExtra("sms_body", content)
try {
registrar.activity().startActivity(intent)
activity!!.startActivity(intent)
result.success("true")
} catch (ex: ActivityNotFoundException) {
result.success("false")
Expand All @@ -164,7 +167,7 @@ class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(urlScheme)
try {
registrar.activity().startActivity(intent)
activity!!.startActivity(intent)
result.success("true")
} catch (ex: ActivityNotFoundException) {
result.success("false")
Expand All @@ -178,7 +181,7 @@ class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {
telegramIntent.setPackage("org.telegram.messenger")
telegramIntent.putExtra(Intent.EXTRA_TEXT, content)
try {
registrar.activity().startActivity(telegramIntent)
activity!!.startActivity(telegramIntent)
result.success("true")
} catch (ex: ActivityNotFoundException) {
result.success("false")
Expand All @@ -189,7 +192,7 @@ class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {
//creating a mutable map of apps
var apps:MutableMap<String, Boolean> = mutableMapOf()
//assigning package manager
val pm: PackageManager =registrar.context().packageManager
val pm: PackageManager =context!!.packageManager
//get a list of installed apps.
val packages = pm.getInstalledApplications(PackageManager.GET_META_DATA)
//intent to check sms app exists
Expand All @@ -211,4 +214,24 @@ class SocialSharePlugin(private val registrar: Registrar): MethodCallHandler {
result.notImplemented()
}
}

override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}

override fun onAttachedToActivity(binding: ActivityPluginBinding) {
activity = binding.getActivity()
}

override fun onDetachedFromActivityForConfigChanges() {
activity = null
}

override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
activity = binding.activity
}

override fun onDetachedFromActivity() {
activity = null
}
}
16 changes: 16 additions & 0 deletions ios/Classes/SocialSharePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,14 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
NSArray *objectsToShare = @[content];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:objectsToShare applicationActivities:nil];
UIViewController *controller =[UIApplication sharedApplication].keyWindow.rootViewController;

// Check if user is on iPad and present popover
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
if ([activityVC respondsToSelector:@selector(popoverPresentationController)]) {
activityVC.popoverPresentationController.sourceView = controller.view;
}
}

[controller presentViewController:activityVC animated:YES completion:nil];
result([NSNumber numberWithBool:YES]);
} else {
Expand All @@ -294,6 +302,14 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
NSArray *objectsToShare = @[content, imgShare];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:objectsToShare applicationActivities:nil];
UIViewController *controller =[UIApplication sharedApplication].keyWindow.rootViewController;

// Check if user is on iPad and present popover
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
if ([activityVC respondsToSelector:@selector(popoverPresentationController)]) {
activityVC.popoverPresentationController.sourceView = controller.view;
}
}

[controller presentViewController:activityVC animated:YES completion:nil];
result([NSNumber numberWithBool:YES]);
}
Expand Down