Skip to content


SharePlay アプリ内メッセージ実装ガイド

SharePlayは、iOS 15 FaceTimeユーザーがデバイス間で共有メディア体験を実現し、リアルタイムでオーディオと動画を同期できる新機能です。SharePlayは、ユーザーが友人や家族と一緒にコンテンツを体験できる優れた方法であり、Brazeの顧客に動画コンテンツのための新たな手段を提供し、アプリケーションを新しいユーザーに紹介する機会を提供します。

SharePlay

概要

Appleが iOS 15 アップデートの一部としてリリースした新しいGroupActivitiesフレームワークにより、Brazeのアプリ内メッセージを活用してSharePlayをアプリケーションに統合し、FaceTimeを活用できます。 SharePlay

ユーザーがFaceTime通話中にSharePlay動画を開始すると、全員の画面上部に「Open」ボタンが表示されます。開くと、すべての対応デバイスでオーディオとビデオが同期され、ユーザーはリアルタイムで一緒に動画を視聴できます。アプリをダウンロードしていないユーザーは、App Storeにリダイレクトされます。

同期メディア再生
同期メディア再生では、誰か1人がSharePlay動画を一時停止すると、すべてのデバイスで一時停止されます。

SharePlayの同期メディア再生

統合

この統合で使用されるアプリ内メッセージは、モーダルアプリ内メッセージビューコントローラーをサブクラス化したものです。設定のガイドは、iOSアプリ内メッセージの高度なユースケース実装ガイドにあります。統合する前に、XcodeプロジェクトにGroupActivitiesエンタイトルメントを追加してください。

ステップ1:XIBのオーバーライドとロード

1
2
3
4
5
6
7
8
override var nibName: String {
  return "ModalVideoViewController"
}

/// Overriding loadView() from ABKInAppMessageModalViewController to provide our own view for the in-app message
override func loadView() {
  Bundle.main.loadNibNamed(nibName, owner: self, options: nil)
}

ステップ2:アプリ内メッセージ用のAVPlayerを構成する

アプリ内メッセージは、軽量な開発者の作業でネイティブに動画を再生できます。これにより、SharePlayなど、AVPlayerVideoControllerのすべての機能にアクセスできます。この例で使用されるアプリ内メッセージは、ネイティブ動画プレーヤーを埋め込むカスタムビューを持つABKInAppMessageModalViewControllerのサブクラスです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func configureVideoPlayer() {
  guard let urlString = inAppMessage.extras?["video_url"] as? String,
        let url = URL(string: urlString) else { return }

  let videoTitle = inAppMessage.extras?["video_title"] as? String
  mediaItem = MediaItem(title: videoTitle ?? "Video Content", url: url)

  let asset = AVAsset(url: url)
  let playerItem = AVPlayerItem(asset: asset)
  player.replaceCurrentItem(with: playerItem)
  playerViewController.player = player

  addChild(playerViewController)
  videoPlayerContainer.addSubview(playerViewController.view)
  playerViewController.didMove(toParent: self)
}

ダッシュボードの設定

キーと値のペア:動画ファイルはアプリ内メッセージのキーと値のペアで設定する必要があり、メディアアイテム自体にアタッチすることはできません。また、コンテンツを表示する前のガードレールとして、beforeInAppMessageDisplayedでURL有効性チェックを追加することもできます。

トリガー:アプリ内メッセージは、再適格性を有効にして、すべてのユーザーに対して適格となるようにする必要があります。これは、メッセージを起動するデフォルトのトリガーと、SharePlayから開始されたときにメッセージを起動するもう1つのトリガーの、2つのトリガーを設定することで実現できます。iOS 15を使用していないユーザーは、ローカルでのみメッセージを表示できます。

ステップ3:グループ視聴アクティビティを作成する

GroupActivityプロトコルに準拠するオブジェクトを作成します。このオブジェクトは、SharePlayライフサイクル全体で共有されるGroupSessionのメタデータになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct MediaItem: Hashable, Codable {
  let title: String
  let url: URL
}

@available(iOS 15, *)
struct MediaItemActivity: GroupActivity {
  static let activityIdentifier = "com.book-demo.GroupWatching"

  let mediaItem: MediaItem

  var metadata: GroupActivityMetadata {
    var metadata = GroupActivityMetadata()
    metadata.type = .watchTogether
    metadata.title = mediaItem.title
    metadata.fallbackURL = mediaItem.url
    return metadata
  }
}

再生の準備

メディアアイテムの再生を準備する際、各グループアクティビティにはprepareForActivation()の3つの状態があります:

  • .activationDisabled - 個別視聴
  • .activationPreferred - 一緒に視聴
  • .cancelled - 無視して適切に処理する

状態がactivationPreferredとして返された場合、それはグループアクティビティライフサイクルの残りの部分をアクティベートするタイミングです。

SharePlayの図

ステップ4:SharePlay APIからアプリ内メッセージを起動する

GroupActivities APIは、動画が存在するかどうかを判断します。存在する場合、SharePlay対応のアプリ内メッセージを起動するカスタムイベントをトリガーする必要があります。CoordinationManagerは、ユーザーが通話から離脱または参加した場合など、SharePlayの状態変更を担当します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private var subscriptions = Set<AnyCancellable>()
private var selectedMediaItem: MediaItem? {
  didSet {
    // Ensure the UI selection always represents the currently playing media.
    guard let _ = selectedMediaItem else { return }

    if !BrazeManager.shared.inAppMessageCurrentlyVisible {
      BrazeManager.shared.logCustomEvent("SharePlay Event")
    }
  }
}

private func launchVideoPlayerIfNecessary() {
  CoordinationManager.shared.$enqueuedMediaItem
      .receive(on: DispatchQueue.main)
      .compactMap { $0 }
      .assign(to: \.selectedMediaItem, on: self)
      .store(in: &subscriptions)
}

ステップ5:アプリ内メッセージの非表示時にグループセッションを離脱する

アプリ内メッセージが非表示になったとき、SharePlayセッションを離脱し、セッションオブジェクトを破棄する適切なタイミングです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
override func viewDidDisappear(_ animated: Bool) {
  super.viewDidDisappear(animated)
  groupSession?.leave()
  CoordinationManager.shared.leave()
}

class CoordinationManager() {
...
  // Published values that the player, and other UI items, observe.
  @Published var enqueuedMediaItem: MediaItem?
  @Published var groupSession: GroupSession<MediaItemActivity>?

  // Clear activity when the user leaves
  func leave() {
    groupSession = nil
    enqueuedMediaItem = nil
  }
...
}

SharePlayボタンの表示設定

SharePlayインジケーターを動的に非表示または表示することがベストプラクティスです。isEligibleForGroupSession変数を使用して、ユーザーが現在FaceTime通話中かどうかを監視します。FaceTime通話中の場合、チャット内の互換性のあるデバイス間で動画を共有するボタンが表示される必要があります。ユーザーが初めてSharePlayを開始すると、元のデバイスにオプションを選択するプロンプトが表示されます。その後、共有先のユーザーのデバイスにコンテンツに参加するためのプロンプトが表示されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private var isEligibleForSharePlay: Bool = false {
  didSet {
    sharePlayButton.isHidden = !isEligibleForSharePlay
  }
}

override func viewDidLoad() {
  super.viewDidLoad()

  // SharePlay button eligibility
  groupStateObserver.$isEligibleForGroupSession
    .receive(on: DispatchQueue.main)
    .assign(to: \.isEligibleForSharePlay, on: self)
    .store(in: &subscriptions)
}
New Stuff!