Skip to content


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

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

SharePlay

概要

iOS 15アップデートの一部としてAppleがリリースした新しい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!