Android SDK dan Media3 native
Unduh Android pemutar dengan kontrol video in- video, playlist yang dapat diseret, shuffle / resume / luring dan pemutaran offline. Integrasikan yang dilindungi menggunakan DRM-X atau native Media3.
Coba Android pemutar #
1.0.0-preview.12 · 7.02 MB · Android 6.0+ (API 23+) · DRM-X 6.0 Player · Diperbarui 2026-09-14
- Buka halaman ini pada telepon Android Anda dan unduh APK.
- Buka berkas yang diunduh. Jika Android bertanya, ijinkan instalasi dari peramban atau manajer berkas yang Anda gunakan, lalu tekan Pasang .
- Buka DRM-X 6.0 Pemutar , tetap terhubung, dan tekan Putar tombol. Aplikasi meminta lisensi streaming ketika Anda menekan Play.
- Buka Pengaturan untuk memilih kualitas, audio, kapsi, atau kecepatan putar. Putar telepon untuk melanjutkan dalam layar penuh.
- Tap Unduh untuk video saat ini atau Unduh daftar putar untuk semua VOD Item. Unduhan menggunakan rendition berlisensi tertinggi yang didukung hingga 1080p pada L1, atau 480p pada L3. Putar luring membuka daftar putar lokal yang komplit dengan next / previous, shuffle, repeat dan autoplay; Online kembali ke daftar putar penuh. Renew Memperbaharui lisensi yang dipilih saat tersambung.
Diunduh media yang sudah diantrian terus di latar belakang. Jika Android menghentikan aplikasi ketika menyiapkan lisensi atau trek, membuka kembali saat tersambung untuk menyelesaikan menyiapkan butir-butir yang tersisa. Unduhan yang tersimpan. Pemutaran offline hanya menggunakan media yang cached; tidak lengkap atau unduhan kadaluarsa memerlukan pelengkapan atau pembaharuan.
Widevine provisioning kegagalan (Media3 6002) sekarang gunakan relay server demokasi terotentikasi ke layanan Google resmi. Sebuah fungsi L3 CDM dapat menerima kunci SD. Perangkat tanpa implementasi Widevine yang bekerja memerlukan perbaikan perangkat / firmware; sebuah lisensi tidak dapat menambahkan dukungan DRM yang hilang.
Sampel APK adalah publik dan ditandatangani untuk evaluasi. AAR dan penuh SDK di bawah ini tetap tersedia melalui akun Konsol yang memenuhi syarat. Jauhkan kunci penandatanganan aplikasi sendiri dan login backend terpisah dari demo ini.
APK checksum dan USB instalasi
SHA-256:
8fa044b82c0abab7ce2a987f349524fd7ad1e78f3c897771f4764cb2aa521180Dengan Android platform -tools dan sebuah otorisasi USB perangkat:
adb install -r drmx-android-player-1.0.0-preview.12.apkInstal APK ini melalui contoh resmi yang sudah ada tanpa uninstall itu. Kunci penandatanganan dan aplikasi yang sama dengan ID pertahankan pengunduhan, lisensi offline, posisi dan preferensi tersimpan. Jika membangun Anda sendiri menggunakan kunci penandatanganan lain, gunakan aplikasi terpisah ID untuk menjaga kedua aplikasi dan mempertahankan lisensi luring sampel.
Apa yang baru dalam Android pemutar preview] 12 #
Dirilis 14 September 2026. Perbaikan download pemutaran membuat permintaan lisensi yang tak terduga ketika Widevine lisensi kadaluwarsa atau memiliki satu menit atau kurang. Ini bisa muncul sebagai Media3 galat 6004, sebuah HTTP error ketika tersambung, atau DNS error ketika terputus.
pemutar sekarang restore lisensi yang diunduh secara lokal. Lisensi yang sah mempertahankan sisa waktu pemutaran mereka; lisensi yang kadaluwarsa menampilkan Hubungkan dan tekan Renew . Peraturan keabsahan dan perlindungan Lisensi tetap dipaksakan oleh perangkat. Diagnostik juga termasuk status numerik HTTP ketika operasi jaringan gagal, tanpa mengekspos header permintaan, URL, atau lisensi tanggapan.
- Instal preview-12 melalui aplikasi resmi yang ada. Simpan data aplikasi dan unduh saat ini.
- Jika WayMaker atau video lain yang diunduh perlu diperbaharui, menyambung ke internet, pilih video itu dan tekan Renew .
- Tunggu Lisensi diperbarui. Siap untuk bermain offline. , lalu pilih Putar offline . Video terenkripsi masih diunduh.
Peluncuran ini mempertahankan kontrol dan fitur playlist. Aplikasi evaluasi publik dan aplikasi yang tertanam pemutar mengidentifikasi previe.12; Konsol yang didistribusikan secara terpisah SDK tetap berada sebelum 10 / bundle 20260910.8.
Apa yang baru dalam Android pemutar preview} 11 #
Aplikasi evaluasi ini termasuk kontrol terbaru pemutar dan perbaikan playlist, dengan gaya interaksi konsisten di seluruh Android dan Apple pemutar.
- Kontrol di dalam video: tengah Play / Pause, Sebelumnya dan Selanjutnya untuk multi- video playlist, CC, Pengaturan dan tombol layar penuh. Kontrol menyembunyikan setelah dua detik sambil bermain; tekan video untuk mengungkapkan mereka lagi.
- Captions and playing settings: gunakan CC untuk menampilkan atau menyembunyikan subtitle yang tersedia, dan Pengaturan untuk memilih bahasa, audio, kecepatan putar dan kualitas yang diijinkan. Pilihan offline hanya gunakan trek yang disertakan dalam unduhan.
- Seret untuk memesan ulang: seret suatu butir playlist untuk mengubah posisinya. Perintah tersimpan bertahan dari sebuah aplikasi restart dan tercermin dalam daftar putar yang diunduh. Menghidupkan ulang menjaga video saat ini diputar. Sentuh penanganan untuk akses Pindah ke atas / Pindahkan ke bawah aksi.
- Shuffle tersimpan dan ulangi: mode yang dipilih tetap disorot dan bertahan dalam pemutaran online dan offline. Dengan mengocok dan mengulang baik, video mengikuti urutan yang disimpan dan berhenti setelah item final. Menu playlist "Play next" aksi telah dihapus.
- Lanjutkan di mana Anda berhenti: setiap video disimpan VOD posisi dikembalikan ketika Anda kembali ke pemutaran streaming atau diunduh. Kemajuan disimpan di perangkat ini untuk penampil saat ini; ini tidak sinkronisasi antar perangkat.
Perubahan pemutar telah diverifikasi pada Samsung S24 Ultra, termasuk penyeretan playlist selama pemutaran, urutan tersimpan, putar resume dan download putar dengan Wi-Fi dan data mobile dinonaktifkan. Tampilan offline masih membutuhkan uncompleted download dan lisensi luring yang dapat dipakai.
Pemutakhiran ini evaluasi publik APK. Konsol yang didistribusikan secara terpisah SDK tetap 1.0.0-preview.10, bundle 20260910.8; instruksi integrasi yang ada di bawah ini mengacu pada bundel itu.
1. Pilih jalur integrasi #
Use DrmXPlayer, the phone sample and the offline manager. Keep your own login and business rules.
PATH B KEEP YOUR UIMedia3 + DRM-X pembantuPertahankan pemutar dan unduh tumpukan. Biarkan DrmXOfflineManager mengelola lisensi persisten.
PATH C NATIVE ONLYMedia3 tanpa AARImplemen kontrak backend yang sama dan lifecycle lisensi asli sendiri. Tidak ada DRM-X pemutar ketergantungan.
Unduh ZIP atau AAR SDK Android di Console → Integrations. Organisasi dengan langganan Professional ($499/bulan) atau Enterprise aktif dapat mengunduhnya. Akun Trial dan Standard tidak dapat mengunduh SDK. Dokumentasi ini, termasuk contoh Media3 native, tersedia untuk umum; pemutaran tetap memerlukan akun berhak akses, konten yang dipublikasikan, dan perangkat kompatibel.
Pratinjau saat ini: 1.0.0-preview.10 bundel pelanggan 20260910.8 · Media3 1.11.0. ZIP berisi sebuah repositori Maven lokal, Gradle wrapper, jengkel README, telepon /TV/ sampel asli, sebuah sampel telepon terinstall APK in apks/, dan catatan integrasi offline. Ini tidak berisi pelanggan kredensial atau film yang dilindungi.
2. Siapkan isi dan backend #
- Paket dan menerbitkan Widevine -kompatibel dengan terenkripsi DASH judul dalam DRM-X Lingkungan. Salin yang tepat Diterbitkan Content ID .
- Mengkonfigurasi server Anda Environment ID, Site Key dan Access KeyGunakan yang dapat diunduh PHP integrasi untuk memulai pekerjaan.
- Instal cek log masuk dan hak pengguna Anda. Aplikasi Anda memanggil backend Anda dengan token pengguna yang kurang terpakai; backend Anda memilih isi, kebijakan, dan URL terpercaya.
- Jalankan pemutaran daring pertama pada perangkat yang mampu melakukan fisik Widevine. Tambahkan akuisisi luring hanya setelah kontrak streaming bekerja.
| Ubah nilai ini | Di mana ia berada | Artinya |
|---|---|---|
| titik akhir sesi | Android | Endpoint-sesi putar HTTPS Anda, bukan server lisensi mentah URL. |
| IntineEndpoint | Android, hanya luring | Anda memperoleh / memperbaharui / rilis otorisasi titik akhir. |
| contentId | Android permintaan; backend validates | Pelihat yang diproteksi Content ID berhak untuk diakses. |
| token akses pelanggan | App memori setelah login | Token pengguna Anda yang singkat, tidak pernah sebuah Site Key atau Access Key. |
| Environment ID, Site Key, Access Key | Hanya konfigurasi rahasia server | DRM-X akun kredensial. Jangan pernah mengirim mereka dalam sebuah APK, HTML atau sumber kontrol. |
| Kebijakan dan muatan terpercaya URL | Backend Anda | Pemetaan hak bisnis dan paket. Jangan terima ini dari aplikasi. |
3. Pasang dan jalankan SDK #
Buka yang diekstrak ZIP's root folder dalam Android Studio. JDK 17, Android SDK 36 dan Android Gradle Plugin 9.2.0; wrapper yang disertakan menggunakan Gradle 9.4.1. Perangkat minimal API adalah 23. Ketergantungan pembangunan memerlukan akses internet. Pilih samples.phone dan Jalankan. Nilai awalnya menggunakan backend demo publik dan judul; ikuti tandanya dan streaming kontrol sebelum beralih ke backend Anda sendiri.
# Windows
gradlew.bat :samples:phone:assembleDebug
# macOS / Linux
sh gradlew :samples:phone:assembleDebug
Untuk aplikasi yang sudah ada, salin ZIP 's maven/ folder ke dalam root projek Anda. Dalam settings.gradle.kts:
dependencyResolutionManagement {
repositories {
maven { url = uri(rootDir.resolve("maven")) }
google()
mavenCentral()
}
}
Dalam modul aplikasi Anda build.gradle.kts:
dependencies {
implementation("com.haihaisoft.drmx:drmx-universal-player:1.0.0-preview.10")
}
Instal standalone AAR saja
Masukan AAR dalam modul aplikasi Anda libs/. Sebuah flat AAR tidak memiliki alternatif otomatis dependensi resolusi, jadi tambahkan tiga pencocokan Media3 ketergantungan sendiri. Jangan instal kedua bentuk.
implementation(files("libs/drmx-universal-player-1.0.0-preview.10.aar"))
implementation("androidx.media3:media3-exoplayer:1.11.0")
implementation("androidx.media3:media3-exoplayer-dash:1.11.0")
implementation("androidx.media3:media3-ui:1.11.0")Dalam AndroidManifest.xml, izinkan akses internet dan menonaktifkan backup untuk sampel minimal ini. Dalam aplikasi produksi yang membutuhkan backup, khususnya mengecualikan device- terikat metadata lisensi offline.
<uses-permission android:name="android.permission.INTERNET" />
<application android:allowBackup="false" android:usesCleartextTraffic="false" ... >
Cari contoh telepon MainActivity.kt untuk drmx.sessionEndpoint, drmx.offlineEndpoint, drmx.contentId dan customer.loginEndpoint. Ubah pengaturan fallback yang ditandai, atau lewatkan Intent extra dari aplikasi setelah log masuk. Pass customer.accessToken di runtime. ZIP README menjelaskan setiap parameter dan demo kait untuk diganti.
Bangun suatu tes APK memakai AAR #
Contoh ini menggunakan proyek telepon yang dapat dijalankan dari SDK ZIP dan secara eksplisit menghubungkan standar AAR. Pendekatan yang sama bekerja untuk aplikasi yang ada Android.
- Unduh dan ekstrak penuh Android SDK ZIP . Buka folder root di Android Studio.
- Simpan
libs/drmx-universal-player-1.0.0-preview.10.aardalam akar yang diekstrak. Gunakan JDK 17, Android SDK 36 dan yang disertakan Gradle wrapper. - Dalam
samples/phone/build.gradle.kts, ganti DRM-X Maven ketergantungan dengan entri berikut di dalamdependencies. Simpan sisa berkas build.
implementation(files(rootProject.file("libs/drmx-universal-player-1.0.0-preview.10.aar")))
implementation("androidx.media3:media3-exoplayer:1.11.0")
implementation("androidx.media3:media3-exoplayer-dash:1.11.0")
implementation("androidx.media3:media3-ui:1.11.0")
Hapus implementation("com.haihaisoft.drmx:drmx-universal-player:1.0.0-preview.10") sehingga sama SDK tidak disertakan dua kali. AAR membutuhkan tiga Media3 ketergantungan yang ditampilkan di atas.
- Untuk menjaga demo yang diunduh bersama dengan membangun pengujian Anda sendiri, ubah modul telepon
applicationIdkecom.example.drmxtest. Biarkan namespace nya tidak berubah bagi sampel yang diberikan ini. - Bangun APK, lalu pasang pada USB- tersambung Android perangkat dengan USB debugging yang diijinkan.
# Windows, from the extracted SDK root
gradlew.bat :samples:phone:assembleDebug
adb install -r samples/phone/build/outputs/apk/debug/phone-debug.apk
# macOS / Linux
sh gradlew :samples:phone:assembleDebug
adb install -r samples/phone/build/outputs/apk/debug/phone-debug.apk
Buka aplikasi tes dan tap Play. Sumber telepon yang diberikan menggunakan demo publik yang sama awalnya. Untuk menguji judul Anda sendiri, ganti sesi yang ditandai / offline / login titik akhir dan Published Content ID in MainActivity.kt, dan memasok otentikasi singkat milik pengguna anda sendiri pada waktu berjalan. Server anda menyimpan Site Key dan Access Key.
Kontrolnya berasal dari... DrmXPlayerView di AARAktivitas yang diberikan menunjukkan Play- to-otorisasi, rotasi responsif, kepemilikan download, pemutaran offline dan pembaharuan. Lihat. contoh integrasi kontrol di bawah ketika menambahkan tampilan ini ke aplikasi anda sendiri.
4. Permintaan server dan kebijakan baku #
Aplikasi Android meminta backend Anda untuk sesi putar. Backend Anda mengkonfirmasi pengguna, verifikasi hak, peta Content ID untuk menerbitkan media dan panggilan DRM-X. Lihat Sesi Playback API untuk kontrak streaming lengkap.
{
"contentId": "YOUR-PUBLISHED-CONTENT-ID",
"contentType": "vod",
"drmSystem": "widevine",
"playbackMode": "streaming",
"platformCapabilities": {
"clientPlatform": "android",
"drmSystems": ["widevine"], "manifestTypes": ["dash"],
"maximumHeight": 1080, "secureDecoder": false, "persistentState": false
}
}
Kemampuan konservatif di atas jangan menegaskan Widevine L1. Gunakan SDK 's kapabilitas pembantu, atau penilaian perangkat Anda sendiri, untuk perangkat aktual. Kemampuan klien membantu seleksi kompabilitas; mereka tidak pernah memberikan kualitas hak.
Sampel PHP bawaan bagi multi-tier-standard untuk putar daring. Pilih kebijakan tunggal yang didokumentasikan ketika paket Anda menggunakan satu kunci. Kebijakan Anda harus cocok dengan model kunci paket dan hak-hak penampil. Ubah konfigurasi server atau pengaturan lingkungannya DRMX_LICENSE_POLICY_TEMPLATE, bukan parameter permintaan dalam pemutar. Lihat lisensi kebijakan .
playback_policy.persistent untuk benar dalam kebijakan server- yang diterbitkan dan memilih lisensi, sewa, pemutaran dan pembaharuan durasi. Referensi menggunakan 7 hari / 3 hari / 48 jam / 7 hari; ini adalah contoh aturan bisnis, bukan persetujuan studio atau sebuah platform-seluruh metadata. Lisensi yang cocok kembali. Widevine tetap otoritatif.5. Path A: putar melalui DrmXPlayer #
Inside your Activity, create a PlayerView, use a secure window and call prepare after login. The wrapper exchanges the session, configures Widevine, applies the returned maximum height and releases the streaming reservation when stopped. Imports come from com.haihaisoft.drmx.player and AndroidX Media3.
val view = PlayerView(this)
setContentView(view)
DrmXPlayer.protectWindow(window)
val player = DrmXPlayer(this, view)
val capabilities = WidevineCapabilities.playbackCapabilities(
clientPlatform = "android",
displayMetrics = resources.displayMetrics,
applicationVersion = "1.0",
)
player.prepare(
endpoint = "https://customer.example/api/drmx/playback-session",
contentId = "YOUR-PUBLISHED-CONTENT-ID",
contentType = "vod", // use live only for a published live title
capabilities = capabilities,
customerAuthenticationHeaders = mapOf("Authorization" to "Bearer $userToken"),
)
// Keep player as an Activity/Fragment-owned field in your actual application.
// Stop when your playback lifecycle ends; close when the owner is destroyed.
// player.stop()
// player.close()
Register DrmXPlayerListener untuk otorisasi, siap, bermain, dan error UI. Tampilkan kode kesalahan yang aman daripada membuang tanda-tanda lisensi atau respon tubuh. Gunakan sampel telepon yang disertakan untuk lifecycle lengkap, kontrol layar penuh dan daftar unduh.
Kontrol pemutar dan rotasi tak terganggu #
Sentuh Putar pada video untuk memulai otorisasi. Membuka layar atau Pengaturan tidak memperoleh lisensi streaming. Jeda / lanjutkan, mengubah pengaturan dan memutar telepon mempertahankan sesi saat ini.

| Kendali | Apa yang bisa dilakukan pelanggan |
|---|---|
| Kualitas | Pilih Auto atau didukung, resolusi berlisensi dari manifes. Pilihan tidak tersedia menjelaskan lisensi atau perangkat / DRM pembatasan. Auto mematuhi pembatasan yang sama. |
| Trek audio | Pilih bahasa audio apapun yang didukung yang disediakan oleh paket. |
| Subtitles / CC | Pilih bahasa judul atau mati. Tombol CC muncul ketika judul didukung ada dan menjungkirkannya secara langsung. |
| Penampilan judul | Sesuaikan fonta, warna teks dan ukuran, warna latar belakang / jendela dan opasitas. Preferensi disimpan pada perangkat. |
| Waktu tidur / kecepatan putar | Putar di 0.25-2 × kecepatan atau jeda secara otomatis setelah interval yang dipilih. |
| Seek / layar lengkap | Scrub the timeline, seek 10 detik, or double-tap either side. Putar ke lansekap tanpa memulai ulang memutar. |
Tiga aksi kompak di bawah gambar ini adalah Unduh (untuk penggunaan offline), Putar offline dan Renew (the luring lisensi offline). Sampel mengunduh satu versi yang diijinkan versi video rendition dan trek subtitle yang didukung; daftar menu luring hanya mengekspos media yang diunduh. Renovasi membutuhkan konektivitas.
Salin log di samping informasi footer salinan kesalahan baru-baru ini sebagai teks, sehingga Anda dapat mengirim dukungan rincian tanpa cuplikan layar. Laporan berisi laporan ID, operasi, SDK/Android/ versi perangkat, numerik CDM/Media3 error, frame stack yang dipilih, koneksi / download / keadaan putar dan sebuah jumlah pengulangan. Mereka tidak termasuk kredensial, URL media, kunci, kunci-set ID, data lisensi dan penuh CDM dump.
Sampel tersebut menyimpan hingga 32 laporan lokal (64 KB) selama lima jam. Ketika tersambung dan ditandatangani masuk, itu mengunggah kesalahan yang tertunda ke backend pelanggan yang terkonfigurasi, paling sekali per 30 detik. Server demo publik mempertahankan peringatan / kesalahan selama lima jam, kombinasi kejadian berulang, tutup berkas di 512 KB dan memangkas setiap menit. Kemajuan rutin dan pemutaran sukses tidak log. Integrasi suai harus secara eksplisit memasok asal mereka sendiri drmx.diagnosticsEndpoint; Kesalahan diagnostik tidak pernah mengganggu pemutaran.
val player = DrmXPlayer(this)
val controls = DrmXPlayerView(this)
controls.bind(player) // Does not acquire a session or license.
controls.onPlayRequested = {
player.prepare(endpoint = sessionEndpoint, contentId = contentId,
capabilities = capabilities, customerAuthenticationHeaders = userHeaders)
}
controls.onFullScreenRequested = { /* resize the existing player view */ }
player.listener = object : DrmXPlayerListener {
override fun onAuthorizing(contentId: String) { controls.setPreparing(true) }
override fun onReady(info: DrmXPlaybackInfo) { controls.setPreparing(false) }
override fun onError(error: PlaybackSessionException) { controls.setPreparing(false) }
}
// Keep protectWindow(window) and the secure video surface.
// At final owner destruction: controls.unbind(); player.close()
Daftar muatan telepon yang diberikan menangani orientasi dan perubahan ukuran layar; itu onConfigurationChanged mengubah pandangan yang sama dan pemutar. Simpan kedua bagian saat menyesuaikannya. Host yang menciptakan Aktivitas harus mempertahankan pemilik pemutaran dan mengatur ulang tampilan. Kematian proses berbeda dari rotasi dan perlu pemulihan keadaan normal. Pilihan 4K / 8K memerlukan isi yang cocok, lisensi hak akses dan dukungan perangkat / DRM; dukungan CDM tetap berlaku.
Untuk gubahan pemutar, stop and release the active offline DRM sesi sebelum memeriksa, memperbaharui atau melepaskan lisensi gigih yang sama. SDK's player.stopForOfflineLicenseOperation { /* call manager here */ } menunggu Media3 antrian putar untuk merilis media. Polos stop() antrian yang bekerja asynchronously. checkLicense() ketika lisensi yang sama sedang diputar; putar sendiri memvalidasi nya CDM negara sampel yang diberikan menunjukkan handoff lengkap dan menonaktifkan tindakan tumpang tindih selama pembaharuan.
6. Cari lisensi dan unduh media #
val offlineManager = DrmXOfflineManager(applicationContext)
val capabilities = WidevineCapabilities.offlinePlaybackCapabilities(
clientPlatform = "android", // android-tv or android-automotive where applicable
displayMetrics = resources.displayMetrics,
applicationVersion = "1.0",
)
offlineManager.acquireLicense(
endpoint = offlineEndpoint,
contentId = contentId,
capabilities = capabilities,
customerAuthenticationHeaders = customerHeaders,
) { result ->
result.onSuccess { stored ->
// Next: select tracks <= stored.maximumHeight and queue their download.
// Acquisition alone does not download the video.
}.onFailure { /* show a safe retry/error state */ }
}
The SDK Simpan yang buram Widevine kunci -set ID dan bukan metadata rahasia. CDM Dia tidak bertahan. DRM License Tokens, kunci mentah, tantangan atau bytes respon lisensi. Abaikan com.haihaisoft.drmx.offline.licenses.v1.xml dari backup.
Buat satu pelamar yang dimiliki Media3 SimpleCache, unduh manajer dan basis data. Gunakan DownloadHelper dengan MediItem berlisensi dan pilih video di dalam maximumHeightDalam Media3 1.11 callback siap adalah onPrepared(helper, tracksInfoUpdated)Sampel telepon enqueueDownload dan OfflineTestRuntime tampilkan implementasi yang dapat dijalankan.
// Inside DownloadHelper's prepared callback, after selecting licensed video:
helper.addAudioLanguagesToSelection("en", "zh-Hans", "zh")
helper.addTextLanguagesToSelection(true, "en", "zh-Hans", "zh")
val selected = helper.getDownloadRequest(offlineLicenseId, byteArrayOf())
val request = offlineManager.createDownloadRequest(contentId, selected.streamKeys)
downloadManager.addDownload(request)
helper.release()
Unduh setiap bahasa yang ingin Anda ekspos luring. Memanggil createDownloadRequest tanpa kunci stream mengunduh semua trek, yang umumnya diboros untuk video adaptif. Tampilkan kemajuan unduh dan tunggu untuk Download.STATE_COMPLETEDUntuk transfer latar belakang produksi, mengintegrasikan Media3 DownloadService, batas penyimpanan dan Android foreground- layanan / pemberitahuan persyaratan; antrian demo berjalan in- proses.
7. Path B: kembalikan dengan Anda yang ada Media3 pemutar #
Baca download selesai dan gunakan kunci stream yang tepat. Pengunduhan dan tumpukan putar harus berbagi lokasi singgahan dan pemetaan kunci yang sama. Contoh ini sengaja mematikan akses upstream untuk pemutaran luring yang ketat:
val cacheOnly = CacheDataSource.Factory()
.setCache(downloadCache)
.setUpstreamDataSourceFactory(null)
val mediaSourceFactory = DefaultMediaSourceFactory(this)
.setDataSourceFactory(cacheOnly)
val nativePlayer = ExoPlayer.Builder(this)
.setMediaSourceFactory(mediaSourceFactory)
.build()
val completed = downloadIndex.getDownload(offlineLicenseId)
require(completed?.state == Download.STATE_COMPLETED)
val playback = offlineManager.createPlayback(contentId, streamKeys = completed!!.request.streamKeys)
nativePlayer.setMediaItem(playback.mediaItem)
nativePlayer.prepare()
nativePlayer.play()
// Release nativePlayer when the owner is destroyed.
Untuk menggunakan aliran offline yang sama dengan Path A, membangun DrmXPlayer dengan ini mediaSourceFactory dan memanggil player.prepareOffline(playback). Pemulihan biasa menggunakan lisensi lokal CDM tanpa meminta yang baru. Entri cache yang hilang seharusnya menghasilkan kesalahan selama penerimaan terputus, bukan diam-diam beralih ke internet.
8. Path C: native Media3, tidak ada DRM-X AAR # }
You are not required to use DrmXPlayer or DrmXOfflineManager. Add the three Media3 dependencies from step 3 and implement the same customer backend contract. Use session.manifestUrl (not session.manifest.url), the returned license URL and bounded authorization headers. Apply the returned maximum height and handle streaming session release on stop, replacement, end, failure and destruction.
Respon lengkap di bawah ini dikompilasi sebagai samples:native bersama dengan rilis SDK. Ini menangani HTTPS, respon terbatas dibaca, otorisasi latar belakang, tanggapan basi dan rilis reservasi. Ganti titik akhir yang ditandai / Content ID dan menyediakan tanda masuk Anda sendiri. Contoh adalah titik awal; tambah penyegaran produksi Anda, refresh, akun-switch, dan app- navigasi lifecycle.
Aktivitas streaming Asli (Kotlin, tidak ada DRM-X ketergantungan)
package com.haihaisoft.drmx.samples.nativeplayer
import android.app.Activity
import android.os.Bundle
import android.view.WindowManager
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.PlaybackException
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView
import org.json.JSONObject
import java.net.HttpURLConnection
import java.net.URI
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
/** Complete native streaming example. No DRM-X AAR or server credentials. */
@UnstableApi
class MainActivity : Activity() {
private lateinit var player: ExoPlayer
private lateinit var status: TextView
private val worker = Executors.newSingleThreadExecutor()
private val closed = AtomicBoolean(false)
private var activeSession: JSONObject? = null
private var requesting = false
private var generation = 0
// CUSTOMIZE: use YOUR authenticated customer backend and Published Content ID.
// The sample can receive these after your application's login via Intent extras.
// Never replace the app login token with a DRM-X Site Key or Access Key.
private val endpoint get() = intent.getStringExtra("drmx.sessionEndpoint")
?: "https://customer.example/api/drmx/playback-session"
private val contentId get() = intent.getStringExtra("drmx.contentId") ?: "YOUR-PUBLISHED-CONTENT-ID"
private val customerToken get() = intent.getStringExtra("customer.accessToken").orEmpty()
override fun onCreate(state: Bundle?) {
super.onCreate(state)
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
val root = LinearLayout(this).apply { orientation = LinearLayout.VERTICAL; fitsSystemWindows = true; setPadding(24, 24, 24, 24) }
status = TextView(this).apply { text = "Native Media3 · connect your backend, then Play"; textSize = 16f }
val view = PlayerView(this)
player = ExoPlayer.Builder(this).build(); view.player = player
root.addView(status)
root.addView(view, LinearLayout.LayoutParams(-1, 0, 1f))
root.addView(Button(this).apply { text = "Play protected video"; setOnClickListener { startPlayback() } })
root.addView(Button(this).apply { text = "Stop & release session"; setOnClickListener { stopPlayback() } })
setContentView(root)
player.addListener(object : Player.Listener {
override fun onPlayerError(error: PlaybackException) { status.text = "Playback error: ${error.errorCodeName}"; releaseSession() }
override fun onPlaybackStateChanged(state: Int) { if (state == Player.STATE_ENDED) releaseSession() }
})
}
private fun startPlayback() {
if (requesting) return
stopPlayback(); requesting = true; status.text = "Authorizing…"
val attempt = generation
val request = JSONObject().put("contentId", contentId).put("contentType", "vod")
.put("drmSystem", "widevine").put("playbackMode", "streaming")
.put("platformCapabilities", JSONObject().put("clientPlatform", "android")
.put("drmSystems", org.json.JSONArray(listOf("widevine")))
.put("manifestTypes", org.json.JSONArray(listOf("dash")))
.put("maximumHeight", 1080).put("secureDecoder", false).put("persistentState", false))
val headers = if (customerToken.isBlank()) emptyMap() else mapOf("Authorization" to "Bearer $customerToken")
worker.execute {
val result = runCatching { JSONObject(post(endpoint, request.toString(), headers)) }
runOnUiThread {
requesting = false
result.onSuccess { session ->
if (closed.get() || attempt != generation) { workerRelease(session); return@onSuccess }
// Keep release information even if contract validation fails.
activeSession = session
runCatching {
require(session.getInt("contractVersion") == 1 && session.getString("contentId") == contentId)
require(session.getString("drmSystem") == "widevine" && session.getString("playbackMode") == "streaming")
val drm = session.getJSONObject("drm")
require(drm.getString("system") == "widevine")
val maximumHeight = session.getJSONObject("policy").getInt("maximumHeight")
require(maximumHeight in 1..4320)
val mediaItem = MediaItem.Builder().setUri(https(session.getString("manifestUrl")))
.setMimeType("application/dash+xml")
.setDrmConfiguration(MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)
.setLicenseUri(https(drm.getString("licenseServerUrl")))
.setForceDefaultLicenseUri(true).setLicenseRequestHeaders(authorization(drm))
.setMultiSession(false).build()).build()
player.trackSelectionParameters = player.trackSelectionParameters.buildUpon()
.setMaxVideoSize(Int.MAX_VALUE, maximumHeight).setPreferredAudioLanguages("en")
.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, true).build()
player.setMediaItem(mediaItem); player.prepare(); player.play()
status.text = "Native Media3 · protected playback"
}.onFailure { status.text = "Invalid session contract. Check your backend."; releaseSession() }
}.onFailure { if (!closed.get()) status.text = "Authorization failed. Check login, Content ID, policy, and network." }
}
}
}
private fun releaseSession() { activeSession?.let(::workerRelease); activeSession = null }
private fun workerRelease(session: JSONObject) {
// A bounded release may finish after Activity destruction, including a
// session response that arrived after the user left the screen.
Thread({ runCatching {
val release = session.getJSONObject("release")
val headers = if (release.has("authorization")) authorization(release)
else authorization(session.getJSONObject("drm"))
post(release.getString("url"), "", headers)
} }, "drmx-native-release").start()
}
private fun stopPlayback() { generation++; player.stop(); player.clearMediaItems(); releaseSession() }
override fun onStop() { stopPlayback(); super.onStop() }
override fun onDestroy() { closed.set(true); stopPlayback(); player.release(); worker.shutdown(); super.onDestroy() }
companion object {
fun https(url: String): String {
val uri = URI(url); require(uri.scheme == "https" && uri.host != null && uri.userInfo == null)
return url
}
fun authorization(drm: JSONObject): Map<String, String> {
val auth = drm.optJSONObject("authorization")
val name = auth?.getString("headerName") ?: "Authorization"
val scheme = auth?.getString("scheme") ?: drm.optString("tokenType", "Bearer")
val value = auth?.getString("value") ?: drm.getString("drmLicenseToken")
require(name.matches(Regex("^[A-Za-z0-9-]{1,64}$")) && scheme.matches(Regex("^[A-Za-z][A-Za-z0-9._-]{0,31}$")))
require(value.isNotBlank() && !value.contains('\r') && !value.contains('\n'))
return mapOf(name to "$scheme $value")
}
fun post(url: String, body: String, headers: Map<String, String>): String {
val connection = URI(https(url)).toURL().openConnection() as HttpURLConnection
try {
connection.requestMethod = "POST"; connection.instanceFollowRedirects = false
connection.connectTimeout = 5000; connection.readTimeout = 15000; connection.doOutput = true
connection.setRequestProperty("Content-Type", "application/json")
headers.forEach { (name, value) -> connection.setRequestProperty(name, value) }
connection.outputStream.use { it.write(body.toByteArray(Charsets.UTF_8)) }
require(connection.responseCode in 200..299) { "Customer request rejected" }
return connection.inputStream.use { stream ->
val output = java.io.ByteArrayOutputStream(); val buffer = ByteArray(8192)
while (true) {
val count = stream.read(buffer); if (count < 0) break
require(output.size() + count <= 1_048_576); output.write(buffer, 0, count)
}
output.toString("UTF-8")
}
} finally { connection.disconnect() }
}
}
}
Untuk lisensi offline asli, gunakan OfflineLicenseHelper.downloadLicense, bertahan tombol buram -set ID Pribadi dan kembalikan dengan MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID).setKeySetId(id)pembantu terkompail berikut meliputi akuisisi, durasi pemeriksaan, pembaruan, rilis dan download / item putar. Ini adalah bukan sebuah aplikasi download lengkap: Anda masih memiliki cache, layanan download, kemajuan, metadata, pengikatan pengguna / perangkat dan terpercaya otorisasi operasi.
Pendukung lisensi asli (Kotlin, tidak ada DRM-X ketergantungan)
package com.haihaisoft.drmx.samples.nativeplayer
import android.content.Context
import android.util.Base64
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.StreamKey
import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.DefaultHttpDataSource
import androidx.media3.exoplayer.dash.DashUtil
import androidx.media3.exoplayer.drm.DrmSessionEventListener
import androidx.media3.exoplayer.drm.OfflineLicenseHelper
import androidx.media3.exoplayer.offline.DownloadRequest
import org.json.JSONObject
/** Native Media3 alternative: no DRM-X AAR. Call blocking operations on a worker.
* Application owns downloads/cache, user/device entitlement, progress and lifecycle.
* Never persist the session, request headers, tokens, challenges or license bytes.
*/
@UnstableApi
class NativeOfflineLicense(context: Context) {
private val storage = context.getSharedPreferences("native.offline.keysets", Context.MODE_PRIVATE)
private val upstream = DefaultHttpDataSource.Factory().setConnectTimeoutMs(10000).setReadTimeoutMs(20000)
// session is the validated response from YOUR offline-license-session endpoint.
fun acquire(session: JSONObject): ByteArray {
validate(session)
val contentId = session.getString("contentId")
require(!storage.contains(contentId)) { "Renew or release the stored license before acquiring again" }
val source = upstream.createDataSource()
val manifest = DashUtil.loadManifest(source, android.net.Uri.parse(MainActivity.https(session.getString("manifestUrl"))))
val format = DashUtil.loadFormatWithDrmInitData(upstream.createDataSource(), manifest.getPeriod(0))
?: error("Missing Widevine initialization data")
val helper = helper(session)
try {
val id = helper.downloadLicense(format)
save(contentId, id)
return id
} finally { helper.release() }
}
fun renew(contentId: String, freshSession: JSONObject) {
validate(freshSession); require(freshSession.getString("contentId") == contentId)
val helper = helper(freshSession)
try { save(contentId, helper.renewLicense(keySet(contentId))) } finally { helper.release() }
}
// Local CDM check only. No token or network license URI is used.
fun remainingSeconds(contentId: String): Pair<Long, Long> {
val config = MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID).build()
val helper = OfflineLicenseHelper.newWidevineInstance(config, upstream, DrmSessionEventListener.EventDispatcher())
try {
val remaining = helper.getLicenseDurationRemainingSec(keySet(contentId))
return Pair(remaining.first, remaining.second)
} finally { helper.release() }
}
fun release(contentId: String, freshSession: JSONObject) {
validate(freshSession); require(freshSession.getString("contentId") == contentId)
val helper = helper(freshSession)
try {
helper.releaseLicense(keySet(contentId))
check(storage.edit().remove(contentId).commit())
} finally { helper.release() }
}
fun downloadRequest(contentId: String, downloadId: String, manifestUrl: String, streamKeys: List<StreamKey>): DownloadRequest {
require(streamKeys.isNotEmpty()) { "Select policy-compliant video, audio and subtitle tracks first" }
return DownloadRequest.Builder(downloadId, android.net.Uri.parse(MainActivity.https(manifestUrl)))
.setMimeType("application/dash+xml").setStreamKeys(streamKeys).setKeySetId(keySet(contentId)).build()
}
fun mediaItem(contentId: String, manifestUrl: String, streamKeys: List<StreamKey>): MediaItem = MediaItem.Builder()
.setUri(MainActivity.https(manifestUrl)).setMimeType("application/dash+xml").setStreamKeys(streamKeys)
.setDrmConfiguration(MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID).setKeySetId(keySet(contentId)).build()).build()
private fun helper(session: JSONObject): OfflineLicenseHelper {
val drm = session.getJSONObject("drm")
// Use HTTP license headers, NOT Widevine optional key-request parameters.
val config = MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)
.setLicenseUri(MainActivity.https(drm.getString("licenseServerUrl")))
.setForceDefaultLicenseUri(true).setLicenseRequestHeaders(MainActivity.authorization(drm)).build()
return OfflineLicenseHelper.newWidevineInstance(config, upstream, DrmSessionEventListener.EventDispatcher())
}
private fun validate(session: JSONObject) {
require(session.getInt("contractVersion") == 1 && session.getString("playbackMode") == "offline")
require(session.getString("drmSystem") == "widevine" && session.getString("contentType") == "vod")
require(session.getJSONObject("policy").getBoolean("persistent"))
}
private fun keySet(contentId: String): ByteArray = Base64.decode(storage.getString(contentId, null)
?: error("No device-bound license for this content"), Base64.NO_WRAP)
private fun save(contentId: String, id: ByteArray) {
check(storage.edit().putString(contentId, Base64.encodeToString(id, Base64.NO_WRAP)).commit())
}
}
Sebelum memanggil pembantu tingkat rendah ini, validasi bahwa respon backend segar cocok dengan yang diminta Content ID, operasi, signed-in user / device dan otorisasi perioda validitas. Persist sebuah stabil licenseId dan terpercaya metadata manifest / track bersama kunci -set IDTidak pernah ada token, jalankan panggilan pembantu di benang pekerja. HTTP penggunaan header setLicenseRequestHeaders pada DRM konfigurasi; Widevine parameter opsional key-request adalah peta yang berbeda.
Integrasi baru harus digunakan AndroidX Media3 DRM dukunganLegacy com.google.android.exoplayer2 proyek harus mengikuti panduan migrasi resmiDan janganlah kamu campur adukkan harta dan anak-anak kamu. AndroidX kelas atau asumsikan sampel compiles tidak berubah terhadap versi yang lebih tua.
9. Periksa, perbarui, rilis dan tukar bahasa #
These are separate actions. Run one at a time after the active offline DRM session has been released: use player.stopForOfflineLicenseOperation { /* one operation below */ } with DrmXPlayer, or release the existing native Media3 player first. Do not check a license while it is playing. A check is optional for displaying durations; it must not prevent renewal of an expired license.
offlineManager.checkLicense(contentId) { result ->
result.onSuccess { license ->
if (license.state == DrmXOfflineLicenseState.EXPIRED) {
// Require renewal online before offering offline playback.
}
}
}
offlineManager.renewLicense(offlineEndpoint, contentId, capabilities, customerHeaders) {
/* update duration and UI after success; show retry on failure */
}
// Only when the customer requests deletion/release:
offlineManager.releaseLicense(offlineEndpoint, contentId, capabilities, customerHeaders) {
/* after success, remove the corresponding encrypted download */
}
getStoredLicense membaca metadata; checkLicense queries otoritas lokal CDM durasi. Renew / release membutuhkan konektivitas dan baru operasional -spesifik otorisasi dari backend Anda. Menghapus media tidak merilis lisensi. Ketika diputus, rilis antrian untuk koneksi berikutnya daripada melaporkan bahwa server telah mengkonfirmasi itu. Tutup manajer ketika pemiliknya hancur.
// Use player.media3Player for the DRM-X wrapper; nativePlayer for plain Media3.
nativePlayer.trackSelectionParameters = nativePlayer.trackSelectionParameters
.buildUpon()
.setPreferredAudioLanguages("en") // Chinese: "zh-Hans", "zh"
.setPreferredTextLanguages("en") // choose a packaged/downloaded language
.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, false) // true = subtitles Off
.build()
Bangun pilihan dari trek yang tersedia dan matikan pilihan yang tak tersedia. Suatu preferensi tak dapat membuat trek bahasa Inggris absen dari paket. Pengguna Offline hanya dapat memilih bahasa yang diunduh. Pertahankan keadaan lisensi / cache di seluruh rotasi layar; layar penuh adalah tampilan / perubahan jendela, bukan alasan untuk memperoleh lisensi lain.
10. Mengimplementasikan titik akhir otorisasi luring #
Aplikasi memposting contentId, contentType: "vod", drmSystem: "widevine", playbackMode: "offline", operation: "acquire" | "renew" | "release", offlineLicenseId (kosong untuk akuisisi awal) dan jujur platformCapabilities. Verifikasi ID pembaruan milik pengguna, perangkat, dan isi. Pilih server- sisi kebijakan, keluarkan yang baru DRM License Token dan kembalikan kontrak yang cocok:
{
"contractVersion": 1, "playbackMode": "offline",
"offlineLicenseId": "YOUR-STABLE-USER-DEVICE-CONTENT-RECORD",
"contentId": "YOUR-PUBLISHED-CONTENT-ID", "contentType": "vod",
"drmSystem": "widevine",
"manifestUrl": "https://media.customer.example/title/manifest.mpd",
"authorizationExpiresAt": "YOUR-FRESH-UTC-EXPIRY",
"drm": {
"system": "widevine",
"licenseServerUrl": "https://license6.drm-x.com/v1/licenses/widevine",
"integrationMode": "direct-token",
"drmLicenseToken": "SHORT-LIVED-OPERATION-AUTHORIZATION",
"tokenType": "Bearer"
},
"policy": {
"persistent": true, "renewAllowed": true, "maximumHeight": 1080,
"allowedTrackTypes": ["AUDIO", "SD", "HD"],
"licenseDurationSeconds": 604800, "rentalDurationSeconds": 259200,
"playbackDurationSeconds": 172800, "renewalDurationSeconds": 604800
}
}
Ini adalah placeholder yang jelas, bukan sebuah respon yang dapat dipakai kembali. Kembalikan nilai baru dari operasi yang sebenarnya. SDK juga mendukung integrationMode: "token-proxy" dengan kekurangan drm.authorization deskripsi. Kembalikan Cache-Control: no-store: tidak pernah log sukses badan otorisasi. Lihat proses yang dapat diunduh SDK 's OFFLINE_INTEGRATION.md dan PHP sampel titik luring untuk penanganan permintaan konkret.
#
Widevine penyediaan dan pengujian jaringan Cina
Menyediakan memuat sertifikat perangkat sebelum akuisisi lisensi isi. Dari previe.9 demo telepon mengirim CDM's signed request through its authenticated composer HTTPS relay ke Google. Respon yang ditandatangani tidak berubah. Ini membantu ketika telepon tidak dapat mencapai layanan provisioning Google secara langsung; relay pelanggan harus masih dapat diakses.
Menyediakan 2.0 menggunakan kotak kunci pabrik. Menyediakan 4.0 menggunakan model kredensial perangkat yang berbeda. Versi ini dipisahkan dari L1/L3 tingkat keamanan, dan pemutar tidak menukar mereka. yang sudah ditetapkan. L3 telepon dapat bermain ketika telepon lain menunggu penyediaan perangkat. Sumber resmi publik yang ditinjau di sini tidak menetapkan bahwa Cina hanya mendukung 2.0. Lihat. NXPPanduan integrasi perangkat dan AndroidPengadaan implementasi.
Laporan galat awal: 10 membedakan transport langsung atau relay, waktu habis /DNS/TLS/HTTP gagal, HTTP status dan waktu berlalu. provisioningModel: BootCertificateChain Menunjukkan AOSP Model 4.0; unknown atau other tidak menetapkan 2.0. PHP log membedakan masukan yang ditolak dari kegagalan upstream Google. Laporan exclude signed payloads, URL, kredensial dan identifikasi perangkat yang unik.
Mutakhirkan APK di tempat, coba streaming dan satu download pada jaringan yang terpengaruh, kemudian pertahankan log Copy dan waktu perkiraan. Existing unduhan dan lisensi yang ditahan. Suatu relay tidak dapat diperbaiki tidak tersedia Widevine atau kredensial ditolak oleh perangkat / Google. Penerimaan nyata pada telepon yang terpengaruh diperlukan.
Dari preview-8, asli L2/L3 atau level-tidak-tahu Widevine putar terbatas ke SD (sampai 576p) sebelum decoding. Teruskan yang asli Android kemampuan melalui backend anda: sesi API engking perangkat lunak Widevine lisensi multi- kunci ke audio /SD Kuncinya. PHP sampel mempertahankan field ini dan juga caps permintaan offline. An SD rendition dan sebuah kebijakan mengizinkan perangkat lunak DRM dibutuhkan; hardware -only dan seragam tunggal-aturan keamanan tetap tidak berubah. Pengaturan menggunakan sebuah panel translucent tanpa meredupkan video. Numeric cryptoErrorCode termasuk dalam laporan kesalahan yang aman.
| Tes / gejala | Diharapkan pemeriksaan perilaku / berikutnya |
|---|---|
| SDK unduh kembali 403 | Pilih sebuah organisasi dengan berlangganan Profesional atau Enterprise yang aktif. Suatu peningkatan yang direncanakan setelah percobaan tidak membuka SDK. |
| Sesi 401 / 403 | Periksa log masuk, hak akses, Lingkungan, Terbitkan Content ID dan kebijakan. Jangan pernah lewati otentikasi. |
| Offline gagal tapi kerja online | Periksa CDM durasi, selesai download, lokasi cache, kunci stream dan semua kunci lisensi yang dibutuhkan. |
| Inggris / Cina hilang | Periksa metadata bahasa paket, trek aktual dan seleksi bahasa offline. |
| L1, HDCP atau gagal decoder | Periksa perangkat keras fisik, provisioning, codec dan output persyaratan. Sebuah string kapabilitas tidak sertifikasi. |
| Reboot, rotasi, upgrade | Surat ijin dan cache yang bertahan dari perubahan lifecycle yang didukung tanpa akuisisi duplikasi. Backup tidak boleh bermigrasi lisensi ke perangkat baru. |
| Mode pesawat udara | Nonaktifkan Wi-Fi dan data mobile juga; restart aplikasi, putar secara lokal dan ganti setiap bahasa yang dijanjikan. |
| Kadaluwarsa, tekanan penyimpanan, tombol akun | Tampilkan keadaan yang jelas tidak tersedia / memperbaharui, memulihkan media yang tidak lengkap, dan memaksakan akses pengguna / perangkat tanpa membocorkan katalog luring pengguna lain. |
Kualifikasi setiap ponsel yang didukung, tablet, Android TV/Google TV, Fire TV atau tertanam Android model untuk Widevine, decoding aman, codec / resolusi, HDCP, eksternal display, clock changes and long disconnection. Tidak setiap Android perangkat memiliki sama DRM kemampuan isi Hollywood membutuhkan perlindungan pemegang hak cipta dan kebutuhan perangkat, tidak hanya sukses decoding.
Universal Player playlist dan shared control #
The Android preview 11 dan aplikasi evaluasi kemudian dan saat ini Android/ Sumber pengembangan Apple berbagi in- video Sebelumnya / Play- Jeda / Berikutnya, CC, Pengaturan dan kontrol layar penuh dengan dua- detik bersembunyi selama pemutaran. Androidmenu playlist tidak lagi termasuk "Play next". Pengaturan pilihan / reappect tetap disorot dan tetap berjalan di restarts. Dengan kedua off, putar mengikuti urutan playlist yang tersimpan dan berhenti di video akhir. Seret handle urutan ulang item tanpa memulai ulang video saat ini; urutan tersimpan juga berlaku untuk playlist yang telah diunduh. Sumber terbaru APIs belum termasuk dalam prematur Console SDK bundel.
Supply the compenent / viewer storageNamespace to that DrmXPlayer and playerView.storageNamespace before setting the playlist. VOD progress is save periocally and on pause / stop, then resume for that Content ID in streaming or download playing. Live playing does not use a saved VOD position. Selesai unduhan mempertahankan perilaku yang sama / resume tanpa sumber media jaringan. Keadaan lokal ini tidak mensinkronkan kemajuan.
Edisi Web dan Android memakai panel pengaturan gelap konsisten dengan kendali biru kompak. Dukungan playlist berikutnya / sebelumnya, shuffle, ulangi satu / semua dan dapat dibatalkan otomatis muka. Setiap item menggunakan permintaan putar yang berwenang baru. Bab dan metadata transkrip berasal dari katalog konten Anda.
Kecepatan putar, timer tidur, takarir, kualitas yang diijinkan, bahasa audio, penanda sesi dan penjatuhan A-B tersedia. Jalan pintas papan ketik, resume opsional, transkrip pencarian dan didukung peramban PiP. Android mempertahankan asli Widevine pemutakhiran dan pembaharuan. Casting dan proses perempatan memerlukan integrasi aplikasi terpisah.
Pengaturan logo profesional dan Enterprise
Branding tetap berada di permukaan video. Buka Pengaturan Berkas Tentang pemutar untuk logo yang berwenang, informasi produk dan versi pemutar. Web juga menawarkan informasi ini pada right- klik. Demo telepon umum termasuk WayMaker, Kebaikan Allah, Minyak Baru dan 4K Tes Video; setiap pemilihan menerima otorisasi sendiri.
Atur playerBranding dalam backend terpercaya Anda ke {"mode":"hidden"} atau {"mode":"custom","logoUrl":"https://your-site.example/logo.png","label":"Your brand"}. Cek platform yang aktif Berlangganan Profesional. Rencana lain menggunakan {"mode":"default"}; permintaan custom / hidden tidak sah kembali 403. Ini terpisah dari watermark keamanan.
Pengunduhan PHP termasuk daftar putar yang dapat disunting dan konfigurasi branding. Android pelanggan ZIP termasuk contoh daftar putar callback. Simpan otorisasi playlist dalam backend Anda; jangan pernah embed API klien kredensial dalam baik pemutar.
DRM-X 6.0