Полный список
MediaPlayer – класс, который позволит вам проигрывать аудио/видео файлы с возможностью сделать паузу и перемотать в нужную позицию. MediaPlayer умеет работать с различными источниками, это может быть: путь к файлу (на SD или в инете), адрес потока, Uri или файл из папки res/raw.
Напишем небольшое приложение аудио-плеер и используем в нем все эти возможности.
Project name: P1261_MediaPlayer
Build Target: Android 2.3.3
Application name: MediaPlayer
Package name: ru.startandroid.develop.p1261mediaplayer
Create Activity: MainActivity
Добавляем строки в strings.xml:
Так это выглядит на экране
Кнопки верхнего ряда запускают проигрывание треков из различных источников. Кнопки среднего ряда – это пауза, возобновление, стоп и чекбокс повторения трека. А в нижнем ряду кнопки перемотки назад/вперед и вывод в лог текущей информации.
Создайте папку res/raw и положите в нее какой-нить звуковой файл с именем explosion.mp3. Например, его можно скачать здесь — http://dl.dropboxusercontent.com/u/6197740/explosion.mp3.
Разбираемся. Сначала создаем константы-пути, которые будет использовать проигрыватель. Это файл в инете (DATA_HTTP), поток в инете (DATA_STREAM), файл на флэшке (DATA_SD) и Uri на мелодию из системы (DATA_URI). Для SD и Uri укажите ваши значения, чтобы такие файлы существовали. (По получению Uri в конце урока есть вспомогательный код)
В onCreate получаем AudioManager, находим на экране чекбокс и настраиваем так, чтобы он включал/выключал режим повтора для плеера.
onClickStart – метод для обработки нажатий на кнопки верхнего ряда. Сначала мы освобождаем ресурсы текущего проигрывателя. Затем в зависимости от нажатой кнопки стартуем проигрывание. Какие методы для этого используются?
setDataSource – задает источник данных для проигрывания
setAudioStreamType – задает аудио-поток, который будет использован для проигрывания. Их существует несколько: STREAM_MUSIC, STREAM_NOTIFICATION и п. Подробнее их можно посмотреть в доках по AudioManager. Предполагаю, что созданы они для того, чтобы можно было задавать разные уровни громкости, например, играм, звонкам и уведомлениям. Этот метод можно и пропустить, если вам не надо явно указывать какой-то поток. Насколько я понял, по умолчанию используется STREAM_MUSIC.
Далее используется метод prepare или prepareAsync (в паре с OnPreparedListener). Эти методы подготавливают плеер к проигрыванию. И, как понятно из названия, prepareAsync делает это асинхронно, и, когда все сделает, сообщит об этом слушателю из метода setOnPreparedListener. А метод prepare работает синхронно. Соотвественно, если хотим прослушать файл из инета, то используем prepareAsync, иначе наше приложение повесится, т.к. заблокируется основной поток, который обслуживает UI.
Ну и метод start запускает проигрывание.
В случае с raw-файлом мы используем метод create. В нем уже будет выполнен метод prepare и нам остается только выполнить start.
Далее мы для плеера включаем/выключаем повтор (setLooping) в зависимости от текущего значения чекбокса. И вешаем слушателя (setOnCompletionListener), который получит уведомление, когда проигрывание закончится.
В методе releaseMP мы выполняем метод release. Он освобождает используемые проигрывателем ресурсы, его рекомендуется вызывать когда вы закончили работу с плеером. Более того, хелп рекомендует вызывать этот метод и при onPause/onStop, если нет острой необходимости держать объект.
В методе onClick мы обрабатываем нажатия на кнопки управления проигрывателем. Какие здесь используются методы?
start – возобновляет проигрывание
seekTo – переход к определенной позиции трека (в милисекундах)
getCurrentPosition – получить текущую позицию (в милисекундах)
getDuration – общая продолжительность трека
isLooping – включен ли режим повтора
getStreamVolume – получить уровень громкости указанного потока
Далее идут методы
onPrepared – метод слушателя OnPreparedListener. Вызывается, когда плеер готов к проигрыванию.
onCompletion – метод слушателя OnCompletionListener. Вызывается, когда достигнут конец проигрываемого содержимого.
В методе onDestroy обязательно освобождаем ресурсы проигрывателя.
В манифесте добавляем права на интернет — android.permission.INTERNET.
Все сохраняем, запускаем приложение. Дизайн получившегося плеера, конечно, не ахти какой :), но нас сейчас интересует функционал.
Еще раз перечислю возможные действия. Нажимая верхние кнопки, мы запускаем проигрывание из различных источников. Кнопки среднего ряда позволят нам поставить паузу, возобновить/остановить проигрывание и включить режим повтора. Кнопки нижнего ряда перематывают назад/вперед на 3 сек (3000 мсек) и выводят инфу в лог.
Я включу проигрывание файла с SD и выведу инфу в лог (кнопка Info).
start SD
Playing true
Time 4702 / 170588
Looping false
Volume 10
Проигрывание идет, текущая позиция – 4-я секунда из 170, режим повтора выключен, громкость — 10.
Уменьшу громкость (кнопками устройства или эмулятора), включу режим повтора (чекбокс Loop), поставлю паузу (кнопка Pause) и снова выведу инфу в лог:
Playing false
Time 46237 / 170588
Looping true
Volume 6
Видим, что проигрывание остановилось, текущая позиция уже 46 секунд, режим повтора включен, а громкость уменьшилась до 6.
Теперь включу проигрывание потока (кнопка Stream). Смотрим лог:
08:49:13.799: D/myLogs(18805): start Stream
08:49:13.809: D/myLogs(18805): prepareAsync
08:49:27.589: D/myLogs(18805): onPrepared
Обратите внимание, сколько прошло времени с начала (prepareAsync) до завершения (onPrepared) подготовки проигрывателя – 14 секунд. Если бы мы использовали метод prepare, а не prepareAsync, то наше приложение было бы недоступно все это время.
Расскажу еще про несколько методов, которые я не использовал в примере, но о которых стоит знать.
Метод reset – сбрасывает плеер в начальное состояние, после него необходимо снова вызвать setDataSource и prepare. Похож на onRelease, но позволяет продолжить работу с этим же объектом. А вот после onRelease надо создавать новый объект MediaPlayer.
Метод setOnBufferingUpdateListener устанавливает слушателя буферизации проигрываемого потока. По идее слушатель будет получать процент буферизации, но у меня оно как-то странно работает — показывает или 0 или 100.
Метод setOnErrorListener устанавливает слушателя для получения ошибок. Особенно это полезно при методe prepareAsync. Если в ходе этого метода возникнут ошибки, то их можно поймать только так.
Метод setWakeMode позволяет ставить стандартную (PowerManager.WakeLock) блокировку на время проигрывания, указав тип блокировки. Не забудьте в манифесте добавить права на WAKE_LOCK.
По поводу видео. Метод setDisplay позволяет указать плееру, куда выводить изображение. Размещаете на экране компонент SurfaceView (вкладка Advanced), вызываете его метод getHolder и полученный объект передаете в setDisplay. Плеер выведет изображение на этот компонент.
Чтобы узнать размер проигрываемого изображения можно использовать методы getVideoHeight и getVideoWidth.
В хелпе класса MediaPlayer есть хорошая схема состояний плеера. Она кажется запутанной, но если посидеть и поразбираться, то вполне можно все понять. Схема полезная, советую вникнуть.
А здесь можно посмотреть какие форматы поддерживаются системой.
Также хелп любезно предоставляет нам код, который позволит просмотреть существующие медиа-файлы в системе:
На следующем уроке:
— работаем с SoundPool
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
How to play audio using the MediaPlayer class and Kotlin
This tutorial will explore how to play and pause audio files in an Android app using MediaPlayer. The first half of this tutorial will focus on how to play audio files which are included within the app itself, while the second half will discuss how to play external audio files and handle errors.
Importing audio files
Sound effects and music that will be used in the app first must be imported into the Android Studio project. To do this, navigate through Project > app then right-click the res folder. Select New > Android Resource Directory
Set the Directory name to ‘raw’ then press OK.
This will create a folder called raw, which is where you will store media files. For this tutorial, we will use an MP3 recording of running water (which you can download below) but you are welcome to use another audio file of your choosing.
Drag and drop the audio file from your computer into the raw folder. Note, you may also be asked to confirm that you wish to move the audio file over to the project.
The water.mp3 file is now ready to be used.
Adding the play and pause buttons
In this section, we will add the play and pause buttons which will control playback. Open up the layout file where you want the buttons to go such as activity_main.xml (found by navigating through Project > app > res > layout). Open the file in Design view and locate the Palette. Search in the Buttons category for the ImageButton widget then drag and drop it into the layout.
A ‘Pick a Resouce’ window will invite you to select an image for the button. Select ic_media_play then press OK to add the button to the layout.
Select the Play button then refer to the Attributes panel. Set the id to ‘playButton’ and the onClick attribute to ‘playSound’. Note the playSound value may not be recognised by Android Studio yet but this will be resolved shortly.
Add another ImageButton like before, except this time use ic_media_pause as the image, set the id to pauseButton and set the onClick attribute to pauseSound. NB: you may have to resolve missing constraints and missing contentDescription errors.
With the play and pause buttons now added to the layout, we can write the Kotlin code which makes the buttons operational.
Making the play and pause buttons operational
To make the buttons operational, open the Kotlin file which manages the layout e.g. MainActivity.kt (found by navigating through Project > app > java > com) then add the following import statements to the top of the file:
Next, declare the following variable before the onCreate function:
The mMediaPlayer variable allows your app to utilise the MediaPlayer class and incorporate audio and video into your app.
Moving on, add the following functions after the onCreate function. We’ll discuss what each function means in turn.
The first function is responsible for playing the water sound. It begins by checking whether or not the mMediaPlayer variable has been assigned an audio file. If it hasn’t, then the MediaPlayer.create(this, R.raw.water) command loads the water.mp3 file and the isLooping = true and start commands begin playing the sound on repeat. On the other hand, if the mMediaPlayer is not null, then this means it has already been assigned an audio file and we can simply resume playback using the start command.
The second function, pauseSound, will only run if the mMediaPlayer variable is not null (i.e. it has been assigned an audio file) and is currently playing audio. If both criteria are met then the pauseSound function will pause playback.
The third function, stopSound, is optional and is included here to show you how you would stop playback as opposed to pausing it. The stop command halts and resets playback of the audio file, while the release() command removes the audio file from the mMediaPlayer variable. Releasing the mMediaPlayer variable when playback stops is good practise because it stops the MediaPlayer class from using the device’s memory and battery unnecessarily.
Finally, the onStop function will run when the activity or app is closed. It checks whether the mMediaPlayer variable has a media file assigned to it. If it does, then the function releases the MediaPlayer class from this file to conserve the device’s memory and battery life.
And that’s it! If you run the app now you should find you can play and pause the water sound on command.
Play external audio files
The MediaPlayer class can also be configured to accept external data sources such as audio files from the user’s device and content from the internet. For example, you load a song from the user’s device as follows:
The above code uses a method called playContentUri to initiate the playback of an audio file based on its Uri (a Uri is a piece of data which locates a file). In addition to loading the audio file using the setDataSource method, the above code also implements a method called setAudioAttributes. The setAudioAttributes method lets you describe the type of content you will be playing. This can be useful in several situations, such as when other apps and hardware interact with your app during playback. The attributes configuration used above specifies that the MediaPlayer will be used to play music. You can explore other attributes such as alarms, speech etc. in the official Android documentation.
Handle MediaPlayer errors
Things can go wrong with the MediaPlayer class from time to time, especially when you are playing external audio files. For example, if your app attempts to play a file which no longer exists then the app could crash if the error is not handled appropriately. One way to handle specific errors is to wrap the MediaPlayer code inside a try/catch block. The try/catch block will «try» a certain task (initiating playback) and «catch» any predefined exceptions (errors). There are two main ways to identify probable exceptions. First, you can test the app yourself and find which exceptions are output in the Logcat when the app crashes (see this tutorial for more information on reading the Logcat). Alternatively, you could read the Android documentation for the methods you are using and find out which exceptions (errors) the method may throw. For example, here is the documentation for the setDataSource method. One of the exceptions it can potentially throw is the IOException. An IOException is caused by an error reading/writing a file and so is likely to be thrown if the app tries to play an audio file which no longer exists. To catch this exception, you could write the following code:
The above code uses a try/catch block to attempt to load an audio file based on its Uri as described in the previous section. In the event that IOException error is thrown, the media player variable is set to null, which essentially removes any data that previously been applied, and the media player is then reset, which prepares the media player to be reused in a new playback attempt.
Источник