Platforma multimedialna Androida zapewnia obsługę odtwarzania różnych popularnych typów multimediów,
aby łatwo zintegrować dźwięk, wideo i obrazy z aplikacjami. Możesz odtworzyć dźwięk lub
wideo z plików multimedialnych przechowywanych w zasobach aplikacji (nieprzetworzone zasoby) z samodzielnych plików
w systemie plików lub ze strumienia danych przychodzącego przez połączenie sieciowe – a wszystko to przy użyciu interfejsów API MediaPlayer
.
Z tego dokumentu dowiesz się, jak korzystać
MediaPlayer
, aby zapisać informacje o odtwarzaniu multimediów
współdziała z użytkownikiem i systemem w celu zapewnienia dobrej wydajności
i komfort użytkowania. Możesz też spróbować
używa ExoPlayer – oprogramowania open source, które możesz dostosować
biblioteka obsługująca funkcje o wysokiej wydajności niedostępne w MediaPlayer
Uwaga: dane audio możesz odtworzyć tylko na standardowym wyjściem wyjściowym. urządzenia. Obecnie jest to głośnik urządzenia mobilnego lub zestaw słuchawkowy Bluetooth. Nie można odtworzyć dźwięku plików w dźwięku rozmowy podczas połączenia.
Podstawy
Do odtwarzania dźwięku i filmu w platformie Androida używane są te klasy:
MediaPlayer
- Ta klasa jest podstawowym interfejsem API do odtwarzania dźwięku i wideo.
AudioManager
- Te zajęcia służą do zarządzania źródłami dźwięku i wyjściem audio na urządzeniu.
Deklaracje w pliku manifestu
Zanim rozpoczniesz programowanie aplikacji przy użyciu MediaPlayer, upewnij się, że w pliku manifestu odpowiednie deklaracje umożliwiające korzystanie z powiązanych funkcji.
- Uprawnienia internetowe – jeśli używasz odtwarzacza MediaPlayer do strumieniowego odtwarzania treści
treści, aplikacja musi żądać dostępu do sieci.
<uses-permission android:name="android.permission.INTERNET" />
- Uprawnienia do blokady uśpienia – jeśli aplikacja odtwarzacza musi trzymać ekran
przed przyciemnieniem lub uśpieniem procesora albo używa funkcji
MediaPlayer.setScreenOnWhilePlaying()
lubMediaPlayer.setWakeMode()
, musisz poprosić o to uprawnienie.<uses-permission android:name="android.permission.WAKE_LOCK" />
Korzystanie z MediaPlayer
Jednym z najważniejszych
elementów struktury medialnej jest
MediaPlayer
zajęcia. Obiekt tej klasy może pobierać, dekodować i odtwarzać dźwięk i obraz
przy minimalnej konfiguracji. Obsługuje kilka różnych źródeł mediów, takich jak:
- Zasoby lokalne
- wewnętrzne identyfikatory URI, np. uzyskane z programu do rozpoznawania treści.
- Zewnętrzne adresy URL (strumieniowanie)
Lista formatów multimediów obsługiwanych przez Androida: zobacz Obsługiwane multimedia Formaty.
Oto przykład:
odtwarzania dźwięku, który jest dostępny jako lokalny, nieprzetworzony zasób (zapisany w pliku
res/raw/
):
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
W tym przypadku plik „raw” Zasób to plik, którego system nie analizować w jakikolwiek sposób. Zawartość tego zasobu nie powinna jednak czy nieprzetworzony dźwięk. Powinien to być prawidłowo zakodowany i sformatowany plik multimedialny w jednym z obsługiwanych formatów.
Oto jak można odtworzyć z identyfikatora URI dostępnego lokalnie w systemie (np. uzyskane za pomocą programu do rozpoznawania treści):
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();
Odtwarzanie ze zdalnego adresu URL w ramach strumieniowego przesyłania danych HTTP wygląda tak:
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();
Uwaga: Jeśli przekazujesz adres URL do strumieniowego przesyłania pliku multimedialnego online, plik musi mieć możliwość pobieranie progresywne.
Uwaga: musisz złapać lub zdać.
IllegalArgumentException
i IOException
, gdy używasz
setDataSource()
, ponieważ
plik, do którego się odwołujesz, może nie istnieć.
Przygotowanie asynchroniczne
Korzystanie z usługi MediaPlayer
jest proste w:
tej zasady. Trzeba jednak pamiętać, że
niezbędne do jego prawidłowej integracji z typową aplikacją na Androida. Dla:
na przykład wywołanie prepare()
może
ich realizacja może zająć dużo czasu,
może wymagać pobrania i dekodowania danych multimedialnych. Podobnie jak w przypadku innych firm,
której wykonanie może zająć dużo czasu, nigdy nie wywoływać jej na stronie
wątku UI aplikacji. Interfejs powoduje wtedy zawieszanie się interfejsu do czasu zwrócenia metody.
co jest bardzo złym doświadczeniem dla użytkowników i może powodować błąd ANR (Aplikacja nie odpowiada). Nawet jeśli
spodziewasz się szybkiego ładowania zasobu, pamiętaj, że wszystko, co zajmuje więcej niż 1/10
na odpowiedź interfejsu użytkownika trwa dłużej niż sekundę, co powoduje wyraźną przerwę i daje
że aplikacja działa wolno.
Aby uniknąć zawieszenia wątku interfejsu użytkownika, utwórz kolejny wątek,
przygotuj MediaPlayer
, a gdy skończysz, powiadom wątek główny. Chociaż jednak
możesz napisać logikę tworzenia wątków
ten wzorzec jest tak powszechny w przypadku korzystania z interfejsu MediaPlayer
, że platforma
zapewnia wygodny sposób na wykonanie tego zadania przy użyciu
Metoda prepareAsync()
. Ta metoda
rozpoczyna przygotowywanie multimediów w tle i zwraca się natychmiast. Gdy media
zakończy się przygotowanie, onPrepared()
metody MediaPlayer.OnPreparedListener
, konfigurowanej przez
Funkcja setOnPreparedListener()
jest wywoływana.
Stan zarządzania
Kolejnym aspektem MediaPlayer
, o którym warto pamiętać, jest:
że bazuje na stanach. Oznacza to, że MediaPlayer
ma stan wewnętrzny
o czym należy pamiętać podczas pisania kodu, ponieważ niektóre operacje
działają tylko wtedy, gdy odtwarzacz jest w określonych stanach. Jeśli wykonujesz operację w
nieprawidłowy stan, system może zgłosić wyjątek lub wywołać inne niepożądane zachowania.
Dokumentacja w
Klasa MediaPlayer
pokazuje kompletny diagram stanu,
wyjaśniające, które metody przenoszenia elementu MediaPlayer
z jednego stanu do innego.
Gdy na przykład tworzysz nowy element MediaPlayer
, znajduje się on w stanie Nieaktywny
stanu. W tym momencie należy zainicjować go, wywołując
Pobieram setDataSource()
do stanu Zainicjowano. Potem trzeba będzie przygotować ją za pomocą
prepare()
lub
Metoda prepareAsync()
. Kiedy
Gdy MediaPlayer
jest gotowy, trafia do sekcji Prepared (Przygotowane)
w tym stanie, co oznacza, że możesz zadzwonić pod numer start()
w celu odtwarzania multimediów. W tym momencie, jak widać na schemacie,
można przełączać między stanami Rozpoczęte, Wstrzymane i Odtwarzanie ukończone.
wywołujących takie metody, jak
start()
,
pause()
i
seekTo()
,
między innymi. Gdy
stop()
, jednak zauważ, że
nie możesz ponownie zadzwonić do użytkownika start()
, dopóki nie
przygotuj ponownie MediaPlayer
.
Zawsze zachowuj diagram stanu.
należy pamiętać przy pisaniu kodu, który wchodzi w interakcje z
MediaPlayer
, ponieważ wywoływanie jego metod z niewłaściwego stanu jest
jest częstą przyczyną błędów.
Zwalnianie odtwarzacza MediaPlayer
MediaPlayer
może zużywać cenne
zasobów systemowych.
Dlatego należy zawsze podjąć dodatkowe środki ostrożności, aby zapobiec
i korzystanie z instancji MediaPlayer
dłużej, niż jest to konieczne. Gdy
po zakończeniu tego procesu, zawsze należy zadzwonić
release()
, aby upewnić się, że:
przydzielone do niej zasoby systemowe są prawidłowo zwalniane. Jeśli na przykład jesteś
za pomocą: MediaPlayer
, a Twoja aktywność otrzymuje wywołanie do: onStop()
, musisz zwolnić MediaPlayer
,
ponieważ
nie ma sensu ich trzymać, gdy aktywność nie wchodzi w interakcję
użytkownika (chyba że odtwarzasz multimedia w tle, co zostało omówione w następnej sekcji).
Oczywiście po wznowieniu lub wznowieniu aktywności musisz:
utwórz nowy plik MediaPlayer
i przygotuj go ponownie, zanim wznowisz odtwarzanie.
Oto jak zwolnić, a następnie unieważnić MediaPlayer
:
Kotlin
mediaPlayer?.release() mediaPlayer = null
Java
mediaPlayer.release(); mediaPlayer = null;
Rozważmy na przykład problemy, które mogą wystąpić, jeśli
zapomniano zwolnić MediaPlayer
, gdy Twoja aktywność jest zatrzymana, ale utwórz
nowy, gdy aktywność zacznie się od nowa. Jak być może wiesz, gdy użytkownik zmieni
orientacja ekranu (lub zmiana konfiguracji urządzenia w inny sposób),
system to umożliwia, ponownie uruchamiając aktywność (domyślnie), dzięki czemu możesz szybko
wykorzystują wszystkie zasoby systemowe jako użytkownik
obraca urządzenie do orientacji pionowej i poziomej, ponieważ
zmiany orientacji ekranu, utworzysz nowy MediaPlayer
,
wersji. Więcej informacji o ponownym uruchamianiu środowiska wykonawczego znajdziesz w artykule Obsługa zmian środowiska wykonawczego.
Być może zastanawiasz się, co się stanie, jeśli zechcesz grać dalej.
„multimedia w tle” nawet gdy użytkownik opuści Twoją aktywność,
sposób działania wbudowanej aplikacji YouTube Music. W tym przypadku potrzebujesz
MediaPlayer
kontrolowane przez Usługę, jak
zostaną omówione w następnej sekcji.
Używanie MediaPlayer w usłudze
Jeśli chcesz, aby multimedia były odtwarzane w tle, nawet gdy aplikacja
nie jest na ekranie, czyli chcesz,
by był on odtwarzany,
interakcji z innymi aplikacjami – wtedy trzeba rozpocząć
i kontrolować
MediaPlayer
instancję z tego miejsca.
Musisz umieścić komponent
MediaPlayer w usłudze MediaBrowserServiceCompat
i zawierające
wchodzi w interakcję z
MediaBrowserCompat
w innej aktywności.
Zachowaj ostrożność przy tej konfiguracji klienta/serwera. Istnieją oczekiwania jak odtwarzacz działający w usłudze działającej w tle współdziała z pozostałymi elementami systemu. Jeśli aplikacja nie spełnia tych oczekiwań, użytkownik może mają złe doświadczenia. Odczytano Tworzenie aplikacji audio .
W tej sekcji znajdziesz specjalne instrukcje dotyczące zarządzania odtwarzaczem MediaPlayer zaimplementowanym w usłudze.
Działanie asynchroniczne
Przede wszystkim, tak jak Activity
, wszystkie działania
Service
to zadanie w jednym wątku przez
domyślnie – jeśli w tej samej aplikacji uruchamiasz aktywność i usługę,
domyślnie używać tego samego wątku („wątku głównego”). W związku z tym usługi muszą
szybkie przetwarzanie przychodzących intencji
i nigdy nie przeprowadzać długich obliczeń. Jeśli jakieś będą obfite
oczekiwane są operacje wykonywania lub blokowania, należy je wykonywać asynchronicznie:
kolejny wątek wdrażany samodzielnie lub z wykorzystaniem dostępnych narzędzi platformy.
do asynchronicznego przetwarzania.
Na przykład gdy używasz uprawnienia MediaPlayer
z wątku głównego,
należy dzwonić pod numer prepareAsync()
, a nie
prepare()
i zaimplementuj
MediaPlayer.OnPreparedListener
, aby otrzymać powiadomienie, gdy przygotowania się zakończą i możesz zacząć grać.
Na przykład:
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(); } }
Obsługa błędów asynchronicznych
W przypadku operacji synchronicznych błędy zwykle występują
być sygnalizowane wyjątkiem lub kodem błędu, ale jeśli używasz asynchronicznego
, upewnij się, że aplikacja została powiadomiona
podejmuj odpowiednie działania. W przypadku atrybutu MediaPlayer
możesz to osiągnąć, implementując tag
MediaPlayer.OnErrorListener
i
konfigurując go w instancji 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! } }
Pamiętaj, że gdy wystąpi błąd, MediaPlayer
przechodzi do stanu Błąd (zobacz dokumentację
MediaPlayer
klasy dla diagramu pełnego stanu)
i trzeba go zresetować, zanim będzie można go użyć.
Używanie blokad uśpienia
Podczas projektowania aplikacji, które odtwarzają multimedia w tle, urządzenie może zostać uśpione. gdy usługa jest uruchomiona. System Android stara się oszczędzać baterii, gdy urządzenie jest w trybie uśpienia, system będzie próbował wyłączyć wszystkie funkcje telefonu Nie jest to konieczne, obejmuje to procesor i sprzęt Wi-Fi. Jeśli jednak Twoja usługa odtwarza lub odtwarza muzykę, chcesz zapobiec przed zakłóceniami w odtwarzaniu.
Aby zapewnić, że Twoja usługa będzie nadal działać zgodnie z tych warunków, należy użyć funkcji „wybudzenia blokad”. Blokada uśpienia to sygnał dla system, w którym aplikacja korzysta z funkcji, która powinna pozostają dostępne nawet wtedy, gdy telefon jest nieaktywny.
Uwaga: blokad uśpienia należy zawsze stosować z umiarem i przytrzymywać je dlatego tak długo, jak to konieczne, ponieważ znacznie zmniejszają żywotność baterii urządzenia.
Aby zapewnić nieprzerwane działanie procesora, gdy MediaPlayer
jest
w trybie odtwarzania, przy inicjowaniu urządzenia MediaPlayer
wywołaj metodę setWakeMode()
. Gdy to zrobisz,
podczas odtwarzania MediaPlayer
trzyma podaną blokadę i zwalnia ją
po wstrzymaniu lub zatrzymaniu:
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);
Jednak uzyskana w tym przykładzie blokada uśpienia gwarantuje jedynie, że procesor pozostanie aktywny. Jeśli
przesyłasz multimedia przez
i używasz Wi-Fi,
WifiLock
jako
który trzeba pozyskać i uwolnić ręcznie. Kiedy zaczniesz przygotowywać
MediaPlayer
ze zdalnym adresem URL, należy utworzyć i uzyskać blokadę sieci Wi-Fi.
Na przykład:
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();
Gdy wstrzymasz lub zatrzymasz odtwarzanie albo gdy nie będziesz już potrzebować sieci, zwolnij blokadę:
Kotlin
wifiLock.release()
Java
wifiLock.release();
Trwa czyszczenie
Jak wspomnieliśmy wcześniej, obiekt MediaPlayer
może wykorzystywać znaczną
zasobów systemowych. Należy więc przechowywać go tylko tak długo, jak to potrzebne,
release()
. To ważne
jawnego wywoływania tej metody czyszczenia, zamiast polegać na funkcji czyszczenia pamięci systemu, ponieważ
odzyskanie pamięci MediaPlayer
przez śmieciar może trochę potrwać,
ponieważ uwzględnia jedynie potrzeby związane z pamięcią i nie brakuje innych zasobów związanych z multimediami.
W przypadku korzystania z usługi należy zawsze zastąpić parametr
Metoda onDestroy()
, która pozwala upewnić się, że publikujesz
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(); } }
Zawsze należy szukać innych możliwości udostępnienia MediaPlayer
a także nie zwalniać go
z możliwością zamknięcia. Jeśli na przykład spodziewasz się, że nie
na odtwarzanie multimediów przez dłuższy czas (np. po utracie ostrości audio),
zdecydowanie należy zwolnić istniejący MediaPlayer
i utworzyć go ponownie
później. Dzień
Jeśli spodziewasz się zatrzymania odtwarzania tylko na bardzo krótki czas, prawdopodobnie
MediaPlayer
, aby uniknąć problemów z tworzeniem i przygotowywaniem
ponownie.
Zarządzanie prawami cyfrowymi (DRM)
Począwszy od Androida 8.0 (poziom interfejsu API 26) MediaPlayer
zawiera interfejsy API, które
umożliwiają odtwarzanie materiałów chronionych DRM. Są podobne do niskopoziomowego interfejsu API udostępnianego przez
MediaDrm
, ale działają one na wyższym poziomie i nie
i udostępnić bazowy mechanizm wyodrębniania, drm i obiekty kryptograficzne.
Chociaż interfejs MediaPlayer DRM API nie zapewnia pełnej funkcjonalności
MediaDrm
, obsługuje większość typowych przypadków użycia.
Obecna implementacja obsługuje te typy treści:
- Lokalne pliki multimedialne chronione przez Widevine
- Zdalne/strumieniowe pliki multimedialne chronione przez Widevine
Ten fragment kodu pokazuje, jak korzystać z nowego odtwarzacza MediaPlayer DRM w prostej implementacji synchronicznej.
Aby zarządzać multimediami kontrolowanymi przez DRM, musisz dodać nowe metody do pliku normalny przebieg wywołań MediaPlayer, jak pokazano poniżej:
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();
Zacznij od zainicjowania obiektu i ustawienia MediaPlayer
jego źródło za pomocą funkcji setDataSource()
,
jak zwykle. Następnie, aby użyć DRM, wykonaj te czynności:
- Jeśli chcesz, aby aplikacja przeprowadzała konfigurację niestandardową, zdefiniuj
OnDrmConfigHelper
i dołącz go do gracz korzystający zsetOnDrmConfigHelper()
- Będziesz dzwonić pod numer
prepare()
. - Będziesz dzwonić pod numer
getDrmInfo()
. Jeśli źródło ma DRM content, metoda zwraca wartość inną niż null Wartość:MediaPlayer.DrmInfo
.
Jeśli MediaPlayer.DrmInfo
istnieje:
- Przeanalizuj mapę dostępnych identyfikatorów UUID i wybierz jeden z nich.
- Przygotuj konfigurację DRM dla bieżącego źródła, wywołując funkcję
prepareDrm()
. - Jeśli masz utworzoną i zarejestrowaną
Wywołanie zwrotne
OnDrmConfigHelper
, nosi nazwę podczas gdyprepareDrm()
. Pozwala to na przeprowadzenie niestandardowej konfiguracji DRM przed otwarciem sesji DRM. Wywołanie zwrotne synchronicznie w wątku o nazwieprepareDrm()
Do dostępu do właściwości DRM, wywołajgetDrmPropertyString()
isetDrmPropertyString()
Unikaj wykonywania długich operacji. - Jeśli urządzenie nie zostało jeszcze obsłużone,
prepareDrm()
również uzyskuje dostęp do serwera obsługi administracyjnej w celu obsługi administracyjnej urządzenia. Może to potrwać zmienną ilość czasu w zależności od połączenia sieciowego. - Aby wysłać tablicę bajtową żądania nieprzejrzystego klucza do serwera licencji, wywołaj
getKeyRequest()
- Aby poinformować mechanizm DRM o odpowiedzi klucza otrzymanej z serwera licencji, wywołaj
provideKeyResponse()
Wynik zależy od typu żądania klucza:- Jeśli odpowiedź jest żądaniem klucza offline, wynikiem jest identyfikator zestawu kluczy. Za pomocą
ten identyfikator zestawu kluczy za pomocą funkcji
restoreKeys()
w celu przywrócenia kluczy do nowego . - Jeśli odpowiedź dotyczy żądania strumieniowego lub zwolnienia, wynik ma wartość null.
- Jeśli odpowiedź jest żądaniem klucza offline, wynikiem jest identyfikator zestawu kluczy. Za pomocą
ten identyfikator zestawu kluczy za pomocą funkcji
Asynchroniczne uruchamianie prepareDrm()
Domyślnie prepareDrm()
działa synchronicznie i blokuje do momentu zakończenia przygotowań. Jednakże
pierwsze przygotowanie systemu DRM na nowym urządzeniu może też wymagać obsługi administracyjnej,
obsługiwane wewnętrznie przez
prepareDrm()
i
może zająć trochę czasu ze względu na operacje sieciowe. Dostępne opcje
unikaj blokowania na
prepareDrm()
, autor:
określić i skonfigurować MediaPlayer.OnDrmPreparedListener
.
Gdy ustawisz OnDrmPreparedListener
,
prepareDrm()
przeprowadza obsługę administracyjną (w razie potrzeby) i przygotowanie w tle. Kiedy
gdy zakończy się udostępnianie i przygotowanie, detektor jest wywoływany. Zalecenia
nie należy przyjmować żadnych założeń na temat sekwencji wywoływania ani wątku, w którym
działa (chyba że jest zarejestrowany w wątku modułu obsługi).
Detektor można wywołać przed lub po
prepareDrm()
„powrót karetki”.
Asynchroniczne konfigurowanie DRM
DRM można zainicjować asynchronicznie, tworząc i rejestrując
MediaPlayer.OnDrmInfoListener
na potrzeby przygotowania do zabezpieczeń DRM oraz
MediaPlayer.OnDrmPreparedListener
, aby uruchomić odtwarzacz.
Współpracują one z
prepareAsync()
, jak pokazano poniżej:
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(); }
Obsługa zaszyfrowanych multimediów
Począwszy od Androida 8.0 (poziom interfejsu API 26) MediaPlayer
może też odszyfrowywać
System CENC (Common Encryption Scheme)
Multimedia zaszyfrowane na poziomie próbki HLS (METHOD=SAMPLE-AES) na potrzeby typów strumieni podstawowych
H.264 i AAC. Wcześniej obsługiwane były pliki multimedialne szyfrowane w pełnym segmencie (metoda=AES-128).
Pobieranie multimediów z narzędzia Content resolver
Inną funkcją, która może być przydatna w odtwarzaczu multimediów, jest możliwość
pobiera muzykę zapisaną na urządzeniu. Możesz to zrobić, wysyłając zapytanie do ContentResolver
o media zewnętrzne:
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()); }
Aby używać tej funkcji z MediaPlayer
, możesz to zrobić:
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...
Więcej informacji
Te strony zawierają omówienie tematów związanych z nagrywaniem, przechowywaniem i odtwarzaniem dźwięku i wideo.