Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

メディア アプリ アーキテクチャの概要

このセクションでは、メディア プレーヤー アプリをメディアコントローラー(UI 用)とメディア セッション(実際のプレーヤー用)に分離する方法を説明します。 また、2 種類のメディア アプリ アーキテクチャ、すなわちオーディオ アプリに適したクライアント / サーバー型の設計と、動画プレーヤー向けのシングル アクティビティ型の設計をご紹介します。 あわせて、メディアアプリがハードウェア コントローラーに応答する方法や、オーディオ出力ストリームを使用する他のアプリと連携する方法についても説明します。

プレーヤーと UI

一般的に、オーディオまたは動画を再生するマルチメディア アプリケーションは、次の 2 つのパートから構成されます。

  • プレーヤー: デジタル メディアを取得して、動画やオーディオとしてレンダリングする
  • UI: プレーヤーを実行し、任意でプレーヤーの状態を表示するためのトランスポート コントロールを備えている

ui-and-player

Android では、デベロッパーはゼロから独自のプレーヤーをビルドするか、次のオプションの中のいずれかを選択することができます。

  • MediaPlayer クラスは、最も一般的なオーディオ / 動画フォーマット、およびデータソースをサポートする必要最小限の機能を備えたプレーヤーに、基本機能を提供します。
  • ExoPlayer は、下位レベルの Android オーディオ API を公開するオープンソース ライブラリです。 ExoPlayer は、DASH や HLS ストリーミングなど、MediaPlayer では対応していない高パフォーマンス機能をサポートしています。 また、ExoPlayer のコードをカスタマイズすると、新しいコンポーネントを容易に追加することができます。 ExoPlayer は、Android バージョン 4.1 以上でのみ利用可能です。

メディア セッションとメディア コントローラー

UI およびプレーヤーには任意の API を使用できますが、基本的に UI と プレーヤーの通信方法の本質は、どのメディア プレーヤー アプリでも同じです。 Android フレームワークでは、「メディア セッション」と 「メディア コントローラ」という 2 つのクラスが定義されています。このクラスにより、明確に定義された構造を使用して、メディア プレーヤー アプリを作成できるようになります。

メディア セッションとメディア コントローラーは、事前定義されたコールバックを使用して互いに通信します。これは、標準的なプレーヤーのアクション(再生、一時停止、停止など)に相当します。また、アプリ固有の特別な動作の定義に利用する拡張可能なカスタム呼び出しも使用します。

controller-and-session

メディア セッション

メディア セッションは、プレーヤーとのあらゆる通信を処理し、 プレーヤー API がアプリのその他の部分から見えないようにします。 プレーヤーを呼び出して制御するのは、このメディア セッションのみです。

このセッションは、プレーヤーの状態(再生中、一時停止中)の表示と再生中のデータの情報を保持します。 また、1 つ以上のメディア コントローラーからのコールバックを受けることができます。 そのため、アプリの UI、および Wear OS や Android Auto で実行中のコンパニオン端末から、プレーヤーを制御することが可能です。

メディア コントローラー

メディア コントローラーは UI を分離します。 UI のコードは、メディア コントローラーのみと通信し、プレーヤーと直接通信することはありません。 メディア コントローラーは、トランスポート コントロールのアクションをメディア セッションへのコールバックに変換します。 また、セッション状態が変化するたびに、メディア セッションからのコールバックを受けます。 これによって、関連する UI が自動的に更新されるようになります。 なお、メディア コントローラーが一度に接続できるメディア セッションは 1 つのみです。

メディア コントローラーとメディア セッションを使用すると、実行時に複数のインターフェースやプレーヤーをデプロイできます。 つまり、アプリを実行している端末の機能に応じて、アプリの表示やパフォーマンスを個別に変えることができます。

動画アプリとオーディオ アプリ

動画の再生中は、視覚と聴覚の両方を使います。 一方、オーディオの再生中は、音を聞きながら、同時に他のアプリを操作することができます。 このように動画アプリとオーディオ アプリではユースケースが違うため、設計も異なります。

動画アプリ

動画アプリには、コンテンツを表示するウィンドウが必要です。 そのため、一般的に動画アプリは、単一の Android アクティビティとして実装されます。 動画を表示する画面は、そのアクティビティの一部となります。

動画プレーヤー アクティビティ

オーディオ アプリ

オーディオ プレーヤーは、常に UI を表示する必要はありません。 いったんオーディオの再生を開始したら、プレーヤーはバックグラウンド タスクとして実行できます。 そのため、ユーザーは他のアプリに切り替えて、その操作をしながら音楽を聴き続けることができます。

Android でこの設計を実装してオーディオ アプリを作成するには、2 つのコンポーネント、つまり UI 用のアクティビティと、プレーヤー用のサービスを使用します。 サービスは、ユーザーが他のアプリに切り替えてもバックグラウンドで実行できます。 このように、オーディオ アプリの 2 つのパートを別々のコンポーネントとして作成することで、各コンポーネントがさらに効率よく動作するようになります。 一般的に、プレーヤーは UI よりも存在期間が長く、UI がない状態で長時間にわたり実行される傾向があります。

オーディオのアクティビティと BrowserService

このクライアント / サーバー型のアプローチを用いて実装するために、サポート ライブラリには、MediaBrowserServiceMediaBrowser という 2 つのクラスが用意されています。 サービス コンポーネントは、MediaBrowserService のサブクラスとして実装され、メディア セッションとそのプレーヤーを含みます。 UI とメディア コントローラーを備えたアクティビティには、MediaBrowserService と通信する MediaBrowser も含まれている必要があります。

MediaBrowserService を使用すると、コンパニオン端末(Android Auto や Android Wear など)は、容易にアプリを検出して接続し、UI アクティビティに一度もアクセスすることなく、コンテンツをブラウジングして再生をコントロールできます。

メディア アプリと Android オーディオのインフラストラクチャ

メディア アプリは、オーディオを再生する他のアプリとうまく共存するよう、適切に設計しなければなりません。 つまり、端末上にあるオーディオを扱う他のアプリと、端末を共有し、連携できるような作りにする必要があります。 また、端末のハードウェア コントロールにも応答しなければなりません。

plays-with-others

これらの動作の全容については、オーディオ出力を制御するの説明をご覧ください。

media-compat ライブラリ

media-compat ライブラリには、音声および動画を再生するアプリの作成に役立つクラスが含まれています。 これらのクラスは、Android 2.3(API レベル 9)以降を実行する端末に対応しています。 他の Android 機能と連携させることで、使いやすく、安心して利用できる Android アプリを作成することができます。

メディア セッションとメディア コントローラーは、media-compat サポート ライブラリで定義された MediaSessionCompat および MediaControllerCompat クラスを使って実装することをお勧めします。 これらのクラスは、Android 5.0(API レベル 21)で導入された以前のバージョンの MediaSession および MediaController クラスに代わるものです。 compat クラスでは同じ機能を提供しており、書き込む API は 1 つだけで済むため、アプリを開発しやすくなっています。 このライブラリは後方互換性があり、可能な場合はメディア セッション メソッドを旧バージョンのプラットフォームに対応した同等のメソッドに変換します。

稼働しているアプリで以前のクラスを使用している場合は、compat クラスにアップデートすることをお勧めします。 compat 版のクラスを使用すると、registerMediaButtonReceiver() へのすべての呼び出し、および RemoteControlClient のあらゆるメソッドを削除できます。

パフォーマンスを計測する

Android 8.0 (API レベル 26)以降では、一部のメディアクラスに getMetrics() メソッドを使用できます。 これは、PersistableBundle オブジェクトを返します。このオブジェクトに、属性と値のマップの形式で構成されている、構成とパフォーマンスの情報が入っています。 getMetrics() メソッドは、次のメディア クラスを対象に定義されています。

メトリクスは各インスタンスで別々に収集され、インスタンスの有効期間中は存続します。 利用できるメトリクスがない場合、メソッドは null を返します。 実際に返されるメトリクスは、クラスによって異なります。