החל מ-Android 8.0 (רמת API 26), MediaPlayer כולל ממשקי API שתומכים בהפעלה של חומרים שמוגנים באמצעות DRM. ממשקי ה-API של MediaPlayer DRM דומים לממשק ה-API ברמה נמוכה שמוצע על ידי MediaDrm, אבל הם פועלים ברמה גבוהה יותר ולא חושפים את האובייקטים הבסיסיים של החילוץ, ה-DRM וההצפנה.
למרות ש-MediaPlayer DRM API לא מספק את הפונקציונליות המלאה של MediaDrm, הוא תומך בתרחישי השימוש הנפוצים ביותר. ההטמעה הנוכחית יכולה לטפל בסוגי התוכן הבאים:
- קבצים מקומיים של מדיה שמוגנים על ידי Widevine
- קבצים של מדיה מרוחקת או סטרימינג של מדיה שמוגנים על ידי Widevine
בקטע הקוד הבא אפשר לראות איך משתמשים בשיטות החדשות של DRM MediaPlayerבהטמעה סינכרונית.
כדי לנהל מדיה שנשלטת על ידי DRM, צריך לכלול את השיטות החדשות לצד התהליך הרגיל של קריאות MediaPlayer, כמו בדוגמה הזו:
Kotlin
mediaPlayer?.apply {
setDataSource()
setOnDrmConfigHelper() // optional, for custom configuration
prepare()
drmInfo?.also {
prepareDrm()
getKeyRequest()
provideKeyResponse()
}
// MediaPlayer is now ready to use
start()
// ...play/pause/resume...
stop()
releaseDrm()
}
Java
setDataSource();
setOnDrmConfigHelper(); // optional, for custom configuration
prepare();
if (getDrmInfo() != null) {
prepareDrm();
getKeyRequest();
provideKeyResponse();
}
// MediaPlayer is now ready to use
start();
// ...play/pause/resume...
stop();
releaseDrm();
מתחילים באתחול האובייקט MediaPlayer והגדרת המקור שלו באמצעות setDataSource(), כרגיל. לאחר מכן, כדי להשתמש ב-DRM, מבצעים את השלבים הבאים:
- אם רוצים שהאפליקציה תבצע הגדרה בהתאמה אישית, צריך להגדיר ממשק
OnDrmConfigHelperולצרף אותו לנגן באמצעותsetOnDrmConfigHelper(). - קוראים לפונקציה
prepare(). - קוראים לפונקציה
getDrmInfo(). אם המקור מכיל תוכן עם DRM, הפונקציה מחזירה ערךMediaPlayer.DrmInfoשאינו null.
אם הסמל MediaPlayer.DrmInfo מופיע:
- בודקים את המפה של ה-UUID הזמינים ובוחרים אחד מהם.
- מכינים את הגדרת ה-DRM למקור הנוכחי על ידי קריאה ל-
prepareDrm().- אם יצרתם ורשמתם קריאה חוזרת (callback) של
OnDrmConfigHelper, היא מופעלת בזמן ש-prepareDrm()פועל. כך תוכלו לבצע הגדרה בהתאמה אישית של מאפייני ה-DRM לפני פתיחת סשן ה-DRM. הקריאה החוזרת מתבצעת באופן סינכרוני בשרשור שקרא ל-prepareDrm(). כדי לגשת למאפייני ה-DRM, קוראים לפונקציותgetDrmPropertyString()ו-setDrmPropertyString(). מומלץ להימנע מביצוע פעולות ארוכות. - אם עדיין לא הוקצו הרשאות למכשיר,
prepareDrm()גם ניגש לשרת הקצאת ההרשאות כדי להקצות הרשאות למכשיר. משך הזמן של הפעולה הזו משתנה בהתאם לחיבור לרשת.
- אם יצרתם ורשמתם קריאה חוזרת (callback) של
- כדי לקבל מערך בייטים של בקשת מפתח אטום לשליחה לשרת רישיונות, קוראים ל-
getKeyRequest(). - כדי לעדכן את מנוע ה-DRM לגבי תגובת המפתח שהתקבלה משרת הרישיונות, צריך להתקשר אל
provideKeyResponse(). התוצאה משתנה בהתאם לסוג בקשת המפתח:- אם התשובה היא לבקשת מפתח אופליין, התוצאה היא מזהה של קבוצת מפתחות. אפשר להשתמש במזהה של קבוצת המפתחות עם
restoreKeys()כדי לשחזר את המפתחות לסשן חדש. - אם התשובה היא לבקשה להפצה או להזרמה, התוצאה היא null.
- אם התשובה היא לבקשת מפתח אופליין, התוצאה היא מזהה של קבוצת מפתחות. אפשר להשתמש במזהה של קבוצת המפתחות עם
הכנת DRM באופן אסינכרוני
כברירת מחדל, הפקודה prepareDrm() פועלת באופן סינכרוני, ונחסמת עד שההכנה מסתיימת. עם זאת, יכול להיות שגם ההכנה הראשונה של DRM במכשיר חדש תדרוש הקצאת הרשאות, שתתבצע באופן פנימי על ידי prepareDrm(), ויכול להיות שייקח זמן עד שהיא תסתיים בגלל פעולת הרשת שנדרשת. כדי להימנע מחסימה ב-prepareDrm(), צריך להגדיר MediaPlayer.OnDrmPreparedListener.
מגדירים OnDrmPreparedListener. prepareDrm() מבצע את ההקצאה (אם צריך) ואת ההכנה ברקע. כשההקצאה וההכנה מסתיימות, המערכת מתקשרת למאזין. אל תניחו הנחות לגבי רצף הקריאות או ה-thread שבו ה-listener פועל (אלא אם רשמתם את ה-listener עם handler thread). המערכת יכולה להתקשר למאזין לפני או אחרי שהפונקציה prepareDrm() מחזירה ערך.
הגדרה של DRM באופן אסינכרוני
אפשר להפעיל את ה-DRM באופן אסינכרוני על ידי יצירה ורישום של MediaPlayer.OnDrmInfoListener להכנת ה-DRM ושל MediaPlayer.OnDrmPreparedListener להפעלת הנגן. הם פועלים בשילוב עם prepareAsync(), כמו בדוגמה הזו:
Kotlin
setOnPreparedListener()
setOnDrmInfoListener()
setDataSource()
prepareAsync()
// ...
// If the data source content is protected you receive a call to the onDrmInfo() callback.
override fun onDrmInfo(mediaPlayer: MediaPlayer, drmInfo: MediaPlayer.DrmInfo) {
mediaPlayer.apply {
prepareDrm()
getKeyRequest()
provideKeyResponse()
}
}
// When prepareAsync() finishes, you receive a call to the onPrepared() callback.
// If there is a DRM, onDrmInfo() sets it up before executing this callback,
// so you can start the player.
override fun onPrepared(mediaPlayer: MediaPlayer) {
mediaPlayer.start()
}
Java
setOnPreparedListener();
setOnDrmInfoListener();
setDataSource();
prepareAsync();
// ...
// If the data source content is protected you receive a call to the onDrmInfo() callback.
onDrmInfo() {
prepareDrm();
getKeyRequest();
provideKeyResponse();
}
// When prepareAsync() finishes, you receive a call to the onPrepared() callback.
// If there is a DRM, onDrmInfo() sets it up before executing this callback,
// so you can start the player.
onPrepared() {
start();
}
טיפול במדיה מוצפנת
החל מ-Android 8.0 (רמת API 26), MediaPlayer יכול גם לפענח Common Encryption Scheme (CENC) ומדיה מוצפנת ברמת הדגימה של HLS (METHOD=SAMPLE-AES) עבור סוגי הזרם הבסיסיים H.264 ו-AAC. בעבר הייתה תמיכה במדיה מוצפנת של פלח מלא (METHOD=AES-128).
מידע נוסף
Jetpack Media3 הוא הפתרון המומלץ להפעלת מדיה באפליקציה. מידע נוסף
בדפים האלה מפורטים נושאים שקשורים להקלטה, לאחסון ולהפעלה של אודיו וסרטונים: