android.media.projection
ממשקי API שהושקו ב-Android 5 (רמת API 21) מאפשרים לכם לתעד את התוכן
של מסך המכשיר כסטרימינג של מדיה שאפשר להפעיל, להקליט או להפעיל בו Cast
במכשירים אחרים, כמו טלוויזיות.
Android 14 (רמת API 34) כולל שיתוף מסך של אפליקציות, שמאפשר למשתמשים משתפים חלון אפליקציה אחד במקום את כל מסך המכשיר, ללא קשר וחלון הראווה. שיתוף מסך של אפליקציה לא כולל את שורת הסטטוס, סרגל הניווט, וגם רכיבים אחרים של ממשק המשתמש מהמסך המשותף – אפילו כשנעשה שימוש בשיתוף מסך של אפליקציה כדי לצלם אפליקציה במסך מלא. רק התוכן של האפליקציה שנבחרה ישותף.
שיתוף מסך של אפליקציות מבטיח את פרטיות המשתמשים, מגביר את הפרודוקטיביות של המשתמשים משפר את ריבוי המשימות בכך שהוא מאפשר למשתמשים להריץ כמה אפליקציות אבל מגביל את שיתוף התוכן לאפליקציה אחת בלבד.
שלושה ייצוגי תצוגה
הקרנת מדיה מתעדת את התוכן של מסך המכשיר או חלון האפליקציה,
לאחר מכן המערכת מקרית את התמונה שצולמה במסך וירטואלי שמציגה את התמונה
Surface
.
![מסך של מכשיר אמיתי מוקרן על מסך וירטואלי. תוכן של
תצוגה וירטואלית שנכתבת אל 'Surface' שסופק על ידי האפליקציה.](https://developer.android.com/static/media/images/grow/media-projection.png?authuser=8&hl=he)
Surface
האפליקציה מספקת את Surface
באמצעות
MediaRecorder
,
SurfaceTexture
, או
ImageReader
, שצורכת
את התוכן של מסך הצילום ואפשר לנהל את התמונות שמעובדות
ב-Surface
בזמן אמת. אפשר לשמור את התמונות כהקלטה או כהפעלת Cast
לטלוויזיה או למכשיר אחר.
מסך אמיתי
מתחילים פעילות של הקרנת מדיה באמצעות קבלת אסימון שמעניק לאפליקציה את
יכולת לתעד את התוכן של מסך המכשיר או של חלון האפליקציה. האסימון
מיוצג על ידי מופע
MediaProjection
בכיתה.
משתמשים בשיטה getMediaProjection()
MediaProjectionManager
שירות מערכת ליצירת מופע MediaProjection
כשמתחילים פעילות חדשה. להתחיל את הפעילות עם כוונה
createScreenCaptureIntent()
לציון מסך
פעולת צילום:
Kotlin
val mediaProjectionManager = getSystemService(MediaProjectionManager::class.java) var mediaProjection : MediaProjection val startMediaProjection = registerForActivityResult( StartActivityForResult() ) { result -> if (result.resultCode == RESULT_OK) { mediaProjection = mediaProjectionManager .getMediaProjection(result.resultCode, result.data!!) } } startMediaProjection.launch(mediaProjectionManager.createScreenCaptureIntent())
Java
final MediaProjectionManager mediaProjectionManager = getSystemService(MediaProjectionManager.class); final MediaProjection[] mediaProjection = new MediaProjection[1]; ActivityResultLauncher<Intent> startMediaProjection = registerForActivityResult( new StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { mediaProjection[0] = mediaProjectionManager .getMediaProjection(result.getResultCode(), result.getData()); } } ); startMediaProjection.launch(mediaProjectionManager.createScreenCaptureIntent());
תצוגה וירטואלית
החלק המרכזי של הקרנת מדיה הוא התצוגה הווירטואלית, שניתן ליצור
על ידי התקשרות
createVirtualDisplay()
במופע של MediaProjection
:
Kotlin
virtualDisplay = mediaProjection.createVirtualDisplay( "ScreenCapture", width, height, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, surface, null, null)
Java
virtualDisplay = mediaProjection.createVirtualDisplay( "ScreenCapture", width, height, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, surface, null, null);
הפרמטרים width
ו-height
מציינים את מידות האובייקט הווירטואלי
מסך. כדי לקבל ערכי רוחב וגובה, השתמש בפונקציה
השקה של WindowMetrics
ממשקי API
ב-Android 11 (רמת API: 30). (פרטים נוספים זמינים במאמר
הקטע גודל הקרנת המדיה).
סוג המסך
להתאים את גודל משטח הקרנת המדיה כדי להפיק פלט ורזולוציה. הגדלת המשטח (רזולוציה נמוכה) לצורך הפעלת Cast של התוכן לטלוויזיות או צגי מחשב וקטן (רזולוציה גבוהה) להקלטת מסך במכשיר.
החל מ-Android 12L (רמת API 32), כשמעבדים תוכן שתועד פני השטח, המערכת משנה את קנה המידה של התוכן באופן אחיד, תוך שמירה על יחס גובה-רוחב, כך ששני מידות התוכן (רוחב וגובה) שווים ל- או פחות מהמידות המתאימות של פני השטח. לאחר מכן התוכן שצולם במרכז,
גישת ההתאמה לעומס (scaling) של Android 12L משפרת את העברת המסך לטלוויזיות בצגים גדולים אחרים על ידי הגדלה של תמונת פני השטח, תוך הקפדה על ביחס הגובה-רוחב המתאים.
הרשאה לשימוש בשירות שפועל בחזית
אם האפליקציה מטרגטת את Android 14 ואילך, קובץ המניפסט של האפליקציה חייב לכלול
הצהרת הרשאה עבור
mediaProjection
סוג השירות שפועל בחזית:
<manifest ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<application ...>
<service
android:name=".MyMediaProjectionService"
android:foregroundServiceType="mediaProjection"
android:exported="false">
</service>
</application>
</manifest>
מפעילים את שירות הקרנת המדיה באמצעות קריאה ל-startForeground()
.
אם לא מציינים בשיחה את סוג השירות שפועל בחזית, סוג ברירת המחדל של סוג השירות
למספר שלם ביטי של סוגי השירותים שפועלים בחזית שמוגדר במניפסט. אם המיקום
המניפסט לא מציין סוגי שירות כלשהם, המערכת מעבירה
MissingForegroundServiceTypeException
הסכמת המשתמשים
האפליקציה שלך חייבת לבקש את הסכמת המשתמש לפני כל סשן של הקרנת מדיה. א'
הוא קריאה יחידה ל-createVirtualDisplay()
. אסימון MediaProjection
צריך להשתמש בה רק פעם אחת כדי לבצע את השיחה.
ב-Android מגרסה 14 ואילך, השיטה createVirtualDisplay()
מקפיצה
SecurityException
אם
האפליקציה מבצעת אחת מהפעולות הבאות:
- מעבירה מופע
Intent
שהוחזר מ-createScreenCaptureIntent()
ל-getMediaProjection()
יותר מפעם אחת - שיחות אל
createVirtualDisplay()
יותר מפעם אחת באותוMediaProjection
מופע
גודל הקרנת מדיה
הקרנת מדיה יכולה לצלם את כל מסך המכשיר או חלון של אפליקציה ללא קשר למצב עיבוד החלק הנצפה בלבד.
גודל ראשוני
באמצעות הקרנת מדיה במסך מלא, האפליקציה שלך חייבת לקבוע את גודל מסך המכשיר. בשיתוף מסך של אפליקציה, האפליקציה שלך לא תוכל לזהות גודל התצוגה שתועדה עד שהמשתמש בחר את אזור הצילום. לכן, הגודל הראשוני של כל הקרנת מדיה הוא הגודל של מסך המכשיר.
שימוש בפלטפורמה WindowManager
השיטה getMaximumWindowMetrics()
כדי להחזיר
אובייקט WindowMetrics
של
מסך המכשיר, גם אם האפליקציה המארחת של הקרנת המדיה פועלת בחלונות מרובים
כך שתופס רק חלק מהמסך.
לקבלת תאימות עד לרמת API 14, אפשר להשתמש ברכיב WindowMetricsCalculator
computeMaximumWindowMetrics()
מספריית Jetpack WindowManager
.
צריך להפעיל את השיטה WindowMetrics
getBounds()
כדי לקבל מידע על הרוחב והגובה של מסך המכשיר.
שינויים בגודל
גודל הקרנת המדיה יכול להשתנות כשמסובבים את המכשיר או שהמשתמש בוחר חלון אפליקציה כאזור הצילום בשיתוף המסך של האפליקציה. הקרנת המדיה עשויה להופיע בפורמט letterbox אם התוכן שצולם שונה ממדדי החלון המקסימלי שמתקבלים כשמדיה הוגדר הקרנה.
כדי לוודא שהקרנת המדיה תואמת במדויק לגודל של התמונה שצולמה
עבור כל אזור שנקלט ובסיבובי מכשירים שונים,
קריאה חוזרת (callback) של onCapturedContentResize()
כדי לשנות את גודל הצילום. (לקבלת מידע נוסף
אפשר לקרוא מידע נוסף בקטע התאמה אישית שבהמשך.
התאמה אישית
האפליקציה שלך יכולה להתאים אישית את חוויית המשתמש להקרנת המדיה עם הרכיבים הבאים
MediaProjection.Callback
ממשקי API:
onCapturedContentVisibilityChanged()
: המדיניות מאפשרת לאפליקציה המארחת (האפליקציה שהפעילה את הקרנת המדיה) להציג או להסתיר את התוכן המשותף.אפשר להשתמש בקריאה חוזרת (callback) כדי להתאים אישית את ממשק המשתמש של האפליקציה בהתאם האזור גלוי למשתמש. לדוגמה, אם האפליקציה גלויה ל משתמש בתוכן המוצג בממשק המשתמש של האפליקציה, האפליקציה שתועדה גלויה גם למשתמש (כפי שמצוין קריאה חוזרת), המשתמש רואה את אותו תוכן פעמיים. שימוש בקריאה חוזרת (callback) כדי לעדכן בממשק המשתמש של האפליקציה כדי להסתיר את התוכן שתועד ולפנות מקום בפריסה עבור תוכן אחר.
onCapturedContentResize()
: המדיניות הזו מאפשרת לאפליקציה המארחת לשנות את הגודל של הקרנת המדיה במרחב הווירטואלי הקרנת המדיה והתצוגהSurface
על סמך גודל הסרטון אזור תצוגה.מופעל בכל פעם שהתוכן שתועד – חלון אפליקציה אחד או חלון מלא מסך המכשיר - משנה את הגודל (עקב סיבוב המכשיר או מעבר למצב חלון אחר). השתמשו ב-API הזה כדי לשנות את הגודל של שני האובייקטים: מסך וירטואלי ומשטח וירטואלי כדי להבטיח שיחס הגובה-רוחב תואם התוכן והצילום לא בפורמט letterbox.
שחזור משאבים
האפליקציה שלך צריכה לרשום את MediaProjection
onStop()
להתקשרות חזרה כדי לקבל הודעה כשסשן הקרנת המדיה נעצר והופך
לא תקין. כשהסשן יופסק, האפליקציה אמורה לשחרר את המשאבים.
שהוא מחזיק, למשל המסך הווירטואלי ושטח ההקרנה. A הופסק
סשן הקרנת מדיה לא יכול עוד ליצור תצוגה וירטואלית חדשה, גם
האפליקציה שלך לא יצרה בעבר תצוגה וירטואלית עבור הקרנת המדיה הזו.
הקריאה החוזרת מופעלת כאשר הקרנת המדיה מסתיימת, כי המשתמש מפסיק את הסשן באופן ידני, או מכיוון שהמערכת מפסיקה את הסשן עבור מסיבה כלשהי.
אם האפליקציה לא מתעדת את הקריאה החוזרת (callback), כל קריאה למספר createVirtualDisplay()
זורקות
IllegalStateException
.
ביטול ההסכמה
מערכת Android מגרסה 14 ואילך מאפשרת שיתוף מסך של אפליקציות כברירת מחדל. כל מדיה סשן הקרנה של האפליקציה מאפשר למשתמשים לשתף חלון של אפליקציה, כל המסך.
כדי להפסיק לשתף את המסך של האפליקציה, צריך להפעיל את
אמצעי תשלום createScreenCaptureIntent(MediaProjectionConfig)
עם ארגומנט MediaProjectionConfig
שהוחזר מקריאה אל
createConfigForDefaultDisplay()
.
שיחה אל createScreenCaptureIntent(MediaProjectionConfig)
עם
ארגומנט MediaProjectionConfig
הוחזר מקריאה אל
createConfigForUserChoice()
זהה
כהתנהגות ברירת המחדל, כלומר קריאה
createScreenCaptureIntent()
.
אפליקציות שניתן לשנות את הגודל שלהן
תמיד צריך להגדיל את גודל האפליקציות להקרנת המדיה (resizeableActivity="true"
). ניתן לשנות את הגודל
אפליקציות תומכות בשינויי תצורת המכשיר ובמצב ריבוי חלונות (ראו
תמיכה בריבוי חלונות).
אם לא ניתן לשנות את גודל האפליקציה, עליה לבצע שאילתה על גבולות התצוגה מתוך חלון
ולהשתמש ב-getMaximumWindowMetrics()
כדי לאחזר את WindowMetrics
של
אזור התצוגה המקסימלי הזמין לאפליקציה :
Kotlin
val windowContext = context.createWindowContext(context.display!!, WindowManager.LayoutParams.TYPE_APPLICATION, null) val projectionMetrics = windowContext.getSystemService(WindowManager::class.java) .maximumWindowMetrics
Java
Context windowContext = context.createWindowContext(context.getDisplay(), WindowManager.LayoutParams.TYPE_APPLICATION, null); WindowMetrics projectionMetrics = windowContext.getSystemService(WindowManager.class) .getMaximumWindowMetrics();
מקורות מידע נוספים
לקבלת מידע נוסף על הקרנת מדיה, ראה צילום וידאו ואודיו.