আপনি ব্যাকগ্রাউন্ডে মিডিয়া চালাতে পারেন এমনকি যখন আপনার অ্যাপ্লিকেশন স্ক্রিনে না থাকে, উদাহরণস্বরূপ, যখন ব্যবহারকারী অন্যান্য অ্যাপ্লিকেশনের সাথে ইন্টারঅ্যাক্ট করছে।
এটি করার জন্য, আপনি একটি MediaBrowserServiceCompat
পরিষেবাতে MediaPlayer এম্বেড করুন এবং এটিকে অন্য কার্যকলাপে একটি MediaBrowserCompat
এর সাথে ইন্টারঅ্যাক্ট করুন৷
এই ক্লায়েন্ট এবং সার্ভার সেটআপ বাস্তবায়নে সতর্ক থাকুন। ব্যাকগ্রাউন্ড সার্ভিসে চলমান একজন প্লেয়ার কীভাবে বাকি সিস্টেমের সাথে ইন্টারঅ্যাক্ট করে সে সম্পর্কে প্রত্যাশা রয়েছে। যদি আপনার অ্যাপ্লিকেশন সেই প্রত্যাশাগুলি পূরণ না করে, ব্যবহারকারীর একটি খারাপ অভিজ্ঞতা হতে পারে। বিস্তারিত জানার জন্য একটি অডিও অ্যাপ তৈরি করা দেখুন।
এই পৃষ্ঠাটি একটি MediaPlayer পরিচালনার জন্য বিশেষ নির্দেশাবলী বর্ণনা করে যখন আপনি এটি একটি পরিষেবার মধ্যে প্রয়োগ করেন।
অ্যাসিঙ্ক্রোনাসভাবে চালান
একটি Activity
মতো, একটি Service
সমস্ত কাজ ডিফল্টরূপে একটি একক থ্রেডে সম্পন্ন হয়। প্রকৃতপক্ষে, আপনি যখন একই অ্যাপ্লিকেশন থেকে একটি কার্যকলাপ এবং একটি পরিষেবা চালান, তখন তারা ডিফল্টরূপে একই থ্রেড ("প্রধান থ্রেড") ব্যবহার করে।
পরিষেবাগুলিকে অবশ্যই ইনকামিং ইন্টেন্টগুলিকে দ্রুত প্রক্রিয়া করতে হবে এবং তাদের প্রতিক্রিয়া দেওয়ার সময় কখনই দীর্ঘ গণনা করতে হবে না। আপনাকে অবশ্যই যেকোন ভারী কাজ করতে হবে বা অ্যাসিঙ্ক্রোনাসভাবে কলগুলিকে ব্লক করতে হবে: হয় অন্য থ্রেড থেকে আপনি নিজেই প্রয়োগ করেন, অথবা অ্যাসিঙ্ক্রোনাস প্রক্রিয়াকরণের জন্য ফ্রেমওয়ার্কের অনেক সুবিধা ব্যবহার করেন।
উদাহরণস্বরূপ, যখন আপনি আপনার প্রধান থ্রেড থেকে MediaPlayer
ব্যবহার করেন, তখন আপনার উচিত:
-
prepare()
এর পরিবর্তেprepareAsync()
কল করুন, এবং - প্রস্তুতি সম্পূর্ণ হলে বিজ্ঞপ্তি পাওয়ার জন্য একটি
MediaPlayer.OnPreparedListener
প্রয়োগ করুন এবং আপনি খেলা শুরু করতে পারেন।
যেমন:
কোটলিন
private const val ACTION_PLAY: String = "com.example.action.PLAY"
class MyService: Service(), MediaPlayer.OnPreparedListener {
private var mMediaPlayer: MediaPlayer? = null
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
...
val action: String = intent.action
when(action) {
ACTION_PLAY -> {
mMediaPlayer = ... // initialize it here
mMediaPlayer?.apply {
setOnPreparedListener(this@MyService)
prepareAsync() // prepare async to not block main thread
}
}
}
...
}
/** Called when MediaPlayer is ready */
override fun onPrepared(mediaPlayer: MediaPlayer) {
mediaPlayer.start()
}
}
জাভা
public class MyService extends Service implements MediaPlayer.OnPreparedListener {
private static final String ACTION_PLAY = "com.example.action.PLAY";
MediaPlayer mediaPlayer = null;
public int onStartCommand(Intent intent, int flags, int startId) {
...
if (intent.getAction().equals(ACTION_PLAY)) {
mediaPlayer = ... // initialize it here
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.prepareAsync(); // prepare async to not block main thread
}
}
/** Called when MediaPlayer is ready */
public void onPrepared(MediaPlayer player) {
player.start();
}
}
অ্যাসিঙ্ক্রোনাস ত্রুটিগুলি পরিচালনা করুন
সিঙ্ক্রোনাস অপারেশনগুলিতে, ত্রুটিগুলি একটি ব্যতিক্রম বা একটি ত্রুটি কোডের সাথে সংকেত করা হয়। আপনি যখন অ্যাসিঙ্ক্রোনাস রিসোর্স ব্যবহার করেন, তবে, আপনাকে আপনার আবেদনের ত্রুটি যথাযথভাবে অবহিত করা উচিত। একটি MediaPlayer
এর ক্ষেত্রে, আপনি একটি MediaPlayer.OnErrorListener
প্রয়োগ করুন এবং এটি আপনার MediaPlayer
উদাহরণে সেট করুন:
কোটলিন
class MyService : Service(), MediaPlayer.OnErrorListener {
private var mediaPlayer: MediaPlayer? = null
fun initMediaPlayer() {
// ...initialize the MediaPlayer here...
mediaPlayer?.setOnErrorListener(this)
}
override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean {
// ... react appropriately ...
// The MediaPlayer has moved to the Error state, must be reset!
}
}
জাভা
public class MyService extends Service implements MediaPlayer.OnErrorListener {
MediaPlayer mediaPlayer;
public void initMediaPlayer() {
// ...initialize the MediaPlayer here...
mediaPlayer.setOnErrorListener(this);
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// ... react appropriately ...
// The MediaPlayer has moved to the Error state, must be reset!
}
}
যখন একটি ত্রুটি ঘটে, MediaPlayer
ত্রুটি অবস্থায় চলে যায়। আপনি এটি আবার ব্যবহার করার আগে এটি পুনরায় সেট করতে হবে। বিস্তারিত জানার জন্য, MediaPlayer
ক্লাসের জন্য সম্পূর্ণ স্টেট ডায়াগ্রাম দেখুন।
ওয়েক লক ব্যবহার করুন
আপনি যখন ব্যাকগ্রাউন্ডে মিউজিক চালান বা স্ট্রিম করেন, তখন আপনার প্লেব্যাকে সিস্টেমকে হস্তক্ষেপ করা থেকে বিরত রাখতে আপনাকে অবশ্যই ওয়েক লক ব্যবহার করতে হবে, উদাহরণস্বরূপ, ডিভাইসটিকে ঘুমাতে যাওয়ার মাধ্যমে।
একটি ওয়েক লক হল সিস্টেমের জন্য একটি সংকেত যে আপনার অ্যাপ্লিকেশন এমন বৈশিষ্ট্যগুলি ব্যবহার করছে যা ফোনটি নিষ্ক্রিয় থাকা সত্ত্বেও উপলব্ধ থাকা উচিত৷
আপনার MediaPlayer
বাজানোর সময় CPU চলতে থাকে তা নিশ্চিত করতে, আপনি যখন আপনার MediaPlayer
আরম্ভ করবেন তখন setWakeMode()
পদ্ধতিতে কল করুন। MediaPlayer
খেলার সময় নির্দিষ্ট লকটি ধরে রাখে এবং বিরতি বা বন্ধ করা হলে লকটি ছেড়ে দেয়:
কোটলিন
mediaPlayer = MediaPlayer().apply {
// ... other initialization here ...
setWakeMode(applicationContext, PowerManager.PARTIAL_WAKE_LOCK)
}
জাভা
mediaPlayer = new MediaPlayer();
// ... other initialization here ...
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
যাইহোক, এই উদাহরণে অর্জিত ওয়েক লক শুধুমাত্র নিশ্চিত করে যে CPU জাগ্রত থাকে। আপনি যদি নেটওয়ার্কের মাধ্যমে মিডিয়া স্ট্রিমিং করেন এবং আপনি Wi-Fi ব্যবহার করেন, আপনি সম্ভবত একটি WifiLock
ও ধরে রাখতে চান, যা আপনাকে অবশ্যই অর্জন করতে হবে এবং ম্যানুয়ালি ছেড়ে দিতে হবে। সুতরাং, আপনি যখন দূরবর্তী URL দিয়ে MediaPlayer
প্রস্তুত করা শুরু করেন, তখন আপনার Wi-Fi লক তৈরি এবং অর্জন করা উচিত।
যেমন:
কোটলিন
val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiLock: WifiManager.WifiLock =
wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock")
wifiLock.acquire()
জাভা
WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
wifiLock.acquire();
আপনি যখন আপনার মিডিয়া থামান বা বন্ধ করেন, বা যখন আপনার আর নেটওয়ার্কের প্রয়োজন হয় না, তখন আপনার লকটি ছেড়ে দেওয়া উচিত:
কোটলিন
wifiLock.release()
জাভা
wifiLock.release();
পরিচ্ছন্নতা সঞ্চালন
যেমন আগে উল্লেখ করা হয়েছে, একটি MediaPlayer
অবজেক্ট একটি উল্লেখযোগ্য পরিমাণ সিস্টেম সংস্থান গ্রহণ করতে পারে, তাই আপনার এটি শুধুমাত্র যতক্ষণ প্রয়োজন ততক্ষণ রাখা উচিত এবং এটি শেষ করার পরে release()
কল করুন। সিস্টেম আবর্জনা সংগ্রহের উপর নির্ভর করার পরিবর্তে এই পরিষ্কারের পদ্ধতিটিকে স্পষ্টভাবে বলা গুরুত্বপূর্ণ কারণ আবর্জনা সংগ্রহকারী MediaPlayer
পুনরুদ্ধার করার আগে এটি কিছু সময় নিতে পারে, কারণ এটি শুধুমাত্র মেমরির প্রয়োজনের প্রতি সংবেদনশীল এবং অন্যান্য মিডিয়া-সম্পর্কিত সংস্থানগুলির অভাবের জন্য নয়। সুতরাং, আপনি যখন একটি পরিষেবা ব্যবহার করছেন তখন, আপনি MediaPlayer
প্রকাশ করছেন তা নিশ্চিত করতে আপনার সর্বদা onDestroy()
পদ্ধতিটি ওভাররাইড করা উচিত:
কোটলিন
class MyService : Service() {
private var mediaPlayer: MediaPlayer? = null
// ...
override fun onDestroy() {
super.onDestroy()
mediaPlayer?.release()
}
}
জাভা
public class MyService extends Service {
MediaPlayer mediaPlayer;
// ...
@Override
public void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) mediaPlayer.release();
}
}
আপনার মিডিয়াপ্লেয়ারটি বন্ধ করার সময় এটি প্রকাশ করা ছাড়াও, আপনার MediaPlayer
প্রকাশ করার অন্যান্য সুযোগগুলির সন্ধান করা উচিত। উদাহরণস্বরূপ, যদি আপনি আশা করেন যে আপনি একটি বর্ধিত সময়ের জন্য মিডিয়া চালাতে পারবেন না (উদাহরণস্বরূপ, অডিও ফোকাস হারানোর পরে), আপনার অবশ্যই আপনার বিদ্যমান MediaPlayer
ছেড়ে দেওয়া উচিত এবং পরে আবার তৈরি করা উচিত। অন্যদিকে, আপনি যদি খুব অল্প সময়ের জন্য প্লেব্যাক বন্ধ করার আশা করেন, তাহলে সম্ভবত আপনার MediaPlayer
ধরে রাখা উচিত যাতে এটি আবার তৈরি করা এবং প্রস্তুত করার ওভারহেড এড়ানো যায়।
আরও জানুন
Jetpack Media3 হল আপনার অ্যাপে মিডিয়া প্লেব্যাকের জন্য প্রস্তাবিত সমাধান। এটি সম্পর্কে আরও পড়ুন .
এই পৃষ্ঠাগুলি অডিও এবং ভিডিও রেকর্ডিং, সঞ্চয় করা এবং প্লে ব্যাক করা সম্পর্কিত বিষয়গুলি কভার করে: