দুই বা ততোধিক অ্যান্ড্রয়েড অ্যাপ একই সাথে একই আউটপুট স্ট্রীমে অডিও চালাতে পারে এবং সিস্টেম সবকিছু একসাথে মিশ্রিত করে। যদিও এটি প্রযুক্তিগতভাবে চিত্তাকর্ষক, এটি একটি ব্যবহারকারীর জন্য খুব উত্তেজক হতে পারে। একই সময়ে প্রতিটি মিউজিক অ্যাপ বাজানো এড়াতে, অ্যান্ড্রয়েড অডিও ফোকাসের ধারণা প্রবর্তন করে। শুধুমাত্র একটি অ্যাপ একবারে অডিও ফোকাস ধরে রাখতে পারে।
যখন আপনার অ্যাপকে অডিও আউটপুট করার প্রয়োজন হয়, তখন এটি অডিও ফোকাসের অনুরোধ করা উচিত। যখন এটির ফোকাস থাকে, তখন এটি শব্দ চালাতে পারে। যাইহোক, আপনি অডিও ফোকাস অর্জন করার পরে আপনি এটি বাজানো শেষ না হওয়া পর্যন্ত রাখতে পারবেন না। অন্য একটি অ্যাপ ফোকাসের অনুরোধ করতে পারে, যা অডিও ফোকাসে আপনার হোল্ডকে অগ্রিম করে। যদি এটি ঘটে থাকে, তাহলে ব্যবহারকারীদের নতুন অডিও উৎস আরও সহজে শুনতে দেওয়ার জন্য আপনার অ্যাপের বাজানো বন্ধ করা বা এর ভলিউম কমানো উচিত।
Android 12 (API স্তর 31) এর আগে, অডিও ফোকাস সিস্টেম দ্বারা পরিচালিত হয় না। সুতরাং, অ্যাপ ডেভেলপারদের অডিও ফোকাস নির্দেশিকা মেনে চলার জন্য উৎসাহিত করা হলেও, Android 11 (API লেভেল 30) বা তার নিচের ডিভাইসে অডিও ফোকাস হারানোর পরেও যদি কোনও অ্যাপ জোরে জোরে বাজতে থাকে, তাহলে সিস্টেম এটিকে আটকাতে পারবে না। যাইহোক, এই অ্যাপের আচরণ ব্যবহারকারীদের খারাপ অভিজ্ঞতার দিকে নিয়ে যায় এবং প্রায়শই ব্যবহারকারীদের দুর্ব্যবহারকারী অ্যাপ আনইনস্টল করতে পারে।
একটি ভাল-পরিকল্পিত অডিও অ্যাপ্লিকেশন এই সাধারণ নির্দেশিকা অনুযায়ী অডিও ফোকাস পরিচালনা করা উচিত:
বাজানো শুরু করার অবিলম্বে
requestAudioFocus()
কে কল করুন এবং যাচাই করুন যে কলটিAUDIOFOCUS_REQUEST_GRANTED
রিটার্ন করে। আপনার মিডিয়া সেশনেরonPlay()
কলব্যাকেrequestAudioFocus()
এ কল করুন।যখন অন্য একটি অ্যাপ অডিও ফোকাস অর্জন করে, তখন বাজানো বন্ধ করুন বা বিরতি দিন, বা ডক (অর্থাৎ, কমিয়ে দিন)।
যখন প্লেব্যাক বন্ধ হয়ে যায় (উদাহরণস্বরূপ, যখন অ্যাপে চালানোর জন্য কিছুই অবশিষ্ট থাকে না), অডিও ফোকাস ত্যাগ করুন। ব্যবহারকারী প্লেব্যাক বিরতি দিলে আপনার অ্যাপটিকে অডিও ফোকাস ত্যাগ করতে হবে না কিন্তু পরে প্লেব্যাক আবার শুরু করতে পারে।
আপনার অ্যাপ যে ধরনের অডিও চালাচ্ছে তা বর্ণনা করতে
AudioAttributes
ব্যবহার করুন। উদাহরণ স্বরূপ, যেসব অ্যাপ স্পিচ চালায়, তাদের জন্যCONTENT_TYPE_SPEECH
উল্লেখ করুন।
চলমান Android এর সংস্করণের উপর নির্ভর করে অডিও ফোকাস ভিন্নভাবে পরিচালনা করা হয়:
- Android 12 (API লেভেল 31) বা তার পরে
- অডিও ফোকাস সিস্টেম দ্বারা পরিচালিত হয়. যখন অন্য অ্যাপ অডিও ফোকাসের অনুরোধ করে তখন সিস্টেম একটি অ্যাপ থেকে অডিও প্লেব্যাককে বিবর্ণ হতে বাধ্য করে। একটি ইনকামিং কল প্রাপ্ত হলে সিস্টেমটি অডিও প্লেব্যাককে নিঃশব্দ করে।
- Android 8.0 (API স্তর 26) Android 11 (API স্তর 30) এর মাধ্যমে
- অডিও ফোকাস সিস্টেম দ্বারা পরিচালিত হয় না, তবে কিছু পরিবর্তন অন্তর্ভুক্ত করে যা Android 8.0 (API স্তর 26) থেকে শুরু করা হয়েছিল।
- Android 7.1 (API স্তর 25) এবং নিম্ন
- অডিও ফোকাস সিস্টেম দ্বারা পরিচালিত হয় না, এবং অ্যাপ্লিকেশনগুলি
requestAudioFocus()
এবংabandonAudioFocus()
ব্যবহার করে অডিও ফোকাস পরিচালনা করে।
Android 12 এবং উচ্চতর সংস্করণে অডিও ফোকাস
অডিও ফোকাস ব্যবহার করে এমন একটি মিডিয়া বা গেম অ্যাপ ফোকাস হারানোর পরে অডিও চালানো উচিত নয়। অ্যান্ড্রয়েড 12 (এপিআই লেভেল 31) এবং উচ্চতর, সিস্টেম এই আচরণটি প্রয়োগ করে। যখন একটি অ্যাপ অডিও ফোকাসের অনুরোধ করে যখন অন্য অ্যাপের ফোকাস থাকে এবং প্লে হচ্ছে, সিস্টেমটি প্লেয়িং অ্যাপটিকে বিবর্ণ হতে বাধ্য করে। এক অ্যাপ থেকে অন্য অ্যাপে যাওয়ার সময় ফেইড-আউটের সংযোজন একটি মসৃণ রূপান্তর প্রদান করে।
এই বিবর্ণ আচরণটি ঘটে যখন নিম্নলিখিত শর্তগুলি পূরণ হয়:
প্রথম, বর্তমানে প্লে করা অ্যাপটি এই সমস্ত মানদণ্ড পূরণ করে:
- অ্যাপটিতে
AudioAttributes.USAGE_MEDIA
বাAudioAttributes.USAGE_GAME
ব্যবহার বৈশিষ্ট্য রয়েছে। - অ্যাপটি সফলভাবে
AudioManager.AUDIOFOCUS_GAIN
এর সাথে অডিও ফোকাসের অনুরোধ করেছে। - কন্টেন্ট টাইপ
AudioAttributes.CONTENT_TYPE_SPEECH
সহ অ্যাপটি অডিও চালাচ্ছে না।
- অ্যাপটিতে
একটি দ্বিতীয় অ্যাপ
AudioManager.AUDIOFOCUS_GAIN
এর সাথে অডিও ফোকাসের অনুরোধ করে।
এই শর্তগুলি পূরণ হলে, অডিও সিস্টেমটি প্রথম অ্যাপটি বিবর্ণ হয়ে যায়। ফেইড আউটের শেষে, সিস্টেমটি প্রথম অ্যাপটিকে ফোকাস হারানোর বিষয়ে অবহিত করে। অ্যাপটি আবার অডিও ফোকাসের অনুরোধ না করা পর্যন্ত অ্যাপের প্লেয়ারগুলি নিঃশব্দ থাকে।
বিদ্যমান অডিও ফোকাস আচরণ
অডিও ফোকাসে একটি সুইচ জড়িত এই অন্যান্য ক্ষেত্রেও আপনার সচেতন হওয়া উচিত।
স্বয়ংক্রিয় হাঁস
স্বয়ংক্রিয় ডাকিং (একটি অ্যাপের অডিও লেভেল সাময়িকভাবে কমিয়ে দেওয়া যাতে অন্যটি স্পষ্টভাবে শোনা যায়) Android 8.0 (API লেভেল 26) এ চালু করা হয়েছিল।
সিস্টেমটি হাঁস পালন করার মাধ্যমে, আপনাকে আপনার অ্যাপে হাঁস পালন করতে হবে না।
স্বয়ংক্রিয় হাঁসও ঘটে যখন একটি অডিও বিজ্ঞপ্তি একটি বাজানো অ্যাপ থেকে ফোকাস দখল করে। বিজ্ঞপ্তি প্লেব্যাকের শুরুটি ডাকিং র্যাম্পের শেষের সাথে সিঙ্ক্রোনাইজ করা হয়।
নিম্নলিখিত শর্ত পূরণ হলে স্বয়ংক্রিয় হাঁস হয়:
প্রথম, বর্তমানে-বাজানো অ্যাপটি এই সমস্ত মানদণ্ড পূরণ করে:
- অ্যাপটি সফলভাবে যেকোনো ধরনের ফোকাস লাভের সাথে অডিও ফোকাসের অনুরোধ করেছে।
- কন্টেন্ট টাইপ
AudioAttributes.CONTENT_TYPE_SPEECH
সহ অ্যাপটি অডিও চালাচ্ছে না। - অ্যাপটি
AudioFocusRequest.Builder.setWillPauseWhenDucked(true)
সেট করেনি।
একটি দ্বিতীয় অ্যাপ
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
এর সাথে অডিও ফোকাসের অনুরোধ করে।
যখন এই শর্তগুলি পূরণ করা হয়, তখন অডিও সিস্টেমটি প্রথম অ্যাপের সমস্ত সক্রিয় প্লেয়ারকে ডক করে যখন দ্বিতীয় অ্যাপটিতে ফোকাস থাকে৷ যখন দ্বিতীয় অ্যাপটি ফোকাস ত্যাগ করে, তখন এটি তাদের আনডাক করে। প্রথম অ্যাপটি যখন ফোকাস হারায় তখন তা জানানো হয় না, তাই এটিকে কিছু করতে হবে না।
নোট করুন যে ব্যবহারকারী যখন বক্তৃতা বিষয়বস্তু শুনছেন তখন স্বয়ংক্রিয় হাঁস সঞ্চালিত হয় না, কারণ ব্যবহারকারী কিছু প্রোগ্রাম মিস করতে পারে। উদাহরণস্বরূপ, ড্রাইভিং দিকনির্দেশের জন্য ভয়েস নির্দেশিকা ডাকা হয় না।
ইনকামিং ফোন কলের জন্য বর্তমান অডিও প্লেব্যাক মিউট করুন
কিছু অ্যাপ্লিকেশান সঠিকভাবে আচরণ করে না এবং ফোন কলের সময় অডিও বাজানো চালিয়ে যায়। এই পরিস্থিতি ব্যবহারকারীকে তাদের কল শোনার জন্য আপত্তিকর অ্যাপ খুঁজে পেতে এবং নিঃশব্দ করতে বা ছেড়ে দিতে বাধ্য করে৷ এটি প্রতিরোধ করার জন্য, একটি ইনকামিং কল থাকাকালীন সিস্টেম অন্যান্য অ্যাপ থেকে অডিও মিউট করতে পারে। যখন একটি ইনকামিং ফোন কল আসে এবং একটি অ্যাপ এই শর্তগুলি পূরণ করে তখন সিস্টেমটি এই বৈশিষ্ট্যটি চালু করে:
- অ্যাপটিতে
AudioAttributes.USAGE_MEDIA
বাAudioAttributes.USAGE_GAME
ব্যবহার বৈশিষ্ট্য রয়েছে। - অ্যাপটি সফলভাবে অডিও ফোকাস (কোন ফোকাস লাভ) অনুরোধ করেছে এবং অডিও চালাচ্ছে।
কল চলাকালীন যদি কোনো অ্যাপ চলতে থাকে, তাহলে কল শেষ না হওয়া পর্যন্ত এর প্লেব্যাক নিঃশব্দ থাকে। যাইহোক, যদি কল চলাকালীন একটি অ্যাপ বাজানো শুরু করে, তবে সেই প্লেয়ারটিকে নিঃশব্দ করা হয় না এই অনুমানে যে ব্যবহারকারী ইচ্ছাকৃতভাবে প্লেব্যাক শুরু করেছেন৷
Android 11 এর মাধ্যমে Android 8.0 এ অডিও ফোকাস
Android 8.0 (API স্তর 26) দিয়ে শুরু করে, আপনি যখন requestAudioFocus()
কল করেন তখন আপনাকে অবশ্যই একটি AudioFocusRequest
প্যারামিটার সরবরাহ করতে হবে। AudioFocusRequest
আপনার অ্যাপের অডিও প্রসঙ্গ এবং ক্ষমতা সম্পর্কে তথ্য রয়েছে। সিস্টেম স্বয়ংক্রিয়ভাবে অডিও ফোকাসের লাভ এবং ক্ষতি পরিচালনা করতে এই তথ্য ব্যবহার করে। অডিও ফোকাস রিলিজ করার জন্য, মেথড abandonAudioFocusRequest()
কে কল করুন যা একটি AudioFocusRequest
এর আর্গুমেন্ট হিসেবেও নেয়। আপনি যখন অনুরোধ করেন এবং ফোকাস ত্যাগ করেন উভয় ক্ষেত্রেই একই AudioFocusRequest
দৃষ্টান্ত ব্যবহার করুন।
একটি AudioFocusRequest
তৈরি করতে, একটি AudioFocusRequest.Builder
ব্যবহার করুন। যেহেতু একটি ফোকাস অনুরোধ সবসময় অনুরোধের ধরন নির্দিষ্ট করতে হবে, টাইপটি নির্মাতার জন্য কনস্ট্রাক্টরে অন্তর্ভুক্ত করা হয়। অনুরোধের অন্যান্য ক্ষেত্র সেট করতে নির্মাতার পদ্ধতি ব্যবহার করুন।
FocusGain
ক্ষেত্র প্রয়োজন; অন্য সব ক্ষেত্র ঐচ্ছিক।
পদ্ধতি | নোট |
---|---|
setFocusGain() | প্রতিটি অনুরোধে এই ক্ষেত্রটি প্রয়োজন। এটি অনুরোধের জন্য প্রি-অ্যান্ড্রয়েড 8.0 কলে ব্যবহৃত durationHint মতো একই মান নেয় requestAudioFocus() : AUDIOFOCUS_GAIN , AUDIOFOCUS_GAIN_TRANSIENT , AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK , বা AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE । |
setAudioAttributes() | AudioAttributes আপনার অ্যাপের ব্যবহারের ক্ষেত্রে বর্ণনা করে। যখন একটি অ্যাপ লাভ করে এবং অডিও ফোকাস হারায় তখন সিস্টেম তাদের দিকে তাকায়। বৈশিষ্ট্যগুলি স্ট্রীম প্রকারের ধারণাকে অগ্রাহ্য করে৷ Android 8.0 (API লেভেল 26) এবং পরবর্তীতে, ভলিউম কন্ট্রোল ব্যতীত অন্য যেকোন অপারেশনের জন্য স্ট্রীম প্রকারগুলি অবহেলিত। ফোকাস অনুরোধে একই বৈশিষ্ট্যগুলি ব্যবহার করুন যা আপনি আপনার অডিও প্লেয়ারে ব্যবহার করেন (যেমন এই টেবিলের অনুসরণে উদাহরণে দেখানো হয়েছে)। একটি নির্দিষ্ট করা না থাকলে, |
setWillPauseWhenDucked() | যখন অন্য একটি অ্যাপ AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK এর সাথে ফোকাস করার অনুরোধ করে, তখন যে অ্যাপটিতে ফোকাস থাকে সে সাধারণত onAudioFocusChange() কলব্যাক পায় না কারণ সিস্টেম নিজেই ডকিং করতে পারে। আপনি যখন ভলিউম ডাকার পরিবর্তে প্লেব্যাক পজ করতে চান, setWillPauseWhenDucked(true) কল করুন এবং একটি OnAudioFocusChangeListener তৈরি এবং সেট করুন, যেমন স্বয়ংক্রিয় ডাকিং -এ বর্ণিত হয়েছে। |
setAcceptsDelayedFocusGain() | অন্য অ্যাপ দ্বারা ফোকাস লক করা হলে অডিও ফোকাসের জন্য একটি অনুরোধ ব্যর্থ হতে পারে। এই পদ্ধতিটি বিলম্বিত ফোকাস লাভকে সক্ষম করে: এটি উপলব্ধ হলে অ্যাসিঙ্ক্রোনাসভাবে ফোকাস অর্জন করার ক্ষমতা। মনে রাখবেন যে বিলম্বিত ফোকাস লাভ শুধুমাত্র তখনই কাজ করে যদি আপনি অডিও অনুরোধে একটি |
setOnAudioFocusChangeListener() | একটি OnAudioFocusChangeListener শুধুমাত্র প্রয়োজন হয় যদি আপনি অনুরোধে willPauseWhenDucked(true) অথবা setAcceptsDelayedFocusGain(true) উল্লেখ করেন। শ্রোতা সেট করার জন্য দুটি পদ্ধতি রয়েছে: একটি হ্যান্ডলার যুক্তি ছাড়াই। হ্যান্ডলার হল সেই থ্রেড যার উপর শ্রোতা চলে। আপনি যদি একটি হ্যান্ডলার নির্দিষ্ট না করেন তবে প্রধান |
নিম্নলিখিত উদাহরণটি দেখায় কিভাবে একটি AudioFocusRequest.Builder
ব্যবহার করে একটি AudioFocusRequest
তৈরি করতে হয় এবং অডিও ফোকাস ত্যাগ করার জন্য অনুরোধ করা যায়:
কোটলিন
// initializing variables for audio focus and playback management audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run { setAudioAttributes(AudioAttributes.Builder().run { setUsage(AudioAttributes.USAGE_GAME) setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) build() }) setAcceptsDelayedFocusGain(true) setOnAudioFocusChangeListener(afChangeListener, handler) build() } val focusLock = Any() var playbackDelayed = false var playbackNowAuthorized = false // requesting audio focus and processing the response val res = audioManager.requestAudioFocus(focusRequest) synchronized(focusLock) { playbackNowAuthorized = when (res) { AudioManager.AUDIOFOCUS_REQUEST_FAILED -> false AudioManager.AUDIOFOCUS_REQUEST_GRANTED -> { playbackNow() true } AudioManager.AUDIOFOCUS_REQUEST_DELAYED -> { playbackDelayed = true false } else -> false } } // implementing OnAudioFocusChangeListener to react to focus changes override fun onAudioFocusChange(focusChange: Int) { when (focusChange) { AudioManager.AUDIOFOCUS_GAIN -> if (playbackDelayed || resumeOnFocusGain) { synchronized(focusLock) { playbackDelayed = false resumeOnFocusGain = false } playbackNow() } AudioManager.AUDIOFOCUS_LOSS -> { synchronized(focusLock) { resumeOnFocusGain = false playbackDelayed = false } pausePlayback() } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> { synchronized(focusLock) { // only resume if playback is being interrupted resumeOnFocusGain = isPlaying() playbackDelayed = false } pausePlayback() } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> { // ... pausing or ducking depends on your app } } }
জাভা
// initializing variables for audio focus and playback management audioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE); playbackAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_GAME) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build(); focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes(playbackAttributes) .setAcceptsDelayedFocusGain(true) .setOnAudioFocusChangeListener(afChangeListener, handler) .build(); final Object focusLock = new Object(); boolean playbackDelayed = false; boolean playbackNowAuthorized = false; // requesting audio focus and processing the response int res = audioManager.requestAudioFocus(focusRequest); synchronized(focusLock) { if (res == AudioManager.AUDIOFOCUS_REQUEST_FAILED) { playbackNowAuthorized = false; } else if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { playbackNowAuthorized = true; playbackNow(); } else if (res == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) { playbackDelayed = true; playbackNowAuthorized = false; } } // implementing OnAudioFocusChangeListener to react to focus changes @Override public void onAudioFocusChange(int focusChange) { switch (focusChange) { case AudioManager.AUDIOFOCUS_GAIN: if (playbackDelayed || resumeOnFocusGain) { synchronized(focusLock) { playbackDelayed = false; resumeOnFocusGain = false; } playbackNow(); } break; case AudioManager.AUDIOFOCUS_LOSS: synchronized(focusLock) { resumeOnFocusGain = false; playbackDelayed = false; } pausePlayback(); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: synchronized(focusLock) { // only resume if playback is being interrupted resumeOnFocusGain = isPlaying(); playbackDelayed = false; } pausePlayback(); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: // ... pausing or ducking depends on your app break; } } }
স্বয়ংক্রিয় হাঁস
অ্যান্ড্রয়েড 8.0 (API লেভেল 26) এ, যখন অন্য একটি অ্যাপ AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
এর সাথে ফোকাস করার অনুরোধ করে, তখন সিস্টেমটি অ্যাপের onAudioFocusChange()
কলব্যাক না করেই ভলিউম পুনরুদ্ধার করতে পারে।
সঙ্গীত এবং ভিডিও প্লেব্যাক অ্যাপের জন্য স্বয়ংক্রিয় হাঁস গ্রহণযোগ্য আচরণ হলেও, কথ্য বিষয়বস্তু চালানোর সময় এটি কার্যকর হয় না, যেমন একটি অডিও বুক অ্যাপে। এই ক্ষেত্রে, অ্যাপটির পরিবর্তে বিরতি দেওয়া উচিত।
আপনি যদি চান যে আপনার অ্যাপের ভলিউম কমানোর পরিবর্তে ডক করতে বলা হলে সেটিকে থামাতে, একটি onAudioFocusChange()
কলব্যাক পদ্ধতি সহ একটি OnAudioFocusChangeListener
তৈরি করুন যা পছন্দসই বিরতি/পুনরায় শুরু করার আচরণ প্রয়োগ করে। শ্রোতা নিবন্ধন করতে setOnAudioFocusChangeListener()
কল করুন এবং স্বয়ংক্রিয় ডাকিং করার পরিবর্তে আপনার কলব্যাক ব্যবহার করার জন্য সিস্টেমকে বলার জন্য setWillPauseWhenDucked(true)
এ কল করুন।
বিলম্বিত ফোকাস লাভ
কখনও কখনও সিস্টেমটি অডিও ফোকাসের জন্য একটি অনুরোধ মঞ্জুর করতে পারে না কারণ ফোকাসটি অন্য অ্যাপ দ্বারা "লক" থাকে, যেমন একটি ফোন কলের সময়৷ এই ক্ষেত্রে, requestAudioFocus()
AUDIOFOCUS_REQUEST_FAILED
প্রদান করে। যখন এটি ঘটে, আপনার অ্যাপটি অডিও প্লেব্যাকের সাথে এগিয়ে যাওয়া উচিত নয় কারণ এটি ফোকাস অর্জন করেনি।
পদ্ধতি, setAcceptsDelayedFocusGain(true)
, যা আপনার অ্যাপকে অ্যাসিঙ্ক্রোনাসভাবে ফোকাসের জন্য একটি অনুরোধ পরিচালনা করতে দেয়। এই পতাকা সেটের সাথে, যখন ফোকাস লক করা থাকে তখন করা একটি অনুরোধ AUDIOFOCUS_REQUEST_DELAYED
প্রদান করে। যখন অডিও ফোকাস লক করা শর্তটি আর বিদ্যমান থাকে না, যেমন একটি ফোন কল শেষ হলে, সিস্টেমটি মুলতুবি ফোকাস অনুরোধ মঞ্জুর করে এবং আপনার অ্যাপকে অবহিত করার জন্য onAudioFocusChange()
এ কল করে।
ফোকাসের বিলম্বিত লাভ পরিচালনা করার জন্য, আপনাকে অবশ্যই একটি OnAudioFocusChangeListener
তৈরি করতে হবে একটি onAudioFocusChange()
কলব্যাক পদ্ধতি যা পছন্দসই আচরণ প্রয়োগ করে এবং setOnAudioFocusChangeListener()
কল করে শ্রোতাকে নিবন্ধন করে।
অ্যান্ড্রয়েড 7.1 এবং তার নিচের সংস্করণে অডিও ফোকাস
যখন আপনি requestAudioFocus()
কল করেন তখন আপনাকে অবশ্যই একটি সময়কালের ইঙ্গিত নির্দিষ্ট করতে হবে, যা অন্য একটি অ্যাপ দ্বারা সম্মানিত হতে পারে যা বর্তমানে ফোকাস ধরে রেখেছে এবং খেলছে:
- স্থায়ী অডিও ফোকাস (
AUDIOFOCUS_GAIN
) অনুরোধ করুন যখন আপনি অদূর ভবিষ্যতের জন্য অডিও চালানোর পরিকল্পনা করেন (উদাহরণস্বরূপ, সঙ্গীত বাজানোর সময়) এবং আপনি আশা করেন যে অডিও ফোকাসের আগের ধারকটি বাজানো বন্ধ করবে। - ক্ষণস্থায়ী ফোকাসের অনুরোধ করুন (
AUDIOFOCUS_GAIN_TRANSIENT
) যখন আপনি অল্প সময়ের জন্য অডিও চালানোর আশা করেন এবং আপনি আশা করেন যে পূর্ববর্তী ধারকটি বাজানো বন্ধ করবে৷ - হাঁসের সাথে ক্ষণস্থায়ী ফোকাসের অনুরোধ করুন (
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
) নির্দেশ করতে যে আপনি অল্প সময়ের জন্য অডিও বাজানোর আশা করছেন এবং পূর্ববর্তী ফোকাসের মালিক যদি এটির অডিও আউটপুট "হাঁস" (কমায়) চালিয়ে যান তবে এটি ঠিক আছে৷ উভয় অডিও আউটপুট অডিও স্ট্রিম মধ্যে মিশ্রিত করা হয়. হাঁস বিশেষভাবে সেই অ্যাপগুলির জন্য উপযুক্ত যেগুলি মাঝে মাঝে অডিও স্ট্রিম ব্যবহার করে, যেমন শ্রবণযোগ্য ড্রাইভিং দিকনির্দেশগুলির জন্য৷
requestAudioFocus()
পদ্ধতিতে একটি AudioManager.OnAudioFocusChangeListener
ও প্রয়োজন। এই শ্রোতা আপনার মিডিয়া সেশনের মালিক একই কার্যকলাপ বা পরিষেবা তৈরি করা উচিত. এটি onAudioFocusChange()
উপর কলব্যাক প্রয়োগ করে যা আপনার অ্যাপটি গ্রহণ করে যখন অন্য কোন অ্যাপ অডিও ফোকাস অর্জন করে বা পরিত্যাগ করে।
নিম্নলিখিত স্নিপেটটি STREAM_MUSIC
স্ট্রীমে স্থায়ী অডিও ফোকাসের অনুরোধ করে এবং অডিও ফোকাসে পরবর্তী পরিবর্তনগুলি পরিচালনা করতে একটি OnAudioFocusChangeListener
নিবন্ধন করে৷ ( একটি অডিও ফোকাস পরিবর্তনের প্রতিক্রিয়াতে শ্রোতার পরিবর্তন নিয়ে আলোচনা করা হয়েছে।)
কোটলিন
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager lateinit var afChangeListener AudioManager.OnAudioFocusChangeListener ... // Request audio focus for playback val result: Int = audioManager.requestAudioFocus( afChangeListener, // Use the music stream. AudioManager.STREAM_MUSIC, // Request permanent focus. AudioManager.AUDIOFOCUS_GAIN ) if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // Start playback }
জাভা
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); AudioManager.OnAudioFocusChangeListener afChangeListener; ... // Request audio focus for playback int result = audioManager.requestAudioFocus(afChangeListener, // Use the music stream. AudioManager.STREAM_MUSIC, // Request permanent focus. AudioManager.AUDIOFOCUS_GAIN); if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // Start playback }
আপনি প্লেব্যাক শেষ করার পরে, abandonAudioFocus()
কল করুন।
কোটলিন
audioManager.abandonAudioFocus(afChangeListener)
জাভা
// Abandon audio focus when playback complete audioManager.abandonAudioFocus(afChangeListener);
এটি সিস্টেমকে সূচিত করে যে আপনার আর ফোকাসের প্রয়োজন নেই এবং সংশ্লিষ্ট OnAudioFocusChangeListener
নিবন্ধন বাতিল করে দেয়। আপনি যদি ক্ষণস্থায়ী ফোকাসের অনুরোধ করেন, তাহলে এটি একটি অ্যাপকে অবহিত করবে যেটি বিরতি দেওয়া বা ডক করা হয়েছে যে এটি চালানো চালিয়ে যেতে পারে বা এর ভলিউম পুনরুদ্ধার করতে পারে।
একটি অডিও ফোকাস পরিবর্তন সাড়া
যখন একটি অ্যাপ অডিও ফোকাস অর্জন করে, অন্য অ্যাপ যখন নিজের জন্য অডিও ফোকাস অনুরোধ করে তখন এটি অবশ্যই তা প্রকাশ করতে সক্ষম হবে। যখন এটি ঘটে, আপনার অ্যাপ AudioFocusChangeListener
এ onAudioFocusChange()
পদ্ধতিতে একটি কল পায় যা আপনি নির্দিষ্ট করেছিলেন যখন অ্যাপটি requestAudioFocus()
বলে।
onAudioFocusChange()
এ পাস করা focusChange
প্যারামিটারটি কী ধরনের পরিবর্তন ঘটছে তা নির্দেশ করে। এটি ফোকাস অর্জনকারী অ্যাপ দ্বারা ব্যবহৃত সময়কাল ইঙ্গিতের সাথে মিলে যায়। আপনার অ্যাপকে যথাযথভাবে সাড়া দেওয়া উচিত।
- ফোকাস ক্ষণস্থায়ী ক্ষতি
- যদি ফোকাস পরিবর্তন ক্ষণস্থায়ী হয় (
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
বাAUDIOFOCUS_LOSS_TRANSIENT
), আপনার অ্যাপটি ডক করা উচিত (যদি আপনি স্বয়ংক্রিয় হাঁসের উপর নির্ভর না করেন) বা খেলা থামাতে হবে কিন্তু অন্যথায় একই অবস্থা বজায় রাখতে হবে।অডিও ফোকাসের ক্ষণস্থায়ী ক্ষতির সময়, আপনার অডিও ফোকাসের পরিবর্তনগুলি পর্যবেক্ষণ করা চালিয়ে যাওয়া উচিত এবং যখন আপনি ফোকাস পুনরুদ্ধার করবেন তখন স্বাভাবিক প্লেব্যাক পুনরায় শুরু করার জন্য প্রস্তুত থাকুন। যখন ব্লকিং অ্যাপ ফোকাস ত্যাগ করে, আপনি একটি কলব্যাক পাবেন (
AUDIOFOCUS_GAIN
)। এই মুহুর্তে, আপনি ভলিউমটিকে স্বাভাবিক স্তরে পুনরুদ্ধার করতে পারেন বা প্লেব্যাক পুনরায় চালু করতে পারেন। - ফোকাস স্থায়ী ক্ষতি
- যদি অডিও ফোকাস ক্ষতি স্থায়ী হয় (
AUDIOFOCUS_LOSS
), অন্য একটি অ্যাপ অডিও চালাচ্ছে৷ আপনার অ্যাপের প্লেব্যাক অবিলম্বে থামানো উচিত, কারণ এটি কখনই একটিAUDIOFOCUS_GAIN
কলব্যাক পাবে না৷ প্লেব্যাক পুনরায় চালু করতে, ব্যবহারকারীকে একটি স্পষ্ট পদক্ষেপ নিতে হবে, যেমন একটি বিজ্ঞপ্তি বা অ্যাপ UI-তে প্লে ট্রান্সপোর্ট কন্ট্রোল টিপে।
নিচের কোড স্নিপেট দেখায় কিভাবে OnAudioFocusChangeListener
এবং এর onAudioFocusChange()
কলব্যাক বাস্তবায়ন করতে হয়। অডিও ফোকাসের স্থায়ী ক্ষতি হলে স্টপ কলব্যাক বিলম্বিত করতে একটি Handler
ব্যবহার লক্ষ্য করুন।
কোটলিন
private val handler = Handler() private val afChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange -> when (focusChange) { AudioManager.AUDIOFOCUS_LOSS -> { // Permanent loss of audio focus // Pause playback immediately mediaController.transportControls.pause() // Wait 30 seconds before stopping playback handler.postDelayed(delayedStopRunnable, TimeUnit.SECONDS.toMillis(30)) } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> { // Pause playback } AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> { // Lower the volume, keep playing } AudioManager.AUDIOFOCUS_GAIN -> { // Your app has been granted audio focus again // Raise volume to normal, restart playback if necessary } } }
জাভা
private Handler handler = new Handler(); AudioManager.OnAudioFocusChangeListener afChangeListener = new AudioManager.OnAudioFocusChangeListener() { public void onAudioFocusChange(int focusChange) { if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { // Permanent loss of audio focus // Pause playback immediately mediaController.getTransportControls().pause(); // Wait 30 seconds before stopping playback handler.postDelayed(delayedStopRunnable, TimeUnit.SECONDS.toMillis(30)); } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { // Pause playback } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { // Lower the volume, keep playing } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { // Your app has been granted audio focus again // Raise volume to normal, restart playback if necessary } } };
হ্যান্ডলার একটি Runnable
ব্যবহার করে যা দেখতে এইরকম:
কোটলিন
private var delayedStopRunnable = Runnable { mediaController.transportControls.stop() }
জাভা
private Runnable delayedStopRunnable = new Runnable() { @Override public void run() { getMediaController().getTransportControls().stop(); } };
ব্যবহারকারী প্লেব্যাক পুনরায় চালু করলে বিলম্বিত স্টপ চালু না হয় তা নিশ্চিত করার জন্য, যেকোনো অবস্থার পরিবর্তনের প্রতিক্রিয়ায় mHandler.removeCallbacks(mDelayedStopRunnable)
কল করুন। উদাহরণস্বরূপ, আপনার কলব্যাকের onPlay()
, onSkipToNext()
ইত্যাদিতে কল removeCallbacks()
করুন৷ আপনার পরিষেবার দ্বারা ব্যবহৃত সংস্থানগুলি পরিষ্কার করার সময় আপনার পরিষেবার onDestroy()
কলব্যাকেও এই পদ্ধতিটি কল করা উচিত৷