प्लेबैक इवेंट को मॉनिटर करना
रजिस्टर किए गए Player.Listener इंस्टेंस को इवेंट की जानकारी दी जाती है. जैसे, स्थिति में बदलाव और वीडियो चलाने में आने वाली गड़बड़ियां. ऐसे इवेंट पाने के लिए लिसनर रजिस्टर करने के लिए:
Kotlin
// Add a listener to receive events from the player. player.addListener(listener)
Java
// Add a listener to receive events from the player. player.addListener(listener);
Player.Listener में डिफ़ॉल्ट तरीके खाली हैं. इसलिए, आपको सिर्फ़ उन तरीकों को लागू करना होगा जिनमें आपकी दिलचस्पी है. तरीकों और उन्हें कब कॉल किया जाता है, इसके बारे में पूरी जानकारी के लिए Javadoc देखें. यहाँ कुछ सबसे अहम तरीकों के बारे में ज़्यादा जानकारी दी गई है.
लिसनर के पास, अलग-अलग इवेंट के लिए कॉलबैक लागू करने या एक सामान्य onEvents कॉलबैक लागू करने का विकल्प होता है. इस कॉलबैक को एक या उससे ज़्यादा इवेंट एक साथ होने के बाद कॉल किया जाता है. Individual callbacks vs onEvents में बताया गया है कि अलग-अलग कामों के लिए, कौनसी सुविधा बेहतर है.
वीडियो चलाने की स्थिति में बदलाव
प्लेयर की स्थिति में हुए बदलावों की जानकारी पाने के लिए, रजिस्टर किए गए Player.Listener में onPlaybackStateChanged(@State int state) लागू करें.
वीडियो चलाने की स्थिति, इन चार में से कोई एक हो सकती है:
Player.STATE_IDLE: यह शुरुआती स्थिति है. यह स्थिति तब होती है, जब प्लेयर बंद हो जाता है और जब वीडियो नहीं चल पाता. इस स्थिति में, प्लेयर के पास सिर्फ़ सीमित संसाधन होंगे.Player.STATE_BUFFERING: प्लेयर, वीडियो को उसकी मौजूदा जगह से तुरंत नहीं चला सकता. आम तौर पर, ऐसा इसलिए होता है, क्योंकि ज़्यादा डेटा लोड करना होता है.Player.STATE_READY: खिलाड़ी, अपनी मौजूदा पोज़िशन से तुरंत खेलना शुरू कर सकता है.Player.STATE_ENDED: प्लेयर ने सभी मीडिया आइटम चला लिए हैं.
इन स्थितियों के अलावा, प्लेयर में playWhenReady फ़्लैग भी होता है. इससे पता चलता है कि उपयोगकर्ता वीडियो चलाने के लिए तैयार है. इस फ़्लैग में हुए बदलावों को onPlayWhenReadyChanged(playWhenReady, @PlayWhenReadyChangeReason int reason) लागू करके पाया जा सकता है.
कोई वीडियो तब चलता है, जब ये तीनों शर्तें पूरी होती हैं:
- प्लेयर
Player.STATE_READYस्थिति में है playWhenReadytrueहैPlayer.getPlaybackSuppressionReasonसे मिली जानकारी के आधार पर, वीडियो चलाने की सुविधा को बंद नहीं किया गया है
इन प्रॉपर्टी की अलग-अलग जांच करने के बजाय, Player.isPlaying को कॉल किया जा सकता है. इस स्थिति में हुए बदलावों को onIsPlayingChanged(boolean isPlaying) लागू करके पाया जा सकता है:
Kotlin
player.addListener( object : Player.Listener { override fun onIsPlayingChanged(isPlaying: Boolean) { if (isPlaying) { // Active playback. } else { // Not playing because playback is paused, ended, suppressed, or the player // is buffering, stopped or failed. Check player.playWhenReady, // player.playbackState, player.playbackSuppressionReason and // player.playerError for details. } } } )
Java
player.addListener( new Player.Listener() { @Override public void onIsPlayingChanged(boolean isPlaying) { if (isPlaying) { // Active playback. } else { // Not playing because playback is paused, ended, suppressed, or the player // is buffering, stopped or failed. Check player.getPlayWhenReady, // player.getPlaybackState, player.getPlaybackSuppressionReason and // player.getPlaybackError for details. } } });
प्लेबैक त्रुटियां
वीडियो चलाने में आने वाली गड़बड़ियों की सूचना पाने के लिए, रजिस्टर किए गए Player.Listener में onPlayerError(PlaybackException error) लागू करें. जब कोई गड़बड़ी होती है, तो इस तरीके को तुरंत कॉल किया जाएगा. ऐसा, वीडियो चलाने की स्थिति Player.STATE_IDLE में बदलने से पहले किया जाएगा. अगर वीडियो नहीं चल रहा है या रुक गया है, तो ExoPlayer.prepare को कॉल करके, वीडियो को फिर से चलाने का अनुरोध किया जा सकता है.
ध्यान दें कि Player लागू करने के कुछ तरीके, गड़बड़ी के बारे में ज़्यादा जानकारी देने के लिए PlaybackException की सबक्लास के इंस्टेंस पास करते हैं. उदाहरण के लिए, ExoPlayer, ExoPlaybackException को पास करता है. इसमें type, rendererIndex, और ExoPlayer के लिए खास तौर पर बनाए गए अन्य फ़ील्ड होते हैं.
यहां दिए गए उदाहरण में, यह पता लगाने का तरीका बताया गया है कि एचटीटीपी नेटवर्क से जुड़ी समस्या की वजह से, वीडियो नहीं चल पाया:
Kotlin
player.addListener( object : Player.Listener { override fun onPlayerError(error: PlaybackException) { val cause = error.cause if (cause is HttpDataSourceException) { // An HTTP error occurred. val httpError = cause // It's possible to find out more about the error both by casting and by querying // the cause. if (httpError is InvalidResponseCodeException) { // Cast to InvalidResponseCodeException and retrieve the response code, message // and headers. } else { // Try calling httpError.getCause() to retrieve the underlying cause, although // note that it may be null. } } } } )
Java
player.addListener( new Player.Listener() { @Override public void onPlayerError(PlaybackException error) { @Nullable Throwable cause = error.getCause(); if (cause instanceof HttpDataSourceException) { // An HTTP error occurred. HttpDataSourceException httpError = (HttpDataSourceException) cause; // It's possible to find out more about the error both by casting and by querying // the cause. if (httpError instanceof HttpDataSource.InvalidResponseCodeException) { // Cast to InvalidResponseCodeException and retrieve the response code, message // and headers. } else { // Try calling httpError.getCause() to retrieve the underlying cause, although // note that it may be null. } } } });
प्लेलिस्ट के ट्रांज़िशन
जब भी प्लेयर, प्लेलिस्ट में मौजूद किसी नए मीडिया आइटम पर स्विच करता है, तब रजिस्टर किए गए Player.Listener ऑब्जेक्ट पर onMediaItemTransition(MediaItem mediaItem, @MediaItemTransitionReason int
reason) कॉल किया जाता है. इस वजह से पता चलता है कि ट्रांज़िशन अपने-आप हुआ, सीक किया गया (उदाहरण के लिए, player.next() को कॉल करने के बाद), एक ही आइटम को दोहराया गया या प्लेलिस्ट में बदलाव की वजह से हुआ (उदाहरण के लिए, अगर अभी चल रहे आइटम को हटा दिया जाता है).
मेटाडेटा
player.getCurrentMediaMetadata() से मिले मेटाडेटा में कई वजहों से बदलाव हो सकता है. जैसे, प्लेलिस्ट ट्रांज़िशन, स्ट्रीम में दिखने वाले मेटाडेटा के अपडेट या मौजूदा MediaItem को वीडियो के बीच में अपडेट करना.
अगर आपको मेटाडेटा में हुए बदलावों के बारे में जानना है, तो onMediaMetadataChanged को सुनें. उदाहरण के लिए, मौजूदा टाइटल दिखाने वाले यूज़र इंटरफ़ेस (यूआई) को अपडेट करने के लिए.
वीडियो नियंत्रण चालू है
Player.seekTo वाले तरीकों को कॉल करने से, रजिस्टर किए गए Player.Listener इंस्टेंस को कॉलबैक की एक सीरीज़ मिलती है:
reason=DISCONTINUITY_REASON_SEEKके साथonPositionDiscontinuity. यहPlayer.seekToको कॉल करने का नतीजा है. कॉलबैक में, सीक करने से पहले और बाद की पोज़िशन के लिएPositionInfoफ़ील्ड होते हैं.onPlaybackStateChangedके साथ, तुरंत स्थिति में बदलाव करने से जुड़ी कोई भी कार्रवाई. ध्यान दें कि ऐसा बदलाव नहीं भी हो सकता है.
व्यक्तिगत कॉलबैक बनाम onEvents
लिसनर के पास, onIsPlayingChanged(boolean isPlaying) जैसे अलग-अलग कॉलबैक और सामान्य onEvents(Player
player, Events events) कॉलबैक को लागू करने का विकल्प होता है. जेनरिक कॉलबैक, Player ऑब्जेक्ट को ऐक्सेस करने की सुविधा देता है. साथ ही, यह events का वह सेट तय करता है जो एक साथ हुआ. यह कॉलबैक, हमेशा उन कॉलबैक के बाद कॉल किया जाता है जो अलग-अलग इवेंट से जुड़े होते हैं.
Kotlin
override fun onEvents(player: Player, events: Player.Events) { if ( events.contains(Player.EVENT_PLAYBACK_STATE_CHANGED) || events.contains(Player.EVENT_PLAY_WHEN_READY_CHANGED) ) { uiModule.updateUi(player) } }
Java
@Override public void onEvents(Player player, Events events) { if (events.contains(Player.EVENT_PLAYBACK_STATE_CHANGED) || events.contains(Player.EVENT_PLAY_WHEN_READY_CHANGED)) { uiModule.updateUi(player); } }
इन मामलों में, अलग-अलग इवेंट का इस्तेमाल करना बेहतर होता है:
- लिसनर को बदलावों की वजहों के बारे में जानना है. उदाहरण के लिए,
onPlayWhenReadyChangedयाonMediaItemTransitionके लिए दिए गए कारण. - लिसनर, सिर्फ़ कॉलबैक पैरामीटर के ज़रिए दी गई नई वैल्यू पर कार्रवाई करता है. इसके अलावा, यह किसी ऐसी चीज़ को ट्रिगर करता है जो कॉलबैक पैरामीटर पर निर्भर नहीं होती.
- लिसनर को लागू करने के लिए, यह ज़रूरी है कि इवेंट को ट्रिगर करने वाले कॉम्पोनेंट का नाम, तरीके के नाम में साफ़ तौर पर लिखा हो.
- लिसनर, आंकड़ों के सिस्टम को रिपोर्ट करता है. इस सिस्टम को सभी इवेंट और स्थिति में होने वाले बदलावों के बारे में पता होना चाहिए.
इन मामलों में, सामान्य onEvents(Player player, Events events) का इस्तेमाल करना चाहिए:
- लिसनर को कई इवेंट के लिए एक ही लॉजिक को ट्रिगर करना है. उदाहरण के लिए,
onPlaybackStateChangedऔरonPlayWhenReadyChanged, दोनों के लिए यूज़र इंटरफ़ेस (यूआई) अपडेट करना. - लिसनर को
Playerऑब्जेक्ट को ऐक्सेस करने की ज़रूरत होती है, ताकि वह आगे के इवेंट ट्रिगर कर सके. उदाहरण के लिए, मीडिया आइटम के ट्रांज़िशन के बाद सीक करना. - लिसनर को एक साथ कई स्टेट वैल्यू का इस्तेमाल करना है. ये वैल्यू, अलग-अलग कॉलबैक के ज़रिए रिपोर्ट की जाती हैं. इसके अलावा, लिसनर को इन वैल्यू का इस्तेमाल
Playergetter तरीकों के साथ करना है. उदाहरण के लिए,onTimelineChangedमें दिए गएTimelineके साथPlayer.getCurrentWindowIndex()का इस्तेमाल सिर्फ़onEventsकॉलबैक के अंदर सुरक्षित होता है. - लिसनर को इस बात में दिलचस्पी है कि इवेंट एक साथ हुए हैं या नहीं.
उदाहरण के लिए, मीडिया आइटम के ट्रांज़िशन की वजह से
onPlaybackStateChangedसेSTATE_BUFFERINGपर.
कुछ मामलों में, लिसनर को अलग-अलग कॉलबैक को सामान्य onEvents कॉलबैक के साथ जोड़ना पड़ सकता है. उदाहरण के लिए, onMediaItemTransition की मदद से मीडिया आइटम में बदलाव की वजहें रिकॉर्ड करने के लिए. हालांकि, सभी स्टेट में बदलावों का इस्तेमाल onEvents में एक साथ किया जा सकता है.
AnalyticsListener का इस्तेमाल करना
ExoPlayer का इस्तेमाल करते समय, addAnalyticsListener को कॉल करके, AnalyticsListener को प्लेयर के साथ रजिस्टर किया जा सकता है. AnalyticsListener लागू करने पर, ज़्यादा जानकारी वाले इवेंट को सुना जा सकता है. ये इवेंट, आंकड़ों और लॉगिंग के लिए काम के हो सकते हैं. ज़्यादा जानकारी के लिए, कृपया Analytics पेज देखें.
EventLogger का इस्तेमाल करना
EventLogger एक AnalyticsListener है, जिसे लाइब्रेरी सीधे तौर पर लॉगिंग के लिए उपलब्ध कराती है. एक लाइन में काम की अतिरिक्त लॉगिंग चालू करने के लिए, ExoPlayer में EventLogger जोड़ें:
Kotlin
player.addAnalyticsListener(EventLogger())
Java
player.addAnalyticsListener(new EventLogger());
ज़्यादा जानकारी के लिए, डीबग लॉगिंग पेज देखें.
वीडियो चलाने की तय की गई जगहों पर इवेंट ट्रिगर करना
कुछ मामलों में, वीडियो चलाने की तय की गई जगहों पर इवेंट ट्रिगर करने की ज़रूरत होती है. PlayerMessage का इस्तेमाल करके, इस सुविधा का फ़ायदा लिया जा सकता है. ExoPlayer.createMessage का इस्तेमाल करके, PlayerMessage बनाया जा सकता है. PlayerMessage.setPosition का इस्तेमाल करके, वीडियो चलाने की वह पोज़िशन सेट की जा सकती है जिस पर इसे लागू किया जाना चाहिए. मैसेज डिफ़ॉल्ट रूप से, प्लेबैक थ्रेड पर लागू होते हैं. हालांकि, PlayerMessage.setLooper का इस्तेमाल करके, इन्हें पसंद के मुताबिक बनाया जा सकता है. PlayerMessage.setDeleteAfterDelivery का इस्तेमाल यह कंट्रोल करने के लिए किया जा सकता है कि वीडियो चलाने की तय की गई पोज़िशन पर पहुंचने पर, मैसेज हर बार दिखेगा या सिर्फ़ पहली बार. ऐसा हो सकता है कि वीडियो को आगे-पीछे करने और बार-बार चलाने के मोड की वजह से, मैसेज कई बार दिखे. PlayerMessage को कॉन्फ़िगर करने के बाद, PlayerMessage.send का इस्तेमाल करके इसे शेड्यूल किया जा सकता है.
Kotlin
player .createMessage { messageType: Int, payload: Any? -> } .setLooper(Looper.getMainLooper()) .setPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 120000) .setPayload(customPayloadData) .setDeleteAfterDelivery(false) .send()
Java
player .createMessage( (messageType, payload) -> { // Do something at the specified playback position. }) .setLooper(Looper.getMainLooper()) .setPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 120_000) .setPayload(customPayloadData) .setDeleteAfterDelivery(false) .send();