I'd like to share an Audio file that I have loaded into a AVPlayerAsset. I was wondering if this is possible, or what the correct way of doing this would look like. Here is what my code looks like:
func shareTrack(track: Track) {
guard let file = track.playerItem else { return } // This is the AVPlayerAsset
let activityController = UIActivityViewController(activityItems: [file], applicationActivities: nil)
activityController.completionWithItemsHandler = { (nil, completed, _, error ) in
if completed {
print("Success")
} else {
print("Canceled")
}
}
DispatchQueue.main.async{
self.present(activityController, animated: true)
}
}
You are using the word "file" but the asset is not a file. It is an asset. Other programs aren't going to know anything about that. If you want to share something, share a file URL.
Related
When I use UIActivityViewController to share an image the close button becomes transparent. I can click on its frame button but it is invisible for the user. And you cannot click outside to close on the sheet.
let activityItemMetadata = LinkMetadataManager(qrImage: image)
let activityVC = UIActivityViewController(
activityItems: [activityItemMetadata],
applicationActivities: nil)
activityVC.completionWithItemsHandler = {(activityType: UIActivityType?, completed: Bool, returnedItems: [Any]?, error: Error?) in
}
activityVC.activityItemsConfiguration = [
UIActivity.ActivityType.mail,
UIActivity.ActivityType.copyToPasteboard,
UIActivity.ActivityType.airDrop,
UIActivity.ActivityType.message
] as? UIActivityItemsConfigurationReading
activityVC.isModalInPresentation = false
self.present(activityVC, animated: true)
Close button appear like this:
Most of your UIActivityViewController code is wrong.
You should not be creating a LinkMetadataManager from the image and then using it as the item you wish to share.
You are trying to create an array of activities and setting those as the activity configuration. This is all wrong.
Your code should look more like the following:
let activityVC = UIActivityViewController(activityItems: [ image ], applicationActivities: nil)
activityVC.completionWithItemsHandler = { (activityType, completed, returnedItems, error) in
if completed || activityType == nil {
// activity view is being dismissed
}
}
present(activityVC, animated: true)
If you have a need to exclude certain activities you can add a line like the following:
activityVC.excludedActivityTypes = [ .assignToContact ] // Optionally exclude specific activities
If you want a bit more control you make use of UIActivityItemsConfiguration. The following is an example:
let configuration = UIActivityItemsConfiguration(objects: [ image ])
configuration.perItemMetadataProvider = { (index, key) in
switch key {
case .linkPresentationMetadata:
// Maybe make use of your LinkMetadataManager class here
var info = LPLinkMetadata()
info.title = "Some Title"
return info
default:
return nil
}
}
let activityVC = UIActivityViewController(activityItemsConfiguration: configuration)
activityVC.completionWithItemsHandler = { (activityType, completed, returnedItems, error) in
if completed || activityType == nil {
// activity view is being dismissed
}
}
present(activityVC, animated: true)
Not able to share the video on twitter through UIActivityViewController.
Text and local video storage works fine. So authentication is not an issue.
If video is stored in the app itself, then the share works fine
Path URL
file:///private/var/containers/Bundle/Application/B7855569-3254-4CC2-9573-254D09528E38/podhunt.app/PlugIns/podhunt-shareExtension.appex/demo_video.mp4
If the path is below, then the twitter share does not work
Path Url
file:///var/mobile/Containers/Data/PluginKitPlugin/5831780C-50AF-41FA-8435-941CAC47EBE6/Documents/10c41d4a-c161-4c78-bc61-ca789804a982.mp4
This does not work
URLSession.shared.downloadTask(with: audioUrl) { location, response, error in
guard let location = location, error == nil else { return }
do {
try FileManager.default.moveItem(at: location, to: destinationUrl)
DispatchQueue.main.async {
let activityVC = UIActivityViewController(activityItems: [destinationUrl], applicationActivities: nil)
self.present(activityVC, animated: true, completion: nil)
}
} catch {
}
}.resume()
This works
URLSession.shared.downloadTask(with: audioUrl) { location, response, error in
guard let location = location, error == nil else { return }
do {
try FileManager.default.moveItem(at: location, to: destinationUrl)
DispatchQueue.main.async {
guard let path = Bundle.main.path(forResource: "demo_video", ofType:"mp4") else {
return
}
let activityVC = UIActivityViewController(activityItems: [URL(fileURLWithPath: path)],applicationActivities: nil)
self.present(activityVC, animated: true, completion: nil)
}
} catch {
}
}.resume()
I am working on iOS app extension.
Resolved. Apparently I was sharing mp3 file as an mp4 to twitter which it does not recognize. You cannot share mp3 file to twitter as it does not support audio format.
I Created and extension for sharing text along with Image.
Here is the extension class
extension UIViewController {
func shareScreen(shareText:String?,shareImage:UIImage?){
var objectsToShare = [AnyObject]()
if let shareTextObj = shareText{
objectsToShare.append(shareTextObj as AnyObject)
}
if let shareImageObj = shareImage{
objectsToShare.append(shareImageObj)
}
if shareText != nil || shareImage != nil{
let activityViewController = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
present(activityViewController, animated: true, completion: nil)
}else{
print("There is nothing to share")
}
}
}
share if its contains images only.
guard loadImage == nil else {
self.shareScreen(shareText: "AppName", shareImage: loadImage)
return
}
For Other share accessories link (Message,Email,Skype,Facebook) it worked.
When Try to share via (LinkedIn & WhatsApp) the image is not showing?
The above code which I tried, Can any one let me know is there any provision to share text along with Image including with linkedIn & WhatsApp.
I'm trying to share video from my app with UIActivityViewController.
So, the process looks like that:
User is tapping on Share button.
I have to prepare video for him with my function saveToShare().
I'm starting animation for my UIActivityIndicatorView and launching saveToShare().
I'm sending notification from saveToShare to my controller.
Observer in my controller is launching function shareVideo().
shareVideo() looks like that:
func videoIsReady() {
self.activityIndicator.stopAnimating()
self.activityIndicator.isHidden = true
let videoName = "NewWatermarkedVideoNew2Share.mov"
let exportPath = NSTemporaryDirectory().appending(videoName)
let exportUrl = URL(fileURLWithPath: exportPath)
let urlData = NSData(contentsOf: exportUrl)
if ((urlData) != nil){
let videoLink = exportUrl
let objectsToShare = [videoLink]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = self.view // so that iPads won't crash
activityVC.setValue("#myhashtag", forKey: "subject")
activityVC.excludedActivityTypes = [UIActivityType.airDrop, UIActivityType.addToReadingList, UIActivityType.assignToContact, UIActivityType.copyToPasteboard, UIActivityType.openInIBooks, UIActivityType.postToTencentWeibo, UIActivityType.postToVimeo, UIActivityType.postToWeibo, UIActivityType.print, UIActivityType.saveToCameraRoll, UIActivityType.postToFlickr, UIActivityType.postToTwitter, UIActivityType(rawValue: "com.apple.reminders.RemindersEditorExtension"), UIActivityType(rawValue: "com.apple.mobilenotes.SharingExtension"),UIActivityType(rawValue: "com.google.Drive.ShareExtension"), UIActivityType(rawValue: "com.apple.mobileslideshow.StreamShareService")]
self.present(activityVC, animated: true, completion: {
})
} else {
print("url is empty...")
}
}
It works, but my UIActivityIndicatorView is not hidden before share dialog and actually is working for several seconds after that dialog is shown.
What is wrong here?
P.S. So, it works if I put UIActivityIndicatorView in DispatchQueue.main.async so my problem is solved but I don't know why this problem was arisen in the first place.
To get it to disappear immediately, you'll want to call the code on the main queue synchronously. To avoid a dead lock (in case videoIsReady() is called from the main queue) use this little extension I've developed:
extension DispatchQueue {
class func safeUISync(execute workItem: DispatchWorkItem) {
if Thread.isMainThread { workItem.perform() }
else { DispatchQueue.main.sync(execute: workItem) }
}
class func safeUISync<T>(execute work: () throws -> T) rethrows -> T {
if Thread.isMainThread { return try work() }
else { return try DispatchQueue.main.sync(execute: work) }
}
}
Now you can call your code as follows:
func videoIsReady() {
DispatchQueue.safeUISync {
self.activityIndicator.stopAnimating()
self.activityIndicator.isHidden = true
}
...
}
You must be calling your videoIsReady() function from a background thread. All UI calls must be made from the main thread or the results are undefined. A common result is for the UI changes to take a LOOONG time to appear. (Another common result is a crash.)
I want to share QR image on tap of button using ActivityViewController.
Below is code that I’ve used :
#IBAction func btnShareQRCode_Clicked(sender: UIButton) {
self.shareQRCodeUsingActivityViewController(self.imageviewQRCode.image!)
}
func shareQRCodeUsingActivityViewController(imageParamater: UIImage) {
let activityItem: [UIImage] = [imageParamater as UIImage]
let objActivityViewController = UIActivityViewController(activityItems: activityItem as [UIImage], applicationActivities: nil)
objActivityViewController.excludedActivityTypes = [UIActivityTypeAirDrop, UIActivityTypeAddToReadingList]
// objActivityViewController.popoverPresentationController?.sourceView = sender
self.presentViewController(objActivityViewController, animated: true, completion: {
objActivityViewController.completionWithItemsHandler = { activity, success, items, error in
if !success { print("cancelled")
return
}
if activity == UIActivityTypeMail {
print("mail")
}
else if activity == UIActivityTypeMessage {
print("message")
}
else if activity == UIActivityTypeSaveToCameraRoll {
print("camera")
}
}
})
}
func completionHandler() {
}
The issue with this is that it is getting crashed on mail stating an error regarding MailComposer.
I want to know how and where these MailComposer function should be handled?
If you are running this on iOS Simulator, Mail component is likely to fail.
Apart from that, I don't think you need to cast your activity items list as UIImage. Simply put an array of objects as a activityItems array.