मीडिया सेशन, ऑडियो या वीडियो के साथ इंटरैक्ट करने का एक बेहतर तरीका देते हैं
प्लेयर. Media3 में, डिफ़ॉल्ट प्लेयर ExoPlayer
क्लास होती है. यह क्लास लागू करती है
Player
इंटरफ़ेस. मीडिया सेशन को प्लेयर से कनेक्ट करने पर, ऐप्लिकेशन इस्तेमाल किया जा सकता है
मीडिया प्लेबैक का विज्ञापन देने और
बाहरी सोर्स पर क्लिक करें.
कमांड, फ़िज़िकल बटन से आ सकती हैं. जैसे, 'चलाएं' बटन हेडसेट या टीवी रिमोट कंट्रोल. वे ऐसे क्लाइंट ऐप्लिकेशन से भी आ सकते हैं जिनमें मीडिया कंट्रोलर, जैसे कि "रोकें" का निर्देश देना Assistant को चालू करें. मीडिया सेशन, इन निर्देशों को मीडिया ऐप्लिकेशन के प्लेयर को डेलिगेट करता है.
मीडिया सेशन कब चुनना चाहिए
MediaSession
लागू करने पर, उपयोगकर्ताओं को प्लेबैक को कंट्रोल करने की अनुमति मिल जाती है:
- अपने हेडफ़ोन के ज़रिए. आम तौर पर, बटन या टच इंटरैक्शन होने पर मीडिया चलाने, रोकने या अगले या पिछला ट्रैक चुनें.
- Google Assistant से बात करके. एक सामान्य पैटर्न यह है कि "ठीक है डिवाइस पर चल रहे किसी भी मीडिया को रोकने के लिए, Google, रोको".
- अपनी Wear OS स्मार्टवॉच के ज़रिए. इससे ज़्यादा से ज़्यादा लोगों को वे अपने फ़ोन पर वीडियो चलाने के दौरान, सामान्य प्लेबैक कंट्रोल इस्तेमाल कर सकते हैं.
- मीडिया कंट्रोल की मदद से. यह कैरसेल हर एक के लिए कंट्रोल दिखाता है मीडिया सत्र चला रहा है.
- टीवी पर. फ़िज़िकल प्लेबैक बटन और प्लैटफ़ॉर्म पर वीडियो चलाने की सुविधा इस्तेमाल करके कार्रवाइयां करें और पावर मैनेजमेंट (जैसे, टीवी, साउंडबार या ए/वी रिसीवर में बंद हो या इनपुट स्विच हो, तो ऐप्लिकेशन पर वीडियो चलना बंद हो जाना चाहिए).
- वीडियो चलाने की प्रोसेस पर असर डालने वाली अन्य बाहरी प्रोसेस.
कई तरह के मामलों में यह बेहतरीन होता है. खास तौर पर, आपको इन बातों का ध्यान रखना चाहिए
MediaSession
का इस्तेमाल तब करें, जब:
- लंबी अवधि के वीडियो कॉन्टेंट स्ट्रीम किया जा रहा हो, जैसे कि फ़िल्में या लाइव टीवी.
- लंबी अवधि के ऑडियो कॉन्टेंट, जैसे कि पॉडकास्ट या संगीत को स्ट्रीम किया जा रहा हो प्लेलिस्ट.
- कोई टीवी ऐप्लिकेशन बनाया जा रहा है.
हालांकि, इस्तेमाल के सभी उदाहरण MediaSession
के हिसाब से सही नहीं होते. आप शायद ये करना चाहें
नीचे दिए गए मामलों में सिर्फ़ Player
का इस्तेमाल करें:
- कम अवधि का कॉन्टेंट दिखाया जा रहा है, जिसमें उपयोगकर्ता की दिलचस्पी और इंटरैक्शन अहम है.
- पेज पर कोई एक भी वीडियो चालू नहीं है. जैसे, व्यक्ति सूची में स्क्रोल कर रहा हो और एक ही समय पर स्क्रीन पर कई वीडियो दिखते हैं.
- शुरुआती जानकारी या पूरी जानकारी देने वाला एक वीडियो चलाया जा रहा है. इसे तय करें कि आपका उपयोगकर्ता उसे लगातार देखे.
- आपका कॉन्टेंट निजता के प्रति संवेदनशील है और आपको बाहरी प्रोसेस के इस्तेमाल की अनुमति नहीं देनी है मीडिया मेटाडेटा ऐक्सेस करने की अनुमति दें (उदाहरण के लिए, ब्राउज़र पर गुप्त मोड)
अगर आपके इस्तेमाल का उदाहरण ऊपर दी गई सूची में से किसी के लिए भी उपयुक्त नहीं है, तो देखें कि आप
इससे, ऐप्लिकेशन में उपयोगकर्ता के ऐक्टिव न होने पर भी वीडियो चलाने की सुविधा मिलती है
उसके साथ शेयर किया जा सकता है. अगर जवाब हां है, तो शायद आप
MediaSession
. अगर आपका जवाब नहीं है, तो शायद आप Player
का इस्तेमाल करना चाहें
आज़माएं.
मीडिया सेशन बनाना
मीडिया सेशन उस प्लेयर के साथ होता है जिसे वह मैनेज करता है. आपके पास यह बनाने का विकल्प है
Context
और Player
ऑब्जेक्ट वाला मीडिया सेशन. आपको बनाना चाहिए और
ज़रूरत पड़ने पर मीडिया सेशन को शुरू कर सकता है, जैसे कि onStart()
या
Activity
, Fragment
या onCreate()
का onResume()
लाइफ़साइकल तरीका
तरीका Service
है जो मीडिया सेशन और उससे जुड़े प्लेयर का मालिक है.
मीडिया सेशन बनाने के लिए, Player
शुरू करें और इसे
MediaSession.Builder
को इस तरह का कॉन्टेंट पसंद है:
Kotlin
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
स्थिति की अपने-आप हैंडलिंग
Media3 लाइब्रेरी, खिलाड़ी की स्थिति. ऐसा करने के लिए, आपको मैन्युअल तरीके से प्लेयर टू सेशन.
यह उस लेगसी अप्रोच से बिलकुल अलग है, जहां आपको कॉन्टेंट बनाने और उसे बनाए रखने की ज़रूरत होती है
PlaybackStateCompat
को प्लेयर से अलग होना चाहिए. उदाहरण के लिए,
कोई गड़बड़ी हुई है.
यूनीक सेशन आईडी
डिफ़ॉल्ट रूप से, MediaSession.Builder
इस खाली स्ट्रिंग के साथ एक सेशन बनाता है
सेशन आईडी. अगर कोई ऐप्लिकेशन सिर्फ़ एक उपयोगकर्ता अनुभव
सेशन इंस्टेंस पर क्लिक करता है, जो सबसे सामान्य स्थिति है.
अगर कोई ऐप्लिकेशन एक साथ कई सेशन के इंस्टेंस मैनेज करना चाहता है, तो
यह पक्का करना ज़रूरी है कि हर सेशन का सेशन आईडी यूनीक हो. सेशन आईडी ये काम कर सकता है:
MediaSession.Builder.setId(String id)
के साथ सेशन बनाते समय सेट की जाएगी.
अगर आपको लगता है कि IllegalStateException
, गड़बड़ी की वजह से आपके ऐप्लिकेशन को क्रैश कर रहा है
IllegalStateException: Session ID must be unique. ID=
को मैसेज भेजो, तो यह है
इस बात की संभावना है कि पहले बनाए गए सेशन से पहले कोई सेशन अचानक बना हो
समान आईडी वाला इंस्टेंस रिलीज़ कर दिया गया है. सेशन को लीक होने से बचाने के लिए
प्रोग्रामिंग की गड़बड़ी होती है, तो ऐसे मामलों का पता लगाकर उनकी सूचना दी जाती है. इसके लिए,
अपवाद.
अन्य क्लाइंट को कंट्रोल दें
वीडियो को कंट्रोल करने के लिए, मीडिया सेशन सबसे अहम है. इसकी मदद से, Google News पर बाहरी स्रोतों से उस प्लेयर को आदेश दें जो आपका मीडिया. ये सोर्स, फ़िज़िकल बटन हो सकते हैं. जैसे, हेडसेट या टीवी रिमोट कंट्रोल या किसी और तरीके से दिए जाने वाले निर्देश, जैसे कि "रोको" Assistant को चालू करें. इसी तरह, हो सकता है कि आप Android को Wear OS पर सूचना पाने और लॉक स्क्रीन कंट्रोल करने की सुविधा देने वाला सिस्टम ताकि आप वॉचफेस से प्लेबैक को नियंत्रित कर सकें. बाहरी क्लाइंट यह कर सकते हैं: अपने मीडिया ऐप्लिकेशन को प्लेबैक के निर्देश देने के लिए मीडिया कंट्रोलर का इस्तेमाल करें. ये हैं जो आपके मीडिया सेशन को मिले. इससे आखिर में, मीडिया प्लेयर.
जब कोई कंट्रोलर आपके मीडिया सेशन से कनेक्ट होने वाला होता है, तो
onConnect()
तरीका को कॉल किया जाता है. दिए गए ControllerInfo
का इस्तेमाल करें
स्वीकार करने का फ़ैसला लेने के लिए
या अस्वीकार करें
अनुरोध किया है. कनेक्शन अनुरोध को स्वीकार करने का उदाहरण में देखें
उपलब्ध निर्देश सेक्शन में बताया गया हो.
कनेक्ट होने के बाद, कंट्रोलर, सेशन को चलाने के निर्देश भेज सकता है. कॉन्टेंट बनाने
सत्र फिर उन कमांड को प्लेयर को सौंप देता है. प्लेबैक और प्लेलिस्ट
Player
इंटरफ़ेस में बताए गए निर्देशों को,
सत्र.
कॉलबैक के अन्य तरीकों से, आपको इनके लिए अनुरोधों को मैनेज करने की सुविधा मिलती है
पसंद के मुताबिक प्लेबैक निर्देश और
प्लेलिस्ट में बदलाव करके.
इन कॉलबैक में भी एक ControllerInfo
ऑब्जेक्ट शामिल होता है, ताकि आप बदलाव कर सकें
और हर कंट्रोलर के हिसाब से हर अनुरोध का जवाब कैसे दिया जाता है.
प्लेलिस्ट में बदलाव करना
मीडिया सेशन, अपने प्लेयर की प्लेलिस्ट में सीधे बदलाव कर सकता है. इसके बारे में यहां बताया गया है
यह
प्लेलिस्ट के लिए ExoPlayer गाइड.
कंट्रोलर भी प्लेलिस्ट में बदलाव कर सकते हैं, अगर:
COMMAND_SET_MEDIA_ITEM
या COMMAND_CHANGE_MEDIA_ITEMS
कंट्रोलर के लिए उपलब्ध है.
आम तौर पर, प्लेलिस्ट में नए आइटम जोड़ने के लिए प्लेयर को MediaItem
की ज़रूरत होती है
के साथ इंस्टेंस
तय किया गया यूआरआई
ताकि उन्हें खेलने में आसानी हो. डिफ़ॉल्ट रूप से, जोड़े गए नए आइटम अपने-आप फ़ॉरवर्ड किए जाते हैं
player.addMediaItem
जैसे प्लेयर मेथड का इस्तेमाल करें.
अगर आपको प्लेयर में जोड़े गए MediaItem
इंस्टेंस को अपनी पसंद के मुताबिक बनाना है, तो
बदलें
onAddMediaItems()
.
यह चरण तब ज़रूरी होता है, जब आपको मीडिया का अनुरोध करने वाले कंट्रोलर की सुविधा देनी हो
बिना तय यूआरआई के. इसके बजाय, MediaItem
में आम तौर पर
इनमें से एक या ज़्यादा फ़ील्ड को, अनुरोध किए गए मीडिया के बारे में बताने के लिए सेट किया गया है:
MediaItem.id
: एक सामान्य आईडी, जिससे मीडिया की पहचान की जाती है.MediaItem.RequestMetadata.mediaUri
: एक अनुरोध यूआरआई, जो किसी कस्टम यूआरएल का इस्तेमाल कर सकता है साथ ही, ज़रूरी नहीं है कि प्लेयर सीधे उसे सीधे चलाए.MediaItem.RequestMetadata.searchQuery
: टेक्स्ट के तौर पर सर्च क्वेरी, उदाहरण के लिए Google Assistant से बात करें.MediaItem.MediaMetadata
: 'टाइटल' जैसा स्ट्रक्चर्ड मेटाडेटा या 'कलाकार' के तौर पर शामिल होना चाहिए.
नई प्लेलिस्ट को अपनी पसंद के मुताबिक बनाने के ज़्यादा विकल्प देखने के लिए,
अतिरिक्त रूप से बदलें
onSetMediaItems()
जिससे आप प्लेलिस्ट में शुरू होने वाला आइटम और उसकी पोज़िशन तय कर सकते हैं. उदाहरण के लिए,
आप किसी एक अनुरोध किए गए आइटम को पूरी प्लेलिस्ट में बड़ा कर सकते हैं और निर्देश दे सकते हैं
प्लेयर का इस्तेमाल करें. ऐप्लिकेशन
onSetMediaItems()
को लागू करने का सैंपल
सेशन के डेमो ऐप्लिकेशन में यह सुविधा देखी जा सकती है.
पसंद के मुताबिक लेआउट और कस्टम निर्देश मैनेज करें
नीचे दिए सेक्शन में, कमांड बटन दबाएं और कंट्रोलर को निर्देश देखें.
सेशन के लिए पसंद के मुताबिक लेआउट तय करें
क्लाइंट ऐप्लिकेशन को यह बताने के लिए कि आपको
उपयोगकर्ता, सेशन का कस्टम लेआउट सेट करें
जब onCreate()
तरीके में MediaSession
बनाया जा रहा हो, तो:
सेवा.
Kotlin
override fun onCreate() { super.onCreate() val likeButton = CommandButton.Builder() .setDisplayName("Like") .setIconResId(R.drawable.like_icon) .setSessionCommand(SessionCommand(SessionCommand.COMMAND_CODE_SESSION_SET_RATING)) .build() val favoriteButton = CommandButton.Builder() .setDisplayName("Save to favorites") .setIconResId(R.drawable.favorite_icon) .setSessionCommand(SessionCommand(SAVE_TO_FAVORITES, Bundle())) .build() session = MediaSession.Builder(this, player) .setCallback(CustomMediaSessionCallback()) .setCustomLayout(ImmutableList.of(likeButton, favoriteButton)) .build() }
Java
@Override public void onCreate() { super.onCreate(); CommandButton likeButton = new CommandButton.Builder() .setDisplayName("Like") .setIconResId(R.drawable.like_icon) .setSessionCommand(new SessionCommand(SessionCommand.COMMAND_CODE_SESSION_SET_RATING)) .build(); CommandButton favoriteButton = new CommandButton.Builder() .setDisplayName("Save to favorites") .setIconResId(R.drawable.favorite_icon) .setSessionCommand(new SessionCommand(SAVE_TO_FAVORITES, new Bundle())) .build(); Player player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player) .setCallback(new CustomMediaSessionCallback()) .setCustomLayout(ImmutableList.of(likeButton, favoriteButton)) .build(); }
उपलब्ध प्लेयर और पसंद के मुताबिक निर्देशों की जानकारी देना
मीडिया ऐप्लिकेशन ऐसे कस्टम कमांड तय कर सकते हैं जिनका इस्तेमाल, उदाहरण के लिए किया जा सकता है
एक कस्टम लेआउट. उदाहरण के लिए, शायद आप ऐसे बटन लागू करना चाहें जो
पसंदीदा आइटम की सूची में मीडिया आइटम को सेव करने के लिए. MediaController
कस्टम निर्देश भेजता है और MediaSession.Callback
उन्हें रिसीव करता है.
यह तय किया जा सकता है कि आपकी साइट पर,
आपके मीडिया सेशन से कनेक्ट होने पर, MediaController
. ऐसा करके,
ओवरराइड किया जा रहा है MediaSession.Callback.onConnect()
. कॉन्फ़िगर करें और वापस जाएं
किसी कनेक्शन का अनुरोध स्वीकार करते समय उपलब्ध कमांड का सेट
onConnect
कॉलबैक तरीके में MediaController
:
Kotlin
private inner class CustomMediaSessionCallback: MediaSession.Callback { // Configure commands available to the controller in onConnect() override fun onConnect( session: MediaSession, controller: MediaSession.ControllerInfo ): MediaSession.ConnectionResult { val sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(SessionCommand(SAVE_TO_FAVORITES, Bundle.EMPTY)) .build() return AcceptedResultBuilder(session) .setAvailableSessionCommands(sessionCommands) .build() } }
Java
class CustomMediaSessionCallback implements MediaSession.Callback { // Configure commands available to the controller in onConnect() @Override public ConnectionResult onConnect( MediaSession session, ControllerInfo controller) { SessionCommands sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(new SessionCommand(SAVE_TO_FAVORITES, new Bundle())) .build(); return new AcceptedResultBuilder(session) .setAvailableSessionCommands(sessionCommands) .build(); } }
MediaController
से अपनी पसंद के मुताबिक निर्देश पाने के अनुरोध पाने के लिए,
Callback
में onCustomCommand()
तरीका.
Kotlin
private inner class CustomMediaSessionCallback: MediaSession.Callback { ... override fun onCustomCommand( session: MediaSession, controller: MediaSession.ControllerInfo, customCommand: SessionCommand, args: Bundle ): ListenableFuture<SessionResult> { if (customCommand.customAction == SAVE_TO_FAVORITES) { // Do custom logic here saveToFavorites(session.player.currentMediaItem) return Futures.immediateFuture( SessionResult(SessionResult.RESULT_SUCCESS) ) } ... } }
Java
class CustomMediaSessionCallback implements MediaSession.Callback { ... @Override public ListenableFuture<SessionResult> onCustomCommand( MediaSession session, ControllerInfo controller, SessionCommand customCommand, Bundle args ) { if(customCommand.customAction.equals(SAVE_TO_FAVORITES)) { // Do custom logic here saveToFavorites(session.getPlayer().getCurrentMediaItem()); return Futures.immediateFuture( new SessionResult(SessionResult.RESULT_SUCCESS) ); } ... } }
अनुरोध करने के लिए,
MediaSession.ControllerInfo
ऑब्जेक्ट की packageName
प्रॉपर्टी जो
Callback
विधियों में पास किया गया है. इससे आप अपने ऐप्लिकेशन की सेटिंग,
दिए गए निर्देश के जवाब में व्यवहार, अगर यह सिस्टम से शुरू होता है, तो आपके
या अन्य क्लाइंट के ऐप्लिकेशन पर.
उपयोगकर्ता के इंटरैक्शन के बाद, कस्टम लेआउट को अपडेट करना
अपने खिलाड़ी से कोई कस्टम कमांड या कोई अन्य इंटरैक्शन मैनेज करने के बाद, आपको
नियंत्रक यूज़र इंटरफ़ेस (यूआई) में दिखाए गए लेआउट को अपडेट करना चाह सकता है. एक सामान्य उदाहरण
एक टॉगल बटन है, जो संबंधित कार्रवाई को ट्रिगर करने के बाद अपना आइकॉन बदल देता है
को इस बटन पर क्लिक करें. लेआउट अपडेट करने के लिए,
MediaSession.setCustomLayout
:
Kotlin
val removeFromFavoritesButton = CommandButton.Builder() .setDisplayName("Remove from favorites") .setIconResId(R.drawable.favorite_remove_icon) .setSessionCommand(SessionCommand(REMOVE_FROM_FAVORITES, Bundle())) .build() mediaSession.setCustomLayout(ImmutableList.of(likeButton, removeFromFavoritesButton))
Java
CommandButton removeFromFavoritesButton = new CommandButton.Builder() .setDisplayName("Remove from favorites") .setIconResId(R.drawable.favorite_remove_icon) .setSessionCommand(new SessionCommand(REMOVE_FROM_FAVORITES, new Bundle())) .build(); mediaSession.setCustomLayout(ImmutableList.of(likeButton, removeFromFavoritesButton));
प्लेबैक निर्देश के व्यवहार को पसंद के मुताबिक बनाएं
Player
इंटरफ़ेस में बताए गए निर्देश के काम करने के तरीके को पसंद के मुताबिक बनाने के लिए, जैसे
play()
या seekToNext()
के तौर पर, अपने Player
को ForwardingPlayer
में रैप करें.
Kotlin
val player = ExoPlayer.Builder(context).build() val forwardingPlayer = object : ForwardingPlayer(player) { override fun play() { // Add custom logic super.play() } override fun setPlayWhenReady(playWhenReady: Boolean) { // Add custom logic super.setPlayWhenReady(playWhenReady) } } val mediaSession = MediaSession.Builder(context, forwardingPlayer).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); ForwardingPlayer forwardingPlayer = new ForwardingPlayer(player) { @Override public void play() { // Add custom logic super.play(); } @Override public void setPlayWhenReady(boolean playWhenReady) { // Add custom logic super.setPlayWhenReady(playWhenReady); } }; MediaSession mediaSession = new MediaSession.Builder(context, forwardingPlayer).build();
ForwardingPlayer
के बारे में ज़्यादा जानने के लिए, ExoPlayer की गाइड देखें
कस्टमाइज़ेशन.
प्लेयर कमांड के अनुरोध करने वाले कंट्रोलर की पहचान करना
जब Player
तरीके को कॉल करने की प्रक्रिया MediaController
से शुरू होती है, तो ये काम किए जा सकते हैं
MediaSession.controllerForCurrentRequest
की मदद से, मूल स्रोत की पहचान करें
और मौजूदा अनुरोध के लिए ControllerInfo
को हासिल करेगा:
Kotlin
class CallerAwareForwardingPlayer(player: Player) : ForwardingPlayer(player) { override fun seekToNext() { Log.d( "caller", "seekToNext called from package ${session.controllerForCurrentRequest?.packageName}" ) super.seekToNext() } }
Java
public class CallerAwareForwardingPlayer extends ForwardingPlayer { public CallerAwareForwardingPlayer(Player player) { super(player); } @Override public void seekToNext() { Log.d( "caller", "seekToNext called from package: " + session.getControllerForCurrentRequest().getPackageName()); super.seekToNext(); } }
मीडिया बटन का जवाब दें
मीडिया बटन, Android डिवाइसों और अन्य सहायक डिवाइस (जैसे, कीबोर्ड, माउस, मॉनिटर, वेबकैम वगैरह) पर मौजूद हार्डवेयर बटन होते हैं
ब्लूटूथ हेडसेट पर चलाएं/रोकें बटन जैसे डिवाइस. Media3 हैंडल
आपके लिए मीडिया बटन इवेंट, जब वे सत्र में पहुंचते हैं और आपको कॉल करते हैं
सेशन प्लेयर पर सही Player
तरीका होना चाहिए.
कोई ऐप्लिकेशन ओवरराइड करके डिफ़ॉल्ट व्यवहार को बदल सकता है
MediaSession.Callback.onMediaButtonEvent(Intent)
. ऐसे मामले में, ऐप्लिकेशन
को एपीआई की हर खास जानकारी को खुद हैंडल करने की ज़रूरत हो सकती है.
गड़बड़ियों को ठीक करना और उनकी रिपोर्ट करना
सेशन से दो तरह की गड़बड़ियां होती हैं और ये कंट्रोलर को रिपोर्ट करती हैं. गंभीर गड़बड़ियों की रिपोर्ट में, सेशन के दौरान तकनीकी तौर पर हुई गड़बड़ी की शिकायत की जाती है ऐसा प्लेयर जिसकी वजह से वीडियो नहीं चलता. गंभीर गड़बड़ियों की रिपोर्ट कंट्रोलर को दी जाती है वे अपने-आप शेड्यूल हो जाते हैं. साधारण गड़बड़ियां गैर-तकनीकी या नीति के मुताबिक हैं ऐसी गड़बड़ियां जिनकी वजह से वीडियो चलाने में कोई रुकावट नहीं आती और मैन्युअल रूप से.
वीडियो चलाने में होने वाली घातक गड़बड़ियां
प्लेयर, सेशन में वीडियो चलाने से जुड़ी किसी गंभीर गड़बड़ी की शिकायत करता है. इसके बाद,
कंट्रोलर को सूचना दी जाएगी कि
Player.Listener.onPlayerError(PlaybackException)
और
Player.Listener.onPlayerErrorChanged(@Nullable PlaybackException)
.
ऐसे मामले में, वीडियो चलाने की स्थिति STATE_IDLE
में बदल जाती है और
MediaController.getPlaybackError()
वह PlaybackException
लौटाता है जिसकी वजह से ऐसा हुआ था
ट्रांज़िशन. कंट्रोलर, PlayerException.errorCode
की जांच करके पता लगा सकता है कि
गड़बड़ी की वजह के बारे में जानकारी.
इंटरऑपरेबिलिटी के लिए, किसी गंभीर गड़बड़ी की कॉपी PlaybackStateCompat
में बनाई जाती है
प्लैटफ़ॉर्म सेशन की स्थिति को STATE_ERROR
में बदलकर और सेटिंग
PlaybackException
के अनुसार गड़बड़ी कोड और मैसेज दिखाता है.
गंभीर गड़बड़ी का कस्टमाइज़ेशन
उपयोगकर्ता को स्थानीय भाषा में और काम की जानकारी देने के लिए, गड़बड़ी कोड,
गड़बड़ी का मैसेज और किसी गंभीर प्लेबैक गड़बड़ी की गड़बड़ी को
सेशन बनाते समय ForwardingPlayer
का इस्तेमाल करने पर:
Kotlin
val forwardingPlayer = ErrorForwardingPlayer(player) val session = MediaSession.Builder(context, forwardingPlayer).build()
Java
Player forwardingPlayer = new ErrorForwardingPlayer(player); MediaSession session = new MediaSession.Builder(context, forwardingPlayer).build();
फ़ॉरवर्ड करने वाला प्लेयर, असल प्लेयर में Player.Listener
रजिस्टर करता है
और उन कॉलबैक को इंटरसेप्ट करता है जो गड़बड़ी की रिपोर्ट करते हैं. पसंद के मुताबिक़
इसके बाद, PlaybackException
को इन लिसनर को ट्रांसफ़र कर दिया जाता है
फ़ॉरवर्ड करने वाले प्लेयर पर रजिस्टर होते हों. यह काम करे, इसके लिए फ़ॉरवर्ड करने वाला प्लेयर
इसकी ऐक्सेस के लिए Player.addListener
और Player.removeListener
को ओवरराइड करता है
वे श्रोता, जिनकी मदद से कस्टमाइज़ किया गया गड़बड़ी कोड, संदेश या अतिरिक्त चीज़ें भेजना चाहते हैं:
Kotlin
class ErrorForwardingPlayer(private val context: Context, player: Player) : ForwardingPlayer(player) { private val listeners: MutableList<Player.Listener> = mutableListOf() private var customizedPlaybackException: PlaybackException? = null init { player.addListener(ErrorCustomizationListener()) } override fun addListener(listener: Player.Listener) { listeners.add(listener) } override fun removeListener(listener: Player.Listener) { listeners.remove(listener) } override fun getPlayerError(): PlaybackException? { return customizedPlaybackException } private inner class ErrorCustomizationListener : Player.Listener { override fun onPlayerErrorChanged(error: PlaybackException?) { customizedPlaybackException = error?.let { customizePlaybackException(it) } listeners.forEach { it.onPlayerErrorChanged(customizedPlaybackException) } } override fun onPlayerError(error: PlaybackException) { listeners.forEach { it.onPlayerError(customizedPlaybackException!!) } } private fun customizePlaybackException( error: PlaybackException, ): PlaybackException { val buttonLabel: String val errorMessage: String when (error.errorCode) { PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> { buttonLabel = context.getString(R.string.err_button_label_restart_stream) errorMessage = context.getString(R.string.err_msg_behind_live_window) } // Apps can customize further error messages by adding more branches. else -> { buttonLabel = context.getString(R.string.err_button_label_ok) errorMessage = context.getString(R.string.err_message_default) } } val extras = Bundle() extras.putString("button_label", buttonLabel) return PlaybackException(errorMessage, error.cause, error.errorCode, extras) } override fun onEvents(player: Player, events: Player.Events) { listeners.forEach { it.onEvents(player, events) } } // Delegate all other callbacks to all listeners without changing arguments like onEvents. } }
Java
private static class ErrorForwardingPlayer extends ForwardingPlayer { private final Context context; private List<Player.Listener> listeners; @Nullable private PlaybackException customizedPlaybackException; public ErrorForwardingPlayer(Context context, Player player) { super(player); this.context = context; listeners = new ArrayList<>(); player.addListener(new ErrorCustomizationListener()); } @Override public void addListener(Player.Listener listener) { listeners.add(listener); } @Override public void removeListener(Player.Listener listener) { listeners.remove(listener); } @Nullable @Override public PlaybackException getPlayerError() { return customizedPlaybackException; } private class ErrorCustomizationListener implements Listener { @Override public void onPlayerErrorChanged(@Nullable PlaybackException error) { customizedPlaybackException = error != null ? customizePlaybackException(error, context) : null; for (int i = 0; i < listeners.size(); i++) { listeners.get(i).onPlayerErrorChanged(customizedPlaybackException); } } @Override public void onPlayerError(PlaybackException error) { for (int i = 0; i < listeners.size(); i++) { listeners.get(i).onPlayerError(checkNotNull(customizedPlaybackException)); } } private PlaybackException customizePlaybackException( PlaybackException error, Context context) { String buttonLabel; String errorMessage; switch (error.errorCode) { case PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW: buttonLabel = context.getString(R.string.err_button_label_restart_stream); errorMessage = context.getString(R.string.err_msg_behind_live_window); break; // Apps can customize further error messages by adding more case statements. default: buttonLabel = context.getString(R.string.err_button_label_ok); errorMessage = context.getString(R.string.err_message_default); break; } Bundle extras = new Bundle(); extras.putString("button_label", buttonLabel); return new PlaybackException(errorMessage, error.getCause(), error.errorCode, extras); } @Override public void onEvents(Player player, Events events) { for (int i = 0; i < listeners.size(); i++) { listeners.get(i).onEvents(player, events); } } // Delegate all other callbacks to all listeners without changing arguments like onEvents. } }
सामान्य गड़बड़ियां
ऐसी सामान्य गड़बड़ियां भेजी जा सकती हैं जो किसी तकनीकी अपवाद की वजह से नहीं हुई हों सभी या किसी खास कंट्रोलर को ऐप्लिकेशन से:
Kotlin
val sessionError = SessionError( SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED, context.getString(R.string.error_message_authentication_expired), ) // Sending a nonfatal error to all controllers. mediaSession.sendError(sessionError) // Interoperability: Sending a nonfatal error to the media notification controller to set the // error code and error message in the playback state of the platform media session. mediaSession.mediaNotificationControllerInfo?.let { mediaSession.sendError(it, sessionError) }
Java
SessionError sessionError = new SessionError( SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED, context.getString(R.string.error_message_authentication_expired)); // Sending a nonfatal error to all controllers. mediaSession.sendError(sessionError); // Interoperability: Sending a nonfatal error to the media notification controller to set the // error code and error message in the playback state of the platform media session. ControllerInfo mediaNotificationControllerInfo = mediaSession.getMediaNotificationControllerInfo(); if (mediaNotificationControllerInfo != null) { mediaSession.sendError(mediaNotificationControllerInfo, sessionError); }
मीडिया नोटिफ़िकेशन कंट्रोलर को भेजी गई एक साधारण गड़बड़ी,
प्लैटफ़ॉर्म सेशन का PlaybackStateCompat
. ऐसा करने से, सिर्फ़ गड़बड़ी का कोड और
गड़बड़ी का मैसेज PlaybackStateCompat
पर सेट हो जाता है, जबकि
PlaybackStateCompat.state
को STATE_ERROR
में नहीं बदला गया.
साधारण गड़बड़ियां पाएं
MediaController
को लागू करने पर एक साधारण गड़बड़ी मिलती है
MediaController.Listener.onError
:
Kotlin
val future = MediaController.Builder(context, sessionToken) .setListener(object : MediaController.Listener { override fun onError(controller: MediaController, sessionError: SessionError) { // Handle nonfatal error. } }) .buildAsync()
Java
MediaController.Builder future = new MediaController.Builder(context, sessionToken) .setListener( new MediaController.Listener() { @Override public void onError(MediaController controller, SessionError sessionError) { // Handle nonfatal error. } });