تنفيذ جلسة وسائط
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
إنشاء
MediaSession
أثناء تجهيز تطبيقك لتشغيل الوسائط. مقتطف الرمز التالي
مثال على كيفية ضبط عمليات معاودة الاتصال والعلامات المناسبة:
Kotlin
session = MediaSession(this, "MusicService").apply {
setCallback(MediaSessionCallback())
setFlags(
MediaSession.FLAG_HANDLES_MEDIA_BUTTONS or MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS
)
}
Java
session = new MediaSession(this, "MusicService");
session.setCallback(new MediaSessionCallback());
session.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
بدء جلسة وسائط
تأكد أيضًا من الاتصال
setActive(true)
عند بدء التشغيل. يجب أن يطلب تطبيقك أيضًا التركيز الصوتي، كما هو موضّح في
إدارة التركيز الصوتي: الخطوات التي يجب اتّباعها
كما هو موضح في المثال التالي:
Kotlin
private fun handlePlayRequest() {
tryToGetAudioFocus()
if (!session.isActive) {
session.isActive = true
}
...
}
Java
private void handlePlayRequest() {
tryToGetAudioFocus();
if (!session.isActive()) {
session.setActive(true);
}
...
}
تعديل حالة التشغيل
تعديل حالة التشغيل في
MediaSession
للتوضيح
حالة الوسائط الحالية:
Kotlin
private fun updatePlaybackState() {
val position: Long =
mediaPlayer
?.takeIf { it.isPlaying }
?.currentPosition?.toLong()
?: PlaybackState.PLAYBACK_POSITION_UNKNOWN
val stateBuilder = PlaybackState.Builder()
.setActions(getAvailableActions()).apply {
setState(mState, position, 1.0f)
}
session.setPlaybackState(stateBuilder.build())
}
private fun getAvailableActions(): Long {
var actions = (PlaybackState.ACTION_PLAY_PAUSE
or PlaybackState.ACTION_PLAY_FROM_MEDIA_ID
or PlaybackState.ACTION_PLAY_FROM_SEARCH)
playingQueue?.takeIf { it.isNotEmpty() }?.apply {
actions = if (mState == PlaybackState.STATE_PLAYING) {
actions or PlaybackState.ACTION_PAUSE
} else {
actions or PlaybackState.ACTION_PLAY
}
if (currentIndexOnQueue > 0) {
actions = actions or PlaybackState.ACTION_SKIP_TO_PREVIOUS
}
if (currentIndexOnQueue < size - 1) {
actions = actions or PlaybackState.ACTION_SKIP_TO_NEXT
}
}
return actions
}
Java
private void updatePlaybackState() {
long position = PlaybackState.PLAYBACK_POSITION_UNKNOWN;
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
position = mediaPlayer.getCurrentPosition();
}
PlaybackState.Builder stateBuilder = new PlaybackState.Builder()
.setActions(getAvailableActions());
stateBuilder.setState(mState, position, 1.0f);
session.setPlaybackState(stateBuilder.build());
}
private long getAvailableActions() {
long actions = PlaybackState.ACTION_PLAY_PAUSE |
PlaybackState.ACTION_PLAY_FROM_MEDIA_ID |
PlaybackState.ACTION_PLAY_FROM_SEARCH;
if (playingQueue == null || playingQueue.isEmpty()) {
return actions;
}
if (mState == PlaybackState.STATE_PLAYING) {
actions |= PlaybackState.ACTION_PAUSE;
} else {
actions |= PlaybackState.ACTION_PLAY;
}
if (currentIndexOnQueue > 0) {
actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS;
}
if (currentIndexOnQueue < playingQueue.size() - 1) {
actions |= PlaybackState.ACTION_SKIP_TO_NEXT;
}
return actions;
}
اضبط MediaMetadata
باستخدام السمة
setMetadata()
. ويتم استدعاء هذه الطريقة مرة واحدة فقط لكل كائن يتم تشغيله. إنه يتيح لك تقديم معلومات إلى
جلسة الوسائط حول الوسائط، بما في ذلك عنوانها وعنوانها الفرعي
فنان أو عمل فني وما إلى ذلك. المثال التالي مصمم خصيصًا للموسيقى
بيانات المقطع الصوتي مخزّنة في فئة بيانات مخصّصة، MediaData
:
Kotlin
private fun updateMetadata(myData: MediaData) {
val metadataBuilder = MediaMetadata.Builder().apply {
// To provide most control over how an item is displayed set the
// display fields in the metadata
putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, myData.displayTitle)
putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE, myData.displaySubtitle)
putString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI, myData.artUri)
// And at minimum the title and artist for legacy support
putString(MediaMetadata.METADATA_KEY_TITLE, myData.title)
putString(MediaMetadata.METADATA_KEY_ARTIST, myData.artist)
// A small bitmap for the artwork is also recommended
putBitmap(MediaMetadata.METADATA_KEY_ART, myData.artBitmap)
// Add any other fields you have for your data as well
}
session.setMetadata(metadataBuilder.build())
}
Java
private void updateMetadata(MediaData myData) {
MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder();
// To provide most control over how an item is displayed set the
// display fields in the metadata
metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE,
myData.displayTitle);
metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE,
myData.displaySubtitle);
metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI,
myData.artUri);
// And at minimum the title and artist for legacy support
metadataBuilder.putString(MediaMetadata.METADATA_KEY_TITLE,
myData.title);
metadataBuilder.putString(MediaMetadata.METADATA_KEY_ARTIST,
myData.artist);
// A small bitmap for the artwork is also recommended
metadataBuilder.putBitmap(MediaMetadata.METADATA_KEY_ART,
myData.artBitmap);
// Add any other fields you have for your data as well
session.setMetadata(metadataBuilder.build());
}
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["# Implement a media session\n\nCreate a\n[`MediaSession`](/reference/android/media/session/MediaSession#MediaSession(android.content.Context,%20java.lang.String))\nwhen your app is preparing to play media. The following code snippet\nis an example of how to set the appropriate callback and flags: \n\n### Kotlin\n\n```kotlin\nsession = MediaSession(this, \"MusicService\").apply {\n setCallback(MediaSessionCallback())\n setFlags(\n MediaSession.FLAG_HANDLES_MEDIA_BUTTONS or MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS\n )\n}\n```\n\n### Java\n\n```java\nsession = new MediaSession(this, \"MusicService\");\nsession.setCallback(new MediaSessionCallback());\nsession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |\n MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);\n```\n\nStart a media session\n---------------------\n\nBe sure to also call\n[`setActive(true)`](/reference/android/media/session/MediaSession#setActive(boolean))\nwhen playback begins. Your app must also request audio focus, as described in\n[Manage audio focus](/media/optimize/audio-focus). These steps are\nshown in the following example: \n\n### Kotlin\n\n```kotlin\nprivate fun handlePlayRequest() {\n\n tryToGetAudioFocus()\n\n if (!session.isActive) {\n session.isActive = true\n }\n ...\n}\n```\n\n### Java\n\n```java\nprivate void handlePlayRequest() {\n\n tryToGetAudioFocus();\n\n if (!session.isActive()) {\n session.setActive(true);\n }\n ...\n}\n```\n\nUpdate the playback state\n-------------------------\n\nUpdate the playback state in the\n[`MediaSession`](/reference/android/media/session/MediaSession) to reflect\nthe state of the current media: \n\n### Kotlin\n\n```kotlin\nprivate fun updatePlaybackState() {\n val position: Long =\n mediaPlayer\n ?.takeIf { it.isPlaying }\n ?.currentPosition?.toLong()\n ?: PlaybackState.PLAYBACK_POSITION_UNKNOWN\n\n val stateBuilder = PlaybackState.Builder()\n .setActions(getAvailableActions()).apply {\n setState(mState, position, 1.0f)\n }\n session.setPlaybackState(stateBuilder.build())\n}\n\nprivate fun getAvailableActions(): Long {\n var actions = (PlaybackState.ACTION_PLAY_PAUSE\n or PlaybackState.ACTION_PLAY_FROM_MEDIA_ID\n or PlaybackState.ACTION_PLAY_FROM_SEARCH)\n\n playingQueue?.takeIf { it.isNotEmpty() }?.apply {\n actions = if (mState == PlaybackState.STATE_PLAYING) {\n actions or PlaybackState.ACTION_PAUSE\n } else {\n actions or PlaybackState.ACTION_PLAY\n }\n if (currentIndexOnQueue \u003e 0) {\n actions = actions or PlaybackState.ACTION_SKIP_TO_PREVIOUS\n }\n if (currentIndexOnQueue \u003c size - 1) {\n actions = actions or PlaybackState.ACTION_SKIP_TO_NEXT\n }\n }\n return actions\n}\n```\n\n### Java\n\n```java\nprivate void updatePlaybackState() {\n long position = PlaybackState.PLAYBACK_POSITION_UNKNOWN;\n if (mediaPlayer != null && mediaPlayer.isPlaying()) {\n position = mediaPlayer.getCurrentPosition();\n }\n PlaybackState.Builder stateBuilder = new PlaybackState.Builder()\n .setActions(getAvailableActions());\n stateBuilder.setState(mState, position, 1.0f);\n session.setPlaybackState(stateBuilder.build());\n}\n\nprivate long getAvailableActions() {\n long actions = PlaybackState.ACTION_PLAY_PAUSE |\n PlaybackState.ACTION_PLAY_FROM_MEDIA_ID |\n PlaybackState.ACTION_PLAY_FROM_SEARCH;\n if (playingQueue == null || playingQueue.isEmpty()) {\n return actions;\n }\n if (mState == PlaybackState.STATE_PLAYING) {\n actions |= PlaybackState.ACTION_PAUSE;\n } else {\n actions |= PlaybackState.ACTION_PLAY;\n }\n if (currentIndexOnQueue \u003e 0) {\n actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS;\n }\n if (currentIndexOnQueue \u003c playingQueue.size() - 1) {\n actions |= PlaybackState.ACTION_SKIP_TO_NEXT;\n }\n return actions;\n}\n```\n\nUpdate the media metadata\n-------------------------\n\nSet the [`MediaMetadata`](/reference/android/media/MediaMetadata) with the\n[`setMetadata()`](/reference/android/media/session/MediaSession#setMetadata(android.media.MediaMetadata))\nmethod. This method is only called once per object that is played. It lets you provide information to\nthe media session about the media, including its title, subtitle,\nartist, artwork, etc. The following example is tailored toward music and\nassumes the track's data is stored in a custom data class, `MediaData`: \n\n### Kotlin\n\n```kotlin\nprivate fun updateMetadata(myData: MediaData) {\n val metadataBuilder = MediaMetadata.Builder().apply {\n // To provide most control over how an item is displayed set the\n // display fields in the metadata\n putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, myData.displayTitle)\n putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE, myData.displaySubtitle)\n putString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI, myData.artUri)\n // And at minimum the title and artist for legacy support\n putString(MediaMetadata.METADATA_KEY_TITLE, myData.title)\n putString(MediaMetadata.METADATA_KEY_ARTIST, myData.artist)\n // A small bitmap for the artwork is also recommended\n putBitmap(MediaMetadata.METADATA_KEY_ART, myData.artBitmap)\n // Add any other fields you have for your data as well\n }\n session.setMetadata(metadataBuilder.build())\n}\n```\n\n### Java\n\n```java\nprivate void updateMetadata(MediaData myData) {\n MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder();\n // To provide most control over how an item is displayed set the\n // display fields in the metadata\n metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE,\n myData.displayTitle);\n metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE,\n myData.displaySubtitle);\n metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI,\n myData.artUri);\n // And at minimum the title and artist for legacy support\n metadataBuilder.putString(MediaMetadata.METADATA_KEY_TITLE,\n myData.title);\n metadataBuilder.putString(MediaMetadata.METADATA_KEY_ARTIST,\n myData.artist);\n // A small bitmap for the artwork is also recommended\n metadataBuilder.putBitmap(MediaMetadata.METADATA_KEY_ART,\n myData.artBitmap);\n // Add any other fields you have for your data as well\n session.setMetadata(metadataBuilder.build());\n}\n```"]]