酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

UIActivityViewControllerを使ってFacebookとFacebook Messengerへ画像を共有できない

撮影した写真を加工して、UIActivityViewControllerを使って共有する機能を実装したところ、「FacebookとFacebook Messengerに画像を共有できない」とフィードバックをいただきました。

処理としては非常にシンプルに生成したUIImageをUIActivityViewControllerを使ってそのまま共有しています。

let vc = UIActivityViewController(activityItems: [ image ], applicationActivities: nil)
present(vc, animated: true, completion: nil)

FacebookとFacebook Messengerで共有できる画像の制限について

Facebookは、自動生成されたテキストを共有できない 的な制約があって、iOS 6くらいの頃に「共有できない不具合だ!」っと指摘されたのが記憶にあります。ソースは思い出せないので、思い出したら記載します。

https://developers.facebook.com/docs/sharing/ios?locale=ja_JP#photos によれば、下記の制限があることがわかりました。

  • 写真のサイズは12MB未満である必要があります。
  • また、利用者のデバイスにはネイティブのiOS用Facebookアプリ(バージョン7.0以上)がインストールされている必要があります。

Facebookアプリのバージョンに関しては調べる方法がないので対処不能として諦めるとして、写真のサイズに関しては共有元であるアプリでも念頭に置く必要がありそうです。

共有時にFacebookやMessengerへの共有であれば縮小してから共有する

UIActivityItemSource を継承したクラスを作ることで、Twitterへ共有する場合はハッシュタグをつけるみたいな使い方ができます。詳しい方法については Qiita などで調べてください 割愛します。

今回は、共有先が FacebookやFacebook Messenger であるならば、画像を縮小してから共有するようにしました。画像を縮小する方法に関しては ググればいくらでも出てくるため 割愛します。

//
//  ShareActivityItem.swift
//  ptcgnote
//
//  Created by KENJI WADA on 2019/05/26.
//  Copyright © 2019 KENJI WADA. All rights reserved.
//

import UIKit

class ImageActivityItem: NSObject, UIActivityItemSource {
    
    private let postToFacebookMessenger = UIActivity.ActivityType(rawValue: "com.facebook.Messenger.ShareExtension")
    
    let image: UIImage
    
    init(image: UIImage) {
        self.image = image
    }
    
    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        return image
    }
    
    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
        
        guard let activityType = activityType else {
            return image
        }
        
        let useRawImage: Bool
        
//        let type = activityType.rawValue
//        print("share to \(type)")
        
        switch activityType {
        case .airDrop:
            useRawImage = false
        case .postToFacebook:
            useRawImage = false
        case postToFacebookMessenger:
            useRawImage = false
        default:
            useRawImage = true
        }
        
        if useRawImage {
            // 指定したアプリ以外は生データを送る
            return image
        }
        
        //TODO: 画像をリサイズする処理を入れる
        return ImageUtils.resize(image, 1024) 
}

Facebook MessengerのActivityTypeに関しては、「objective c - iOS: Disabling WhatsApp in UIActivityViewController? - Stack Overflow」を参考にして実装しました。

ImageActivityItemの使い方は下記の通りです。

let activityItems = [
        ImageActivityItem(image: image)
]
let vc = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
present(vc, animated: true, completion: nil)