Android kotlin play sound

Полный список

— работаем с SoundPool

На прошлом уроке мы рассмотрели MediaPlayer, который подходит для проигрывания продолжительных треков. SoundPool же подходит для случая, когда вам необходимо многократное воспроизведение небольших файлов. Самый простой пример – игры. Когда есть короткий звук какого-либо действия (прыжка, выстрела и т.п.) и этот звук достаточно часто необходимо воспроизводить. SoundPool один раз загружает этот звук в память и оттуда его воспроизводит, что, конечно, неплохо в плане производительности.

Класс SoundPool несложен. Позволяет загрузить звук в память, проиграть его, ставить паузу, регулировать громкость (левый и правый каналы), менять скорость воспроизведения, ограничивать кол-во одновременно воспроизводимых звуков, использовать приоритеты.

Напишем простое приложение, в котором рассмотрим все эти возможности.

Project name: P1271_SoundPool
Build Target: Android 2.3.3
Application name: SoundPool
Package name: ru.startandroid.develop.p1271soundpool
Create Activity: MainActivity

Добавим строки в strings.xml:

Только кнопка для запуска воспроизведения.

Для тестов нам понадобится пара звуков. Я буду использовать explosion.ogg (взрыв) и shot.ogg (выстрел). Поместим explosion.ogg в папку assets, а shot.ogg в папку res/raw.

Сначала создаем SoundPool. На вход ему передаем:
— максимальное кол-во одновременно воспроизводимых файлов
— аудио-поток, который будет использоваться
— некий параметр качества, который пока что игнорируется системой. Рекомендуется передавать туда 0

Методом setOnLoadCompleteListener мы устанавливаем слушателя загрузки. Загрузка аудио-файлов происходит асинхронно, и по ее окончании срабатывает метод onLoadComplete этого слушателя.

Далее загружаем файлы. Для этого используются различные варианты метода load. Чтобы загрузить файл из raw, необходимо указать Context, ID raw-файла и приоритет. Приоритет пока что также игнорируется системой, рекомендуется передавать туда 1.

Чтобы загрузить файл из assets используем другую реализацию метода load, которая на вход требует AssetFileDescriptor и приоритет. AssetFileDescriptor можно получить, используя метод openFd класса AssetManager, указав имя файла. Приоритет снова никакой роли не играет, передаем 1.

У метода load есть несколько реализаций, я специально показал две разных для наглядности. В хелпе вы можете найти ту, которая вам более подходит.

Метод load возвращает нам ID загруженного файла. Используя этот ID, мы будем проигрывать файл.

В методе onClick запускаем воспроизведение файлов. Для этого используется метод play. На вход он требует ряд параметров:
— ID файла. Тот самый, который мы получили от метода load.
— громкость левого канала (от 0.0 до 1.0)
— громкость правого канала (от 0.0 до 1.0)
— приоритет. Этот приоритет уже не декоративный, а вполне себе используемый. Далее увидим, где он нужен.
— количество повторов. Т.е. файл будет воспроизведен один раз точно + то количество раз, которое вы здесь укажете
— скорость воспроизведения. Можно задать от половины нормальной скорости до двойной (0.5 — 2).

Метод play возвращает ID потока, используемого для проигрывания файла. Этот ID можно использовать для дальнейшего изменения настроек в процессе проигрывания файла, а также для паузы.

Метод onLoadComplete слушателя OnLoadCompleteListener выполняется, когда SoundPool загружает файл. На вход вы получаете сам SoundPool, ID файла (тот же, что и load возвращал) и статус (0, если успешно)

Все сохраним и запустим приложение.

08:38:12.726: D/myLogs(333): soundIdShot = 1
08:38:12.726: D/myLogs(333): soundIdExplosion = 2
08:38:12.855: D/myLogs(333): onLoadComplete, sampleId = 1, status = 0
08:38:12.976: D/myLogs(333): onLoadComplete, sampleId = 2, status = 0

Видно, что загрузка звуков заняла определенное время. Жмем Play и слышим, как приложение играет оба звука одновременно.

Параметры метода play

Давайте поменяем громкость. Перепишем onClick:

Теперь один звук более слышен слева, а другой справа.

Поменяем кол-во повторов:

Теперь звук выстрела воспроизведен 6 раз (1 + 5 повторов), а звук взрыва – 3 раза (1 + 2 повтора).

