receive_sharing_intent
receive_sharing_intent copied to clipboard
iOS app does not recieve Intent on the latest iOS version
Hey, I made all the setup for both platforms. It builds and I can see my app in share options in given app (youtube). On Android device I can recieve intent in my app, and iOS does not work.
Any idea why can't recieve text in my iOS app ? Regards
struggling to make it work on iOS and would love to hear update on this
Doesn't work on the latest version too on iOS. Sharing intent does nothing when clicked
I was with the same problem and fixed it just adding the "group.your.app.path" to the Capability of the "Shared Extension" target. Same thing I add in the Runner target.
@lecavallari
Do you mean to add it into App Groups ? Or change Bundle Identifier in Share Extension? Have you tested on the latest OS ?
Yes, try to add the "group.your.app.path" in the App Groups of the Share Extension target. The same way you did in the App Groups of the Runner target. I'm not able to teste in a real device, but it works well in the simulators.
I'm having a similar problem. It must be a problem with my xcode setup? Here's what mine looks like
@lecavallari I have similar setup as @boxabirds
I have tested on iOS 13 and it works. So it does not work only on the latest iOS version
@KasemJaffer do you confirm the bug? are you planning to work on it ?
FYI, I just tried running the example app on my iPad with OS 14 and it runs fine. So might be implementation issue.
Very likely. What’s the issue though? It’s proving elusive.
On Thu, 7 Jan 2021 at 14:23, Angga Dwi Arifandi [email protected] wrote:
FYI, I just tried running the example app on my iPad with OS 14 and it runs fine. So might be implementation issue.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/KasemJaffer/receive_sharing_intent/issues/116#issuecomment-756147229, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABD62JUXQCG53OF77JXLG3SYW7XZANCNFSM4VHBZTIQ .
Very likely. What’s the issue though? It’s proving elusive. … On Thu, 7 Jan 2021 at 14:23, Angga Dwi Arifandi @.***> wrote: FYI, I just tried running the example app on my iPad with OS 14 and it runs fine. So might be implementation issue. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#116 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABD62JUXQCG53OF77JXLG3SYW7XZANCNFSM4VHBZTIQ .
Basically on iOS 14.0 when app is selected via the share sheet, it does nothing (not opening the app at all). I'm currently investigating it.
Yes agreed. Sorry I meant what is the cause …
On Thu, 7 Jan 2021 at 14:51, Angga Dwi Arifandi [email protected] wrote:
Very likely. What’s the issue though? It’s proving elusive. … <#m_-112722070415764581_> On Thu, 7 Jan 2021 at 14:23, Angga Dwi Arifandi @.***> wrote: FYI, I just tried running the example app on my iPad with OS 14 and it runs fine. So might be implementation issue. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#116 (comment) https://github.com/KasemJaffer/receive_sharing_intent/issues/116#issuecomment-756147229>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABD62JUXQCG53OF77JXLG3SYW7XZANCNFSM4VHBZTIQ .
Basically on iOS 14.0 when app is selected via the share sheet, it does nothing (not opening the app at all). I'm currently investigating it.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/KasemJaffer/receive_sharing_intent/issues/116#issuecomment-756162895, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABD62LZQPPPGN4MJW44RXTSYXC53ANCNFSM4VHBZTIQ .
Yes agreed. Sorry I meant what is the cause … On Thu, 7 Jan 2021 at 14:51, Angga Dwi Arifandi [email protected] wrote: … Very likely. What’s the issue though? It’s proving elusive. … <#m_-112722070415764581_> On Thu, 7 Jan 2021 at 14:23, Angga Dwi Arifandi @.***> wrote: FYI, I just tried running the example app on my iPad with OS 14 and it runs fine. So might be implementation issue. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#116 (comment) <#116 (comment)>>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABD62JUXQCG53OF77JXLG3SYW7XZANCNFSM4VHBZTIQ . Basically on iOS 14.0 when app is selected via the share sheet, it does nothing (not opening the app at all). I'm currently investigating it. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#116 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABD62LZQPPPGN4MJW44RXTSYXC53ANCNFSM4VHBZTIQ .
Alright finally found the solution, this is what worked for me
- Upgrade to the latest version of the package (previously I was using 1.4.0+2, now I upgrade to 1.4.2 (don't forget to run flutter pub upgrade)
- Because I have 2 flavor setup on my project (dev and prod), I use this code below as a bundle identifier
var hostAppBundleIdentifier = Bundle.main.bundleIdentifier?
.replacingOccurrences(of: ".share-extension", with: "")
turns out it can be null at times, so I need to add a default value in case of null.
3. Previously the order of initialization on the Flutter side was textStream
then mediaStream
, when I reversed it suddenly it's working.
Before
// For sharing or opening urls/text coming from outside the app while the app is in the memory
_textStreamSubscription = ReceiveSharingIntent.getTextStream().listen(
_onSharedText,
);
// For sharing or opening urls/text coming from outside the app while the app is closed
ReceiveSharingIntent.getInitialText().then(_onSharedText);
// For sharing or opening files coming from outside the app while the app is in the memory
_mediaStreamSubscription = ReceiveSharingIntent.getMediaStream().listen(
_onSharedMedia,
);
// For sharing or opening media coming from outside the app while the app is closed
ReceiveSharingIntent.getInitialMedia().then(_onSharedMedia);
After
// For sharing or opening files coming from outside the app while the app is in the memory
_mediaStreamSubscription = ReceiveSharingIntent.getMediaStream().listen(
_onSharedMedia,
);
// For sharing or opening media coming from outside the app while the app is closed
ReceiveSharingIntent.getInitialMedia().then(_onSharedMedia);
// For sharing or opening urls/text coming from outside the app while the app is in the memory
_textStreamSubscription = ReceiveSharingIntent.getTextStream().listen(
_onSharedText,
);
// For sharing or opening urls/text coming from outside the app while the app is closed
ReceiveSharingIntent.getInitialText().then(_onSharedText);
After I did steps above, it started to work. I hope that helps someone.
I'm facing same issue in iOS the app open after post text but stream never listen any thing even null not show
Hi, are there any updates? I did the full iOS configuration (Share extension, app group, provisioning profiles, ...). My project runs but when I share text or media my app is launched but the value is null. Is there an implementation issue in the ShareViewController file?
This is how my ShareViewController looks like: `
//
// ShareViewController.swift
// Share Extension
//
// Created by Jordan de Vogelaere on 11/01/2021.
// Copyright © 2021 The Chromium Authors. All rights reserved.
//
import UIKit
import Social
import MobileCoreServices
import Photos
class ShareViewController: SLComposeServiceViewController {
// TODO: IMPORTANT: This should be your host app bundle identifier
let hostAppBundleIdentifier = Bundle.main.bundleIdentifier?
.replacingOccurrences(of: ".Share-Extension", with: "")
let sharedKey = "ShareKey"
var sharedMedia: [SharedMediaFile] = []
var sharedText: [String] = []
let imageContentType = kUTTypeImage as String
let videoContentType = kUTTypeMovie as String
let textContentType = kUTTypeText as String
let urlContentType = kUTTypeURL as String
let fileURLType = kUTTypeFileURL as String;
override func isContentValid() -> Bool {
return true
}
override func viewDidLoad() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
if let content = extensionContext!.inputItems[0] as? NSExtensionItem {
if let contents = content.attachments {
for (index, attachment) in (contents).enumerated() {
if attachment.hasItemConformingToTypeIdentifier(imageContentType) {
handleImages(content: content, attachment: attachment, index: index)
} else if attachment.hasItemConformingToTypeIdentifier(textContentType) {
handleText(content: content, attachment: attachment, index: index)
} else if attachment.hasItemConformingToTypeIdentifier(fileURLType) {
handleFiles(content: content, attachment: attachment, index: index)
} else if attachment.hasItemConformingToTypeIdentifier(urlContentType) {
handleUrl(content: content, attachment: attachment, index: index)
} else if attachment.hasItemConformingToTypeIdentifier(videoContentType) {
handleVideos(content: content, attachment: attachment, index: index)
}
}
}
}
}
override func didSelectPost() {
print("didSelectPost");
}
override func configurationItems() -> [Any]! {
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
return []
}
private func handleText (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
attachment.loadItem(forTypeIdentifier: textContentType, options: nil) { [weak self] data, error in
if error == nil, let item = data as? String, let this = self {
this.sharedText.append(item)
// If this is the last item, save imagesData in userDefaults and redirect to host app
if index == (content.attachments?.count)! - 1 {
let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
userDefaults?.set(this.sharedText, forKey: this.sharedKey)
userDefaults?.synchronize()
this.redirectToHostApp(type: .text)
}
} else {
self?.dismissWithError()
}
}
}
private func handleUrl (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
attachment.loadItem(forTypeIdentifier: urlContentType, options: nil) { [weak self] data, error in
if error == nil, let item = data as? URL, let this = self {
this.sharedText.append(item.absoluteString)
// If this is the last item, save imagesData in userDefaults and redirect to host app
if index == (content.attachments?.count)! - 1 {
let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
userDefaults?.set(this.sharedText, forKey: this.sharedKey)
userDefaults?.synchronize()
this.redirectToHostApp(type: .text)
}
} else {
self?.dismissWithError()
}
}
}
private func handleImages (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
attachment.loadItem(forTypeIdentifier: imageContentType, options: nil) { [weak self] data, error in
if error == nil, let url = data as? URL, let this = self {
// Always copy
let fileName = this.getFileName(from: url, type: .image)
let newPath = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")!
.appendingPathComponent(fileName)
let copied = this.copyFile(at: url, to: newPath)
if(copied) {
this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .image))
}
// If this is the last item, save imagesData in userDefaults and redirect to host app
if index == (content.attachments?.count)! - 1 {
let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey)
userDefaults?.synchronize()
this.redirectToHostApp(type: .media)
}
} else {
self?.dismissWithError()
}
}
}
private func handleVideos (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
attachment.loadItem(forTypeIdentifier: videoContentType, options: nil) { [weak self] data, error in
if error == nil, let url = data as? URL, let this = self {
// Always copy
let fileName = this.getFileName(from: url, type: .video)
let newPath = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")!
.appendingPathComponent(fileName)
let copied = this.copyFile(at: url, to: newPath)
if(copied) {
guard let sharedFile = this.getSharedMediaFile(forVideo: newPath) else {
return
}
this.sharedMedia.append(sharedFile)
}
// If this is the last item, save imagesData in userDefaults and redirect to host app
if index == (content.attachments?.count)! - 1 {
let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey)
userDefaults?.synchronize()
this.redirectToHostApp(type: .media)
}
} else {
self?.dismissWithError()
}
}
}
private func handleFiles (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
attachment.loadItem(forTypeIdentifier: fileURLType, options: nil) { [weak self] data, error in
if error == nil, let url = data as? URL, let this = self {
// Always copy
let fileName = this.getFileName(from :url, type: .file)
let newPath = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")!
.appendingPathComponent(fileName)
let copied = this.copyFile(at: url, to: newPath)
if (copied) {
this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .file))
}
if index == (content.attachments?.count)! - 1 {
let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey)
userDefaults?.synchronize()
this.redirectToHostApp(type: .file)
}
} else {
self?.dismissWithError()
}
}
}
private func dismissWithError() {
print("[ERROR] Error loading data!")
let alert = UIAlertController(title: "Error", message: "Error loading data", preferredStyle: .alert)
let action = UIAlertAction(title: "Error", style: .cancel) { _ in
self.dismiss(animated: true, completion: nil)
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
private func redirectToHostApp(type: RedirectType) {
let url = URL(string: "ShareMedia://dataUrl=\(sharedKey)#\(type)")
var responder = self as UIResponder?
let selectorOpenURL = sel_registerName("openURL:")
while (responder != nil) {
if (responder?.responds(to: selectorOpenURL))! {
let _ = responder?.perform(selectorOpenURL, with: url)
}
responder = responder!.next
}
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
enum RedirectType {
case media
case text
case file
}
func getExtension(from url: URL, type: SharedMediaType) -> String {
let parts = url.lastPathComponent.components(separatedBy: ".")
var ex: String? = nil
if (parts.count > 1) {
ex = parts.last
}
if (ex == nil) {
switch type {
case .image:
ex = "PNG"
case .video:
ex = "MP4"
case .file:
ex = "TXT"
}
}
return ex ?? "Unknown"
}
func getFileName(from url: URL, type: SharedMediaType) -> String {
var name = url.lastPathComponent
if (name.isEmpty) {
name = UUID().uuidString + "." + getExtension(from: url, type: type)
}
return name
}
func copyFile(at srcURL: URL, to dstURL: URL) -> Bool {
do {
if FileManager.default.fileExists(atPath: dstURL.path) {
try FileManager.default.removeItem(at: dstURL)
}
try FileManager.default.copyItem(at: srcURL, to: dstURL)
} catch (let error) {
print("Cannot copy item at \(srcURL) to \(dstURL): \(error)")
return false
}
return true
}
private func getSharedMediaFile(forVideo: URL) -> SharedMediaFile? {
let asset = AVAsset(url: forVideo)
let duration = (CMTimeGetSeconds(asset.duration) * 1000).rounded()
let thumbnailPath = getThumbnailPath(for: forVideo)
if FileManager.default.fileExists(atPath: thumbnailPath.path) {
return SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video)
}
var saved = false
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
// let scale = UIScreen.main.scale
assetImgGenerate.maximumSize = CGSize(width: 360, height: 360)
do {
let img = try assetImgGenerate.copyCGImage(at: CMTimeMakeWithSeconds(600, preferredTimescale: Int32(1.0)), actualTime: nil)
try UIImage.pngData(UIImage(cgImage: img))()?.write(to: thumbnailPath)
saved = true
} catch {
saved = false
}
return saved ? SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video) : nil
}
private func getThumbnailPath(for url: URL) -> URL {
let fileName = Data(url.lastPathComponent.utf8).base64EncodedString().replacingOccurrences(of: "==", with: "")
let path = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(hostAppBundleIdentifier)")!
.appendingPathComponent("\(fileName).jpg")
return path
}
class SharedMediaFile: Codable {
var path: String; // can be image, video or url path. It can also be text content
var thumbnail: String?; // video thumbnail
var duration: Double?; // video duration in milliseconds
var type: SharedMediaType;
init(path: String, thumbnail: String?, duration: Double?, type: SharedMediaType) {
self.path = path
self.thumbnail = thumbnail
self.duration = duration
self.type = type
}
// Debug method to print out SharedMediaFile details in the console
func toString() {
print("[SharedMediaFile] \n\tpath: \(self.path)\n\tthumbnail: \(self.thumbnail)\n\tduration: \(self.duration)\n\ttype: \(self.type)")
}
}
enum SharedMediaType: Int, Codable {
case image
case video
case file
}
func toData(data: [SharedMediaFile]) -> Data {
let encodedData = try? JSONEncoder().encode(data)
return encodedData!
}
}
extension Array {
subscript (safe index: UInt) -> Element? {
return Int(index) < count ? self[Int(index)] : nil
}
}
`
any updates !!!
i have the same problem
Having same problem on iOS. I found out, that ShareViewController.swift will not get executed at all. I tried to add several Breakpoints in XCode and nearly every function and nothing was reached here during sharing-process.
Is something else required in order to bundle ShareViewController.swift really with the Extension?
I finally made it work after applying all these steps (only 2 of these hints where missing at my side): https://github.com/KasemJaffer/receive_sharing_intent/issues/82#issuecomment-686332264
However, wenn I share text from Safari this way into my flutter app, the Safari browser will stay in somehow modal thing that the whole app can't be used anymore and needs to be killed.
I finally made it work after applying all these steps (only 2 of these hints where missing at my side): #82 (comment)
However, wenn I share text from Safari this way into my flutter app, the Safari browser will stay in somehow modal thing that the whole app can't be used anymore and needs to be killed.
not working for me
After the last update of library it started working.
For me problems started when upgrading from 1.4.2 to 1.4.3. The app opened on a sharing intent, but nothing was shared. A simple pubspec change fixed it: receive_sharing_intent: ^1.4.3 to receive_sharing_intent: 1.4.2 (mind the missing ^, so it's fixed to 1.4.2)
Not working for me. Android works fine, but iOS is not receiving the Intent
Me too , still not working
It could be the last patch that was merged, see https://github.com/KasemJaffer/receive_sharing_intent/pull/117#issuecomment-773196108
Problem is I guess that hasMatchingSchemePrefix blocks all shared text. If I remove that or I remove the "ShareMedia" from line 10: private var customSchemePrefix = "";
it works again. But with these changes, sometimes if I share an url from Safari, Safari crashes #24
This behaviour was not in 1.4.2
It could be the last patch that was merged, see #117 (comment)
Problem is I guess that hasMatchingSchemePrefix blocks all shared text. If I remove that or I remove the "ShareMedia" from line 10: private var customSchemePrefix = "";
it works again. But with these changes, sometimes if I share an url from Safari, Safari crashes #24
This behaviour was not in 1.4.2
I have downgrade to 1.4.2 and still doesn't work , my app open but nothing received.
@woutervanwijk I don't know if this the cause of your particular issue on the latest version but I do think that I introduced a bug in my previous PR that I have addressed here: https://github.com/KasemJaffer/receive_sharing_intent/pull/140
let me know if that ends up being your issue as well.
any updates ??
Have you created a separate provision profile for ShareExtension?
I think it is depending on the source app (not your app, apps that should list up your app to share the content) I tried a number of apps including Facebook, Youtube and Linkedin etc, none of them is displaying my app to share the content, except google app. Even inside my app, I have a function to share my app content with other apps, I don't see my app on the app list to share the content (I'm using the share package). I guess Apple definitely has changed how the share intent list is fetched and displayed on the apps.
would be nice if someone can confirm this from Apple's changelog somewhere.
Possible fix, see #148
I had a similar issue (after opening the application, the stream was never updated). I found that my issue was made of using another library, that requires calling application(_:open:options:)
in the AppDelegate, which "muted" the function in this plugin. I have made some updates, which you can find in the pull-request. I hope it will help you fix your problem.
In the pull-request, there is also included the fixing of an issue when on iOS this plugin was opening the incorrect application.