आपके पास बैकग्राउंड में मीडिया चलाने का विकल्प होता है. भले ही, आपका ऐप्लिकेशन स्क्रीन पर न हो. उदाहरण के लिए, जब उपयोगकर्ता दूसरे ऐप्लिकेशन का इस्तेमाल कर रहा हो.
ऐसा करने के लिए, MediaPlayer को MediaBrowserServiceCompat
सेवा में एम्बेड करें और किसी दूसरी गतिविधि में MediaBrowserCompat
के साथ इंटरैक्ट करें.
क्लाइंट और सर्वर के इस सेटअप को लागू करते समय सावधानी बरतें. बैकग्राउंड सेवा में चल रहे प्लेयर के बाकी सिस्टम के साथ इंटरैक्ट करने के तरीके के बारे में उम्मीदें होती हैं. अगर आपका ऐप्लिकेशन उन उम्मीदों पर खरा नहीं उतरता है, तो उपयोगकर्ता को खराब अनुभव मिल सकता है. ज़्यादा जानकारी के लिए, ऑडियो ऐप्लिकेशन बनाना लेख पढ़ें.
इस पेज पर, किसी सेवा में MediaPlayer को लागू करने पर, उसे मैनेज करने के लिए खास निर्देश दिए गए हैं.
एसिंक्रोनस तरीके से चलाना
Activity
की तरह ही, Service
में भी डिफ़ॉल्ट रूप से, सभी काम एक ही थ्रेड में किए जाते हैं. असल में, जब एक ही ऐप्लिकेशन से कोई ऐक्टिविटी और सेवा चलाई जाती है, तो वे डिफ़ॉल्ट रूप से एक ही थ्रेड ("मुख्य थ्रेड") का इस्तेमाल करती हैं.
सेवाओं को आने वाले इंटेंट को तुरंत प्रोसेस करना चाहिए. साथ ही, उनका जवाब देते समय लंबे समय तक कैलकुलेशन नहीं करना चाहिए. आपको किसी भी तरह का भारी काम या कॉल को ब्लॉक करने की प्रोसेस, एसिंक्रोनस तरीके से करनी होगी. इसके लिए, खुद से बनाई गई किसी थ्रेड का इस्तेमाल करें या एसिंक्रोनस प्रोसेसिंग के लिए, फ़्रेमवर्क की कई सुविधाओं का इस्तेमाल करें.
उदाहरण के लिए, मुख्य थ्रेड से MediaPlayer
का इस्तेमाल करते समय, आपको:
prepare()
के बजायprepareAsync()
को कॉल करें औरMediaPlayer.OnPreparedListener
लागू करें, ताकि आपको सूचना मिल सके कि तैयारी पूरी हो गई है और गेम खेला जा सकता है.
उदाहरण के लिए:
Kotlin
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()
}
}
Java
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
इंस्टेंस में सेट करें:
Kotlin
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!
}
}
Java
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
चलने के दौरान सीपीयू काम करता रहे, MediaPlayer
को शुरू करते समय setWakeMode()
तरीके को कॉल करें. वीडियो चलाने के दौरान, MediaPlayer
बटन से लॉक किया जा सकता है. वीडियो रोकने या बंद करने पर, लॉक हट जाता है:
Kotlin
mediaPlayer = MediaPlayer().apply {
// ... other initialization here ...
setWakeMode(applicationContext, PowerManager.PARTIAL_WAKE_LOCK)
}
Java
mediaPlayer = new MediaPlayer();
// ... other initialization here ...
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
हालांकि, इस उदाहरण में हासिल किया गया वेक लॉक सिर्फ़ यह पक्का करता है कि सीपीयू चालू रहे. अगर नेटवर्क पर मीडिया स्ट्रीम किया जा रहा है और वाई-फ़ाई का इस्तेमाल किया जा रहा है, तो हो सकता है कि आप WifiLock
को भी होल्ड करना चाहें. इसे मैन्युअल तरीके से हासिल और रिलीज़ करना होगा. इसलिए, जब रिमोट यूआरएल की मदद से MediaPlayer
को तैयार करना शुरू करें, तो आपको वाई-फ़ाई लॉक बनाना और उसे हासिल करना चाहिए.
उदाहरण के लिए:
Kotlin
val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiLock: WifiManager.WifiLock =
wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock")
wifiLock.acquire()
Java
WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
wifiLock.acquire();
मीडिया को रोकने या बंद करने पर या जब आपको नेटवर्क की ज़रूरत न हो, तो आपको लॉक को हटा देना चाहिए:
Kotlin
wifiLock.release()
Java
wifiLock.release();
क्लीनअप करना
जैसा कि हमने पहले बताया था, MediaPlayer
ऑब्जेक्ट, सिस्टम के काफ़ी संसाधनों का इस्तेमाल कर सकता है. इसलिए, आपको इसे सिर्फ़ तब तक रखना चाहिए, जब तक आपको इसकी ज़रूरत है. साथ ही, काम पूरा होने के बाद release()
को कॉल करें. सिस्टम के गै़रबेज कलेक्शन पर भरोसा करने के बजाय, यह ज़रूरी है कि आप साफ़ तौर पर इस क्लीनअप तरीके को कॉल करें. ऐसा इसलिए, क्योंकि गै़रबेज कलेक्टर को MediaPlayer
वापस पाने में कुछ समय लग सकता है. ऐसा इसलिए, क्योंकि यह सिर्फ़ मेमोरी की ज़रूरतों के हिसाब से काम करता है, न कि मीडिया से जुड़े अन्य संसाधनों की कमी के हिसाब से. इसलिए, किसी सेवा का इस्तेमाल करने पर, आपको हमेशा onDestroy()
तरीके को बदल देना चाहिए. इससे यह पक्का किया जा सकता है कि MediaPlayer
को रिलीज़ किया जा रहा है:
Kotlin
class MyService : Service() {
private var mediaPlayer: MediaPlayer? = null
// ...
override fun onDestroy() {
super.onDestroy()
mediaPlayer?.release()
}
}
Java
public class MyService extends Service {
MediaPlayer mediaPlayer;
// ...
@Override
public void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) mediaPlayer.release();
}
}
आपको हमेशा अपने MediaPlayer
को रिलीज़ करने के अन्य मौके भी ढूंढने चाहिए. ऐसा, ऐप्लिकेशन बंद होने के समय ही नहीं, बल्कि अन्य समय में भी किया जा सकता है. उदाहरण के लिए, अगर आपको लगता है कि ऑडियो फ़ोकस हटने के बाद, लंबे समय तक मीडिया नहीं चलाया जा सकेगा, तो आपको अपने मौजूदा MediaPlayer
को रिलीज़ करना चाहिए और बाद में फिर से बनाना चाहिए. दूसरी ओर, अगर आपको वीडियो चलाना सिर्फ़ कुछ समय के लिए रोकना है, तो MediaPlayer
को न हटाएं. ऐसा करने से, आपको फिर से वीडियो बनाने और उसे तैयार करने में लगने वाले समय और ऊर्जा की बचत होगी.
ज़्यादा जानें
आपके ऐप्लिकेशन में मीडिया चलाने के लिए, Jetpack Media3 का सुझाव दिया जाता है. इसके बारे में ज़्यादा पढ़ें.
इन पेजों पर, ऑडियो और वीडियो रिकॉर्ड करने, सेव करने, और चलाने से जुड़े विषयों के बारे में बताया गया है: