Uygulamanız ekranda görünmediğinde bile (ör. kullanıcı diğer uygulamalarla etkileşimdeyken) medya oynatabilirsiniz.
Bunu yapmak için MediaPlayer'ı bir MediaBrowserServiceCompat
hizmetine yerleştirir ve başka bir etkinlikteki MediaBrowserCompat
ile etkileşime girmesini sağlarsınız.
Bu istemci ve sunucu kurulumunu uygularken dikkatli olun. Arka plan hizmetinde çalışan bir oynatıcının sistemin geri kalanıyla nasıl etkileşime geçtiğiyle ilgili beklentiler vardır. Uygulamanız bu beklentileri karşılamıyorsa kullanıcı kötü bir deneyim yaşayabilir. Ayrıntılar için İşitsel Uygulama Oluşturma başlıklı makaleyi inceleyin.
Bu sayfada, bir MediaPlayer'ı bir hizmetin içine uygularken yönetmeyle ilgili özel talimatlar açıklanmaktadır.
Eşzamansız olarak çalıştırma
Activity
gibi, Service
'teki tüm işlemler varsayılan olarak tek bir ileti dizisinde yapılır. Aslında, aynı uygulamadan bir etkinlik ve hizmet çalıştırdığınızda bunlar varsayılan olarak aynı iş parçacığı ("ana iş parçacığı") kullanır.
Hizmetler, gelen amaçları hızlı bir şekilde işlemeli ve bunlara yanıt verirken hiçbir zaman uzun hesaplamalar yapmamalıdır. Ağır işleri veya engelleyen çağrıları eşzamansız olarak yapmanız gerekir: Kendi uyguladığınız başka bir iş parçacığından veya çerçevenin eşzamansız işleme için sunduğu birçok olanağı kullanarak.
Örneğin, ana ileti dizisinizden MediaPlayer
kullanırken şunları yapmalısınız:
prepare()
yerineprepareAsync()
çağrısı yapın ve- Hazırlık tamamlandığında ve oynamaya başlayabildiğinizde bildirim almak için bir
MediaPlayer.OnPreparedListener
oluşturun.
Örnek:
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();
}
}
Eşzamansız hataları işleme
Eşzamanlı işlemlerde hatalar bir istisna veya hata koduyla işaretlenir. Ancak, asenkron kaynakları kullandığınızda uygulamanızı hataları uygun şekilde bilgilendirmeniz gerekir. MediaPlayer
durumunda, bir MediaPlayer.OnErrorListener
uygulayıp MediaPlayer
örneğinizde ayarlarsınız:
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!
}
}
Hata oluştuğunda MediaPlayer
Hata durumuna geçer. Yeniden kullanabilmek için sıfırlamanız gerekir. Ayrıntılar için MediaPlayer
sınıfının tam durum şemasına bakın.
Uyanık kalma kilitlerini kullanma
Arka planda müzik çalarken veya müzik akışı yaparken sistemin oynatma işleminize müdahale etmesini (ör. cihazı uyku moduna alarak) önlemek için uyanık kalma kilitlerini kullanmanız gerekir.
Uyandırma kilidi, uygulamanızın telefon boştayken bile kullanılabilecek özellikleri kullandığını sisteme bildiren bir sinyaldir.
MediaPlayer
oynatılırken CPU'nun çalışmaya devam etmesini sağlamak için MediaPlayer
'unuzu başlatırken setWakeMode()
yöntemini çağırın. MediaPlayer
, oynatma sırasında belirtilen kilidi tutar ve duraklatıldığında veya durdurulduğunda kilidi serbest bırakır:
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);
Ancak bu örnekte edinilen uyanık kalma kilidi yalnızca CPU'nun uyanık kalmasını sağlar. Ağ üzerinden medya aktarıyor ve kablosuz ağ kullanıyorsanız muhtemelen WifiLock
de almak istersiniz. Bu lisansı manuel olarak edinip bırakmanız gerekir. Bu nedenle, uzak URL ile MediaPlayer
'yi hazırlamaya başladığınızda kablosuz kilidi oluşturup edinmeniz gerekir.
Örnek:
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();
Medyanızı duraklattığınızda veya durdurduğunuzda ya da ağa artık ihtiyaç duymadığınızda kilidi açmanız gerekir:
Kotlin
wifiLock.release()
Java
wifiLock.release();
Temizleme işlemi gerçekleştirme
Daha önce de belirtildiği gibi, MediaPlayer
nesnesi önemli miktarda sistem kaynağı tüketebilir. Bu nedenle, nesneyi yalnızca ihtiyacınız olduğu sürece tutmalı ve işiniz bittiğinde release()
işlevini çağırmalısınız. Sistem çöp toplama işlemine güvenmek yerine bu temizleme yöntemini açıkça çağırmanız önemlidir. Bunun nedeni, çöp toplayıcının MediaPlayer
öğesini geri almasının biraz zaman alabilmesidir. Bunun nedeni, çöp toplayıcının yalnızca bellek ihtiyaçlarına duyarlı olması ve medyayla ilgili diğer kaynakların eksikliğine duyarlı olmamasıdır. Bu nedenle, bir hizmet kullanıyorsanız MediaPlayer
'i yayınladığınızdan emin olmak için her zaman onDestroy()
yöntemini geçersiz kılmanız gerekir:
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();
}
}
Kapatma sırasında yayınlamanın yanı sıra MediaPlayer
'inizi yayınlamak için her zaman başka fırsatlar arayın. Örneğin, uzun süre boyunca medya oynatamayacağınızı düşünüyorsanız (ör. ses odağını kaybettikten sonra) mevcut MediaPlayer
öğenizi mutlaka yayınlayın ve daha sonra tekrar oluşturun. Öte yandan, oynatmayı yalnızca çok kısa bir süre için durdurmayı planlıyorsanız yeniden oluşturma ve hazırlama masrafından kaçınmak için MediaPlayer
dosyanızı saklamanız önerilir.
Daha fazla bilgi
Uygulamanızda medya oynatma için önerilen çözüm Jetpack Media3'tür. Bu konu hakkında daha fazla bilgi edinin.
Bu sayfalarda ses ve video kaydetme, depolama ve oynatma ile ilgili konular ele alınmaktadır: