Ringkasan MediaPlayer

Kerangka kerja multimedia Android menyertakan dukungan untuk memutar berbagai jenis media umum, jadi Anda bisa dengan mudah mengintegrasikan audio, video, dan gambar ke dalam aplikasi Anda. Anda dapat memutar audio atau video dari file media yang disimpan dalam resource aplikasi (resource mentah), dari file yang berdiri sendiri dalam sistem file, atau dari aliran data yang masuk melalui koneksi jaringan, semuanya menggunakan MediaPlayer API.

Dokumen ini menunjukkan cara menggunakan MediaPlayer untuk menulis pemutaran media aplikasi yang berinteraksi dengan pengguna dan sistem untuk memperoleh kinerja yang baik dan pengalaman pengguna yang menyenangkan. Atau, Anda mungkin ingin untuk menggunakan ExoPlayer, yang merupakan open source yang dapat disesuaikan library yang mendukung fitur performa tinggi yang tidak tersedia di MediaPlayer

Catatan: Anda hanya dapat memutar data audio ke output standar perangkat seluler. Saat ini, perangkat tersebut mencakup speaker perangkat seluler atau headset Bluetooth. Anda tidak dapat memutar 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 berbasis jaringan aplikasi Anda harus meminta akses jaringan.
    <uses-permission android:name="android.permission.INTERNET" />
    
  • Izin Penguncian Layar Saat Aktif - Jika aplikasi pemutar Anda perlu mempertahankan layar dari meredupkan atau mengaktifkan prosesor dari mode tidur, atau menggunakan MediaPlayer.setScreenOnWhilePlaying() atau Metode MediaPlayer.setWakeMode(), Anda harus meminta izin ini.
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

Menggunakan MediaPlayer

Salah satu komponen terpenting dari kerangka kerja media adalah MediaPlayer . Objek class ini dapat mengambil, mendekode, serta memutar audio dan 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 mengetahui daftar format media yang didukung Android, lihat daftar Media yang Didukung Formats.

Berikut contohnya cara memutar audio yang tersedia sebagai sumber daya mentah lokal (disimpan dalam res/raw/):

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, "raw" sumber daya adalah file yang tidak mencoba menguraikan dengan cara tertentu. Namun, isi referensi ini tidak boleh berupa audio mentah. Harus berupa file media yang dienkode dan diformat dengan benar menjadi satu format yang didukung.

Dan berikut ini cara memutar dari URI yang tersedia secara lokal di 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: download progresif.

Perhatian: Anda harus menangkap atau meneruskan IllegalArgumentException dan IOException saat menggunakan setDataSource(), karena file yang Anda rujuk mungkin tidak ada.

Persiapan asinkron

Anda dapat menggunakan MediaPlayer dengan mudah di prinsip ini. Namun, penting untuk diingat bahwa ada beberapa hal lagi yang perlu mengintegrasikannya dengan benar dengan aplikasi Android biasa. Sebagai contoh, panggilan ke prepare() dapat memakan waktu lama untuk dilaksanakan, karena mungkin diperlukan pengambilan dan dekode data media. Jadi, seperti halnya dengan yang mungkin memakan waktu lama, Anda tidak boleh memanggilnya dari UI thread aplikasi. Tindakan tersebut akan menyebabkan UI hang sampai metode kembali, yang merupakan pengalaman pengguna yang sangat buruk dan dapat menyebabkan {i>error<i} ANR (Aplikasi Tidak Merespons). Meskipun jika Anda berharap sumber daya Anda dimuat dengan cepat, ingat bahwa apa pun yang membutuhkan lebih dari sepersepuluh satu detik untuk merespons di UI menyebabkan jeda yang terlihat dan memberi kesan bahwa aplikasi Anda lambat kepada pengguna.

Untuk menghindari penangguhan UI thread, buat thread lain ke menyiapkan MediaPlayer dan memberi tahu thread utama jika sudah selesai. Namun, meskipun Anda bisa menulis logika threading pola ini sangat umum saat menggunakan MediaPlayer sehingga framework menyediakan cara mudah untuk menyelesaikan tugas ini dengan menggunakan Metode prepareAsync(). Metode ini mulai menyiapkan media di latar belakang dan segera kembali. Saat media selesai persiapan, onPrepared() dari MediaPlayer.OnPreparedListener, yang dikonfigurasi melalui setOnPreparedListener() dipanggil.

