প্লেব্যাক ইভেন্টগুলি শোনা হচ্ছে
ইভেন্টগুলি, যেমন অবস্থার পরিবর্তন এবং প্লেব্যাক ত্রুটি, নিবন্ধিত 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 এ রূপান্তরিত হওয়ার ঠিক আগে এই পদ্ধতিটি কল করা হবে। 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 অবজেক্টে কল করা হয়। কারণটি নির্দেশ করে যে এটি একটি স্বয়ংক্রিয় রূপান্তর, একটি seek (উদাহরণস্বরূপ player.next() কল করার পরে), একই আইটেমের পুনরাবৃত্তি, অথবা একটি প্লেলিস্ট পরিবর্তনের কারণে (উদাহরণস্বরূপ, যদি বর্তমানে প্লে করা আইটেমটি সরানো হয়)।
মেটাডেটা
player.getCurrentMediaMetadata() থেকে ফিরে আসা মেটাডেটা অনেক কারণে পরিবর্তিত হতে পারে: প্লেলিস্ট ট্রানজিশন, ইন-স্ট্রিম মেটাডেটা আপডেট অথবা প্লেব্যাকের মাঝখানে বর্তমান MediaItem আপডেট করা।
যদি আপনি মেটাডেটা পরিবর্তনে আগ্রহী হন, উদাহরণস্বরূপ, বর্তমান শিরোনাম দেখানো একটি UI আপডেট করতে, তাহলে আপনি onMediaMetadataChanged শুনতে পারেন।
খুঁজছি
Player.seekTo পদ্ধতিতে কল করার ফলে নিবন্ধিত Player.Listener উদাহরণগুলিতে ধারাবাহিক কলব্যাক আসে:
-
onPositionDiscontinuitywithreason=DISCONTINUITY_REASON_SEEK। এটিPlayer.seekToকল করার সরাসরি ফলাফল। কলব্যাকে seek-এর আগে এবং পরে অবস্থানের জন্যPositionInfoক্ষেত্র রয়েছে। -
onPlaybackStateChangedseek সম্পর্কিত যেকোনো তাৎক্ষণিক অবস্থার পরিবর্তনের সাথে। মনে রাখবেন যে এই ধরনের পরিবর্তন নাও হতে পারে।
ব্যক্তিগত কলব্যাক বনাম 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অবজেক্ট অ্যাক্সেস করতে হবে। - শ্রোতা একাধিক স্টেট মান ব্যবহার করতে চান যা পৃথক কলব্যাকের মাধ্যমে একসাথে রিপোর্ট করা হয়, অথবা
Playergetter পদ্ধতির সাথে একত্রিত করা হয়। উদাহরণস্বরূপ,onTimelineChangedএ প্রদত্তTimelineসাথেPlayer.getCurrentWindowIndex()ব্যবহার করা শুধুমাত্রonEventsকলব্যাকের মধ্যে থেকেই নিরাপদ। - শ্রোতা জানতে আগ্রহী যে ঘটনাগুলি যৌক্তিকভাবে একসাথে ঘটেছে কিনা। উদাহরণস্বরূপ,
onPlaybackStateChangedমিডিয়া আইটেম ট্রানজিশনের কারণেSTATE_BUFFERINGএ পরিবর্তিত হয়েছে।
কিছু ক্ষেত্রে, শ্রোতাদেরকে জেনেরিক onEvents কলব্যাকের সাথে পৃথক কলব্যাক একত্রিত করতে হতে পারে, উদাহরণস্বরূপ onMediaItemTransition দিয়ে মিডিয়া আইটেম পরিবর্তনের কারণ রেকর্ড করতে, তবে শুধুমাত্র তখনই কাজ করতে হবে যখন সমস্ত অবস্থা পরিবর্তনগুলি onEvents এ একসাথে ব্যবহার করা যেতে পারে।
AnalyticsListener ব্যবহার করা
ExoPlayer ব্যবহার করার সময়, addAnalyticsListener কল করে প্লেয়ারের সাথে একটি AnalyticsListener নিবন্ধিত করা যেতে পারে। AnalyticsListener বাস্তবায়নগুলি বিশ্লেষণ এবং লগিংয়ের উদ্দেশ্যে কার্যকর হতে পারে এমন বিস্তারিত ইভেন্টগুলি শুনতে সক্ষম। আরও বিশদের জন্য অনুগ্রহ করে বিশ্লেষণ পৃষ্ঠাটি দেখুন।
EventLogger ব্যবহার করা
EventLogger হল একটি AnalyticsListener যা লগিং এর উদ্দেশ্যে সরাসরি লাইব্রেরি দ্বারা সরবরাহ করা হয়। একটি একক লাইনের মাধ্যমে দরকারী অতিরিক্ত লগিং সক্ষম করতে EventLogger কে একটি ExoPlayer এ যুক্ত করুন:
কোটলিন
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();