প্লেব্যাক ঘটনা শোনা
ইভেন্ট, যেমন অবস্থার পরিবর্তন এবং প্লেব্যাক ত্রুটি, নিবন্ধিত Player.Listener দৃষ্টান্তে রিপোর্ট করা হয়। এই ধরনের ইভেন্টগুলি পেতে একজন শ্রোতাকে নিবন্ধন করতে:
কোটলিন
// Add a listener to receive events from the player. player.addListener(listener)
জাভা
// 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) প্রয়োগ করে এই অবস্থার পরিবর্তনগুলি প্রাপ্ত করা যেতে পারে:
কোটলিন
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. } } } )
জাভা
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 রূপান্তরিত হওয়ার সাথে সাথেই এই পদ্ধতিটি কল করা হবে৷STATE_IDLE৷ ExoPlayer.prepare কল করে ব্যর্থ বা বন্ধ প্লেব্যাকগুলি পুনরায় চেষ্টা করা যেতে পারে।
মনে রাখবেন যে কিছু Player বাস্তবায়ন ব্যর্থতা সম্পর্কে অতিরিক্ত তথ্য প্রদান করতে PlaybackException সাবক্লাসের উদাহরণ পাস করে। উদাহরণ স্বরূপ, ExoPlayer ExoPlaybackException পাস করে, যার type , rendererIndex এবং অন্যান্য ExoPlayer-নির্দিষ্ট ক্ষেত্র রয়েছে।
একটি HTTP নেটওয়ার্কিং সমস্যার কারণে প্লেব্যাক ব্যর্থ হলে কীভাবে সনাক্ত করা যায় তা নিম্নলিখিত উদাহরণটি দেখায়:
কোটলিন
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. } } } } )
জাভা
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. } } } });
প্লেলিস্ট ট্রানজিশন
যখনই প্লেয়ার প্লেলিস্টে একটি নতুন মিডিয়া আইটেম পরিবর্তন করে onMediaItemTransition(MediaItem mediaItem, @MediaItemTransitionReason int reason) নিবন্ধিত Player.Listener অবজেক্টে কল করা হয়। কারণটি নির্দেশ করে যে এটি একটি স্বয়ংক্রিয় রূপান্তর ছিল কিনা, একটি অনুসন্ধান (উদাহরণস্বরূপ player.next() কল করার পরে), একই আইটেমের পুনরাবৃত্তি, বা প্লেলিস্ট পরিবর্তনের কারণে (উদাহরণস্বরূপ, যদি বর্তমানে বাজানো আইটেমটি সরানো হয়)।
মেটাডেটা
player.getCurrentMediaMetadata() থেকে ফিরে আসা মেটাডেটা অনেক কারণে পরিবর্তিত হতে পারে: প্লেলিস্ট ট্রানজিশন, ইন-স্ট্রীম মেটাডেটা আপডেট বা বর্তমান MediaItem মিড-প্লেব্যাক আপডেট করা।
আপনি যদি মেটাডেটা পরিবর্তনে আগ্রহী হন, উদাহরণস্বরূপ বর্তমান শিরোনাম দেখায় এমন একটি UI আপডেট করতে, আপনি onMediaMetadataChanged শুনতে পারেন।
খুঁজছেন
Player.seekTo পদ্ধতিতে কল করার ফলে রেজিস্টার্ড Player.Listener দৃষ্টান্তগুলিতে কলব্যাকের একটি সিরিজ হয়:
-
onPositionDiscontinuitywithreason=DISCONTINUITY_REASON_SEEK। এটিPlayer.seekToকল করার সরাসরি ফলাফল। কলব্যাকে অনুসন্ধানের আগে এবং পরে অবস্থানের জন্যPositionInfoক্ষেত্র রয়েছে৷ -
onPlaybackStateChangedচেঞ্জের সাথে সম্পর্কিত যেকোনো তাৎক্ষণিক অবস্থা পরিবর্তনের সাথে পরিবর্তন করা হয়েছে। মনে রাখবেন যে এই ধরনের পরিবর্তন নাও হতে পারে।
ব্যক্তিগত কলব্যাক বনাম onEvents
শ্রোতারা onIsPlayingChanged(boolean isPlaying) এবং জেনেরিক onEvents(Player player, Events events) কলব্যাকের মতো পৃথক কলব্যাক বাস্তবায়নের মধ্যে বেছে নিতে পারেন। জেনেরিক কলব্যাক Player অবজেক্টে অ্যাক্সেস প্রদান করে এবং একসাথে ঘটে যাওয়া events সেট নির্দিষ্ট করে। এই কলব্যাকটিকে সর্বদা কলব্যাকের পরে বলা হয় যা পৃথক ইভেন্টের সাথে সম্পর্কিত।
কোটলিন
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) } }
জাভা
@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উভয়ের জন্য একটি UI আপডেট করা। - শ্রোতার আরও ইভেন্টগুলি ট্রিগার করতে
Playerঅবজেক্ট অ্যাক্সেস করতে হবে, উদাহরণস্বরূপ একটি মিডিয়া আইটেম ট্রানজিশনের পরে খোঁজা৷ - শ্রোতা একাধিক রাষ্ট্রীয় মান ব্যবহার করতে চায় যা একসাথে পৃথক কলব্যাকের মাধ্যমে রিপোর্ট করা হয়, বা
Playerগেটার পদ্ধতির সাথে একত্রিত হয়। উদাহরণস্বরূপ,onTimelineChangedএ প্রদত্তTimelineসাথেPlayer.getCurrentWindowIndex()ব্যবহার করা শুধুমাত্রonEventsকলব্যাকের মধ্যে থেকে নিরাপদ। - ঘটনাগুলো যৌক্তিকভাবে একসাথে ঘটেছে কিনা তা নিয়ে শ্রোতা আগ্রহী। উদাহরণস্বরূপ, একটি মিডিয়া আইটেম স্থানান্তরের কারণে
onPlaybackStateChangedহয়েSTATE_BUFFERINGএ পরিণত হয়েছে৷
কিছু ক্ষেত্রে, শ্রোতাদেরকে জেনেরিক onEvents কলব্যাকের সাথে স্বতন্ত্র কলব্যাকগুলিকে একত্রিত করতে হতে পারে, উদাহরণস্বরূপ onMediaItemTransition এর সাথে মিডিয়া আইটেম পরিবর্তনের কারণগুলি রেকর্ড করার জন্য, কিন্তু শুধুমাত্র একবারই কাজ করে যখন সমস্ত রাজ্য পরিবর্তনগুলি onEvents এ একসাথে ব্যবহার করা যায়৷
AnalyticsListener ব্যবহার করে
ExoPlayer ব্যবহার করার সময়, addAnalyticsListener কল করে একজন AnalyticsListener প্লেয়ারের সাথে নিবন্ধিত হতে পারে। AnalyticsListener বাস্তবায়নগুলি বিশদ ইভেন্টগুলি শুনতে সক্ষম যা বিশ্লেষণ এবং লগিং উদ্দেশ্যে কার্যকর হতে পারে। আরও বিস্তারিত জানার জন্য অনুগ্রহ করে বিশ্লেষণ পৃষ্ঠা দেখুন।
EventLogger ব্যবহার করে
EventLogger হল একটি AnalyticsListener যা সরাসরি লাইব্রেরি দ্বারা লগিংয়ের উদ্দেশ্যে সরবরাহ করা হয়। একটি একক লাইন দিয়ে দরকারী অতিরিক্ত লগিং সক্ষম করতে একটি ExoPlayer এ EventLogger যোগ করুন:
কোটলিন
player.addAnalyticsListener(EventLogger())
জাভা
player.addAnalyticsListener(new EventLogger());
আরো বিস্তারিত জানার জন্য ডিবাগ লগিং পৃষ্ঠা দেখুন।
নির্দিষ্ট প্লেব্যাক অবস্থানে গুলি চালানোর ঘটনা
কিছু ব্যবহারের ক্ষেত্রে নির্দিষ্ট প্লেব্যাক অবস্থানে ফায়ারিং ইভেন্টের প্রয়োজন হয়। এটি PlayerMessage ব্যবহার করে সমর্থিত। ExoPlayer.createMessage ব্যবহার করে একটি PlayerMessage তৈরি করা যেতে পারে। প্লেব্যাক অবস্থান যেখানে এটি কার্যকর করা উচিত তা PlayerMessage.setPosition ব্যবহার করে সেট করা যেতে পারে। বার্তাগুলি প্লেব্যাক থ্রেডে ডিফল্টরূপে কার্যকর করা হয়, তবে PlayerMessage.setLooper ব্যবহার করে এটি কাস্টমাইজ করা যেতে পারে। PlayerMessage.setDeleteAfterDelivery প্রতিবার নির্দিষ্ট প্লেব্যাক অবস্থানের সম্মুখীন হলে বার্তাটি কার্যকর করা হবে কিনা তা নিয়ন্ত্রণ করতে ব্যবহার করা যেতে পারে (এটি অনুসন্ধান এবং পুনরাবৃত্তি মোডের কারণে একাধিকবার ঘটতে পারে), বা শুধুমাত্র প্রথমবার৷ একবার PlayerMessage কনফিগার হয়ে গেলে, PlayerMessage.send ব্যবহার করে এটি নির্ধারণ করা যেতে পারে।
কোটলিন
player .createMessage { messageType: Int, payload: Any? -> } .setLooper(Looper.getMainLooper()) .setPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 120000) .setPayload(customPayloadData) .setDeleteAfterDelivery(false) .send()
জাভা
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();