Framework multimedia Android menyertakan dukungan untuk memutar berbagai jenis media umum, sehingga
Anda dapat dengan mudah mengintegrasikan audio, video, dan gambar ke dalam aplikasi. Anda dapat memutar audio atau
video dari file media yang disimpan dalam resource aplikasi (resource mentah), dari file mandiri
dalam sistem file, atau dari aliran data yang masuk melalui koneksi jaringan, semuanya menggunakan MediaPlayer
API.
Dokumen ini menunjukkan cara menggunakan
MediaPlayer
untuk menulis aplikasi pemutaran media
yang berinteraksi dengan pengguna dan sistem untuk mendapatkan performa yang baik dan
pengalaman pengguna yang menyenangkan. Atau, Anda mungkin ingin
menggunakan ExoPlayer, yang merupakan library open source yang dapat disesuaikan
dan mendukung fitur performa tinggi yang tidak tersedia di MediaPlayer
Catatan: Anda hanya dapat memutar data audio ke perangkat output standar. Saat ini, perangkat tersebut mencakup speaker perangkat seluler atau headset Bluetooth. Anda tidak dapat memutar file suara dalam audio percakapan selama panggilan berlangsung.
Dasar-dasar
Class berikut digunakan untuk memutar suara dan video dalam framework Android:
MediaPlayer
- Class ini adalah API utama untuk memutar suara dan video.
AudioManager
- Class ini mengelola sumber audio dan output audio di perangkat.
Deklarasi manifes
Sebelum memulai pengembangan pada aplikasi menggunakan MediaPlayer, pastikan manifes Anda memiliki deklarasi yang sesuai untuk mengizinkan penggunaan fitur terkait.
- Izin Internet - Jika Anda menggunakan MediaPlayer untuk melakukan streaming konten berbasis
jaringan, aplikasi Anda harus meminta akses jaringan.
<uses-permission android:name="android.permission.INTERNET" />
- Izin Penguncian Layar Saat Aktif - Jika aplikasi pemutar perlu menjaga layar
agar tidak meredup atau prosesor tidak memasuki mode tidur, atau menggunakan metode
MediaPlayer.setScreenOnWhilePlaying()
atauMediaPlayer.setWakeMode()
, Anda harus meminta izin ini.<uses-permission android:name="android.permission.WAKE_LOCK" />
Menggunakan MediaPlayer
Salah satu komponen terpenting dari framework media adalah
class
MediaPlayer
. Objek class ini dapat mengambil, mendekode, dan memutar audio serta video
dengan penyiapan minimal. Class ini mendukung beberapa sumber media yang berbeda, seperti:
- Resource lokal
- URI internal, seperti yang mungkin Anda peroleh dari Content Resolver
- URL eksternal (streaming)
Untuk daftar format media yang didukung Android, lihat halaman Format Media yang Didukung.
Berikut ini contoh
cara memutar audio yang tersedia sebagai resource mentah lokal (disimpan di direktori
res/raw/
aplikasi Anda):
Kotlin
var 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
Dalam hal ini, resource "mentah" adalah file yang tidak dicoba diurai oleh sistem dengan cara tertentu. Namun, konten resource ini tidak boleh berupa audio mentah. Konten harus berupa file media yang dienkode dan diformat dengan benar dalam salah satu format yang didukung.
Dan berikut ini cara memutar dari URI yang tersedia secara lokal dalam sistem (yang Anda peroleh melalui Content Resolver, misalnya):
Kotlin
val myUri: Uri = .... // initialize Uri here val mediaPlayer = MediaPlayer().apply { setAudioAttributes( AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ) setDataSource(applicationContext, myUri) prepare() start() }
Java
Uri myUri = ....; // initialize Uri here MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioAttributes( new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ); mediaPlayer.setDataSource(getApplicationContext(), myUri); mediaPlayer.prepare(); mediaPlayer.start();
Melakukan pemutaran dari URL jarak jauh melalui streaming HTTP akan terlihat seperti ini:
Kotlin
val url = "http://........" // your URL here val mediaPlayer = MediaPlayer().apply { setAudioAttributes( AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ) setDataSource(url) prepare() // might take long! (for buffering, etc) start() }
Java
String url = "http://........"; // your URL here MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioAttributes( new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ); mediaPlayer.setDataSource(url); mediaPlayer.prepare(); // might take long! (for buffering, etc) mediaPlayer.start();
Catatan: Jika Anda meneruskan URL untuk melakukan streaming file media online, file tersebut harus dapat didownload secara progresif.
Perhatian: Anda harus menangkap atau meneruskan
IllegalArgumentException
dan IOException
saat menggunakan
setDataSource()
, karena
file yang Anda referensikan mungkin tidak ada.
Persiapan asinkron
Pada prinsipnya, penggunaan MediaPlayer
dapat dilakukan dengan mudah. Namun, perlu diingat bahwa beberapa hal lagi
diperlukan untuk mengintegrasikannya dengan benar menggunakan aplikasi Android standar. Misalnya,
panggilan ke prepare()
dapat
memerlukan waktu lama untuk dieksekusi karena
mungkin memerlukan pengambilan dan decoding data media. Jadi, seperti halnya metode
apa pun yang mungkin memerlukan waktu lama untuk dieksekusi, Anda tidak boleh memanggilnya dari
UI thread aplikasi Anda. Jika hal tersebut dilakukan, UI akan hang sampai metode kembali, yang merupakan pengalaman pengguna yang sangat buruk dan dapat menyebabkan error ANR (Aplikasi Tidak Merespons). Meskipun
Anda mengharapkan resource dimuat dengan cepat, ingat bahwa apa pun yang memerlukan waktu lebih dari sepersepuluh
detik untuk merespons di UI akan menyebabkan jeda yang cukup signifikan dan memberikan
kesan bahwa aplikasi Anda lambat kepada pengguna.
Untuk menghindari UI thread yang macet, buat thread lain untuk
menyiapkan MediaPlayer
dan beri tahu thread utama jika sudah selesai. Namun, meskipun
Anda dapat menulis sendiri logika threading, pola ini sangat umum saat menggunakan MediaPlayer
sehingga framework
menyediakan cara yang mudah untuk menyelesaikan tugas ini menggunakan
metode prepareAsync()
. Metode ini
mulai menyiapkan media di latar belakang dan segera ditampilkan. Setelah media
selesai disiapkan, metode onPrepared()
dari MediaPlayer.OnPreparedListener
yang dikonfigurasi melalui
setOnPreparedListener()
akan dipanggil.
Mengelola status
Aspek lain dari MediaPlayer
yang harus Anda ingat adalah
berbasis status. Artinya, MediaPlayer
memiliki status internal
yang harus selalu Anda ketahui saat menulis kode, karena operasi tertentu
hanya akan valid saat pemutar dalam status tertentu. Jika Anda menjalankan operasi dalam
status yang salah, sistem dapat menampilkan pengecualian atau menyebabkan perilaku lain yang tidak diinginkan.
Dokumentasi di
class MediaPlayer
menunjukkan diagram status lengkap,
yang menjelaskan metode mana yang memindahkan MediaPlayer
dari satu status ke status lainnya.
Misalnya, saat Anda membuat MediaPlayer
baru, class tersebut akan berada dalam status
Tidak ada aktivitas. Pada saat itu, Anda harus menginisialisasinya dengan memanggil setDataSource()
, membawanya ke status Diinisialisasi. Setelah itu, Anda harus mempersiapkannya menggunakan
metode prepare()
atau
prepareAsync()
. Setelah
selesai disiapkan, MediaPlayer
akan memasuki status Disiapkan, yang berarti Anda dapat memanggil start()
agar memutar media. Pada tahap tersebut, seperti yang diilustrasikan dalam diagram, Anda dapat beralih antara status Started, Pause, dan PlaybackCompleted dengan memanggil metode seperti start()
, pause()
, seekTo()
, dan lain-lain. Namun, saat
memanggil stop()
, perhatikan bahwa Anda
tidak dapat memanggil start()
lagi sampai Anda
menyiapkan MediaPlayer
lagi.
Selalu perhatikan diagram status saat menulis kode yang berinteraksi dengan objek MediaPlayer
, karena memanggil metodenya dari status yang salah sering kali menyebabkan bug.
Merilis MediaPlayer
MediaPlayer
dapat memakai
resource sistem yang berharga.
Oleh karena itu, Anda harus selalu melakukan tindakan pencegahan tambahan untuk memastikan bahwa Anda tidak
mempertahankan instance MediaPlayer
lebih lama dari yang diperlukan. Setelah
selesai, Anda harus selalu memanggil
release()
untuk memastikan
resource sistem apa pun yang dialokasikan untuknya dirilis dengan benar. Misalnya, jika Anda
menggunakan MediaPlayer
dan aktivitas menerima panggilan ke onStop()
, Anda harus melepaskan MediaPlayer
,
karena
tidak masuk akal untuk mempertahankannya saat aktivitas Anda tidak berinteraksi dengan
pengguna (kecuali jika Anda memutar media di latar belakang, yang akan dibahas di bagian berikutnya).
Saat aktivitas dilanjutkan atau dimulai ulang, tentu saja Anda perlu
membuat MediaPlayer
baru dan mempersiapkannya lagi sebelum melanjutkan pemutaran.
Berikut cara merilis dan menghapus MediaPlayer
:
Kotlin
mediaPlayer?.release() mediaPlayer = null
Java
mediaPlayer.release(); mediaPlayer = null;
Sebagai contoh, pertimbangkan masalah yang dapat terjadi jika Anda
lupa merilis MediaPlayer
saat aktivitas dihentikan, tetapi buat
yang baru saat aktivitas dimulai lagi. Seperti yang Anda ketahui, saat pengguna mengubah
orientasi layar (atau mengubah konfigurasi perangkat dengan cara lain),
sistem akan menanganinya dengan memulai ulang aktivitas (secara default), sehingga Anda dapat dengan cepat
menggunakan semua resource sistem saat pengguna
memutar perangkat bolak-balik antara potret dan lanskap, karena pada setiap
perubahan orientasi, Anda akan membuat MediaPlayer
baru yang tidak pernah
dilepaskan. (Untuk informasi selengkapnya tentang pemulaian ulang waktu proses, lihat Menangani Perubahan Waktu Proses.)
Anda mungkin ingin tahu apa yang terjadi jika ingin terus memutar
"media latar belakang" bahkan saat pengguna meninggalkan aktivitas, dengan cara yang sama
seperti perilaku aplikasi Musik bawaan. Dalam hal ini, yang Anda butuhkan adalah
MediaPlayer
yang dikontrol oleh Layanan, seperti yang
dibahas di bagian berikutnya
Menggunakan MediaPlayer dalam layanan
Jika ingin media diputar di latar belakang bahkan saat aplikasi
tidak ada di layar—yaitu, Anda ingin media terus diputar saat pengguna
berinteraksi dengan aplikasi lain—Anda harus memulai
Layanan dan mengontrol
instance MediaPlayer
dari sana.
Anda harus menyematkan
MediaPlayer di layanan MediaBrowserServiceCompat
dan membuatnya
berinteraksi dengan
MediaBrowserCompat
dalam aktivitas lain.
Anda harus berhati-hati dengan penyiapan klien/server ini. Ada ekspektasi tentang cara pemutar yang berjalan di layanan latar belakang berinteraksi dengan bagian sistem lainnya. Jika aplikasi Anda tidak memenuhi ekspektasi tersebut, pengguna mungkin akan mendapatkan pengalaman yang buruk. Baca Membangun Aplikasi Audio untuk detail selengkapnya.
Bagian ini menjelaskan petunjuk khusus untuk mengelola MediaPlayer jika diterapkan dalam layanan.
Menjalankan secara asinkron
Pertama-tama, seperti Activity
, semua tugas di
Service
dilakukan dalam satu thread secara
default—bahkan, jika Anda menjalankan aktivitas dan layanan dari aplikasi yang sama, keduanya
menggunakan thread yang sama ("thread utama") secara default. Oleh karena itu, layanan perlu
memproses intent yang masuk dengan cepat
dan tidak pernah melakukan komputasi yang panjang saat meresponsnya. Jika ada panggilan pekerjaan
yang berat atau pemblokiran yang diharapkan, Anda harus melakukan tugas tersebut secara asinkron: baik dari
thread lain yang Anda terapkan sendiri, atau menggunakan berbagai fasilitas framework
untuk pemrosesan asinkron.
Misalnya, saat menggunakan MediaPlayer
dari thread utama,
Anda harus memanggil prepareAsync()
, bukan
prepare()
, dan mengimplementasikan
MediaPlayer.OnPreparedListener
agar diberi tahu saat persiapan selesai dan Anda dapat mulai melakukan pemutaran.
Contoh:
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(); } }
Menangani error asinkron
Pada operasi sinkron, error biasanya akan
diberi sinyal dengan pengecualian atau kode error, tetapi setiap kali menggunakan resource
asinkron, Anda harus memastikan bahwa aplikasi diberi tahu
tentang error dengan tepat. Dalam kasus MediaPlayer
,
Anda dapat melakukannya dengan menerapkan
MediaPlayer.OnErrorListener
dan
menyetelnya dalam instance 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! } }
Penting untuk diingat bahwa saat terjadi error, MediaPlayer
akan berpindah ke status Error (lihat dokumentasi class
MediaPlayer
untuk mengetahui diagram status lengkap)
dan Anda harus meresetnya sebelum dapat menggunakannya lagi.
Menggunakan penguncian layar saat aktif
Saat mendesain aplikasi yang memutar media di latar belakang, perangkat mungkin akan masuk ke mode tidur saat layanan Anda sedang berjalan. Sistem Android mencoba menghemat baterai saat perangkat tidur, sistem akan mencoba menonaktifkan fitur ponsel yang tidak diperlukan, termasuk hardware Wi-Fi dan CPU. Namun, jika layanan Anda memutar atau melakukan streaming musik, Anda ingin mencegah sistem mengganggu pemutaran Anda.
Untuk memastikan layanan terus berjalan dalam kondisi tersebut, Anda harus menggunakan "penguncian layar saat aktif". Penguncian layar saat aktif adalah cara untuk memberi tahu sistem bahwa aplikasi Anda menggunakan beberapa fitur yang seharusnya tetap tersedia meskipun ponsel sedang tidak ada aktivitas.
Pemberitahuan: Anda harus selalu menggunakan penguncian layar saat aktif dan menahannya hanya selama benar-benar diperlukan, karena fitur ini secara signifikan mengurangi masa pakai baterai perangkat.
Untuk memastikan CPU terus berjalan saat MediaPlayer
diputar, panggil metode setWakeMode()
saat melakukan inisialisasi MediaPlayer
. Setelah Anda melakukannya,
MediaPlayer
akan menahan kunci yang ditentukan saat video diputar, lalu akan melepas kunci
saat dijeda atau dihentikan:
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);
Namun, penguncian layar saat aktif yang diperoleh dalam contoh ini hanya menjamin bahwa CPU akan tetap aktif. Jika
Anda melakukan streaming media melalui
jaringan dan menggunakan Wi-Fi, Anda mungkin juga perlu menyimpan
WifiLock
, yang harus diperoleh dan dirilis secara manual. Jadi, saat Anda mulai menyiapkan
MediaPlayer
dengan URL jarak jauh, Anda harus membuat dan mendapatkan kunci Wi-Fi.
Contoh:
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();
Saat menjeda atau menghentikan media, atau saat tidak lagi memerlukan jaringan, Anda harus melepaskan penguncian:
Kotlin
wifiLock.release()
Java
wifiLock.release();
Melakukan pembersihan
Seperti yang disebutkan sebelumnya, objek MediaPlayer
dapat menggunakan
resource sistem dalam jumlah yang signifikan, jadi sebaiknya Anda menyimpannya hanya selama yang Anda perlukan dan memanggil
release()
setelah selesai. Penting untuk memanggil
metode pembersihan ini secara eksplisit daripada mengandalkan pembersihan sampah memori sistem karena
mungkin perlu waktu beberapa saat sebelum pembersih sampah memori mengklaim kembali MediaPlayer
,
karena hanya sensitif terhadap kebutuhan memori dan bukan kekurangan resource terkait media lainnya.
Jadi, jika menggunakan layanan, Anda harus selalu mengganti
metode onDestroy()
untuk memastikan Anda merilis
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(); } }
Anda juga harus selalu mencari peluang lain untuk merilis MediaPlayer
, selain merilisnya saat dinonaktifkan. Misalnya, jika Anda berharap tidak dapat
memutar media dalam waktu lama (misalnya setelah kehilangan fokus audio),
Anda harus merilis MediaPlayer
yang sudah ada dan membuatnya lagi
nanti. Di
sisi lain, jika Anda hanya ingin menghentikan pemutaran untuk waktu yang sangat singkat, sebaiknya Anda
mempertahankan MediaPlayer
untuk menghindari overhead pembuatan dan persiapan
lagi.
Manajemen Hak Digital (DRM)
Mulai Android 8.0 (API level 26), MediaPlayer
menyertakan API yang
mendukung pemutaran materi yang dilindungi DRM. API ini mirip dengan API level rendah yang disediakan oleh
MediaDrm
, tetapi beroperasi pada level yang lebih tinggi serta tidak
mengekspos objek ekstraktor, drm, dan kripto yang mendasarinya.
Meskipun MediaPlayer DRM API tidak menyediakan fungsi
MediaDrm
penuh, API ini mendukung kasus penggunaan yang paling umum. Implementasi
saat ini dapat menangani jenis konten berikut:
- File media lokal yang dilindungi Widevine
- File media jarak jauh/streaming yang dilindungi Widevine
Cuplikan kode berikut menunjukkan cara menggunakan metode MediaPlayer DRM yang baru dalam implementasi sinkron sederhana.
Untuk mengelola media yang dikontrol DRM, Anda harus menyertakan metode baru tersebut bersama alur panggilan MediaPlayer yang biasa, seperti yang ditunjukkan di bawah ini:
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();
Mulailah dengan melakukan inisialisasi objek MediaPlayer
dan menetapkan
sumbernya menggunakan setDataSource()
,
seperti biasa. Kemudian, untuk menggunakan DRM, lakukan langkah-langkah berikut:
- Jika Anda ingin aplikasi melakukan konfigurasi kustom, tentukan
antarmuka
OnDrmConfigHelper
, dan lampirkan ke pemain menggunakansetOnDrmConfigHelper()
. - Panggil
prepare()
. - Panggil
getDrmInfo()
. Jika sumbernya memiliki konten DRM, metode ini akan menampilkan nilaiMediaPlayer.DrmInfo
non-null.
Jika MediaPlayer.DrmInfo
ada:
- Periksa peta UUID yang tersedia dan pilih salah satunya.
- Persiapkan konfigurasi DRM untuk sumber saat ini dengan memanggil
prepareDrm()
. - Jika Anda membuat dan mendaftarkan callback
OnDrmConfigHelper
, callback tersebut akan dipanggil saatprepareDrm()
dieksekusi. Hal ini memungkinkan Anda melakukan konfigurasi kustom properti DRM sebelum membuka sesi DRM. Callback dipanggil secara sinkron dalam thread yang memanggilprepareDrm()
. Untuk mengakses properti DRM, panggilgetDrmPropertyString()
dansetDrmPropertyString()
. Jangan melakukan operasi yang panjang. - Jika perangkat belum disediakan,
prepareDrm()
juga akan mengakses server penyediaan untuk menyediakan perangkat. Tindakan ini dapat memerlukan waktu yang bervariasi, bergantung pada konektivitas jaringan. - Untuk mendapatkan array byte permintaan kunci buram untuk dikirim ke server lisensi, panggil
getKeyRequest()
. - Untuk memberi tahu mesin DRM tentang respons kunci yang diterima dari server lisensi, panggil
provideKeyResponse()
. Hasilnya bergantung pada jenis permintaan kunci:- Jika respons ditujukan untuk permintaan kunci offline, hasilnya akan berupa ID rangkaian kunci Anda dapat menggunakan
ID kumpulan kunci ini dengan
restoreKeys()
untuk memulihkan kunci ke sesi baru. - Jika respons ditujukan untuk permintaan streaming atau rilis, hasilnya adalah null.
- Jika respons ditujukan untuk permintaan kunci offline, hasilnya akan berupa ID rangkaian kunci Anda dapat menggunakan
ID kumpulan kunci ini dengan
Menjalankan prepareDrm()
secara asinkron
Secara default, prepareDrm()
berjalan secara sinkron, melakukan pemblokiran hingga persiapan selesai. Namun, persiapan DRM yang pertama kali di perangkat baru mungkin juga memerlukan penyediaan, yang
ditangani secara internal oleh
prepareDrm()
, dan
mungkin memerlukan waktu beberapa saat untuk diselesaikan karena melibatkan operasi jaringan. Anda dapat
menghindari pemblokiran di
prepareDrm()
dengan
menentukan dan menetapkan MediaPlayer.OnDrmPreparedListener
.
Jika Anda menetapkan OnDrmPreparedListener
,
prepareDrm()
akan melakukan penyediaan (jika diperlukan) dan persiapan di latar belakang. Saat
penyediaan dan persiapan selesai, pemroses akan dipanggil. Anda tidak boleh membuat asumsi apa pun tentang urutan panggilan atau thread tempat pemroses berjalan (kecuali jika pemroses terdaftar dengan thread pengendali).
Pemroses dapat dipanggil sebelum atau setelah prepareDrm()
ditampilkan.
Menyiapkan DRM secara asinkron
Anda dapat menginisialisasi DRM secara asinkron dengan membuat dan mendaftarkan
MediaPlayer.OnDrmInfoListener
untuk persiapan DRM dan
MediaPlayer.OnDrmPreparedListener
untuk memulai pemutar.
Keduanya berfungsi bersama dengan
prepareAsync()
, seperti yang ditunjukkan di bawah ini:
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(); }
Menangani media yang dienkripsi
Mulai dari Android 8.0 (API level 26), MediaPlayer
juga dapat mendekripsi
Common Encryption Scheme (CENC) dan
media terenkripsi tingkat sampel HLS (METHOD=CONTOH-AES) untuk jenis streaming dasar
H.264, dan AAC. Sebelumnya, media terenkripsi segmen penuh (METHOD=AES-128) didukung.
Mengambil media dari ContentResolver
Fitur lain yang mungkin berguna dalam aplikasi pemutar media adalah kemampuan untuk
mengambil musik yang ada di pengguna pada perangkat. Anda dapat melakukannya dengan meminta ContentResolver
untuk media eksternal:
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()); }
Untuk menggunakannya dengan MediaPlayer
, Anda dapat melakukan hal berikut:
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 { setAudioAttributes( AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ) 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.setAudioAttributes( new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ); mediaPlayer.setDataSource(getApplicationContext(), contentUri); // ...prepare and start...
Pelajari lebih lanjut
Halaman ini membahas topik yang berkaitan dengan perekaman, penyimpanan, dan pemutaran kembali audio dan video.