Звук выстрела стал в два раза медленнее, а звук взрыва – в два раза быстрее.

Приоритет

Теперь давайте разберемся с приоритетом и кол-вом одновременно проигрываемых звуков. Хелп гласит:

«Priority runs low to high, i.e. higher numbers are higher priority. Priority is used when a call to play() would cause the number of active streams to exceed the value established by the maxStreams parameter when the SoundPool was created. In this case, the stream allocator will stop the lowest priority stream. If there are multiple streams with the same low priority, it will choose the oldest stream to stop. In the case where the priority of the new stream is lower than all the active streams, the new sound will not play and the play() function will return a streamID of zero.«

Т.е. приоритет используется, когда кол-во звуков, которое необходимо воспроизводить в данный момент, превышает максимально допустимое кол-во (мы его указывали при создании SoundPool, константа MAX_STREAMS). В этом случае звуки с низким приоритетом будут остановлены. Если есть несколько звуков с одинаково низким приоритетом, то останавливаются более старые. Если максимальное количество звуков уже достигнуто, и вы пытаетесь воспроизвести звук с низким приоритетом, то он не будет проигран, а метод play вернет 0 вместо ID потока.

Читайте также:  Drm media converter андроид

Давайте проведем тесты и понаблюдаем все это в действии.

Звука у нас всего два. Поэтому, чтобы добиться конфликта, давайте для нашего SoundPool поставим кол-во одновременно воспроизводимых звуков равное одному:

onClick перепишем так:

Я, конечно, понимаю, что ставить паузу в основном потоке это #непофэншуюивообщенекомильфо, но в данном уроке я считаю это допустимым, чтобы не городить лишний код. Так что не обращайте на это внимание )

Мы начнем проигрывать звук выстрела 11 раз, а спустя пару секунд запустим звук взрыва. Выстрелы к тому моменту еще не успеют отзвучать, поэтому поглядим, как поведет себя система в данной ситуации. Напоминаю, что у нас сейчас установлен лимит на кол-во звуков = 1.

Заодно будем выводить в лог ID потоков, которые возвращает нам метод play.

Все сохраняем, запускаем, жмем Play. Я слышу 4 выстрела, потом взрыв. Т.е. при попытке воспроизвести взрыв система видит, что надо одновременно играть два звука: уже звучащий — выстрел и новый — взрыв. А лимит позволяет в один момент времени играть только один звук. Приоритеты у звуков одинаковые. Следовательно, система останавливает более старый звук, в нашем случае это выстрелы.

09:24:35.035: D/myLogs(754): streamIDShot = 1
09:24:37.092: D/myLogs(754): streamIDExplosion = 2

Разница в две секунды. ID потоков получены по обоим звукам.

Попробуем выставить для выстрелов приоритет более высокий, чем у взрыва.

Нарисуем у выстрела приоритет = 1, а у взрыва остался 0.

Сохраняем, запускаем, жмем Play.

Прога воспроизводит все выстрелы. Звук взрыва вообще не воспроизводится. Как и в прошлый раз у системы был выбор, но в этот раз она отменила взрыв и продолжила играть выстрелы, т.к. приоритеты выстрелов выше.

09:28:32.906: D/myLogs(788): streamIDShot = 1
09:28:34.934: D/myLogs(788): streamIDExplosion = 0

Видим, что для взрыва метод play вернул 0 вместо ID потока. Это значит, что звук не воспроизводился.

Пауза

Давайте посмотрим на возможности паузы. Мы можем приостановить какие-то определенные звуки, а можем все сразу.

Увеличим снова лимит звуков:

Мы запускаем проигрывание 10 выстрелов и 6 взрывов. Через 2 секунды приостанавливаем выстрелы, а еще через 3 секунды возобновляем. Для этого используются методы pause и resume, на вход которым даем ID потока из play.

Сохраняем, запускаем, жмем Play. Слышим выстрелы и взрывы. Затем выстрелы стихают, остаются только взрывы. Затем выстрелы снова возобновляются и все стихает. Counter-terrorist win )

Попробуем приостановить все звуки.

Для этого используем методы autoPause и autoResume. При проигрывании у нас будет пауза в три секунды, потом все возобновится.

Меняем уже играющий звук

Пока звук воспроизводится, вы можете повлиять на его характеристики, которые были заданы в методе play:

