How do you show a dialog when sharing a video with the FBSDK?

986 Views Asked by At

When sharing still photos, I can make my app switch to Facebook to share that image. It doesn't seem to work the same with video.

This shares a photo just fine. It moves to the Facebook application to confirm the post:

let sharePhoto = FBSDKSharePhoto()
sharePhoto.image = photo

let content = FBSDKSharePhotoContent()
content.photos = [sharePhoto]

let shareDialog: FBSDKShareDialog = FBSDKShareDialog()
shareDialog.shareContent = content
shareDialog.mode = .native
shareDialog.show()

Similarly, I cannot do this when sharing video! No dialog, does not switch to the Facebook application, and does not post the video:

let shareVdo: FBSDKShareVideo = FBSDKShareVideo()
shareVdo.videoURL = self.fileURL
let vdoContent = FBSDKShareVideoContent()
vdoContent.video = shareVdo

let shareDialog: FBSDKShareDialog = FBSDKShareDialog()
shareDialog.shareContent = vdoContent
shareDialog.mode = .native
shareDialog.show()

This will share my video, but immediately with no dialog, or moving to the Facebook app first!

let shareVdo: FBSDKShareVideo = FBSDKShareVideo()
shareVdo.videoURL = self.fileURL
let vdoContent = FBSDKShareVideoContent()
vdoContent.video = shareVdo
FBSDKShareAPI.share(with: vdoContent, delegate:self)

According to the documentation, I may have needed to convert my fileURL to an asset URL. I'm unclear if I should use the FBSDKShareAPI or not:

let shareVdo: FBSDKShareVideo = FBSDKShareVideo()
let asset = AVAsset(url: self.fileURL)
let assetURL = self.getAssetUrl(asset:asset)
shareVdo.videoURL = assetURL
let vdoContent = FBSDKShareVideoContent()
vdoContent.video = shareVdo
//FBSDKShareAPI.share(with: vdoContent, delegate:self)

let shareDialog: FBSDKShareDialog = FBSDKShareDialog()
shareDialog.shareContent = vdoContent
shareDialog.mode = .native
shareDialog.show()

If I uncomment the FBSDKShareAPI.share function call, I see "TIC Read Status" printed in my console, and it eventually posts to Facebook, but does this without showing a native share dialog. (Basically it invisibly shares to Facebook without any visual feedback to the user). I want it to move to the Facebook app with the content to be confirmed by the user, just like how sharing a photo works in my app.

Yet another attempt was to use FBSDKShareVideo with initializer arguments "videoURL" and "previewPhoto". I made sure the video is under 12 megabytes (in my case it was 4.4 MB), sharePhoto and that fileURL were both valid. The share dialog does not work, meaning it doesn't shift into the native Facebook app. The Facebook developers guide shows it using an imagePickerController, which might mean that the SDK requires the video coming from your camera roll.

let photo = self.uiImages[0]

let sharePhoto = FBSDKSharePhoto()
sharePhoto.image = photo

let filePath = self.fileURL

// get size of video in bytes
do {
    var fileSize : UInt64
    let attr = try FileManager.default.attributesOfItem(atPath: (filePath?.path)!)
    fileSize = attr[FileAttributeKey.size] as! UInt64

    print(fileSize)

} catch {
    print("Error: \(error)")
}

let shareVideo = FBSDKShareVideo(videoURL: self.fileURL, previewPhoto: sharePhoto)

let content = FBSDKShareVideoContent()
content.video = shareVideo

let shareDialog: FBSDKShareDialog = FBSDKShareDialog()

shareDialog.shareContent = content

shareDialog.mode = .native
shareDialog.show()
1

There are 1 best solutions below

0
On BEST ANSWER

Here's how I got it to work. There's a particular URL format that FB requires.

if let lastAsset = fetchResult.firstObject {
  let localID = lastAsset.localIdentifier
  let assetID = localID.replacingOccurrences(of: "/.*", with: "", options: NSString.CompareOptions.regularExpression, range: nil)
  let ext = "mp4"
  let assetURLStr = "assets-library://asset/asset.\(ext)?id=\(assetID)&ext=\(ext)"
  let video = FBSDKShareVideo(videoURL: URL(string: assetURLStr))
  let content = FBSDKShareVideoContent()
  content.video = video                    
  let dialog = FBSDKShareDialog()
  dialog.delegate = self
  dialog.shareContent = content
  dialog.shouldFailOnDataError = true
  dialog.mode = .automatic                    
  dialog.fromViewController = self

  dialog.show()
}

This uses the other approach with ShareDialog() instead of FBSDKShareDialog()

let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let fetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions)
if let lastAsset = fetchResult.firstObject {
  let localID = lastAsset.localIdentifier
  let assetID = localID.replacingOccurrences(of: "/.*", with: "", options: NSString.CompareOptions.regularExpression, range: nil)
  let ext = "mp4"
  let assetURLStr = "assets-library://asset/asset.\(ext)?id=\(assetID)&ext=\(ext)"
  let video = Video(url: URL(string: assetURLStr)!)
  let content = VideoShareContent(video: video)
  let dialog = ShareDialog(content: content)
  dialog.failsOnInvalidData = true
  dialog.mode = .automatic
  dialog.presentingViewController = self
  do {
    try dialog.show()
  } catch {
    print(error)
  }
}