Mengelola status

Aspek lain dari MediaPlayer yang harus Anda ingat adalah bahwa kode itu berbasis negara bagian. Artinya, MediaPlayer memiliki status internal yang harus selalu Anda perhatikan ketika menulis kode, karena operasi tertentu hanya valid saat pemutar dalam status tertentu. Jika Anda melakukan operasi saat salah, sistem dapat menampilkan pengecualian atau menyebabkan perilaku lain yang tidak diinginkan.

Dokumentasi dalam Class MediaPlayer menampilkan diagram status lengkap, yang menjelaskan metode mana yang memindahkan MediaPlayer dari satu status ke status lainnya. Misalnya, saat Anda membuat MediaPlayer baru, instance tersebut akan berada dalam mode Idle status. Pada saat itu, Anda harus menginisialisasinya dengan memanggil setDataSource(), menghadirkannya ke status Diinisialisasi. Setelah itu, Anda harus menyiapkannya menggunakan prepare() atau Metode prepareAsync(). Kapan MediaPlayer selesai disiapkan, proses akan memasuki Prepared yang berarti Anda dapat memanggil start() untuk membuatnya memutar media. Pada saat itu, seperti diilustrasikan dalam diagram, Anda dapat berpindah antara status Started, Dijeda, dan PlaybackCompleted dengan memanggil metode seperti start(), pause(), dan seekTo(), di antara yang lainnya. Jika Anda memanggil stop(), tetapi, perhatikan bahwa Anda tidak dapat menelepon start() lagi sampai Anda siapkan MediaPlayer lagi.

Selalu pertahankan diagram status ingat saat menulis kode yang berinteraksi dengan MediaPlayer, karena memanggil metodenya dari status yang salah merupakan penyebab umum {i>bug<i}.

Merilis MediaPlayer

MediaPlayer dapat menghabiskan resource sistem. Oleh karena itu, Anda harus selalu mengambil tindakan pencegahan tambahan untuk memastikan Anda tidak bergantung pada instance MediaPlayer lebih lama dari yang diperlukan. Jika Anda selesai, Anda harus selalu memanggil release() untuk memastikan sumber daya sistem yang dialokasikan untuknya dilepaskan dengan benar. Misalnya, jika Anda menggunakan MediaPlayer dan aktivitas Anda menerima panggilan ke onStop(), Anda harus melepaskan MediaPlayer, karena hal itu tidak masuk akal untuk menyimpannya saat aktivitas Anda sedang tidak berinteraksi pengguna (kecuali jika Anda memutar media di latar belakang, yang akan dibahas di bagian berikutnya). Tentu saja, saat aktivitas Anda dilanjutkan atau dimulai ulang, buat MediaPlayer baru dan siapkan 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 bisa terjadi jika Anda lupa merilis MediaPlayer saat aktivitas Anda dihentikan, tetapi buat yang baru ketika aktivitas dimulai lagi. Seperti yang mungkin Anda ketahui, ketika pengguna mengubah orientasi layar (atau mengubah konfigurasi perangkat dengan cara lain), sistem menanganinya dengan memulai ulang aktivitas (secara {i>default<i}), sehingga Anda mungkin menghabiskan semua sumber daya sistem sebagai pengguna memutar perangkat bolak-balik antara potret dan lanskap, karena pada setiap perubahan orientasi, Anda membuat MediaPlayer baru yang tidak pernah data. (Untuk informasi selengkapnya tentang pemulaian ulang waktu proses, lihat Menangani Perubahan Waktu Proses.)

Anda mungkin bertanya-tanya apa yang terjadi jika Anda ingin terus bermain "media latar belakang" bahkan saat pengguna meninggalkan aktivitas Anda, hampir sama perilaku aplikasi Musik bawaan. Dalam hal ini, yang Anda butuhkan adalah MediaPlayer yang dikontrol oleh Layanan, sebagai dibahas di bagian berikutnya

Menggunakan MediaPlayer dalam layanan

Jika Anda ingin media tetap diputar di latar belakang bahkan saat aplikasi tidak ada di layar—artinya, Anda ingin video terus diputar saat pengguna dengan aplikasi lain—maka Anda harus memulai Layanan dan kontrol MediaPlayer dari sana. Anda harus menyematkan MediaPlayer di layanan MediaBrowserServiceCompat dan memiliki berinteraksi dengan MediaBrowserCompat dalam aktivitas lain.