На вход методам идет ID потока (который вернул play) и необходимое вам значение параметра.

Например, поработаем с громкостью:

Выстрелы начнут играть в одном канале, взрывы — в другом. А через две секунды они поменяются каналами.

Выгрузка

Осталось упомянуть про еще два метода.

unload – выгрузит указанный звук из памяти. На вход требует ID звука, который возвращал метод load.

release – освобождает все ресурсы SoundPool, более он не сможет быть используемым и ссылку на него необходимо об-null-ить.

На следующем уроке:

— используем Audio Focus

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Создание собственного Android-диктофона с помощью Kotlin

Мультимедийный фреймворк Android поддерживает запись и воспроизведение аудио. В этой статье я покажу, как разработать простое приложение для звукозаписи, которое будет записывать аудио и сохранять его в локальном хранилище Android-устройства с помощью MediaRecorder из Android SDK.

Вы также узнаете, как запросить разрешения у пользователя в режиме реального времени и как работать с локальным хранилищем Android-устройства.

Создание пользовательского интерфейса

Сперва нам нужно создать интерфейс для звукозаписи. Это простой layout с тремя кнопками, которые будут использоваться для запуска, приостановки/возобновления и остановки записи.

Запрос требуемых разрешений

После создания пользовательского интерфейса мы можем начать использовать MediaRecorder для реализации основной функциональности нашего приложения. Но сначала нам нужно запросить необходимые разрешения для записи аудио и доступа к локальному хранилищу. Cделаем мы это это с помощью нескольких простых строк кода в нашем файле AndroidManifest.xml :

Также нужно проверить, одобрил ли пользователь разрешения, прежде чем мы сможем использовать наш MediaRecorder . Сделаем это в Activity MainActivity.kt :

Читайте также:  Callx для андроида что это

Примечание: позже эти строки кода будут перемещены в OnClickListener кнопки начала записи аудио, чтобы мы могли убедиться, что MediaRecorder не будет запущен без необходимых разрешений.

Запись и сохранение аудио

Добавление OnClickListeners

Добавим слушатели к кнопкам, чтобы они реагировали на пользовательские события. Как я упоминал ранее, проверка на наличие необходимых разрешений будет добавлена в OnClickListener кнопки начала записи аудио:

Настройка MediaRecorder

Далее нам нужно указать путь для сохранения аудио и настроить MediaRecorder.

Мы берём путь к корню нашего внешнего хранилища и добавляем в него имя нашей записи и тип файла. После этого мы создаём объект MediaRecorder и определяем источник звука, аудиокодер, формат и файл для записи.

Запись и сохранение аудио

Код, используемый для запуска MediaRecorder , определяется в OnClickListener кнопки начала записи аудио:

Как видите, нужно вызвать функцию prepare , прежде чем мы сможем начать запись. Мы также встраиваем вызов в блок try-catch, чтобы приложение не сломалось при сбое функции prepare .

OnClickListeners кнопки остановки записи очень похож на код выше.

Здесь мы проверяем, работает ли в данный момент MediaRecorder , прежде чем мы остановим запись, потому что наше приложение сломается, если метод stop будет вызван, в то время как MediaRecorder не будет запущен. После этого мы меняем переменную состояния на false , чтобы пользователь не мог снова нажать кнопку остановки.

Нам осталось определить OnClickListener для кнопки приостановки/возобновления.

В этих двух методах мы проверяем, работает ли MediaRecorder . Если работает, мы приостановим запись и изменим текст кнопки для возобновления. При повторном нажатии запись возобновится.

Наконец, мы можем записать аудио и прослушать его, открыв файл recording.mp3 , который будет сохранён в нашем локальном хранилище. Просто откройте проводник файлов и сделайте поиск по имени файла recording.mp3 .

Исходный код

Вот полный исходный код нашего приложения:

Заключение

Теперь вы знаете, как работает MediaRecorder , как запрашивать разрешения в режиме реального времени и почему это важно делать. Вы также узнали о локальном хранилище вашего устройства Android и о том, как хранить в нём данные.

Более сложная версия этого приложения, в которой есть некоторые дополнительные функции, такие как воспроизведение ваших записей с помощью MediaPlayer , доступна на Github.

Источник

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:

Читайте также:  Ufc 2 mobile android

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.

Источник

Оцените статью