MediaPlayer'a genel bakış

Android multimedya çerçevesi, yaygın olarak kullanılan çeşitli medya türlerini oynatma desteği içerir, böylece ses, video ve resimleri uygulamalarınıza kolayca entegre edebilirsiniz. Uygulamanızın kaynaklarında (ham kaynaklar) depolanan medya dosyalarından, dosya sistemindeki bağımsız dosyalardan veya ağ bağlantısı üzerinden gelen bir veri akışından gelen ses veya video dosyalarını oynatabilirsiniz. Bunların tümü MediaPlayer API'lerini kullanır.

Bu belgede, iyi performans ve iyi bir kullanıcı deneyimi sağlamak amacıyla kullanıcı ve sistemle etkileşimde bulunan bir medya oynatma uygulaması yazmak için MediaPlayer özelliğinin nasıl kullanılacağı gösterilmektedir. Alternatif olarak, MediaPlayer bölgesinde bulunmayan yüksek performanslı özellikleri destekleyen özelleştirilebilir bir açık kaynak kitaplığı olan ExoPlayer'ı kullanabilirsiniz.

Not: Ses verilerini yalnızca standart çıkış cihazında çalabilirsiniz. Mevcut durumda bu, mobil cihaz hoparlörü veya Bluetooth mikrofonlu kulaklıktır. Arama sırasında konuşmadaki ses dosyalarını çalamazsınız.

Temel bilgiler

Android çerçevesinde ses ve video oynatmak için aşağıdaki sınıflar kullanılır:

MediaPlayer
Bu sınıf, ses ve video oynatmak için kullanılan birincil API'dir.
AudioManager
Bu sınıf, bir cihazdaki ses kaynaklarını ve ses çıkışını yönetir.

Manifest beyanları

MediaPlayer kullanarak uygulamanızda geliştirme işlemlerine başlamadan önce, manifest dosyanızda ilgili özelliklerin kullanımına izin veren uygun beyanların bulunduğundan emin olun.

  • İnternet İzni: Ağ tabanlı içerik akışı için MediaPlayer kullanıyorsanız uygulamanızın ağ erişimi istemesi gerekir.
    <uses-permission android:name="android.permission.INTERNET" />
    
  • Uyandırma Kilidi İzni: Oynatıcı uygulamanızın ekranın kararmasını veya işlemcinin uyku moduna girmesini engellemesi gerekiyorsa ya da MediaPlayer.setScreenOnWhilePlaying() ya da MediaPlayer.setWakeMode() yöntemlerini kullanıyorsa bu izni talep etmeniz gerekir.
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

MediaPlayer'ı kullanma

Medya çerçevesinin en önemli bileşenlerinden biri MediaPlayer sınıfıdır. Bu sınıftaki bir nesne, minimum kurulumla hem ses hem de videoyu getirebilir, kodunu çözebilir ve oynatabilir. Aşağıdakiler gibi birkaç farklı medya kaynağını destekler:

  • Yerel kaynaklar
  • İçerik Çözücü'den edinebileceğinizler gibi dahili URI'lar
  • Harici URL'ler (akış)

Android'in desteklediği medya biçimlerinin listesi için Desteklenen Medya Biçimleri sayfasına bakın.

Yerel ham kaynak olarak bulunan (uygulamanızın res/raw/ dizinine kaydedilir) sesin nasıl çalınacağını gösteren bir örneği aşağıda bulabilirsiniz:

Kotlin

var mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1)
mediaPlayer.start() // no need to call prepare(); create() does that for you

Java

MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you

Bu durumda "ham" kaynak, sistemin belirli bir şekilde ayrıştırmaya çalışmadığı bir dosyadır. Ancak bu kaynağın içeriği ham ses olmamalıdır. Desteklenen biçimlerden birinde düzgün şekilde kodlanmış ve biçimlendirilmiş bir medya dosyası olmalıdır.

Sistemde yerel olarak bulunan bir URI'dan (örneğin, İçerik Çözücü aracılığıyla edindiğiniz) şu şekilde oynatabilirsiniz:

Kotlin

val myUri: Uri = .... // initialize Uri here
val mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(applicationContext, myUri)
    prepare()
    start()
}

Java

Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();

HTTP akışı aracılığıyla uzak bir URL'den oynatma aşağıdaki gibi görünür:

Kotlin

val url = "http://........" // your URL here
val mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(url)
    prepare() // might take long! (for buffering, etc)
    start()
}

Java

String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();

Not: Online medya dosyası akışı için bir URL iletiyorsanız dosya aşamalı olarak indirilebilmelidir.

Dikkat: Referans verdiğiniz dosya var olmayabileceği için setDataSource() kullanırken IllegalArgumentException ve IOException öğelerini yakalamanız veya geçmeniz gerekir.

Eşzamansız hazırlık

MediaPlayer kullanımı prensip olarak basit olabilir. Ancak, uygulamayı tipik bir Android uygulamasıyla doğru bir şekilde entegre etmek için birkaç şeyin daha olması gerektiğini unutmamak gerekir. Örneğin, prepare() çağrısının yürütülmesi medya verilerinin getirilmesini ve kodunun çözülmesini içerebileceğinden bu çağrının yürütülmesi uzun sürebilir. Bu nedenle, yürütülmesi uzun sürebilecek tüm yöntemlerde olduğu gibi, bu yöntemi asla uygulamanızın kullanıcı arayüzü iş parçacığından çağırmamalısınız. Bu işlem, kullanıcı arayüzünün yöntem geri gelene kadar beklemesine neden olur. Bu da çok kötü bir kullanıcı deneyimi oluşturur ve ANR (Uygulama Yanıt Vermiyor) hatasına neden olabilir. Kaynağınızın hızlı yüklenmesini bekleseniz bile, kullanıcı arayüzünde yanıt vermesi saniyenin onda birinden uzun süren herhangi bir özelliğin fark edilir bir duraklamaya neden olacağını ve kullanıcıya uygulamanızın yavaş olduğu izlenimi vereceğini unutmayın.

Kullanıcı arayüzü iş parçacığınızı askıya almaktan kaçınmak için MediaPlayer'yi hazırlamak ve tamamlandığında ana iş parçacığına bildirmek üzere başka bir iş parçacığı oluşturun. Bununla birlikte, iş parçacığı mantığını kendiniz yazabilirsiniz ancak bu kalıp MediaPlayer kullanılırken o kadar yaygındır ki çerçeve, bu görevi prepareAsync() yöntemini kullanarak gerçekleştirmek için kolay bir yol sağlar. Bu yöntem, medyayı arka planda hazırlamaya başlar ve hemen geri döner. Medyanın hazırlanması bittiğinde, setOnPreparedListener() ile yapılandırılan MediaPlayer.OnPreparedListener onPrepared() yöntemi çağrılır.

Yönetici durumu

MediaPlayer ile ilgili göz önünde bulundurmanız gereken diğer bir nokta, eyalet temelli olmasıdır. Yani MediaPlayer, kodunuzu yazarken her zaman bilmeniz gereken dahili bir duruma sahiptir. Çünkü belirli işlemler yalnızca oynatıcı belirli durumlardayken geçerlidir. Bir işlemi yanlış durumdayken gerçekleştirirseniz sistem bir istisna oluşturabilir veya başka istenmeyen davranışlara neden olabilir.

MediaPlayer sınıfındaki dokümanlarda, hangi yöntemlerin MediaPlayer öğesini bir durumdan diğerine taşıdığını açıklayan eksiksiz bir durum diyagramı gösterilir. Örneğin, yeni bir MediaPlayer oluşturduğunuzda bu öğe Boşta durumunda olur. Bu noktada setDataSource() yöntemini çağırarak başlatabilir ve Başlatıldı durumuna getirin. Daha sonra, prepare() veya prepareAsync() yöntemini kullanarak hazırlamanız gerekir. MediaPlayer hazırlama işlemini tamamladığında Hazırlandı durumuna geçer. Bu, medyayı oynatması için start() çağırabileceğiniz anlamına gelir. Bu noktada şemanın da gösterdiği gibi, diğer yöntemler arasında start(), pause() ve seekTo() gibi yöntemleri çağırarak Başlatıldı, Duraklatıldı ve Oynatma Tamamlandı durumları arasında geçiş yapabilirsiniz. Ancak stop() numaralı telefonu aradığınızda, MediaPlayer kodunu yeniden hazırlayana kadar start() öğesini tekrar çağıramayacağınızı unutmayın.

Bir MediaPlayer nesnesiyle etkileşimde bulunan kod yazarken durum diyagramını her zaman aklınızda bulundurun. Hataların yaygın nedenlerinden birinin yöntemlerini yanlış durumda çağırmaktır.

MediaPlayer'ı serbest bırakma

MediaPlayer, değerli sistem kaynaklarını tüketebilir. Bu nedenle, bir MediaPlayer örneğini gereğinden uzun süre kullanmamak için her zaman ekstra önlemler almanız gerekir. Bu işlemi tamamladığınızda kendisine ayrılan sistem kaynaklarının düzgün bir şekilde serbest bırakıldığından emin olmak için her zaman release() yöntemini çağırmalısınız. Örneğin, MediaPlayer kullanıyorsanız ve etkinliğiniz onStop() çağrısı alırsa MediaPlayer özelliğini serbest bırakmanız gerekir. Zira etkinliğiniz, kullanıcıyla etkileşim kurmadığında (arka planda medya oynatmıyorsanız, bu konu bir sonraki bölümde ele alınmaktadır). Etkinliğiniz devam ettirildiğinde veya yeniden başlatıldığında, elbette yeni bir MediaPlayer oluşturmanız ve oynatmayı devam ettirmeden önce tekrar hazırlamanız gerekir.

MediaPlayer aboneliğinizi iptal etmek ve ardından geçersiz kılmak için aşağıdaki adımları uygulayın:

Kotlin

mediaPlayer?.release()
mediaPlayer = null

Java

mediaPlayer.release();
mediaPlayer = null;

Örnek olarak, etkinliğiniz durdurulduğunda MediaPlayer öğesini serbest bırakmayı unutursanız ve etkinlik tekrar başladığında yeni bir sorun oluşturursanız ortaya çıkabilecek sorunları düşünün. Bildiğiniz gibi, kullanıcı ekran yönünü değiştirdiğinde (veya cihaz yapılandırmasını başka bir şekilde değiştirdiğinde) sistem, etkinliği yeniden başlatarak bu işlemi gerçekleştirir (varsayılan olarak). Bu nedenle, kullanıcı cihazı dikey ve yatay arasında döndürdüğünde tüm sistem kaynaklarını hızla tüketebilirsiniz. Bunun nedeni, her yön değişiminde asla serbest bırakmadığınız yeni bir MediaPlayer oluşturmanızdır. (Çalışma zamanı yeniden başlatmaları hakkında daha fazla bilgi için Çalışma Zamanı Değişikliklerini İşleme konusuna bakın.)

Yerleşik Müzik uygulamasının davranışı gibi, kullanıcı etkinliğinizden ayrıldığında bile "arka plan medyasını" oynatmaya devam etmek istediğinizde ne olacağını merak ediyor olabilirsiniz. Bu durumda, bir sonraki bölümde açıklandığı gibi, bir Hizmet tarafından kontrol edilen bir MediaPlayer gerekir

MediaPlayer'ı bir hizmette kullanma

Medyanızın uygulamanız ekranda olmadığında bile arka planda oynatılmasını, yani kullanıcı diğer uygulamalarla etkileşimde bulunurken oynatmaya devam etmesini istiyorsanız bir Hizmeti başlatmanız ve MediaPlayer örneğini buradan kontrol etmeniz gerekir. MediaPlayer'ı bir MediaBrowserServiceCompat hizmetine yerleştirmeniz ve başka bir etkinlikteki MediaBrowserCompat ile etkileşim kurmasını sağlamanız gerekir.

Bu istemci/sunucu kurulumu konusunda dikkatli olmalısınız. 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şılamazsa kullanıcı kötü bir deneyim yaşayabilir. Tüm ayrıntılar için Ses Uygulaması Oluşturma bölümünü okuyun.

Bu bölümde, bir hizmetin içinde uygulandığında MediaPlayer'ın yönetilmesine ilişkin özel talimatlar açıklanmaktadır.

Eşzamansız olarak çalıştırma

Öncelikle, Activity gibi, bir Service öğesindeki tüm işler varsayılan olarak tek bir iş parçacığında gerçekleştirilir. Hatta aynı uygulamadan bir etkinlik ve hizmet çalıştırıyorsanız bunlar varsayılan olarak aynı iş parçacığını ("ana iş parçacığı") kullanır. Bu nedenle, hizmetlerin gelen niyetleri hızlı bir şekilde işlemesi ve yanıt verirken asla uzun hesaplamalar yapmaması gerekir. Herhangi bir ağır iş veya engelleme çağrısı olması gerekiyorsa bu görevleri, kendi uyguladığınız başka bir iş parçacığından veya çerçevenin eşzamansız işleme için birçok olanağını kullanarak eşzamansız olarak gerçekleştirmeniz gerekir.

Örneğin, ana iş parçanızdan bir MediaPlayer kullanırken prepare() yerine prepareAsync() çağrısı yapmanız ve hazırlık tamamlandığında bildirim almak, ardından oynamaya başlayabilmek için MediaPlayer.OnPreparedListener uygulamanız gerekir. Örneğin:

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, normalde bir istisna veya hata kodu ile hatalara işaret edilir. Ancak eşzamansız kaynakları her kullandığınızda uygulamanıza hataların uygun şekilde bildirildiğinden emin olmanız gerekir. MediaPlayer kullanıyorsanız bu işlemi, MediaPlayer.OnErrorListener uygulayıp MediaPlayer örneğinize ayarlayarak yapabilirsiniz:

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!
    }
}

Bir hata meydana geldiğinde MediaPlayer öğesinin Hata durumuna geçtiğini unutmayın (tam durum şeması için MediaPlayer sınıfının dokümanlarına bakın) ve tekrar kullanmadan önce durumu sıfırlamanız gerekir.

Uyanık kalma kilitlerini kullanma

Arka planda medya oynatan uygulamalar tasarlarken, hizmetiniz çalışırken cihaz uyku moduna geçebilir. Android sistemi, cihaz uyku sırasında pil tasarrufu yapmaya çalıştığından CPU ve kablosuz donanım gibi telefonun gerekli olmayan özelliklerini kapanmaya çalışır. Ancak hizmetiniz müzik çalıyor veya canlı çalıyorsa sistemin çalmanıza müdahale etmesini önlemek istersiniz.

Hizmetinizin bu koşullar altında çalışmaya devam etmesini sağlamak için "uyanık kalma kilitleri" kullanmanız gerekir. Uyanık kalma kilidi, telefon boşta olsa bile uygulamanızın kullanılabilir durumda kalması gereken bir özellik kullandığını sisteme bildirmenin bir yoludur.

Not: Uyanık kalma kilitlerini her zaman dikkatli bir şekilde kullanmalı ve cihazın pil ömrünü önemli ölçüde kısalttığından, yalnızca gerçekten gerekli olduğu süre boyunca tutmalısınız.

MediaPlayer çalışırken CPU'nun çalışmaya devam etmesini sağlamak için MediaPlayer cihazınızı başlatırken setWakeMode() yöntemini çağırın. Bunu yaptığınızda, MediaPlayer oyun sırasında belirtilen kilidi tutar ve duraklatıldığında veya durduğunda kilidi açar:

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 alınan uyanık kalma kilidi yalnızca CPU'nun uyanık kalmasını garanti eder. Ağ üzerinden medya akışı gerçekleştiriyorsanız ve kablosuz ağ kullanıyorsanız muhtemelen bir WifiLock bulundurmak da iyi bir fikir olabilir. Bunları manuel olarak alıp yayınlamanız gerekir. Bu nedenle, MediaPlayer öğesini uzak URL ile hazırlamaya başladığınızda kablosuz ağ kilidini oluşturup edinmeniz gerekir. Örneğin:

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 ihtiyacınız olmadığında kilidi bırakmanız gerekir:

Kotlin

wifiLock.release()

Java

wifiLock.release();

Temizlik işlemi gerçekleştiriliyor

Daha önce de belirtildiği gibi, MediaPlayer nesnesi önemli miktarda sistem kaynağını tüketebilir. Bu nedenle, nesneyi ihtiyacınız olduğu sürece saklamalı ve işiniz bittiğinde release() kodunu çağırmalısınız. Sistemin atık toplama yöntemini kullanmak yerine bu temizleme yöntemini açıkça çağırmak önemlidir. Çünkü çöp toplayıcının MediaPlayer öğesini geri toplaması biraz zaman alabilir. Çünkü bu yöntem yalnızca bellek ihtiyaçlarına karşı hassastır ve medyayla ilgili diğer kaynakların yetersizliğini dikkate almaz. Bu nedenle, bir hizmet kullanırken MediaPlayer öğesini serbest bıraktığı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();
   }
}

MediaPlayer cihazınızı kapatırken yayınlama dışında her zaman diğer fırsatları da aramalısınız. Örneğin, uzun süre medya oynatamayı düşünüyorsanız (örneğin, ses odağını kaybettikten sonra) mevcut MediaPlayer öğenizi kesinlikle serbest bırakmalı ve daha sonra tekrar oluşturmanız gerekir. Öte yandan, oynatmayı yalnızca çok kısa bir süre için durdurmayı düşünüyorsanız tekrar oluşturma ve hazırlama ek yükünden kaçınmak için MediaPlayer cihazınızı beklemelisiniz.

Dijital Hak Yönetimi (DRM)

Android 8.0 (API düzeyi 26) sürümünden başlayarak MediaPlayer, DRM korumalı materyalin oynatılmasını destekleyen API'ler içerir. Bunlar, MediaDrm tarafından sağlanan alt seviye API'ye benzer ancak daha yüksek düzeyde çalışır ve temel ayıklayıcı, drm ve şifreleme nesnelerini açığa çıkarmaz.

MediaPlayer DRM API, MediaDrm ürününün tüm işlevlerini sunmasa da en yaygın kullanım alanlarını destekler. Mevcut uygulama aşağıdaki içerik türlerini işleyebilir:

  • Widevine korumalı yerel medya dosyaları
  • Widevine korumalı uzak/akış medya dosyaları

Aşağıdaki kod snippet'i, yeni DRM MediaPlayer yöntemlerinin basit bir eşzamanlı uygulamada nasıl kullanılacağını gösterir.

DRM kontrollü medyayı yönetmek için aşağıda gösterildiği gibi, MediaPlayer çağrılarının normal akışının yanı sıra yeni yöntemleri de eklemeniz gerekir:

Kotlin

mediaPlayer?.apply {
    setDataSource()
    setOnDrmConfigHelper() // optional, for custom configuration
    prepare()
    drmInfo?.also {
        prepareDrm()
        getKeyRequest()
        provideKeyResponse()
    }

    // MediaPlayer is now ready to use
    start()
    // ...play/pause/resume...
    stop()
    releaseDrm()
}

Java

setDataSource();
setOnDrmConfigHelper(); // optional, for custom configuration
prepare();
if (getDrmInfo() != null) {
  prepareDrm();
  getKeyRequest();
  provideKeyResponse();
}

// MediaPlayer is now ready to use
start();
// ...play/pause/resume...
stop();
releaseDrm();

MediaPlayer nesnesini başlatarak ve her zamanki gibi setDataSource() kullanarak kaynağını ayarlayarak başlayın. Ardından, DRM'yi kullanmak için aşağıdaki adımları uygulayın:

  1. Uygulamanızın özel yapılandırma yapmasını istiyorsanız bir OnDrmConfigHelper arayüzü tanımlayın ve setOnDrmConfigHelper() kullanarak oynatıcıya ekleyin.
  2. Şu numaraya telefon et: prepare().
  3. Şu numaraya telefon et: getDrmInfo(). Kaynakta DRM içeriği varsa yöntem, boş olmayan bir MediaPlayer.DrmInfo değeri döndürür.

MediaPlayer.DrmInfo varsa:

  1. Kullanılabilir UUID eşlemesini inceleyin ve bir tane seçin.
  2. prepareDrm() yöntemini çağırarak geçerli kaynak için DRM yapılandırmasını hazırlayın.
    • Bir OnDrmConfigHelper geri çağırması oluşturup kaydettiyseniz bu geri çağırma, prepareDrm() yürütülürken çağrılır. Bu şekilde, DRM oturumunu açmadan önce DRM özellikleri için özel yapılandırma işlemi gerçekleştirebilirsiniz. Geri çağırma, prepareDrm() adlı iş parçacığında eşzamanlı olarak çağrılır. DRM özelliklerine erişmek için getDrmPropertyString() ve setDrmPropertyString() çağrısı yapın. Uzun süren işlemler yapmaktan kaçının.
    • Cihazın temel hazırlığı henüz yapılmadıysa prepareDrm(), cihazın temel hazırlığını yapmak için temel hazırlık sunucusuna da erişir. Bu işlem, ağ bağlantısına bağlı olarak değişebilir.
  3. Lisans sunucusuna gönderilecek bir opak anahtar isteği bayt dizisi almak için getKeyRequest() çağrısı yapın.
  4. Lisans sunucusundan alınan anahtar yanıtı hakkında DRM motoruna bilgi vermek için provideKeyResponse() numaralı telefonu arayın. Sonuç, anahtar isteğinin türüne bağlıdır:
    • Yanıt çevrimdışı anahtar isteği içinse sonuç, anahtar ayarı tanımlayıcısı olur. Anahtarları yeni bir oturuma geri yüklemek için bu anahtar grubu tanımlayıcısını restoreKeys() ile kullanabilirsiniz.
    • Yanıt bir akış veya yayın isteği içinse sonuç boş olur.

prepareDrm() eşzamansız olarak çalıştırma

Varsayılan olarak prepareDrm() eşzamanlı şekilde çalışır ve hazırlık tamamlanana kadar engelleme yapar. Bununla birlikte, yeni bir cihazda ilk DRM hazırlığı da gerekebilir. Temel hazırlık, prepareDrm() tarafından dahili olarak gerçekleştirilir ve ilgili ağ işlemi nedeniyle tamamlanması biraz zaman alabilir. MediaPlayer.OnDrmPreparedListener tanımlayıp ayarlayarak prepareDrm() ürününde engellemenin önüne geçebilirsiniz.

Bir OnDrmPreparedListener ayarladığınızda prepareDrm(), temel hazırlığı (gerekirse) ve hazırlığı arka planda gerçekleştirir. Temel hazırlık ve hazırlık sona erdiğinde dinleyici çağrılır. İşleyici bir işleyici iş parçacığına kayıtlı değilse çağrı sırası veya işleyicinin çalıştığı iş parçacığı hakkında herhangi bir varsayımda bulunmamalısınız. İşleyici, prepareDrm() geri dönmesinden önce veya sonra çağrılabilir.

DRM'yi eşzamansız olarak ayarlama

DRM'yi hazırlamak için MediaPlayer.OnDrmInfoListener, oynatıcıyı başlatmak için de MediaPlayer.OnDrmPreparedListener oluşturup kaydederek DRM'yi eşzamansız olarak başlatabilirsiniz. Bunlar aşağıda gösterildiği gibi prepareAsync() ile birlikte çalışır:

Kotlin

setOnPreparedListener()
setOnDrmInfoListener()
setDataSource()
prepareAsync()
// ...

// If the data source content is protected you receive a call to the onDrmInfo() callback.
override fun onDrmInfo(mediaPlayer: MediaPlayer, drmInfo: MediaPlayer.DrmInfo) {
    mediaPlayer.apply {
        prepareDrm()
        getKeyRequest()
        provideKeyResponse()
    }
}

// When prepareAsync() finishes, you receive a call to the onPrepared() callback.
// If there is a DRM, onDrmInfo() sets it up before executing this callback,
// so you can start the player.
override fun onPrepared(mediaPlayer: MediaPlayer) {
    mediaPlayer.start()
}

Java

setOnPreparedListener();
setOnDrmInfoListener();
setDataSource();
prepareAsync();
// ...

// If the data source content is protected you receive a call to the onDrmInfo() callback.
onDrmInfo() {
  prepareDrm();
  getKeyRequest();
  provideKeyResponse();
}

// When prepareAsync() finishes, you receive a call to the onPrepared() callback.
// If there is a DRM, onDrmInfo() sets it up before executing this callback,
// so you can start the player.
onPrepared() {

start();
}

Şifrelenmiş medyayı işleme

MediaPlayer, Android 8.0'dan (API düzeyi 26) başlayarak H.264 ve AAC temel akış türleri için Ortak Şifreleme Şeması (CENC) ve HLS örnek düzeyinde şifrelenmiş medyanın (METHOD=SAMPLE-AES) şifresini de çözebilir. Tam segmentli şifrelenmiş medya (METHOD=AES-128) daha önce destekleniyordu.

ContentSolutionr'dan medya alma

Bir medya oynatıcı uygulamasında yararlı olabilecek başka bir özellik de kullanıcının cihazındaki müzikleri alabilmesidir. Bunu, ContentResolver içinde harici medya için sorgulayarak yapabilirsiniz:

Kotlin

val resolver: ContentResolver = contentResolver
val uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val cursor: Cursor? = resolver.query(uri, null, null, null, null)
when {
    cursor == null -> {
        // query failed, handle error.
    }
    !cursor.moveToFirst() -> {
        // no media on the device
    }
    else -> {
        val titleColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE)
        val idColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID)
        do {
            val thisId = cursor.getLong(idColumn)
            val thisTitle = cursor.getString(titleColumn)
            // ...process entry...
        } while (cursor.moveToNext())
    }
}
cursor?.close()

Java

ContentResolver contentResolver = getContentResolver();
Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor == null) {
    // query failed, handle error.
} else if (!cursor.moveToFirst()) {
    // no media on the device
} else {
    int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
    int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
    do {
       long thisId = cursor.getLong(idColumn);
       String thisTitle = cursor.getString(titleColumn);
       // ...process entry...
    } while (cursor.moveToNext());
}

Bu özelliği MediaPlayer ile birlikte kullanmak için şunları yapabilirsiniz:

Kotlin

val id: Long = /* retrieve it from somewhere */
val contentUri: Uri =
    ContentUris.withAppendedId(android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id )

mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(applicationContext, contentUri)
}

// ...prepare and start...

Java

long id = /* retrieve it from somewhere */;
Uri contentUri = ContentUris.withAppendedId(
        android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);

mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(getApplicationContext(), contentUri);

// ...prepare and start...

Daha fazla bilgi

Bu sayfalarda ses ve video kaydetme, depolama ve oynatmayla ilgili konular ele alınmaktadır.