Android マルチメディア フレームワークは、音声、動画、画像のアプリへの統合を容易に行えるようにするため、一般に使用されているさまざまなメディアタイプの再生をサポートしています。アプリのリソース(生リソース)に保存されたメディア ファイル、ファイルシステム内のスタンドアロン ファイル、ネットワーク接続を介したデータ ストリーミングからの音声や動画の再生を、すべて MediaPlayer
API を使用して行えます。
このドキュメントでは、優れたパフォーマンスと快適なユーザー エクスペリエンスが得られるようユーザーおよびシステムとやりとりを行うメディア再生アプリの作成方法を説明します。
注: 音声データは標準出力デバイスでのみ再生できます。現時点で該当するのは、モバイル デバイスのスピーカーまたは Bluetooth ヘッドセットです。通話中に音声ファイルを再生して会話の音声にすることはできません。
基本情報
Android フレームワークでの音声と動画の再生には、次のクラスを使用します。
MediaPlayer
- このクラスは、音声と動画の再生においてメインとなる API です。
AudioManager
- このクラスは、デバイスの音声ソースと音声出力の管理に使用します。
マニフェストの宣言
MediaPlayer を使用するアプリの開発を始める前に、関連機能を使えるようにするための宣言がマニフェストに含まれていることを確認してください。
- インターネット権限 - MediaPlayer を使用してネットワークベースのコンテンツをストリーミングする場合は、アプリでネットワーク アクセスを要求する必要があります。
<uses-permission android:name="android.permission.INTERNET" />
- wake lock 権限 - プレーヤー アプリで画面が暗くならないようにしたり、プロセッサをスリープ状態にしないようにしたり、
MediaPlayer.setScreenOnWhilePlaying()
メソッドやMediaPlayer.setWakeMode()
メソッドを使用したりする場合は、この権限を要求する必要があります。<uses-permission android:name="android.permission.WAKE_LOCK" />
MediaPlayer の使用
MediaPlayer
クラスは、メディア フレームワークの重要なコンポーネントです。このクラスのオブジェクトを使用すると、音声と動画の両方のフェッチ、デコード、再生を最小限の設定で行えます。また、次のような複数のメディアソースをサポートしています。
- ローカル リソース
- コンテンツ リゾルバから取得できるような内部 URI
- 外部 URL(ストリーミング)
Android がサポートするメディア形式の一覧については、サポートされるメディア形式のページをご覧ください。
以下に、ローカル生リソースとして利用可能な音声(アプリの res/raw/
ディレクトリに保存されている)を再生する方法の例を示します。
Kotlin
var mediaPlayer: MediaPlayer? = MediaPlayer.create(context, R.raw.sound_file_1) mediaPlayer?.start() // no need to call prepare(); create() does that for you
Java
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1); mediaPlayer.start(); // no need to call prepare(); create() does that for you
ここで、「生」リソースとは、システムにより特定の方法でパースされないファイルのことです。ただし、リソースの内容は生の音声であってはなりません。適切にエンコードおよびフォーマットされた、サポート対象形式のメディア ファイルである必要があります。
これを、システム内でローカルに利用可能な URI(たとえば、コンテンツ リゾルバから取得したもの)から再生する方法は次のとおりです。
Kotlin
val myUri: Uri = .... // initialize Uri here val mediaPlayer: MediaPlayer? = MediaPlayer().apply { setAudioStreamType(AudioManager.STREAM_MUSIC) setDataSource(applicationContext, myUri) prepare() start() }
Java
Uri myUri = ....; // initialize Uri here MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setDataSource(getApplicationContext(), myUri); mediaPlayer.prepare(); mediaPlayer.start();
リモート URL から HTTP ストリーミングで再生する方法は次のとおりです。
Kotlin
val url = "http://........" // your URL here val mediaPlayer: MediaPlayer? = MediaPlayer().apply { setAudioStreamType(AudioManager.STREAM_MUSIC) setDataSource(url) prepare() // might take long! (for buffering, etc) start() }
Java
String url = "http://........"; // your URL here MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setDataSource(url); mediaPlayer.prepare(); // might take long! (for buffering, etc) mediaPlayer.start();
注: URL を渡してオンライン メディア ファイルをストリーミングする場合は、そのファイルがプログレッシブ ダウンロード可能でなければなりません。
注意: 参照するファイルが存在しない可能性もあるため、setDataSource()
を使用する場合は、IllegalArgumentException
と IOException
を catch または pass する必要があります。
非同期での準備
MediaPlayer
の使い方は、原則的には簡単です。ただし、通常の Android アプリと適切に統合するには、さらにいくつかの注意事項があります。たとえば、prepare()
の呼び出しは、メディアデータのフェッチとデコードを伴う可能性があるため、実行に時間がかかる場合があります。そのため、実行に時間がかかる可能性のある他のメソッドと同様、アプリの UI スレッドから呼び出さないようにしなければなりません。UI スレッドから呼び出してしまうと、メソッドが返されるまで UI がハングし、ユーザー エクスペリエンスの低下や ANR(アプリケーション応答なし)エラーを招く可能性があるためです。リソースの読み込みはすぐに終わると思われる場合でも、UI のレスポンスに 1/10 秒以上かかると顕著な一時停止が発生すること、ユーザーに遅いアプリという印象を与えることを忘れないでください。
UI スレッドのハングを回避するには、別のスレッドを生成して MediaPlayer
の準備を行い、完了したらメインスレッドに通知するようにします。このスレッド処理のロジックは、自分で記述することもできます。ただ、この処理は MediaPlayer
を使用する場合にはよく行われるため、フレームワークにはそのための prepareAsync()
メソッドが用意されており、これを使用するほうが便利です。このメソッドは、バックグラウンドでメディアの準備を開始すると、すぐに戻ってきます。メディアの準備が完了したら、setOnPreparedListener()
で設定した MediaPlayer.OnPreparedListener
の onPrepared()
メソッドが呼び出されます。
状態の管理
MediaPlayer
についてもう一つ忘れてはならないのが、状態ベースであるという点です。つまり、操作によっては、プレーヤーが特定の状態のときにのみ有効になります。そのため、コードを記述する際には、常に MediaPlayer
の内部状態を意識する必要があります。状態に適さない操作を行うと、システムから例外がスローされるなど、望ましくない動作が発生する可能性があります。
MediaPlayer
クラスのドキュメントには完全な状態遷移図が示されており、 の状態がどのメソッドによりどう変わるかがわかるようになっています。
たとえば、新たに作成された MediaPlayer
は「アイドル」状態です。その時点で、setDataSource()
を呼び出して初期化する必要がありますが、それにより「初期化済み」状態になります。その後、prepare()
メソッドまたは prepareAsync()
メソッドを使用して準備する必要があります。MediaPlayer
の準備が完了すると、「準備完了」状態になります。つまり、start()
を呼び出してメディアを再生できます。図が示すように、この時点では、start()
、pause()
、seekTo()
などのメソッドを呼び出すことで、「開始済み」、「一時停止」、「再生完了」の各状態間を行き来できます。ただし、stop()
を呼び出した場合は、MediaPlayer
を再度準備するまで start()
を呼び出すことはできません。
状態に合わないメソッドの呼び出しは、よく見られるバグです。MediaPlayer
オブジェクトを操作するコードを記述する際は、常に状態遷移図を念頭に置いてください。
MediaPlayer の解放
MediaPlayer
は、貴重なシステム リソースを消費しうるものです。
そのため、MediaPlayer
インスタンスが必要以上に長く存在することのないよう、常に特別な措置を講じなければなりません。使用を終了したら必ず release()
を呼び出して、割り当てられたシステム リソースが適切に解放されるようにする必要があります。たとえば、MediaPlayer
を使用中にアクティビティで onStop()
呼び出しを受け取った場合は、MediaPlayer
を解放する必要があります。アクティビティとユーザーとの間にやりとりがない間、これを保持しておく意味はあまりないからです(バックグラウンドでメディアを再生している場合を除きます。これについては次のセクションで説明します)。
当然のことながら、アクティビティを再開または再起動するときには、再生を再開する前に、MediaPlayer
を新たに作成してもう一度準備を行う必要があります。
MediaPlayer
の解放と無効化は次のように行います。
Kotlin
mediaPlayer?.release() mediaPlayer = null
Java
mediaPlayer.release(); mediaPlayer = null;
例として、MediaPlayer
をアクティビティ停止時に解放し忘れ、アクティビティ再開時に新しく作成した場合に起こりうる問題を考えてみましょう。ご存知のように、ユーザーが画面の向きを変更する(またはそのようにデバイス設定を変更する)と、その処理のためにシステムによってアクティビティが再起動されます(デフォルトの場合)。これにより、ユーザーがデバイスの縦向きと横向きを切り替えるたびに、大量のシステム リソースが一度に消費されることになります。向きが変わるたびに、MediaPlayer
が解放されず、新たに作成されるためです。ランタイムの再起動の詳細については、構成の変更を処理するをご覧ください。
ユーザーがアクティビティを離れた場合でも、組み込みの音楽アプリで行うのと同様に、「バックグラウンド メディア」の再生を続けたい場合はどうすればよいか、という疑問が生じるかもしれません。その場合は、次のセクションで説明するように、サービスで制御する MediaPlayer
が必要になります。
サービス内での MediaPlayer の使用
アプリが画面上にないときでも、バックグラウンドからメディアを再生する場合、つまり、ユーザーが他のアプリを操作している間も再生を続ける場合は、サービスを開始して、そこから MediaPlayer
インスタンスを制御する必要があります。
それには、MediaPlayer を MediaBrowserServiceCompat
サービスに埋め込んで、別のアクティビティで MediaBrowserCompat
から操作します。
このクライアント サーバーのセットアップには注意が必要です。バックグラウンド サービスで実行されるプレーヤーと、システムの他の部分とのやりとりの方法に、いくつかの前提があるためです。アプリがこれらの前提を満たさない場合は、ユーザー エクスペリエンスが低下する可能性があります。詳細については、オーディオ アプリの作成をご覧ください。
このセクションでは、サービス内に実装された MediaPlayer を管理する際の特別な手順について説明します。
非同期での実行
まず大事なことは、Activity
と同様に、Service
内の作業はデフォルトですべて単一のスレッドで行われるということです。実際に、アクティビティとサービスを同じアプリから実行すると、デフォルトでは両方とも同じスレッド(「メインスレッド」)を使用します。そのため、サービスでは受信インテントを迅速に処理し、応答に時間がかかる計算は行わないようにする必要があります。負荷の高い作業や進行を妨げる呼び出しになると予測されるタスクは、非同期で実行する必要があります。そのためには、別のスレッドを自分で実装するか、Android フレームワークがサポートするさまざまな非同期処理用の仕組みを使用します。
たとえば、メインスレッドから MediaPlayer
を使用する場合は、prepare()
ではなく prepareAsync()
を呼び出し、MediaPlayer.OnPreparedListener
を実装することによって、再生開始の準備が完了したら通知を受けるようにします。コード例を以下に示します。
Kotlin
private const val ACTION_PLAY: String = "com.example.action.PLAY" class MyService: Service(), MediaPlayer.OnPreparedListener { private var mMediaPlayer: MediaPlayer? = null override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { ... val action: String = intent.action when(action) { ACTION_PLAY -> { mMediaPlayer = ... // initialize it here mMediaPlayer?.apply { setOnPreparedListener(this@MyService) prepareAsync() // prepare async to not block main thread } } } ... } /** Called when MediaPlayer is ready */ override fun onPrepared(mediaPlayer: MediaPlayer) { mediaPlayer.start() } }
Java
public class MyService extends Service implements MediaPlayer.OnPreparedListener { private static final String ACTION_PLAY = "com.example.action.PLAY"; MediaPlayer mediaPlayer = null; public int onStartCommand(Intent intent, int flags, int startId) { ... if (intent.getAction().equals(ACTION_PLAY)) { mediaPlayer = ... // initialize it here mediaPlayer.setOnPreparedListener(this); mediaPlayer.prepareAsync(); // prepare async to not block main thread } } /** Called when MediaPlayer is ready */ public void onPrepared(MediaPlayer player) { player.start(); } }
非同期エラーの処理
同期操作の場合は、通常、エラーは例外またはエラーコードで通知されますが、非同期リソースを使用する場合は常に、アプリにエラーが適切に通知されるよう注意する必要があります。MediaPlayer
についてこれを行うには、次のように、MediaPlayer.OnErrorListener
を実装して MediaPlayer
インスタンスに設定します。
Kotlin
class MyService : Service(), MediaPlayer.OnErrorListener { private var mediaPlayer: MediaPlayer? = null fun initMediaPlayer() { // ...initialize the MediaPlayer here... mediaPlayer?.setOnErrorListener(this) } override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean { // ... react appropriately ... // The MediaPlayer has moved to the Error state, must be reset! } }
Java
public class MyService extends Service implements MediaPlayer.OnErrorListener { MediaPlayer mediaPlayer; public void initMediaPlayer() { // ...initialize the MediaPlayer here... mediaPlayer.setOnErrorListener(this); } @Override public boolean onError(MediaPlayer mp, int what, int extra) { // ... react appropriately ... // The MediaPlayer has moved to the Error state, must be reset! } }
エラーが発生すると、MediaPlayer
は「エラー」状態に移行し(完全な状態遷移図については クラスのドキュメントを参照)、再び使用するにはリセットが必要になるので注意してください。
wake lock の使用
バックグラウンドでメディアを再生するアプリを設計する際には、サービスの実行中にデバイスがスリープ状態になることも考慮する必要があります。Android システムでは、デバイスのスリープ中は電池を節約するため、CPU や Wi-Fi のハードウェアなど、不要なスマートフォン機能がすべてオフになります。 しかし、サービスで音楽を再生またはストリーミングしている場合は、それがシステムにより妨げられないようにする必要があります。
このような状況下でもサービスが実行され続けるようにするには、「wake lock」を使用する必要があります。wake lock とは、スマートフォンがアイドル状態でも、アプリで使用中の機能はそのまま使用可能にしておく必要があることをシステムに伝える方法です。
注意: wake lock は、常に慎重に判断のうえ、本当に必要な場合にのみ使用してください。これを使用すると、デバイスの電池寿命が大幅に短くなるためです。
MediaPlayer
の再生中は CPU が実行され続けるようにするには、 の初期化時に setWakeMode()
メソッドを呼び出します。これにより、再生中は指定したロックが MediaPlayer
によって保持され、一時停止または停止したときに解除されます。
Kotlin
mediaPlayer = MediaPlayer().apply { // ... other initialization here ... setWakeMode(applicationContext, PowerManager.PARTIAL_WAKE_LOCK) }
Java
mediaPlayer = new MediaPlayer(); // ... other initialization here ... mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
ただし、この例で取得した wake lock では、CPU が実行され続けることのみが保証されます。Wi-Fi を含むネットワークを介してメディアをストリーミングする場合は、WifiLock
も保持すべきですが、これについては手動で取得と解除を行う必要があります。Wi-Fi ロックの作成と取得は、リモート URL を使用して MediaPlayer
の準備を開始するときに行います。
コード例を以下に示します。
Kotlin
val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager val wifiLock: WifiManager.WifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock") wifiLock.acquire()
Java
WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE)) .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock"); wifiLock.acquire();
メディアを一時停止または停止するときや、ネットワークが不要になったときは、ロックを解除します。
Kotlin
wifiLock.release()
Java
wifiLock.release();
クリーンアップの実施
前述のように、MediaPlayer
オブジェクトはシステム リソースを大量に消費する可能性があるため、必要な間だけ保持し、作業が終了したら release()
を呼び出すようにします。システムのガベージ コレクションに頼るのではなく、このクリーンアップ メソッドを明示的に呼び出すことが重要です。その理由は、ガベージ コレクターが MediaPlayer
使用分の回収を開始するまでには時間がかかる場合があることと、反応するのはメモリの需要に対してのみで、他のメディア関連リソースの不足には対応できないことです。
そのため、サービスを使用している場合は、以下のようにして、必ず onDestroy()
メソッドをオーバーライドし、MediaPlayer
を確実に解放するようにします。
Kotlin
class MyService : Service() { private var mediaPlayer: MediaPlayer? = null // ... override fun onDestroy() { super.onDestroy() mediaPlayer?.release() } }
Java
public class MyService extends Service { MediaPlayer mediaPlayer; // ... @Override public void onDestroy() { super.onDestroy(); if (mediaPlayer != null) mediaPlayer.release(); } }
使用終了時の解放の他にも、MediaPlayer
を解放できる機会を常に探るようにします。たとえば、長時間メディアの再生ができないと予測される場合(音声フォーカスを失った場合など)は、既存の MediaPlayer
を必ず解放し、後で再度作成するようにします。一方、短時間だけ再生を停止する場合は、MediaPlayer
をそのまま保持して、再度の作成と準備にかかるオーバーヘッドを回避するほうがよいでしょう。
デジタル著作権管理(DRM)
Android 8.0(API レベル 26)以降の MediaPlayer
には、DRM で保護された素材の再生をサポートする API が含まれています。これらは、MediaDrm
で利用できる低レベル API に似ていますが、より高いレベルで動作し、基礎となる Extractor オブジェクト、Drm オブジェクト、Crypto オブジェクトは公開されません。
MediaPlayer DRM API は、MediaDrm
の機能をすべて提供するわけではありませんが、一般的な用途はサポートしています。現在の実装では、次のコンテンツ タイプを処理できます。
- Widevine で保護されたローカル メディア ファイル
- Widevine で保護されたリモート(またはストリーミング)メディア ファイル
次のコード スニペットは、単純な同期実装における新しい MediaPlayer の DRM メソッドの使用例を示しています。
DRM で保護されたメディアを管理するには、以下に示すように、MediaPlayer 呼び出しの通常のフローに新しいメソッドを含める必要があります。
Kotlin
mediaPlayer?.apply { setDataSource() setOnDrmConfigHelper() // optional, for custom configuration prepare() drmInfo?.also { prepareDrm() getKeyRequest() provideKeyResponse() } // MediaPlayer is now ready to use start() // ...play/pause/resume... stop() releaseDrm() }
Java
setDataSource(); setOnDrmConfigHelper(); // optional, for custom configuration prepare(); if (getDrmInfo() != null) { prepareDrm(); getKeyRequest(); provideKeyResponse(); } // MediaPlayer is now ready to use start(); // ...play/pause/resume... stop(); releaseDrm();
まずは、通常どおり setDataSource()
を使用してソースの設定を行い、MediaPlayer
オブジェクトを初期化します。次に、DRM を使用するため、以下の手順を行います。
- アプリでカスタム設定を使用する場合は、
OnDrmConfigHelper
インターフェースを定義し、これをsetOnDrmConfigHelper()
を使用してプレーヤーにアタッチします。 prepare()
を呼び出します。getDrmInfo()
を呼び出します。ソースに DRM コンテンツが含まれる場合、このメソッドから null 以外のMediaPlayer.DrmInfo
値が返されます。
MediaPlayer.DrmInfo
が存在する場合:
- 使用可能な UUID のマップを調べ、1 つを選択します。
prepareDrm()
を呼び出して、現在のソースに対する DRM 設定を準備します。OnDrmConfigHelper
コールバックを作成して登録した場合は、prepareDrm()
の実行中にこのコールバックが呼び出されます。これにより、DRM セッションが開かれる前に DRM プロパティのカスタム設定を行えます。このコールバックは、prepareDrm()
を呼び出したスレッドと同期して呼び出されます。DRM プロパティにアクセスするには、getDrmPropertyString()
とsetDrmPropertyString()
を呼び出します。 長時間の操作は避けてください。- デバイスがまだプロビジョニングされていない場合、
prepareDrm()
ではプロビジョニング サーバーにアクセスしてデバイスのプロビジョニングを行います。これにかかる時間は、ネットワーク接続に依存します。 - ライセンス サーバーに送信する不透明なキーリクエスト バイト配列を取得するには、
getKeyRequest()
を呼び出します。 - ライセンス サーバーから受信したキーレスポンスについて DRM エンジンに通知するには、
provideKeyResponse()
を呼び出します。結果はキーリクエストのタイプによって、次のように異なります。- オフライン キーリクエストに対するレスポンスの場合、結果はキーセット ID になります。このキーセット ID を使用して
restoreKeys()
を呼び出すことにより、キーを新しいセッションに復元できます。 - ストリーミングまたは解放のリクエストに対するレスポンスの場合、結果は null になります。
- オフライン キーリクエストに対するレスポンスの場合、結果はキーセット ID になります。このキーセット ID を使用して
非同期での prepareDrm()
の実行
デフォルトでは、prepareDrm()
は同期的に実行され、準備が完了するまで他はブロックされます。しかし、新しいデバイスにおける最初の DRM の準備では、prepareDrm()
内部でプロビジョニングの処理も必要になる場合があり、関連するネットワーク オペレーションによっては終了まで時間がかかる可能性があります。このような prepareDrm()
によるブロックは、MediaPlayer.OnDrmPreparedListener
を定義して設定することで回避できます。
OnDrmPreparedListener
を設定した場合は、prepareDrm()
によるプロビジョニング(必要な場合)と準備はバックグラウンドで行われます。プロビジョニングと準備が完了すると、リスナーが呼び出されます。呼び出しの順序やリスナーが実行されるスレッドについては、いかなる想定もしないでください(リスナーをハンドラ スレッドに登録した場合を除く)。
リスナーの呼び出しは、prepareDrm()
から戻る前にも後にも起こりえます。
非同期での DRM の設定
DRM の準備には MediaPlayer.OnDrmInfoListener
を、またプレーヤーの起動には MediaPlayer.OnDrmPreparedListener
を作成して登録することにより、DRM を非同期で初期化できます。
これらは、以下に示すように、prepareAsync()
と連携して動作します。
Kotlin
setOnPreparedListener() setOnDrmInfoListener() setDataSource() prepareAsync() // ... // If the data source content is protected you receive a call to the onDrmInfo() callback. override fun onDrmInfo(mediaPlayer: MediaPlayer, drmInfo: MediaPlayer.DrmInfo) { mediaPlayer.apply { prepareDrm() getKeyRequest() provideKeyResponse() } } // When prepareAsync() finishes, you receive a call to the onPrepared() callback. // If there is a DRM, onDrmInfo() sets it up before executing this callback, // so you can start the player. override fun onPrepared(mediaPlayer: MediaPlayer) { mediaPlayer.start() }
Java
setOnPreparedListener(); setOnDrmInfoListener(); setDataSource(); prepareAsync(); // ... // If the data source content is protected you receive a call to the onDrmInfo() callback. onDrmInfo() { prepareDrm(); getKeyRequest(); provideKeyResponse(); } // When prepareAsync() finishes, you receive a call to the onPrepared() callback. // If there is a DRM, onDrmInfo() sets it up before executing this callback, // so you can start the player. onPrepared() { start(); }
暗号化メディアの処理
Android 8.0(API レベル 26)以降の MediaPlayer
では、共通暗号化スキーム(CENC)と、基本的なストリーミング タイプである H.264 および AAC 用の HLS サンプルレベル暗号化メディア(METHOD=SAMPLE-AES)の復号も可能です。以前は、フルセグメント暗号化メディア(METHOD = AES-128)がサポートされていました。
ContentResolver からのメディアの取得
メディア プレーヤー アプリでもう一つ便利なのは、ユーザーがデバイスに保存した音楽を取得できる機能です。これを行うには、次のように、外部メディアの ContentResolver
にクエリを送信します。
Kotlin
val resolver: ContentResolver = contentResolver val uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI val cursor: Cursor? = resolver.query(uri, null, null, null, null) when { cursor == null -> { // query failed, handle error. } !cursor.moveToFirst() -> { // no media on the device } else -> { val titleColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE) val idColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID) do { val thisId = cursor.getLong(idColumn) val thisTitle = cursor.getString(titleColumn) // ...process entry... } while (cursor.moveToNext()) } } cursor?.close()
Java
ContentResolver contentResolver = getContentResolver(); Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; Cursor cursor = contentResolver.query(uri, null, null, null, null); if (cursor == null) { // query failed, handle error. } else if (!cursor.moveToFirst()) { // no media on the device } else { int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE); int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID); do { long thisId = cursor.getLong(idColumn); String thisTitle = cursor.getString(titleColumn); // ...process entry... } while (cursor.moveToNext()); }
これを MediaPlayer
で使用するには、次のようにします。
Kotlin
val id: Long = /* retrieve it from somewhere */ val contentUri: Uri = ContentUris.withAppendedId(android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id ) mediaPlayer = MediaPlayer().apply { setAudioStreamType(AudioManager.STREAM_MUSIC) setDataSource(applicationContext, contentUri) } // ...prepare and start...
Java
long id = /* retrieve it from somewhere */; Uri contentUri = ContentUris.withAppendedId( android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id); mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setDataSource(getApplicationContext(), contentUri); // ...prepare and start...
サンプルコード
BasicMediaDecoder サンプルと DeviceOwner サンプルは、このページで説明した API の使用方法を示しています。
詳細
下記のページでは、音声と動画の記録、保存、再生について説明しています。