Anda harus berhati-hati dengan penyiapan klien/server ini. Ada ekspektasi tentang bagaimana pemutar yang berjalan di layanan latar belakang berinteraksi dengan sistem file. Jika aplikasi Anda tidak memenuhi harapan tersebut, pengguna mungkin memiliki pengalaman buruk. {i>Read<i} 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 berfungsi dalam Service dilakukan dalam satu thread dengan secara default—bahkan, jika Anda menjalankan aktivitas dan layanan dari aplikasi yang sama, menggunakan thread yang sama ("thread utama") secara default. Oleh karena itu, layanan perlu memproses intent yang masuk dengan cepat dan jangan pernah melakukan komputasi yang panjang saat meresponsnya. Jika ada masalah berat atau memblokir panggilan yang diharapkan, Anda harus melakukan tugas tersebut secara asinkron: thread lain yang Anda terapkan sendiri, atau menggunakan banyak fasilitas framework untuk pemrosesan asinkron.

Misalnya, saat menggunakan MediaPlayer dari thread utama, Anda harus memanggil prepareAsync(), bukan prepare(), dan implementasikan MediaPlayer.OnPreparedListener agar diberi tahu saat persiapan selesai dan Anda dapat mulai bermain. 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 Anda menggunakan Anda harus memastikan bahwa aplikasi Anda diberi tahu {i>error<i} secara 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 berpindah ke status Error (lihat dokumentasi untuk Class MediaPlayer untuk diagram status lengkap) dan Anda harus meresetnya sebelum dapat menggunakannya lagi.

Menggunakan penguncian layar saat aktif

Saat merancang aplikasi yang memutar media di latar belakang, perangkat mungkin tidur saat layanan Anda berjalan. Karena sistem Android mencoba menghemat baterai saat perangkat tidur, sistem akan mencoba mematikan fitur ponsel yang tidak perlu, termasuk CPU dan perangkat keras WiFi. Tetapi, jika layanan Anda memutar atau {i>streaming<i} musik, Anda ingin mencegah sistem agar tidak mengganggu pemutaran.

Untuk memastikan bahwa layanan Anda terus berjalan berdasarkan kondisi itu, Anda harus menggunakan "penguncian layar saat aktif". Penguncian layar saat aktif adalah cara untuk memberi sinyal untuk sistem di mana aplikasi Anda menggunakan beberapa fitur yang seharusnya tetap tersedia bahkan jika ponsel tidak ada aktivitas.

Perhatikan: Anda harus selalu menggunakan penguncian layar saat aktif dengan hemat dan menahannya hanya selama benar-benar diperlukan, karena cara itu mengurangi masa pakai baterai secara signifikan perangkat seluler.

Untuk memastikan CPU terus berjalan saat MediaPlayer Anda diputar, panggil metode setWakeMode() saat melakukan inisialisasi MediaPlayer. Setelah Anda melakukannya, MediaPlayer akan menahan kunci yang ditentukan saat memutar dan melepaskan 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 Anda menggunakan Wi-Fi, Anda mungkin ingin mengadakan WifiLock sebagai yang harus Anda dapatkan dan rilis secara manual. Jadi, saat Anda mulai mempersiapkan 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 Anda menjeda atau menghentikan media, atau saat Anda tidak lagi memerlukan jaringan, Anda harus melepaskan kunci:

Kotlin

wifiLock.release()

Java

wifiLock.release();

Melakukan pembersihan

Seperti yang disebutkan sebelumnya, objek MediaPlayer dapat menggunakan jumlah sumber daya sistem, jadi Anda harus menyimpannya hanya selama yang Anda butuhkan dan release() jika sudah selesai. Penting 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 sensitif terhadap kebutuhan memori dan tidak kekurangan sumber daya terkait media lainnya. Jadi, jika Anda 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 harus selalu mencari peluang lain untuk merilis MediaPlayer juga, selain melepaskannya saat dimatikan. Misalnya, jika Anda berharap tidak dapat memutar media untuk jangka waktu yang lama (misalnya, setelah kehilangan fokus audio), Anda harus merilis MediaPlayer yang sudah ada dan membuatnya lagi nanti. Pada di sisi lain, jika Anda hanya ingin menghentikan pemutaran untuk waktu yang sangat singkat, Anda mungkin simpan MediaPlayer untuk menghindari overhead saat pembuatan dan penyiapan untuk mencoba lagi perintah.

Manajemen Hak Digital (DRM)

Mulai Android 8.0 (level API 26), MediaPlayer menyertakan API yang mendukung pemutaran materi yang dilindungi DRM. API ini mirip dengan API tingkat rendah yang disediakan oleh MediaDrm, tetapi beroperasi pada level yang lebih tinggi dan tidak mengekspos objek ekstraktor, drm, dan kripto yang mendasarinya.

Meskipun MediaPlayer DRM API tidak menyediakan fungsi MediaDrm, mendukung kasus penggunaan paling umum. Tujuan 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 DRM MediaPlayer yang baru metode dalam implementasi sinkron sederhana.

Untuk mengelola media yang dikontrol DRM, Anda perlu menyertakan metode baru ini bersama alur biasa panggilan MediaPlayer, 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();

Mulai dengan menginisialisasi objek dan setelan MediaPlayer sumbernya menggunakan setDataSource(), seperti biasa. Kemudian, untuk menggunakan DRM, lakukan langkah-langkah berikut:

  1. Jika Anda ingin aplikasi melakukan konfigurasi khusus, tentukan OnDrmConfigHelper, dan melampirkannya ke pemain menggunakan setOnDrmConfigHelper().
  2. Panggil prepare().
  3. Panggil getDrmInfo(). Jika sumber memiliki DRM konten tersebut, metode akan mengembalikan nilai {i>non-null<i} Nilai MediaPlayer.DrmInfo.

Jika MediaPlayer.DrmInfo ada:

  1. Periksa peta UUID yang tersedia dan pilih salah satunya.
  2. Persiapkan konfigurasi DRM untuk sumber saat ini dengan memanggil prepareDrm().
    • Jika Anda membuat dan mendaftarkan Callback OnDrmConfigHelper, proses ini disebut sementara prepareDrm() sedang dieksekusi. Hal ini memungkinkan Anda melakukan konfigurasi kustom DRM sebelum membuka sesi DRM. Callback dipanggil secara sinkron di thread yang memanggil prepareDrm(). Kepada mengakses properti DRM, panggil getDrmPropertyString() dan setDrmPropertyString(). Jangan melakukan operasi yang panjang.
    • Jika perangkat belum disediakan, prepareDrm() juga mengakses server penyediaan untuk menyediakan perangkat. Proses ini dapat memerlukan jumlah waktu yang bervariasi, tergantung pada konektivitas jaringan.
  3. Untuk mendapatkan array byte permintaan kunci buram untuk dikirim ke server lisensi, panggil getKeyRequest().
  4. 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.
    • Jika respons ditujukan untuk permintaan streaming atau rilis, hasilnya adalah null.

Menjalankan prepareDrm() secara asinkron

Secara default, prepareDrm() berjalan secara sinkron, melakukan pemblokiran hingga persiapan selesai. Namun, persiapan DRM pertama pada perangkat baru mungkin juga memerlukan penyediaan, ditangani secara internal oleh prepareDrm(), dan mungkin memakan waktu lebih lama untuk diselesaikan karena operasi jaringan yang terlibat. Anda dapat hindari pemblokiran di prepareDrm() kali menentukan dan menetapkan MediaPlayer.OnDrmPreparedListener.

Saat Anda menetapkan OnDrmPreparedListener, prepareDrm() melakukan penyediaan (jika diperlukan) dan persiapan di latar belakang. Kapan dan persiapan telah selesai, pemroses dipanggil. Anda seharusnya tidak membuat asumsi apa pun tentang urutan pemanggilan atau thread di mana berjalan (kecuali jika pemroses didaftarkan dengan thread pengendali). Pemroses dapat dipanggil sebelum atau setelah prepareDrm() akan dikembalikan.

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. Mereka bekerja sama 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 Android 8.0 (level API 26), MediaPlayer juga dapat mendekripsi {i>Common Encryption Scheme <i}(CENC) dan Media terenkripsi tingkat sampel HLS (METHOD=SAMPLE-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 perangkat pengguna. 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.