Skip to content


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

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

SharePlay

概要

iOS 15 更新の一部として Apple によってリリースされた新しい GroupActivities フレームワークを使用すると、Braze アプリ内メッセージを利用して SharePlay をアプリケーションに統合することで、FaceTime を活用できるようになります。 SharePlay

ユーザーが FaceTime 通話で SharePlay ビデオを開始すると、全員の画面の上部に [開く] ボタンが表示されます。開くと、オーディオとビデオがすべての互換性のあるデバイス間で同期され、ユーザーはリアルタイムで動画を一緒に視聴できるようになります。アプリをダウンロードしていない人は、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)
}

ダッシュボードの構成

キーと値のペア:動画ファイルはアプリ内メッセージのキーと値のペアで設定する必要があり、メディア項目自体に添付することはできません。コンテンツを表示する前に、ガードレールとして beforeInAppMesageDisplayed に 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!