Medyayı arka planda oynatın

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:

Ö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: